diff options
2068 files changed, 96000 insertions, 48224 deletions
diff --git a/.clang-format b/.clang-format index f7527b8927..1df6c35bfb 100644 --- a/.clang-format +++ b/.clang-format @@ -19,7 +19,7 @@ AllowAllParametersOfDeclarationOnNextLine: false # AllowShortEnumsOnASingleLine: true # AllowShortBlocksOnASingleLine: Never # AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Inline +# AllowShortFunctionsOnASingleLine: All # AllowShortLambdasOnASingleLine: All # AllowShortIfStatementsOnASingleLine: Never # AllowShortLoopsOnASingleLine: false diff --git a/.gitattributes b/.gitattributes index 45ea6c25e8..8d2fb108ba 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,8 @@ thirdparty/* linguist-vendored * text=auto eol=lf # Except for bat files, which are Windows only files *.bat eol=crlf +# And some test files where the EOL matters +*.test.txt -text # The above only works properly for Git 2.10+, so for older versions # we need to manually list the binary files we don't want modified. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ebbbe345fd..e7e88e95d7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -139,10 +139,10 @@ doc_classes/* @godotengine/documentation # Platform /platform/android/ @godotengine/android -/platform/iphone/ @godotengine/ios +/platform/ios/ @godotengine/ios /platform/javascript/ @godotengine/html5 /platform/linuxbsd/ @godotengine/linux-bsd -/platform/osx/ @godotengine/macos +/platform/macos/ @godotengine/macos /platform/uwp/ @godotengine/uwp /platform/windows/ @godotengine/windows diff --git a/.github/actions/godot-build/action.yml b/.github/actions/godot-build/action.yml index 7af3516f71..75f3d9ab37 100644 --- a/.github/actions/godot-build/action.yml +++ b/.github/actions/godot-build/action.yml @@ -35,5 +35,5 @@ runs: run: | echo "Building with flags:" ${{ env.SCONSFLAGS }} if ! ${{ inputs.tools }}; then rm -rf editor; fi # Ensure we don't include editor code. - scons p=${{ inputs.platform }} target=${{ inputs.target }} tools=${{ inputs.tools }} tests=${{ inputs.tests }} --jobs=2 ${{ env.SCONSFLAGS }} + scons p=${{ inputs.platform }} target=${{ inputs.target }} tools=${{ inputs.tools }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} ls -l bin/ diff --git a/.github/workflows/ios_builds.yml b/.github/workflows/ios_builds.yml index 40f091e234..03277edc1d 100644 --- a/.github/workflows/ios_builds.yml +++ b/.github/workflows/ios_builds.yml @@ -30,7 +30,7 @@ jobs: uses: ./.github/actions/godot-build with: sconsflags: ${{ env.SCONSFLAGS }} - platform: iphone + platform: ios target: release tools: false tests: false diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 0c6a140e28..0a0160326c 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: include: - - name: Editor w/ Mono (target=release_debug, tools=yes, tests=yes) + - name: Editor w Mono (target=release_debug, tools=yes, tests=yes) cache-name: linux-editor-mono target: release_debug tools: true @@ -31,12 +31,12 @@ jobs: proj-conv: true artifact: true - - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes) + - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes, linker=gold) cache-name: linux-editor-double-sanitizers target: debug tools: true tests: true - sconsflags: float=64 use_asan=yes use_ubsan=yes + sconsflags: float=64 use_asan=yes use_ubsan=yes linker=gold proj-test: true # Can be turned off for PRs that intentionally break compat with godot-cpp, # until both the upstream PR and the matching godot-cpp changes are merged. @@ -46,12 +46,12 @@ jobs: # Skip 2GiB artifact speeding up action. artifact: false - - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes) + - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld) cache-name: linux-editor-llvm-sanitizers target: debug tools: true tests: true - sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes + sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes linker=lld bin: "./bin/godot.linuxbsd.tools.64.llvm.san" build-mono: false # Skip 2GiB artifact speeding up action. @@ -88,7 +88,7 @@ jobs: sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \ libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip \ - llvm libspeechd-dev speech-dispatcher + llvm libspeechd-dev speech-dispatcher fontconfig libfontconfig-dev - name: Setup Godot build cache uses: ./.github/actions/godot-cache @@ -170,12 +170,18 @@ jobs: mv "regression-test-project-4.0" "test_project" # Editor is quite complicated piece of software, so it is easy to introduce bug here - - name: Open and close editor + - name: Open and close editor (Vulkan) if: ${{ matrix.proj-test }} run: | VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true misc/scripts/check_ci_log.py sanitizers_log.txt + - name: Open and close editor (GLES3) + if: ${{ matrix.proj-test }} + run: | + DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --rendering-driver opengl3 --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true + misc/scripts/check_ci_log.py sanitizers_log.txt + # Run test project - name: Run project if: ${{ matrix.proj-test }} @@ -212,13 +218,14 @@ jobs: if: ${{ matrix.godot-cpp-test }} run: | cd godot-cpp/test - scons target=${{ matrix.target }} -j2 + scons target=${{ matrix.target }} cd ../.. - name: Prepare artifact if: ${{ matrix.artifact }} run: | strip bin/godot.* + chmod +x bin/godot.* - name: Upload artifact uses: ./.github/actions/upload-artifact diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml index 9b8ffc45a7..0ad0995bb7 100644 --- a/.github/workflows/macos_builds.yml +++ b/.github/workflows/macos_builds.yml @@ -5,7 +5,7 @@ on: [push, pull_request] env: # Only used for the cache key. Increment version to force clean build. GODOT_BASE_BRANCH: master-v3 - SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes use_volk=yes + SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes concurrency: group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos @@ -24,7 +24,7 @@ jobs: target: release_debug tools: true tests: true - bin: "./bin/godot.osx.opt.tools.64" + bin: "./bin/godot.macos.opt.tools.64" - name: Template (target=release, tools=no) cache-name: macos-template @@ -45,11 +45,15 @@ jobs: - name: Setup python and scons uses: ./.github/actions/godot-deps + - name: Setup Vulkan SDK + run: | + sh misc/scripts/install_vulkan_sdk_macos.sh + - name: Compilation uses: ./.github/actions/godot-build with: sconsflags: ${{ env.SCONSFLAGS }} - platform: osx + platform: macos target: ${{ matrix.target }} tools: ${{ matrix.tools }} tests: ${{ matrix.tests }} @@ -65,6 +69,7 @@ jobs: - name: Prepare artifact run: | strip bin/godot.* + chmod +x bin/godot.* - name: Upload artifact uses: ./.github/actions/upload-artifact diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index d7d07b7022..81c7042663 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -37,6 +37,10 @@ jobs: run: | bash ./misc/scripts/clang_format.sh + - name: Header guards formatting checks (header_guards.sh) + run: | + bash ./misc/scripts/header_guards.sh + - name: Python style checks via black (black_format.sh) run: | bash ./misc/scripts/black_format.sh @@ -40,6 +40,7 @@ FireForge <67974470+fire-forge@users.noreply.github.com> <isaacr.7.2005@gmail.co foxydevloper <12120644+foxydevloper@users.noreply.github.com> Fredia Huya-Kouadio <fhuyakou@gmail.com> Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@google.com> +Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@fb.com> Geequlim <geequlim@gmail.com> Gilles Roudiere <gilles.roudiere@gmail.com> Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr> @@ -128,6 +129,7 @@ RaphaelHunter <raphael10241024@gmail.com> <raphael20141024@gmail.com> Rémi Verschelde <rverschelde@gmail.com> <remi@verschelde.fr> Rhody Lugo <rhodylugo@gmail.com> <rhodylugo@me.com> Ricardo Subtil <ricasubtil@gmail.com> +Rindbee <idleman@yeah.net> Robin Hübner <profan@prfn.se> <robinhubner@gmail.com> romulox_x <romulox_x@yahoo.com> Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com> @@ -139,6 +141,7 @@ Swarnim Arun <swarnimarun11@gmail.com> Theo Hallenius <redsymbzone@hotmail.com> Tomasz Chabora <kobewi4e@gmail.com> Twarit <wtwarit@gmail.com> +Vitika9 <vitika.program@gmail.com> V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com> Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr> Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com> diff --git a/AUTHORS.md b/AUTHORS.md index 36be7c4501..a409a1cea5 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -52,7 +52,6 @@ name is available. Bojidar Marinov (bojidar-bg) Brian Semrau (briansemrau) Bruno Lourenço (MadEqua) - bruvzg Cameron Reikes (creikey) Camille Mohr-Daurat (pouleyKetchoupp) Caner Demirer (cdemirer) @@ -64,8 +63,8 @@ name is available. Dana Olson (adolson) Daniel J. Ramirez (djrm) Daniel Rakos (aqnuep) - dankan1890 Danil Alexeev (dalexeev) + dankan1890 David Cambré (Gallilus) David Sichma (DavidSichma) David Snopek (dsnopek) @@ -85,7 +84,7 @@ name is available. Eveline Jarosz (Marqin) Fabian Mathews (supagu) Fabio Alessandrelli (Faless) - fabriceci + Fabrice Cipolla (fabriceci) Ferenc Arn (tagcup) FireForge (fire-forge) follower @@ -122,8 +121,8 @@ name is available. Jérôme Gully (Nutriz) Jia Jun Chai (SkyLucilfer) Joan Fons Sanchez (JFonS) - Johannes Witt (HaSa1002) Johan Manuel (29jm) + Johannes Witt (HaSa1002) Jordan Schidlowsky (winterpixelgames) Joshua Grams (JoshuaGrams) Juan Linietsky (reduz) @@ -187,6 +186,7 @@ name is available. Paul Batty (Paulb23) Paul Joannon (paulloz) Paul Trojahn (ptrojahn) + PÄvels NadtoÄajevs (bruvzg) PaweÅ‚ Fertyk (pfertyk) Pawel Kowal (pkowal1982) Pawel Lampe (Scony) @@ -232,6 +232,7 @@ name is available. Twarit Waikar (IronicallySerious) Umang Kalra (theoway) Vinzenz Feenstra (vinzenz) + Vitika Soni (Vitika9) 박한얼 (volzhs) V. Vamsi Krishna (vkbsb) Wilhem Barbier (nounoursheureux) @@ -246,3 +247,4 @@ name is available. Zak Stam (zaksnet) Zher Huei Lee (leezh) ZuBsPaCe + 风é’å±± (Rindbee) @@ -21,27 +21,33 @@ generous deed immortalized in the next stable release of Godot Engine. ## Silver sponsors + Affray Interactive <https://scp.games/pandemic> ASIFA-Hollywood <https://www.asifa-hollywood.org> - ORE System <https://ore-system.com> + Playful Studios <https://playfulstudios.com> + Robot Gentleman <http://robotgentleman.com> ## Bronze sponsors + Basically Games Brandon Lamb Bri Daniel Kaplan Garry Newman Gordon MacPherson Hunter Dickson + Isaiah smith + Kenney <https://kenney.nl> Kitcat490 Kyle Szklenski Maxim Karsten - Nik Rudenko Moonwards <https://www.moonwards.com> + Nik Rudenko TrampolineTales <https://trampolinetales.com> ## Mini sponsors AD Ford + Albin Lundahl Andres Hernandez Andrew Bowen Andrew Dunai @@ -75,8 +81,10 @@ generous deed immortalized in the next stable release of Godot Engine. Patrick Horn Patrick Schmidt Rami - Relintai + René Habermann Ronnie Cheng + Ryan Heath + Samantha ShikadiGum Slobodan Milnovic Stephan Lanfermann @@ -101,15 +109,14 @@ generous deed immortalized in the next stable release of Godot Engine. David Snopek Ed Morley First Last + Frank Kurka Hunter Jones Jacobus Dens - Jasper Brooks Javier Roman Joan Fons Jonathan Wright Jon Woodward Karl Werf - Kevin Vu Klavdij Voncina Maciej Pendolski Manuele Finocchiaro @@ -141,11 +148,12 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Mill Adam Nakonieczny Adam Nelson + Adam Stankiewicz Adrian Adamiak Alexander Erlemann - Alexander J Maynard Alex Khayrullin alice gambrell + Alo Mis Andrew Cunningham Andrew Farr Andriy @@ -154,21 +162,19 @@ generous deed immortalized in the next stable release of Godot Engine. Arch Henderson III Arthur S. Muszynski BasicIncomePlz - BoomHorseHat + Brandon Hawkinson BrizzleBrip c64cosmin Cameron Connolly Charles Gray Charlie Whitfield - Chase Taranto Chris Petrich Chris Serino - Craig Ostrin + Collin Rapp Craig Scarborough Craig Smith Cristopher CzechBlueBear - D DagobertDick Daniel Hernández Alcojor Daniel Tebbutt @@ -176,12 +182,11 @@ generous deed immortalized in the next stable release of Godot Engine. David Thomason Daylon J Williams Dennis Belfrage - Dev To Be curious Dimitri Nüscheler Donn Eddy Eric Brand + Eric Churches Eugenio Hugo Salgüero Jáñez - EXUREI Felix Winterhalter flesk foxydevloper @@ -200,22 +205,19 @@ generous deed immortalized in the next stable release of Godot Engine. Horváth-Lázár Péter Hu Hund Hunter Barabas - HurrieCrane Jaap Marsman Jamal Bencharki James Couzens - Jan Sælid Jared Jared White Jean-Sébastien Ross Jennifer Wilcox - Jeremi Biernacki Jesús Chicharro Joel Fivat Johnathan Kupferer + John Duplechain John Stinson Josef Stumpfegger - Jose Malheiro Jose Manuel Muñoz Perez Joshie Sparks Joshua Flores @@ -225,6 +227,7 @@ generous deed immortalized in the next stable release of Godot Engine. Julian Todd Juraj Móza JUSTIN CARROLL + Justin Palmer Kelteseth Kevan Khora @@ -247,30 +250,27 @@ generous deed immortalized in the next stable release of Godot Engine. Martin Soucek matt Matt Greene + Matthew Dana Max Kryschi - medecau Michael Dürwald Michael Policastro - Miika Moilanen MikadoSC Mike Barbee nate etan - Nick Abousselam - Nicola Cocchiaro Nicolás Carrasco + Nikita Blizniuk Oliver Dick Oscar Campos Paul Hocker Paul Von Zimmerman - Pavel Kotlyar Pedro Pete Goodwin - Peter Richmond Petr Malac - PhaineOfCatz - RafaÅ‚ Michno + Petrus Prinsloo + Philip Woods + R + RaiRu RAMupgrade - Raymond Harris Reilt Rene Tailleur Rhodochrone @@ -278,39 +278,35 @@ generous deed immortalized in the next stable release of Godot Engine. Rob Robert McDermott Rob McInroy - Rocknight Studios RodZilla Romeo Disca Ronnie Ashlock Ronny Mühle Russ Ryan Breaker - Ryan Heath Ryan Miller Ryan Scott Samuel Hummerstone Samuel Judd - Sean Morgan - Sebastian Hutter + schroedinger's possum Serban Serafimescu Sergey Fonaryov - Sergey Minakov Shishir Tandale Sing Chun Lee + Skides SKison Song Junwoo spacechase0 Stephan Hennion Steven Landow Stoned Xander + Sven Carstensen Teslatech + Thomas Bjarnelöf Thomas Kurz - Tim Suess Tobias Bocanegra Tobias Raggl - Todd Smith Tom Glenn - Tom Wor Torbulous toto bibi Troy Kinsella @@ -326,7 +322,6 @@ generous deed immortalized in the next stable release of Godot Engine. ## Silver donors - 1D_Inc Aaron Oldenburg A. B. Adam Brunnmeier @@ -350,7 +345,6 @@ generous deed immortalized in the next stable release of Godot Engine. Alder Stefano Alejandro Saucedo AleMax - Ales Jelovcan Alessandro Senese Alex Chan Alex Clavelle @@ -359,6 +353,7 @@ generous deed immortalized in the next stable release of Godot Engine. Allen Schade Amar Å ahinović Andre Altmueller + Andrei Pufu Andre Stackhouse Andrew Groot andrew james morris @@ -367,7 +362,6 @@ generous deed immortalized in the next stable release of Godot Engine. Ano Nim Anthony Avina Anton Bouwer - Antti Vesanen Arch Toasty Arda Erol Arthur Brainville @@ -380,7 +374,6 @@ generous deed immortalized in the next stable release of Godot Engine. Austin Miller Azar Gurbanov AzulCrescent - b110110 Balázs Batári Beau Seymour Behzad Ghaffari @@ -394,8 +387,9 @@ generous deed immortalized in the next stable release of Godot Engine. Bjarne Voigtländer Black Block Blunderjack - Brad Harms + BoiLudens Bram + Brian Brian Ford Bronson Zgeb Burney Waring @@ -406,19 +400,19 @@ generous deed immortalized in the next stable release of Godot Engine. Carlos Rios Carl van der Geest Casey - Cassidy James Chad Steadman Checkpoint Charlie Chris Jagusch Chris Langford Chris Ridenour + Christian Kaltenecker Christian Mauduit + Christian Scholz Christian Winter Christoffer Dahlblom Christophe Gagnier - Christopher Chin Christoph Woinke - ClicheChloe + Codex404 Cody Parker Conall O Conner Lane @@ -427,8 +421,11 @@ generous deed immortalized in the next stable release of Godot Engine. Craig Post CT Cullen Canejo + cynwav Dakota Watkins + Daniel H. Bahr Danielle Cheney + Dare Looks Daren Scot Wilson Dave Walker David Baker @@ -437,6 +434,7 @@ generous deed immortalized in the next stable release of Godot Engine. David Maziarka David Rapisarda Devin Carraway + Devin R Dimitri Roche Dmytro Korchynskyi Dominik Wetzel @@ -447,15 +445,14 @@ generous deed immortalized in the next stable release of Godot Engine. Ducky Duobix Duodecimal - Eduardo Teixeira Edward Herbert Edward Swartz Egon Elbre - eiki kanou Elgenzay Elias Nykrem Elijah Anderson Emerson MX + Ends Ephemeral Eric Stokes Eric Walkingshaw @@ -480,35 +477,29 @@ generous deed immortalized in the next stable release of Godot Engine. George Marques Gon Shibayama Green Fox - Greg Lincoln - Greg Olson Greyson Richey Grid Grominet Guillaume Pham Ngoc Guldoman Guo Hongci - gurehamu Haplo Hayden Foley Heribert Hirth + Hylian Ensemble Ian Richard Kunert Ian Williams IndustrialRobot Inki Crow iveks - izzy kestrel - Jackson Harmer Jacob D Jaguar Jake D - Jake Huxell Jako Danar James James A F Manley + James Allen James Gary - James Guardino - James Quincy James Thomas Jamie Massey Janis Skuja @@ -521,12 +512,14 @@ generous deed immortalized in the next stable release of Godot Engine. Jeff Hungerford Jeffrey Berube Jennifer Graves + Jeramie Jesse Dubay - Jim Engstrand + João Pedro Braz Joe Hurdle Joe Klemmer John Anders Stav John Bruce + Johnny Deepman Jonas Jonas Arndt Jonas Bernemann @@ -537,12 +530,13 @@ generous deed immortalized in the next stable release of Godot Engine. Jonathan Ellis Jonathan G Jonathan Turner + Jon Oakes Jon Sully Jordan West Jordy Goodridge Jorge Antunes - Jorge Araya Navarro Jose Francisco 'Yiro' Vera Girona + José Gabriel González Joseph Catrambone Josh P Josh Taylor @@ -557,6 +551,7 @@ generous deed immortalized in the next stable release of Godot Engine. Justin Hamilton Justin Spedding KaDokta + Kalydi Balázs Karol Wojtasiuk (Drakonter) Katsuomi Kobayashi Keedong Park @@ -577,17 +572,17 @@ generous deed immortalized in the next stable release of Godot Engine. kycho Kyle Burnett Kyle Jacobs - La diagonale du poulpe Lasse le Dous Laurent CHEA Laurent Dethoor Laxman Pradhan + Lech Rozanski Leland Vakarian Lemin LEMMiNO Leonardo Baumle - Leonardo Dimano Levi Lindsey + LF Linus Lind Lundgren Logan Apple Ludovic DELVAL @@ -601,7 +596,7 @@ generous deed immortalized in the next stable release of Godot Engine. Marcos Heitor Carvalho Markie Music Mark Jad - Mark Malone + Mark Tyler Markus Martin Markus Michael Egger Markus Strompen @@ -617,9 +612,9 @@ generous deed immortalized in the next stable release of Godot Engine. Maxime Santerre Maxwell McStuffings - meinkush Melissa Mears Merlyn Morgan-Graham + Mert Kasar Metal Demon 2000 mhilbrunner Michael @@ -643,7 +638,6 @@ generous deed immortalized in the next stable release of Godot Engine. moulefrite MrAZIE Mrjemandem - Nathan Fish Nathaniel neighty Neil Blakey-Milner @@ -654,7 +648,7 @@ generous deed immortalized in the next stable release of Godot Engine. Nicholas Orlowski Nick Eldrenkamp Nick Macholl - Niclas Eriksen + Nico Greve Nicolas Goll-Perrier Nicolas Rosset Nicolò Brigadoi Calamari @@ -662,6 +656,7 @@ generous deed immortalized in the next stable release of Godot Engine. Nima Farid Noel Billig Noesis + obscuresteel Okatima Oleg Reva Oliver Ambrose @@ -678,7 +673,6 @@ generous deed immortalized in the next stable release of Godot Engine. PaweÅ‚ Åyczkowski Peter Höglund Philip Ludington (MrPhil) - Philip Woods Pierre Caye Pixel Archipel pj @@ -689,20 +683,17 @@ generous deed immortalized in the next stable release of Godot Engine. pwab RackBar Dingum Rafa Laguna - Raffaele Aramo Ragnar Pettersson Rainer Amler Rammeow - Recep Karademir red1939 + Relintai Remi Rampin Remtaine Reneator - René Habermann Riccardo Marini Richard Hayes Richard Ivánek - Richard Néveri Riley Robin Ward RobotCritter @@ -710,26 +701,25 @@ generous deed immortalized in the next stable release of Godot Engine. Rodrigo Loli Roger Smith Roglozor + Roka Roland RzÄ…sa Roman Papush Ronald Ho Hip (CrimsonZA) - Ronan Roy Scayged + Russ Ryan Groom + Ryan Mueller Rykk - Sam Edson Sammy Fischer Sangeeth Pavithran - schroedinger's possum - Scott Longley Sean Dee Sebastian Michailidis SeongWan Kim Sessamekesh + Seth Drebitko SeungJong k Shaidak Shane - Shane Sicienski Shane Spoor Silver1063 simdee @@ -746,11 +736,12 @@ generous deed immortalized in the next stable release of Godot Engine. Soheib El-Harrache Solene Waked Sophie Winter + Space Hedgehog + Sparky Squidgy Squirrel Stéphane Roussel Stephen Rice - Steve Cloete Steven Drovie summerblind Sung soo Choi @@ -758,10 +749,12 @@ generous deed immortalized in the next stable release of Godot Engine. SxP tadashi endo Tarch + Techwizz Terry The Domis4 Theodore Lindsey TheVoiceInMyHead + TheWint Thibaut DECROMBECQUE thomas Thomas Bechtold @@ -774,8 +767,7 @@ generous deed immortalized in the next stable release of Godot Engine. Tim Gleason Tim Klein Timothy B. MacDonald - Title Plinsut - TMoney + Tim Riley Toadile Tobias Bradtke Tom Coxon @@ -802,18 +794,20 @@ generous deed immortalized in the next stable release of Godot Engine. Vitaliy Sapronenko Vi Watch Vladimir Savin + Vuli Nux Wapiti . - Watchinofoye Wiley Thompson William Bodin William Edwards William F Siqueira + Windvis Woonki Moon Wyatt Goodin - yakcyll + Xananax Yan Shi - Yegor Smirnov + yust Zach H. + Zekim Zher Huei Lee è•æƒŸå… è²´å® å°æ¾ diff --git a/SConstruct b/SConstruct index 50cb43b218..d0d03bd8dc 100644 --- a/SConstruct +++ b/SConstruct @@ -138,6 +138,7 @@ env_base.__class__.CommandNoCache = methods.CommandNoCache env_base.__class__.Run = methods.Run env_base.__class__.disable_warnings = methods.disable_warnings env_base.__class__.force_optimization_on_debug = methods.force_optimization_on_debug +env_base.__class__.module_add_dependencies = methods.module_add_dependencies env_base.__class__.module_check_dependencies = methods.module_check_dependencies env_base["x86_libtheora_opt_gcc"] = False @@ -195,7 +196,7 @@ opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False)) opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False)) opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False)) -opts.Add("disable_classes", "Disable given classes (comma separated)", "") +opts.Add("build_feature_profile", "Path to a file containing a feature build profile", "") opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True)) opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True)) opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "") @@ -260,7 +261,7 @@ else: ): selected_platform = "linuxbsd" elif sys.platform == "darwin": - selected_platform = "osx" + selected_platform = "macos" elif sys.platform == "win32": selected_platform = "windows" else: @@ -272,6 +273,20 @@ else: if selected_platform != "": print("Automatically detected platform: " + selected_platform) +if selected_platform in ["macos", "osx"]: + if selected_platform == "osx": + # Deprecated alias kept for compatibility. + print('Platform "osx" has been renamed to "macos" in Godot 4.0. Building for platform "macos".') + # Alias for convenience. + selected_platform = "macos" + +if selected_platform in ["ios", "iphone"]: + if selected_platform == "iphone": + # Deprecated alias kept for compatibility. + print('Platform "iphone" has been renamed to "ios" in Godot 4.0. Building for platform "ios".') + # Alias for convenience. + selected_platform = "ios" + if selected_platform in ["linux", "bsd", "x11"]: if selected_platform == "x11": # Deprecated alias kept for compatibility. @@ -323,21 +338,27 @@ for path in module_search_paths: # Add module options. for name, path in modules_detected.items(): + sys.path.insert(0, path) + import config + if env_base["modules_enabled_by_default"]: enabled = True - - sys.path.insert(0, path) - import config - try: enabled = config.is_enabled() except AttributeError: pass - sys.path.remove(path) - sys.modules.pop("config") else: enabled = False + # Add module-specific options. + try: + for opt in config.get_opts(selected_platform): + opts.Add(opt) + except AttributeError: + pass + + sys.path.remove(path) + sys.modules.pop("config") opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled)) methods.write_modules(modules_detected) @@ -399,6 +420,24 @@ if selected_platform in platform_list: env = env_base.Clone() + # Default num_jobs to local cpu count if not user specified. + # SCons has a peculiarity where user-specified options won't be overridden + # by SetOption, so we can rely on this to know if we should use our default. + initial_num_jobs = env.GetOption("num_jobs") + altered_num_jobs = initial_num_jobs + 1 + env.SetOption("num_jobs", altered_num_jobs) + if env.GetOption("num_jobs") == altered_num_jobs: + cpu_count = os.cpu_count() + if cpu_count is None: + print("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.") + else: + safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1 + print( + "Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument." + % (cpu_count, safer_cpu_count) + ) + env.SetOption("num_jobs", safer_cpu_count) + if env["compiledb"]: # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later. from SCons import __version__ as scons_raw_version @@ -536,7 +575,7 @@ if selected_platform in platform_list: ) # Apple LLVM versions differ from upstream LLVM version \o/, compare # in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions - elif env["platform"] == "osx" or env["platform"] == "iphone": + elif env["platform"] == "macos" or env["platform"] == "ios": vanilla = methods.is_vanilla_clang(env) if vanilla and cc_version_major < 6: print( @@ -667,6 +706,7 @@ if selected_platform in platform_list: sys.modules.pop("detect") modules_enabled = OrderedDict() + env.module_dependencies = {} env.module_icons_paths = [] env.doc_class_path = {} @@ -678,6 +718,10 @@ if selected_platform in platform_list: import config if config.can_build(env, selected_platform): + # Disable it if a required dependency is missing. + if not env.module_check_dependencies(name): + continue + config.configure(env) # Get doc classes paths (if present) try: @@ -700,6 +744,7 @@ if selected_platform in platform_list: sys.modules.pop("config") env.module_list = modules_enabled + methods.sort_module_list(env) methods.update_version(env.module_version_string) @@ -720,7 +765,27 @@ if selected_platform in platform_list: if env["tools"]: env.Append(CPPDEFINES=["TOOLS_ENABLED"]) - methods.write_disabled_classes(env["disable_classes"].split(",")) + + disabled_classes = [] + + if env["build_feature_profile"] != "": + print("Using build feature profile: " + env["build_feature_profile"]) + import json + + try: + ft = json.load(open(env["build_feature_profile"])) + if "disabled_classes" in ft: + disabled_classes = ft["disabled_classes"] + if "disabled_build_options" in ft: + dbo = ft["disabled_build_options"] + for c in dbo: + env[c] = dbo[c] + except: + print("Error opening feature build profile: " + env["build_feature_profile"]) + Exit(255) + + methods.write_disabled_classes(disabled_classes) + if env["disable_3d"]: if env["tools"]: print( @@ -742,15 +807,6 @@ if selected_platform in platform_list: if env["minizip"]: env.Append(CPPDEFINES=["MINIZIP_ENABLED"]) - editor_module_list = [] - if env["tools"] and not env.module_check_dependencies("tools", editor_module_list): - print( - "Build option 'module_" - + x - + "_enabled=no' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template)." - ) - Exit(255) - if not env["verbose"]: methods.no_verbose(sys, env) @@ -802,6 +858,9 @@ if selected_platform in platform_list: # Microsoft Visual Studio Project Generation if env["vsproj"]: + if os.name != "nt": + print("Error: The `vsproj` option is only usable on Windows with Visual Studio.") + Exit(255) env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]] methods.generate_vs_project(env, GetOption("num_jobs")) methods.generate_cpp_hint_file("cpp.hint") diff --git a/core/SCsub b/core/SCsub index df3e7a547a..d4462fa546 100644 --- a/core/SCsub +++ b/core/SCsub @@ -129,7 +129,7 @@ if env["builtin_zstd"]: "decompress/zstd_decompress_block.c", "decompress/zstd_decompress.c", ] - if env["platform"] in ["android", "iphone", "linuxbsd", "osx"]: + if env["platform"] in ["android", "ios", "linuxbsd", "macos"]: # Match platforms with ZSTD_ASM_SUPPORTED in common/portability_macros.h thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S") thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources] @@ -188,7 +188,6 @@ SConscript("os/SCsub") SConscript("math/SCsub") SConscript("crypto/SCsub") SConscript("io/SCsub") -SConscript("multiplayer/SCsub") SConscript("debugger/SCsub") SConscript("input/SCsub") SConscript("variant/SCsub") diff --git a/core/config/engine.cpp b/core/config/engine.cpp index 782d369ae6..1a6093869f 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -194,11 +194,11 @@ bool Engine::is_validation_layers_enabled() const { } void Engine::set_print_error_messages(bool p_enabled) { - _print_error_enabled = p_enabled; + CoreGlobals::print_error_enabled = p_enabled; } bool Engine::is_printing_error_messages() const { - return _print_error_enabled; + return CoreGlobals::print_error_enabled; } void Engine::add_singleton(const Singleton &p_singleton) { @@ -246,6 +246,14 @@ void Engine::get_singletons(List<Singleton> *p_singletons) { } } +String Engine::get_write_movie_path() const { + return write_movie_path; +} + +void Engine::set_write_movie_path(const String &p_path) { + write_movie_path = p_path; +} + void Engine::set_shader_cache_path(const String &p_path) { shader_cache_path = p_path; } diff --git a/core/config/engine.h b/core/config/engine.h index 82e3ee5487..68562643e7 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -76,6 +76,7 @@ private: static Engine *singleton; + String write_movie_path; String shader_cache_path; public: @@ -138,6 +139,9 @@ public: Dictionary get_license_info() const; String get_license_text() const; + void set_write_movie_path(const String &p_path); + String get_write_movie_path() const; + void set_shader_cache_path(const String &p_path); String get_shader_cache_path() const; diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 7145e628c1..5c4bcc687a 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -488,7 +488,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // We need to test both possibilities as extensions for Linux binaries are optional // (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck'). -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!found) { // Attempt to load PCK from macOS .app bundle resources. found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_filename + ".pck")); @@ -511,8 +511,9 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b if (found) { Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK && !p_ignore_override) { - // Load override from location of the executable. - // Optional, we don't mind if it fails. + // Load overrides from the PCK and the executable location. + // Optional, we don't mind if either fails. + _load_settings_text("res://override.cfg"); _load_settings_text(exec_path.get_base_dir().plus_file("override.cfg")); } return err; @@ -1197,6 +1198,9 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("display/window/size/window_height_override", 0); custom_prop_info["display/window/size/window_height_override"] = PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"); // 8K resolution + GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true); + GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor", false); + GLOBAL_DEF_BASIC("audio/buses/default_bus_layout", "res://default_bus_layout.tres"); custom_prop_info["audio/buses/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"); GLOBAL_DEF_RST("audio/general/2d_panning_strength", 1.0f); diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 26ecd41353..56130134a0 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -46,8 +46,8 @@ namespace core_bind { ResourceLoader *ResourceLoader::singleton = nullptr; -Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) { - return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads); +Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) { + return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode)); } ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) { @@ -121,7 +121,7 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) { } void ResourceLoader::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE)); ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get); @@ -147,9 +147,9 @@ void ResourceLoader::_bind_methods() { ////// ResourceSaver ////// -Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, BitField<SaverFlags> p_flags) { - ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + String(p_path) + "'."); - return ::ResourceSaver::save(p_path, p_resource, p_flags); +Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags) { + ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + p_path + "'."); + return ::ResourceSaver::save(p_resource, p_path, p_flags); } Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_resource) { @@ -174,7 +174,7 @@ void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_form ResourceSaver *ResourceSaver::singleton = nullptr; void ResourceSaver::_bind_methods() { - ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &ResourceSaver::save, DEFVAL((uint32_t)FLAG_NONE)); + ClassDB::bind_method(D_METHOD("save", "resource", "path", "flags"), &ResourceSaver::save, DEFVAL(""), DEFVAL((uint32_t)FLAG_NONE)); ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions); ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver); @@ -231,6 +231,14 @@ void OS::crash(const String &p_message) { CRASH_NOW_MSG(p_message); } +Vector<String> OS::get_system_fonts() const { + return ::OS::get_singleton()->get_system_fonts(); +} + +String OS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { + return ::OS::get_singleton()->get_system_font_path(p_font_name, p_bold, p_italic); +} + String OS::get_executable_path() const { return ::OS::get_singleton()->get_executable_path(); } @@ -323,6 +331,39 @@ Vector<String> OS::get_cmdline_args() { return cmdlinev; } +Vector<String> OS::get_cmdline_user_args() { + List<String> cmdline = ::OS::get_singleton()->get_cmdline_user_args(); + Vector<String> cmdlinev; + for (const String &E : cmdline) { + cmdlinev.push_back(E); + } + + return cmdlinev; +} + +void OS::set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments) { + List<String> args_list; + for (const String &restart_argument : p_restart_arguments) { + args_list.push_back(restart_argument); + } + + ::OS::get_singleton()->set_restart_on_exit(p_restart, args_list); +} + +bool OS::is_restart_on_exit_set() const { + return ::OS::get_singleton()->is_restart_on_exit_set(); +} + +Vector<String> OS::get_restart_on_exit_arguments() const { + List<String> args = ::OS::get_singleton()->get_restart_on_exit_arguments(); + Vector<String> args_vector; + for (List<String>::Element *E = args.front(); E; E = E->next()) { + args_vector.push_back(E->get()); + } + + return args_vector; +} + String OS::get_locale() const { return ::OS::get_singleton()->get_locale(); } @@ -589,6 +630,8 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_processor_count"), &OS::get_processor_count); ClassDB::bind_method(D_METHOD("get_processor_name"), &OS::get_processor_name); + ClassDB::bind_method(D_METHOD("get_system_fonts"), &OS::get_system_fonts); + ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "bold", "italic"), &OS::get_system_font_path, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path); ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false)); @@ -604,6 +647,11 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name); ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args); + ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args); + + ClassDB::bind_method(D_METHOD("set_restart_on_exit", "restart", "arguments"), &OS::set_restart_on_exit, DEFVAL(Vector<String>())); + ClassDB::bind_method(D_METHOD("is_restart_on_exit_set"), &OS::is_restart_on_exit_set); + ClassDB::bind_method(D_METHOD("get_restart_on_exit_arguments"), &OS::get_restart_on_exit_arguments); ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &OS::delay_usec); ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &OS::delay_msec); @@ -885,6 +933,7 @@ Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) { void Geometry2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle); + ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &Geometry2D::segment_intersects_circle); ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &Geometry2D::segment_intersects_segment); ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &Geometry2D::line_intersects_line); @@ -1217,19 +1266,13 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const { return data; } -String File::get_as_text() const { +String File::get_as_text(bool p_skip_cr) const { ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission."); - String text; uint64_t original_pos = f->get_position(); const_cast<FileAccess *>(*f)->seek(0); - String l = get_line(); - while (!eof_reached()) { - text += l + "\n"; - l = get_line(); - } - text += l; + String text = f->get_as_utf8_string(p_skip_cr); const_cast<FileAccess *>(*f)->seek(original_pos); @@ -1426,7 +1469,7 @@ void File::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer", "length"), &File::get_buffer); ClassDB::bind_method(D_METHOD("get_line"), &File::get_line); ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &File::get_csv_line, DEFVAL(",")); - ClassDB::bind_method(D_METHOD("get_as_text"), &File::get_as_text); + ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &File::get_as_text, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_md5", "path"), &File::get_md5); ClassDB::bind_method(D_METHOD("get_sha256", "path"), &File::get_sha256); ClassDB::bind_method(D_METHOD("is_big_endian"), &File::is_big_endian); @@ -1844,7 +1887,7 @@ void Thread::_start_func(void *ud) { ::Thread::set_name(func_name); Callable::CallError ce; - t->target_callable.call(nullptr, 0, t->ret, ce); + t->target_callable.callp(nullptr, 0, t->ret, ce); if (ce.error != Callable::CallError::CALL_OK) { t->running.clear(); ERR_FAIL_MSG("Could not call function '" + func_name + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + "."); @@ -2286,6 +2329,10 @@ bool Engine::is_editor_hint() const { return ::Engine::get_singleton()->is_editor_hint(); } +String Engine::get_write_movie_path() const { + return ::Engine::get_singleton()->get_write_movie_path(); +} + void Engine::set_print_error_messages(bool p_enabled) { ::Engine::get_singleton()->set_print_error_messages(p_enabled); } @@ -2335,6 +2382,8 @@ void Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint); + ClassDB::bind_method(D_METHOD("get_write_movie_path"), &Engine::get_write_movie_path); + ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages); ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages); @@ -2418,7 +2467,7 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra const Variant *args[2] = { &cmd, &data }; Variant retval; Callable::CallError err; - capture.call(args, 2, retval, err); + capture.callp(args, 2, retval, err); ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(capture, args, 2, err)); ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, "Error calling 'capture' to callable: " + String(capture) + ". Return type is not bool."); r_captured = retval; diff --git a/core/core_bind.h b/core/core_bind.h index c116ac4986..98bf34e07d 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -71,7 +71,7 @@ public: static ResourceLoader *get_singleton() { return singleton; } - Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false); + Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE); ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array()); Ref<Resource> load_threaded_get(const String &p_path); @@ -109,7 +109,7 @@ public: static ResourceSaver *get_singleton() { return singleton; } - Error save(const String &p_path, const Ref<Resource> &p_resource, BitField<SaverFlags> p_flags); + Error save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags); Vector<String> get_recognized_extensions(const Ref<Resource> &p_resource); void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front); void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver); @@ -170,6 +170,8 @@ public: void alert(const String &p_alert, const String &p_title = "ALERT!"); void crash(const String &p_message); + Vector<String> get_system_fonts() const; + String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const; String get_executable_path() const; int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false); int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false); @@ -180,12 +182,17 @@ public: bool is_process_running(int p_pid) const; int get_process_id() const; + void set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments = Vector<String>()); + bool is_restart_on_exit_set() const; + Vector<String> get_restart_on_exit_arguments() const; + bool has_environment(const String &p_var) const; String get_environment(const String &p_var) const; bool set_environment(const String &p_var, const String &p_value) const; String get_name() const; Vector<String> get_cmdline_args(); + Vector<String> get_cmdline_user_args(); String get_locale() const; String get_locale_language() const; @@ -409,7 +416,7 @@ public: Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes. String get_line() const; Vector<String> get_csv_line(const String &p_delim = ",") const; - String get_as_text() const; + String get_as_text(bool p_skip_cr = false) const; String get_md5(const String &p_path) const; String get_sha256(const String &p_path) const; @@ -674,6 +681,9 @@ public: void set_editor_hint(bool p_enabled); bool is_editor_hint() const; + // `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect. + String get_write_movie_path() const; + void set_print_error_messages(bool p_enabled); bool is_printing_error_messages() const; diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 24d8b0af6e..dc0ab72a86 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -31,7 +31,6 @@ #include "core_constants.h" #include "core/input/input_event.h" -#include "core/multiplayer/multiplayer.h" #include "core/object/class_db.h" #include "core/os/keyboard.h" #include "core/variant/variant.h" @@ -570,9 +569,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING); - BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LINK); - BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER); @@ -620,15 +617,14 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR); - BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NETWORK); - BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_HELPER); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_GROUP); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_BITFIELD); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE); @@ -656,25 +652,13 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR); - BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NOSCRIPT); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_CONST); - BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL); - BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VARARG); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE); BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT); - // rpc - BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_DISABLED", Multiplayer::RPC_MODE_DISABLED); - BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY_PEER", Multiplayer::RPC_MODE_ANY_PEER); - BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTHORITY", Multiplayer::RPC_MODE_AUTHORITY); - - BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE", Multiplayer::TRANSFER_MODE_UNRELIABLE); - BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE_ORDERED", Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED); - BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_RELIABLE", Multiplayer::TRANSFER_MODE_RELIABLE); - BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT); @@ -687,11 +671,14 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3", Variant::VECTOR3); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4", Variant::VECTOR4); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4I", Variant::VECTOR4I); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUATERNION", Variant::QUATERNION); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM3D", Variant::TRANSFORM3D); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PROJECTION", Variant::PROJECTION); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH); diff --git a/core/core_constants.h b/core/core_constants.h index d5b3b156b2..5e05b7a931 100644 --- a/core/core_constants.h +++ b/core/core_constants.h @@ -42,4 +42,4 @@ public: static int64_t get_global_constant_value(int p_idx); }; -#endif // GLOBAL_CONSTANTS_H +#endif // CORE_CONSTANTS_H diff --git a/core/core_globals.cpp b/core/core_globals.cpp new file mode 100644 index 0000000000..45297b459f --- /dev/null +++ b/core/core_globals.cpp @@ -0,0 +1,35 @@ +/*************************************************************************/ +/* core_globals.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core_globals.h" + +bool CoreGlobals::leak_reporting_enabled = true; +bool CoreGlobals::print_line_enabled = true; +bool CoreGlobals::print_error_enabled = true; diff --git a/servers/rendering/renderer_thread_pool.h b/core/core_globals.h index 4626490d32..c5e614dc0a 100644 --- a/servers/rendering/renderer_thread_pool.h +++ b/core/core_globals.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_thread_pool.h */ +/* core_globals.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERERTHREADPOOL_H -#define RENDERERTHREADPOOL_H +#ifndef CORE_GLOBALS_H +#define CORE_GLOBALS_H -#include "core/templates/thread_work_pool.h" +// Home for state needed from global functions +// that cannot be stored in Engine or OS due to e.g. circular includes -class RendererThreadPool { +class CoreGlobals { public: - ThreadWorkPool thread_work_pool; - - static RendererThreadPool *singleton; - RendererThreadPool(); - ~RendererThreadPool(); + static bool leak_reporting_enabled; + static bool print_line_enabled; + static bool print_error_enabled; }; -#endif // RENDERERTHREADPOOL_H +#endif // CORE_GLOBALS_H diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index d0fd4feaa5..a164eb7a57 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -185,7 +185,7 @@ String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const return ""; } -Error ResourceFormatSaverCrypto::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Error err; Ref<X509Certificate> cert = p_resource; Ref<CryptoKey> key = p_resource; diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index fb4f7dd88f..10c9564ad9 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -125,7 +125,7 @@ public: class ResourceFormatSaverCrypto : public ResourceFormatSaver { public: - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; virtual bool recognize(const Ref<Resource> &p_resource) const; }; diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h index eacef268cc..008e9e92b5 100644 --- a/core/crypto/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -115,4 +115,5 @@ public: static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]); static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]); }; + #endif // CRYPTO_CORE_H diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 378c3af8aa..751e8a6371 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DEBUGGER_MARSHARLLS_H -#define DEBUGGER_MARSHARLLS_H +#ifndef DEBUGGER_MARSHALLS_H +#define DEBUGGER_MARSHALLS_H #include "core/object/script_language.h" @@ -69,4 +69,4 @@ struct DebuggerMarshalls { }; }; -#endif // DEBUGGER_MARSHARLLS_H +#endif // DEBUGGER_MARSHALLS_H diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 263c75760b..d495a8ee20 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -43,6 +43,8 @@ HashMap<StringName, EngineDebugger::Profiler> EngineDebugger::profilers; HashMap<StringName, EngineDebugger::Capture> EngineDebugger::captures; HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; +void (*EngineDebugger::allow_focus_steal_fn)(); + void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name); profilers.insert(p_name, p_func); @@ -133,7 +135,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, singleton->poll_events(true); } -void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) { +void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)()) { register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more. if (p_uri.is_empty()) { return; @@ -174,6 +176,8 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp)); } + + allow_focus_steal_fn = p_allow_focus_steal_fn; } void EngineDebugger::deinitialize() { diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index a8a791f9b0..236d5e5f63 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -100,13 +100,15 @@ protected: static HashMap<StringName, Capture> captures; static HashMap<String, CreatePeerFunc> protocols; + static void (*allow_focus_steal_fn)(); + public: _FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; } _FORCE_INLINE_ static bool is_active() { return singleton != nullptr && script_debugger != nullptr; } _FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; }; - static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints); + static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)()); static void deinitialize(); static void register_profiler(const StringName &p_name, const Profiler &p_profiler); static void unregister_profiler(const StringName &p_name); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index c73e2eb3fb..23ee977df4 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -452,6 +452,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { msg.push_back(error_str); ERR_FAIL_COND(!script_lang); msg.push_back(script_lang->debug_get_stack_level_count() > 0); + if (allow_focus_steal_fn) { + allow_focus_steal_fn(); + } send_message("debug_enter", msg); Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode(); diff --git a/core/doc_data.cpp b/core/doc_data.cpp index 89e7a8dc71..df86cd1dc2 100644 --- a/core/doc_data.cpp +++ b/core/doc_data.cpp @@ -115,6 +115,31 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met p_method.name = p_methodinfo.name; p_method.description = p_desc; + if (p_methodinfo.flags & METHOD_FLAG_VIRTUAL) { + p_method.qualifiers = "virtual"; + } + + if (p_methodinfo.flags & METHOD_FLAG_CONST) { + if (!p_method.qualifiers.is_empty()) { + p_method.qualifiers += " "; + } + p_method.qualifiers += "const"; + } + + if (p_methodinfo.flags & METHOD_FLAG_VARARG) { + if (!p_method.qualifiers.is_empty()) { + p_method.qualifiers += " "; + } + p_method.qualifiers += "vararg"; + } + + if (p_methodinfo.flags & METHOD_FLAG_STATIC) { + if (!p_method.qualifiers.is_empty()) { + p_method.qualifiers += " "; + } + p_method.qualifiers += "static"; + } + return_doc_from_retinfo(p_method, p_methodinfo.return_val); for (int i = 0; i < p_methodinfo.arguments.size(); i++) { @@ -123,7 +148,7 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); if (default_arg_index >= 0) { Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; - argument.default_value = default_arg.get_construct_string(); + argument.default_value = default_arg.get_construct_string().replace("\n", ""); } p_method.arguments.push_back(argument); } diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index d5c49b01e9..867b1fc637 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -46,9 +46,12 @@ static String get_type_name(const PropertyInfo &p_info) { return p_info.hint_string + "*"; } } - if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD))) { + if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) { return String("enum::") + String(p_info.class_name); } + if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_BITFIELD))) { + return String("bitfield::") + String(p_info.class_name); + } if (p_info.class_name != StringName()) { return p_info.class_name; } @@ -128,11 +131,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { Variant::VECTOR3, vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, { Variant::VECTOR3I, 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) }, { Variant::TRANSFORM2D, 6 * sizeof(float), 6 * sizeof(float), 6 * sizeof(double), 6 * sizeof(double) }, + { Variant::VECTOR4, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) }, + { Variant::VECTOR4I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) }, { Variant::PLANE, (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(double), (vec3_elems + 1) * sizeof(double) }, { Variant::QUATERNION, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) }, { Variant::AABB, (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(double), (vec3_elems * 2) * sizeof(double) }, { Variant::BASIS, (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) }, { Variant::TRANSFORM3D, (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(double), (vec3_elems * 4) * sizeof(double) }, + { Variant::PROJECTION, 4 * 4 * sizeof(float), 4 * 4 * sizeof(float), 4 * 4 * sizeof(double), 4 * 4 * sizeof(double) }, { Variant::COLOR, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float) }, { Variant::STRING_NAME, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, { Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, @@ -166,11 +172,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { static_assert(type_size_array[Variant::VECTOR3][sizeof(void *)] == sizeof(Vector3), "Size of Vector3 mismatch"); static_assert(type_size_array[Variant::VECTOR3I][sizeof(void *)] == sizeof(Vector3i), "Size of Vector3i mismatch"); static_assert(type_size_array[Variant::TRANSFORM2D][sizeof(void *)] == sizeof(Transform2D), "Size of Transform2D mismatch"); + static_assert(type_size_array[Variant::VECTOR4][sizeof(void *)] == sizeof(Vector4), "Size of Vector4 mismatch"); + static_assert(type_size_array[Variant::VECTOR4I][sizeof(void *)] == sizeof(Vector4i), "Size of Vector4i mismatch"); static_assert(type_size_array[Variant::PLANE][sizeof(void *)] == sizeof(Plane), "Size of Plane mismatch"); static_assert(type_size_array[Variant::QUATERNION][sizeof(void *)] == sizeof(Quaternion), "Size of Quaternion mismatch"); static_assert(type_size_array[Variant::AABB][sizeof(void *)] == sizeof(AABB), "Size of AABB mismatch"); static_assert(type_size_array[Variant::BASIS][sizeof(void *)] == sizeof(Basis), "Size of Basis mismatch"); static_assert(type_size_array[Variant::TRANSFORM3D][sizeof(void *)] == sizeof(Transform3D), "Size of Transform3D mismatch"); + static_assert(type_size_array[Variant::PROJECTION][sizeof(void *)] == sizeof(Projection), "Size of Projection mismatch"); static_assert(type_size_array[Variant::COLOR][sizeof(void *)] == sizeof(Color), "Size of Color mismatch"); static_assert(type_size_array[Variant::STRING_NAME][sizeof(void *)] == sizeof(StringName), "Size of StringName mismatch"); static_assert(type_size_array[Variant::NODE_PATH][sizeof(void *)] == sizeof(NodePath), "Size of NodePath mismatch"); @@ -253,6 +262,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { Variant::TRANSFORM2D, "x", 0, 0, 0, 0 }, { Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, { Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) }, + { Variant::VECTOR4, "x", 0, 0, 0, 0 }, + { Variant::VECTOR4, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, + { Variant::VECTOR4, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, + { Variant::VECTOR4, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) }, + { Variant::VECTOR4I, "x", 0, 0, 0, 0 }, + { Variant::VECTOR4I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, + { Variant::VECTOR4I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, + { Variant::VECTOR4I, "w", 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) }, { Variant::PLANE, "normal", 0, 0, 0, 0 }, { Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, { Variant::QUATERNION, "x", 0, 0, 0, 0 }, diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h index 7346e182f1..1bc455ea67 100644 --- a/core/extension/extension_api_dump.h +++ b/core/extension/extension_api_dump.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef API_DUMP_H -#define API_DUMP_H +#ifndef EXTENSION_API_DUMP_H +#define EXTENSION_API_DUMP_H #include "core/extension/native_extension.h" @@ -42,4 +42,4 @@ public: }; #endif -#endif // API_DUMP_H +#endif // EXTENSION_API_DUMP_H diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index 58103e3af3..ef0b590030 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -344,6 +344,10 @@ static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_con return VariantTypeConstructor<Vector3i>::variant_from_type; case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: return VariantTypeConstructor<Transform2D>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::variant_from_type; case GDNATIVE_VARIANT_TYPE_PLANE: return VariantTypeConstructor<Plane>::variant_from_type; case GDNATIVE_VARIANT_TYPE_QUATERNION: @@ -354,6 +358,8 @@ static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_con return VariantTypeConstructor<Basis>::variant_from_type; case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: return VariantTypeConstructor<Transform3D>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::variant_from_type; case GDNATIVE_VARIANT_TYPE_COLOR: return VariantTypeConstructor<Color>::variant_from_type; case GDNATIVE_VARIANT_TYPE_STRING_NAME: @@ -421,6 +427,10 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con return VariantTypeConstructor<Vector3i>::type_from_variant; case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: return VariantTypeConstructor<Transform2D>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::type_from_variant; case GDNATIVE_VARIANT_TYPE_PLANE: return VariantTypeConstructor<Plane>::type_from_variant; case GDNATIVE_VARIANT_TYPE_QUATERNION: @@ -431,6 +441,8 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con return VariantTypeConstructor<Basis>::type_from_variant; case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: return VariantTypeConstructor<Transform3D>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::type_from_variant; case GDNATIVE_VARIANT_TYPE_COLOR: return VariantTypeConstructor<Color>::type_from_variant; case GDNATIVE_VARIANT_TYPE_STRING_NAME: diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index ccd6fb0f7e..041a6e5112 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -67,11 +67,14 @@ typedef enum { GDNATIVE_VARIANT_TYPE_VECTOR3, GDNATIVE_VARIANT_TYPE_VECTOR3I, GDNATIVE_VARIANT_TYPE_TRANSFORM2D, + GDNATIVE_VARIANT_TYPE_VECTOR4, + GDNATIVE_VARIANT_TYPE_VECTOR4I, GDNATIVE_VARIANT_TYPE_PLANE, GDNATIVE_VARIANT_TYPE_QUATERNION, GDNATIVE_VARIANT_TYPE_AABB, GDNATIVE_VARIANT_TYPE_BASIS, GDNATIVE_VARIANT_TYPE_TRANSFORM3D, + GDNATIVE_VARIANT_TYPE_PROJECTION, /* misc types */ GDNATIVE_VARIANT_TYPE_COLOR, @@ -252,13 +255,10 @@ typedef void *GDNativeExtensionClassLibraryPtr; typedef enum { GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1, GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2, - GDNATIVE_EXTENSION_METHOD_FLAG_NOSCRIPT = 4, - GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 8, - GDNATIVE_EXTENSION_METHOD_FLAG_REVERSE = 16, /* used for events */ - GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 32, - GDNATIVE_EXTENSION_METHOD_FLAG_FROM_SCRIPT = 64, - GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 128, - GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 256, + GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 4, + GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 8, + GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 16, + GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 32, GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL, } GDNativeExtensionClassMethodFlags; @@ -540,7 +540,7 @@ typedef struct { void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value); + void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); @@ -582,4 +582,4 @@ typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface * } #endif -#endif +#endif // GDNATIVE_INTERFACE_H diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index 262e28b442..b69859b441 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -182,7 +182,7 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl ClassDB::bind_method_custom(class_name, method); } -void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) { +void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) { NativeExtension *self = static_cast<NativeExtension *>(p_library); StringName class_name = p_class_name; @@ -190,7 +190,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE //Extension *extension = &self->extension_classes[class_name]; - ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value); + ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield); } void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) { diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h index 8f106f753d..b7238d2899 100644 --- a/core/extension/native_extension.h +++ b/core/extension/native_extension.h @@ -49,7 +49,7 @@ class NativeExtension : public Resource { static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value); + static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); @@ -97,4 +97,4 @@ public: virtual String get_resource_type(const String &p_path) const; }; -#endif // NATIVEEXTENSION_H +#endif // NATIVE_EXTENSION_H diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h index 5594f6c0de..ed80cd6b7a 100644 --- a/core/extension/native_extension_manager.h +++ b/core/extension/native_extension_manager.h @@ -71,4 +71,4 @@ public: VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus) -#endif // NATIVEEXTENSIONMANAGER_H +#endif // NATIVE_EXTENSION_MANAGER_H diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 5a71bcbef3..f5874a3dec 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -2,6 +2,7 @@ # Source: https://github.com/gabomdq/SDL_GameControllerDB # Windows +03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, 03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, 03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, 03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, @@ -10,7 +11,7 @@ 03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, 03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, +03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, 03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, @@ -18,24 +19,27 @@ 03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000151000000000000,8BitDo M30 Modkit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, 03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows, -03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows, 03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, 03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, +030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows, 03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, @@ -43,19 +47,20 @@ 03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows, 03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, @@ -63,21 +68,12 @@ 03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, 030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, 03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows, -030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -85,6 +81,13 @@ 030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, @@ -93,10 +96,8 @@ 03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, 03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, -03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, 03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, @@ -121,7 +122,11 @@ 030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, @@ -135,7 +140,6 @@ 03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows, 030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, 03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000c0160000e105000000000000,Dual Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows, @@ -158,25 +162,21 @@ 030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, 030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows, 03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, 03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows, 03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows, 03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows, @@ -184,15 +184,14 @@ 03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows, 03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows, 03000000b40400001224000000000000,Flydigi Vader 2 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, -030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, +030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, 0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, 03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, 03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows, 03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows, 03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,rightshoulder:b7,lefttrigger:a3,righttrigger:a4,platform:Windows, +03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000280400000140000000000000,GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, @@ -217,41 +216,40 @@ 030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a2,start:b9,x:b3,y:b4,platform:Windows, +030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, +030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows, 03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, -03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, -03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, -030000000d0f00004900000000000000,Hatsune Miku Sho PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, 030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, 03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00005100000000000000,Hori Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008600000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f0000ba00000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000f0d00000010000000000000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows, 030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008700000000000000,Hori Fightstick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008800000000000000,Hori Fightstick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, 030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, +030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -289,27 +287,33 @@ 030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows, -03000000790000004e95000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, +03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, +03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, 03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows, 03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, 030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, +03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, 03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, 03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, 030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, 030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, 03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000250900000017000000000000,Joypad to Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, 03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows, 03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, @@ -331,6 +335,7 @@ 030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, 030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, 03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -340,41 +345,44 @@ 03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -78696e70757403000000000000000000,Mad Catz Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, 03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, 030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, 0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00001030000000000000,Mayflash Sega Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, -0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000790000000018000000000000,Mayflash WiiU Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, 0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows, +03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows, 030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows, 030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, 030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, 030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, 030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows, 03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows, -030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -388,6 +396,7 @@ 03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, 03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, 030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, @@ -398,9 +407,8 @@ 0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows, 03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, -03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, -03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, -03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, +03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, 03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, 03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, @@ -434,6 +442,7 @@ 03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d620000013a7000000000000,PowerA Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -476,7 +485,6 @@ 03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f10e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, @@ -494,6 +502,7 @@ 03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, 03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, @@ -502,6 +511,7 @@ 03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, 03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, 030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, 030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, 030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows, @@ -509,11 +519,12 @@ 030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, 030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, 030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, +030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows, 030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, 030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, @@ -529,12 +540,13 @@ 03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, 03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, 03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows, 030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, @@ -576,25 +588,25 @@ 03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows, 03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, 03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows, -03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, 03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, 03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, 03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, +0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, 03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, 030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, +03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, +0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, 03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, 030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, 03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, @@ -608,18 +620,20 @@ 03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, 03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000381000003014000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000381000003114000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, -030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows, 03000000d620000011a7000000000000,Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000f600000000000000,Switch Hori,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000000d0f0000f600000000000000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, 030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows, 03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, @@ -631,12 +645,14 @@ 030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, -030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, 030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows, +03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -644,6 +660,7 @@ 030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, 03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, 03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b10,x:b3,y:b4,platform:Windows, 03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, 03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, @@ -664,7 +681,7 @@ 030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, 03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, @@ -683,6 +700,7 @@ 03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, @@ -716,17 +734,25 @@ 03000000172700004431000000000000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows, 03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, # Mac OS X -030000008f0e00000300000009010000,2In1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, 03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, 03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, @@ -735,14 +761,18 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X, +03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, @@ -750,14 +780,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, 03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, -03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, 03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, 03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -768,8 +797,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, 03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X, +030000006f0e00008401000003010000,Faceoff Premiere Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X, 03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, @@ -777,22 +806,30 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, 030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X, 030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, -03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, +03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X, 030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, 030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, @@ -810,14 +847,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, 03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,x:b8,y:b12,start:b36,rightshoulder:b28,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a20,righty:a8,lefttrigger:a12,righttrigger:a16,platform:Mac OS X, 03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, 0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, -03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -03000000790000000018000000000000,Mayflash WiiU Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X, +03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, 030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X, 030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, 03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, @@ -835,18 +873,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000901000002010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, -030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, 030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,x:b15,y:b12,back:b0,guide:b16,start:b3,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Mac OS X, +030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, 030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -857,6 +897,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000000d0f0000c100000072050000,Retro Bit Sega Genesis 6B Controller,a:b2,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b8,rightshoulder:b6,righttrigger:b7,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, @@ -864,31 +907,37 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X, +03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X, 03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, -03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, -030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, -030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, 03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, 03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, 05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, 050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, 050000004e696d6275732b008b000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, 05000000556e6b6e6f776e2048494400,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, 03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, 030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X, 03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, 030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -912,6 +961,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -919,33 +969,42 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # Linux 030000005e0400008e02000020010000,8BitDo Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, 03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, 03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, 03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux, 05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, 030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, @@ -955,9 +1014,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -971,7 +1030,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, 05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 05000000050b00000045000031000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, 05000000050b00000045000040000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, @@ -986,8 +1045,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000503200000210000045010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, 05000000503200000210000046010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, 05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, -03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, -03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, 03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, @@ -1005,12 +1062,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, 03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, 030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux, 03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -1025,30 +1082,33 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000280400000140000000010000,Gravis Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, 030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, 03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, 030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00008500000010010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00004d00000011010000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux, 030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f0000aa00000011010000,Hori Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1058,14 +1118,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f0000c100000011010000,Horipad S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -050000000d0f0000f600000001000000,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux, 03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, -03000000fd0500000030000000010000,InterAct GoPad I73000,a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux, 03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, 0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, @@ -1109,28 +1172,29 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, 0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, -03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Linux, +0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux, 030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, +030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, 030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux, 030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b00000b050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b00000b050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000dd02000003020000,Microsoft Xbox One 2015,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1147,14 +1211,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux, 03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux, -050000004e696d6275732b0000000000,Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux, 060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, @@ -1164,8 +1229,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux, 03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, -050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux, 05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -1189,6 +1254,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00008001000011010000,PDP Faceoff Nintendo Switch Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1203,12 +1269,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, 03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1240,9 +1308,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, +03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, 030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, 030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, @@ -1286,16 +1360,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, 03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, 03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, -03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, -030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, +030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000632500007505000010010000,Shanwan PS3 PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000bc2000000055000010010000,Shanwan PS3 PC ,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005f140000c501000010010000,Shanwan Trust,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, @@ -1303,23 +1374,25 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, 03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, 03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, 03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux, 03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, +030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, 03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, 030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1332,17 +1405,19 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux, 030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux, 030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000012b3000010010000,Thrustmaster vibrating,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, 030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, @@ -1385,6 +1460,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000130b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000120b000007050000,Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,misc1:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, 050000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, @@ -1396,22 +1472,34 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # Android 38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, 64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, 64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, 34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, -05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, +38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f2038426974446f204c69,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, +32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, +38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, 64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, 66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, 66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, +33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, 05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, 38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, @@ -1419,12 +1507,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, -61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, -05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, +05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, @@ -1436,17 +1529,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, -33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, 63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, 32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, 30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, 05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1464,12 +1560,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, 64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, 532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, -65346535636333663931613264643164,Joy Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, -33346566643039343630376565326335,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -35313531613435623366313835326238,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -38383665633039363066383334653465,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -39363561613936303237333537383931,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, +33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, 4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, @@ -1482,22 +1578,24 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, -32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,x:b23,y:b24,start:b30,rightshoulder:b28,lefttrigger:b25,righttrigger:b26,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Android, -65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,leftshoulder:b3,rightshoulder:b20,lefttrigger:b9,start:b18,guide:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,platform:Android, -436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,leftshoulder:b3,rightshoulder:b20,lefttrigger:b9,start:b18,guide:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,platform:Android, -31323564663862633234646330373138,Mega Drive,a:b23,b:b22,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, +436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +484a5a204d6179666c61736820576969,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, 37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, 64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, 33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, -30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,leftshoulder:b20,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, +30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, 32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, 050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, -34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, 36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, 4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, @@ -1512,7 +1610,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, 4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, 506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, -62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,leftshoulder:b9,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, +62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, 61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, 32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, 050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1540,6 +1638,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, 36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1554,22 +1656,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, 33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, -66386565396238363534313863353065,Sanwa Mobile,a:b21,b:b22,leftshoulder:b23,leftx:a0,lefty:a1,rightshoulder:b24,platform:Android, +66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, 32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, 37316565396364386635383230353365,Saturn,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -38613865396530353338373763623431,Saturn,a:b0,b:b1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, +38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, 61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, 30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, 66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, 66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, 62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, 5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, -63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, +63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, 476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, @@ -1579,8 +1679,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, 30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30386438313564306161393537333663,Wii Classic Controller,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -33333034646336346339646538643633,Wii Classic Controller,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, 050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1618,6 +1718,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, 4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, 4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, +050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS, +050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, +050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS, +050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, diff --git a/core/input/input.cpp b/core/input/input.cpp index da0c6cb62a..e08647f5ea 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1187,7 +1187,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J return event; } -void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[]) { +void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[(size_t)HatDir::MAX]) { for (int i = 0; i < mapping.bindings.size(); i++) { const JoyBinding binding = mapping.bindings[i]; if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) { diff --git a/core/input/input_builders.py b/core/input/input_builders.py index 748ec06133..c0dac26f02 100644 --- a/core/input/input_builders.py +++ b/core/input/input_builders.py @@ -47,9 +47,9 @@ def make_default_controller_mappings(target, source, env): platform_variables = { "Linux": "#if X11_ENABLED", "Windows": "#ifdef WINDOWS_ENABLED", - "Mac OS X": "#ifdef OSX_ENABLED", + "Mac OS X": "#ifdef MACOS_ENABLED", "Android": "#if defined(__ANDROID__)", - "iOS": "#ifdef IPHONE_ENABLED", + "iOS": "#ifdef IOS_ENABLED", "Javascript": "#ifdef JAVASCRIPT_ENABLED", "UWP": "#ifdef UWP_ENABLED", } diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 3c104c2c86..8ad2193fca 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -816,7 +816,7 @@ String InputEventMouseMotion::to_string() { // Work around the fact vformat can only take 5 substitutions but 7 need to be passed. String mask_and_position_and_relative = vformat("button_mask=%s, position=(%s), relative=(%s)", button_mask_string, String(get_position()), String(get_relative())); - return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%d)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted()); + return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted()); } bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { diff --git a/core/input/shortcut.h b/core/input/shortcut.h index 0c9689cdcb..daec410039 100644 --- a/core/input/shortcut.h +++ b/core/input/shortcut.h @@ -55,4 +55,5 @@ public: static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2); }; + #endif // SHORTCUT_H diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index 0a900078b7..f82d6f077f 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -34,6 +34,7 @@ #include "core/io/file_access.h" #include "core/os/memory.h" #include "core/os/os.h" +#include "core/templates/local_vector.h" String DirAccess::_get_root_path() const { switch (_access_type) { @@ -286,11 +287,16 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to); + const size_t copy_buffer_limit = 65536; // 64 KB + fsrc->seek_end(0); int size = fsrc->get_position(); fsrc->seek(0); err = OK; - while (size--) { + size_t buffer_size = MIN(size * sizeof(uint8_t), copy_buffer_limit); + LocalVector<uint8_t> buffer; + buffer.resize(buffer_size); + while (size > 0) { if (fsrc->get_error() != OK) { err = fsrc->get_error(); break; @@ -300,7 +306,14 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { break; } - fdst->store_8(fsrc->get_8()); + int bytes_read = fsrc->get_buffer(buffer.ptr(), buffer_size); + if (bytes_read <= 0) { + err = FAILED; + break; + } + fdst->store_buffer(buffer.ptr(), bytes_read); + + size -= bytes_read; } } diff --git a/core/io/dir_access.h b/core/io/dir_access.h index 22017efaa3..d5318dfb45 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -108,6 +108,8 @@ public: if (da->remove(p_path) != OK) { ERR_FAIL_MSG("Cannot remove file or directory: " + p_path); } + } else { + ERR_FAIL_MSG("Cannot remove non-existent file or directory: " + p_path); } } diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index da25f23917..8ed3d40c22 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -377,7 +377,7 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { return i; } -String FileAccess::get_as_utf8_string() const { +String FileAccess::get_as_utf8_string(bool p_skip_cr) const { Vector<uint8_t> sourcef; uint64_t len = get_length(); sourcef.resize(len + 1); @@ -388,7 +388,7 @@ String FileAccess::get_as_utf8_string() const { w[len] = 0; String s; - s.parse_utf8((const char *)w); + s.parse_utf8((const char *)w, -1, p_skip_cr); return s; } diff --git a/core/io/file_access.h b/core/io/file_access.h index e2c11142d7..3386800686 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -113,7 +113,7 @@ public: virtual String get_line() const; virtual String get_token() const; virtual Vector<String> get_csv_line(const String &p_delim = ",") const; - virtual String get_as_utf8_string() const; + virtual String get_as_utf8_string(bool p_skip_cr = false) const; /** * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index b8382e61d9..e41491a92c 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -70,29 +70,29 @@ public: Error open_after_magic(Ref<FileAccess> p_base); - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte - virtual bool file_exists(const String &p_name); ///< return true if a file exists + virtual bool file_exists(const String &p_name) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file); - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); + virtual uint64_t _get_modified_time(const String &p_file) override; + virtual uint32_t _get_unix_permissions(const String &p_file) override; + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; FileAccessCompressed() {} virtual ~FileAccessCompressed(); diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 0d1ee6a4d8..6200f87a7a 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -60,33 +60,33 @@ public: Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true); Error open_and_parse_password(Ref<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 bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual String get_path() const; /// returns the path for the current open file - virtual String get_path_absolute() const; /// returns the absolute path for the current open file + virtual String get_path() const override; /// returns the path for the current open file + virtual String get_path_absolute() const override; /// returns the absolute path for the current open file - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes - virtual bool file_exists(const String &p_name); ///< return true if a file exists + virtual bool file_exists(const String &p_name) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file); - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); + virtual uint64_t _get_modified_time(const String &p_file) override; + virtual uint32_t _get_unix_permissions(const String &p_file) override; + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; FileAccessEncrypted() {} ~FileAccessEncrypted(); diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 868b8ed481..f2bd2aa832 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -45,31 +45,31 @@ public: static void cleanup(); virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte + virtual uint8_t get_8() const override; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; ///< get an array of bytes - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_byte); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes + virtual void flush() override; + virtual void store_8(uint8_t p_byte) override; ///< store a byte + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes - virtual bool file_exists(const String &p_name); ///< return true if a file exists + virtual bool file_exists(const String &p_name) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file) { return 0; } - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } + virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } + virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } FileAccessMemory() {} }; diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index c7431752c0..ceadc715a1 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -132,29 +132,29 @@ public: RESPONSE_GET_MODTIME, }; - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte - virtual bool file_exists(const String &p_path); ///< return true if a file exists + virtual bool file_exists(const String &p_path) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file); - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); + virtual uint64_t _get_modified_time(const String &p_file) override; + virtual uint32_t _get_unix_permissions(const String &p_file) override; + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; static void configure(); diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index e656f6b885..023758ac0f 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -148,35 +148,35 @@ class FileAccessPack : public FileAccess { uint64_t off; Ref<FileAccess> f; - virtual Error _open(const String &p_path, int p_mode_flags); - virtual uint64_t _get_modified_time(const String &p_file) { return 0; } - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } + virtual Error _open(const String &p_path, int p_mode_flags) override; + virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } + virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } public: - virtual bool is_open() const; + virtual bool is_open() const override; - virtual void seek(uint64_t p_position); - virtual void seek_end(int64_t p_position = 0); - virtual uint64_t get_position() const; - virtual uint64_t get_length() const; + virtual void seek(uint64_t p_position) override; + virtual void seek_end(int64_t p_position = 0) override; + virtual uint64_t get_position() const override; + virtual uint64_t get_length() const override; - virtual bool eof_reached() const; + virtual bool eof_reached() const override; - virtual uint8_t get_8() const; + virtual uint8_t get_8() const override; - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual void set_big_endian(bool p_big_endian); + virtual void set_big_endian(bool p_big_endian) override; - virtual Error get_error() const; + virtual Error get_error() const override; - virtual void flush(); - virtual void store_8(uint8_t p_dest); + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; - virtual bool file_exists(const String &p_name); + virtual bool file_exists(const String &p_name) override; FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file); }; @@ -217,33 +217,33 @@ class DirAccessPack : public DirAccess { PackedData::PackedDir *_find_dir(String p_dir); public: - virtual Error list_dir_begin(); - virtual String get_next(); - virtual bool current_is_dir() const; - virtual bool current_is_hidden() const; - virtual void list_dir_end(); + virtual Error list_dir_begin() override; + virtual String get_next() override; + virtual bool current_is_dir() const override; + virtual bool current_is_hidden() const override; + virtual void list_dir_end() override; - virtual int get_drive_count(); - virtual String get_drive(int p_drive); + virtual int get_drive_count() override; + virtual String get_drive(int p_drive) override; - virtual Error change_dir(String p_dir); - virtual String get_current_dir(bool p_include_drive = true) const; + virtual Error change_dir(String p_dir) override; + virtual String get_current_dir(bool p_include_drive = true) const override; - virtual bool file_exists(String p_file); - virtual bool dir_exists(String p_dir); + virtual bool file_exists(String p_file) override; + virtual bool dir_exists(String p_dir) override; - virtual Error make_dir(String p_dir); + virtual Error make_dir(String p_dir) override; - virtual Error rename(String p_from, String p_to); - virtual Error remove(String p_name); + virtual Error rename(String p_from, String p_to) override; + virtual Error remove(String p_name) override; - uint64_t get_space_left(); + uint64_t get_space_left() override; - virtual bool is_link(String p_file) { return false; } - virtual String read_link(String p_file) { return p_file; } - virtual Error create_link(String p_source, String p_target) { return FAILED; } + virtual bool is_link(String p_file) override { return false; } + virtual String read_link(String p_file) override { return p_file; } + virtual Error create_link(String p_source, String p_target) override { return FAILED; } - virtual String get_filesystem_type() const; + virtual String get_filesystem_type() const override; DirAccessPack(); }; diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index 6ea603546a..74a48192f3 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -85,29 +85,29 @@ class FileAccessZip : public FileAccess { void _close(); public: - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte - virtual bool file_exists(const String &p_name); ///< return true if a file exists + virtual bool file_exists(const String &p_name) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } + virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } // todo + virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file); ~FileAccessZip(); diff --git a/core/io/image.cpp b/core/io/image.cpp index 473d70bd7c..2d87523ca4 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -416,8 +416,8 @@ int Image::get_height() const { return height; } -Vector2 Image::get_size() const { - return Vector2(width, height); +Vector2i Image::get_size() const { + return Vector2i(width, height); } bool Image::has_mipmaps() const { @@ -1339,6 +1339,108 @@ void Image::crop(int p_width, int p_height) { crop_from_point(0, 0, p_width, p_height); } +void Image::rotate_90(ClockDirection p_direction) { + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); + ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); + ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); + + int saved_width = height; + int saved_height = width; + + if (width != height) { + int n = MAX(width, height); + resize(n, n, INTERPOLATE_NEAREST); + } + + bool used_mipmaps = has_mipmaps(); + if (used_mipmaps) { + clear_mipmaps(); + } + + { + uint8_t *w = data.ptrw(); + uint8_t src[16]; + uint8_t dst[16]; + uint32_t pixel_size = get_format_pixel_size(format); + + // Flip. + + if (p_direction == CLOCKWISE) { + for (int y = 0; y < height / 2; y++) { + for (int x = 0; x < width; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(x, height - y - 1, pixel_size, w, dst); + + _put_pixelb(x, height - y - 1, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } else { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width / 2; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(width - x - 1, y, pixel_size, w, dst); + + _put_pixelb(width - x - 1, y, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + + // Transpose. + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (x < y) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(y, x, pixel_size, w, dst); + + _put_pixelb(y, x, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + } + + if (saved_width != saved_height) { + resize(saved_width, saved_height, INTERPOLATE_NEAREST); + } else if (used_mipmaps) { + generate_mipmaps(); + } +} + +void Image::rotate_180() { + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); + ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); + ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); + + bool used_mipmaps = has_mipmaps(); + if (used_mipmaps) { + clear_mipmaps(); + } + + { + uint8_t *w = data.ptrw(); + uint8_t src[16]; + uint8_t dst[16]; + uint32_t pixel_size = get_format_pixel_size(format); + + for (int y = 0; y < height / 2; y++) { + for (int x = 0; x < width; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(width - x - 1, height - y - 1, pixel_size, w, dst); + + _put_pixelb(width - x - 1, height - y - 1, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + + if (used_mipmaps) { + generate_mipmaps(); + } +} + void Image::flip_y() { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats."); @@ -2478,15 +2580,15 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const V create(p_width, p_height, p_mipmaps, p_format, p_data); } -Rect2 Image::get_used_rect() const { +Rect2i Image::get_used_rect() const { if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) { - return Rect2(Point2(), Size2(width, height)); + return Rect2i(0, 0, width, height); } int len = data.size(); if (len == 0) { - return Rect2(); + return Rect2i(); } int minx = 0xFFFFFF, miny = 0xFFFFFFF; @@ -2512,15 +2614,15 @@ Rect2 Image::get_used_rect() const { } if (maxx == -1) { - return Rect2(); + return Rect2i(); } else { - return Rect2(minx, miny, maxx - minx + 1, maxy - miny + 1); + return Rect2i(minx, miny, maxx - minx + 1, maxy - miny + 1); } } -Ref<Image> Image::get_rect(const Rect2 &p_area) const { +Ref<Image> Image::get_rect(const Rect2i &p_area) const { Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format)); - img->blit_rect(Ref<Image>((Image *)this), p_area, Point2(0, 0)); + img->blit_rect(Ref<Image>((Image *)this), p_area, Point2i(0, 0)); return img; } @@ -2557,7 +2659,7 @@ void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2 r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y; } -void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { +void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) { ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); int srcdsize = p_src->data.size(); @@ -2599,7 +2701,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po } } -void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { +void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) { ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); @@ -2649,7 +2751,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co } } -void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { +void Image::blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) { ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); int srcdsize = p_src->data.size(); @@ -2684,7 +2786,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P } } -void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { +void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) { ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); @@ -2756,7 +2858,7 @@ void Image::fill(const Color &p_color) { _repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height); } -void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) { +void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats."); Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs()); @@ -3217,6 +3319,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress); ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed); + ClassDB::bind_method(D_METHOD("rotate_90", "direction"), &Image::rotate_90); + ClassDB::bind_method(D_METHOD("rotate_180"), &Image::rotate_180); + ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges); ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha); ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear); diff --git a/core/io/image.h b/core/io/image.h index 6b323e5eb3..9d415423be 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -209,7 +209,7 @@ private: public: int get_width() const; ///< Get image width int get_height() const; ///< Get image height - Vector2 get_size() const; + Vector2i get_size() const; bool has_mipmaps() const; int get_mipmap_count() const; @@ -254,6 +254,9 @@ public: void crop_from_point(int p_x, int p_y, int p_width, int p_height); void crop(int p_width, int p_height); + void rotate_90(ClockDirection p_direction); + void rotate_180(); + void flip_x(); void flip_y(); @@ -370,15 +373,15 @@ public: Ref<Image> get_image_from_mipmap(int p_mipamp) const; void bump_map_to_normal_map(float bump_scale = 1.0); - void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); - void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); - void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); - void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); + void blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest); + void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest); + void blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest); + void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest); void fill(const Color &p_color); - void fill_rect(const Rect2 &p_rect, const Color &p_color); + void fill_rect(const Rect2i &p_rect, const Color &p_color); - Rect2 get_used_rect() const; - Ref<Image> get_rect(const Rect2 &p_area) const; + Rect2i get_used_rect() const; + Ref<Image> get_rect(const Rect2i &p_area) const; static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)); static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)); diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 5820ec0c09..b0f74f8db5 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -31,6 +31,7 @@ #include "logger.h" #include "core/config/project_settings.h" +#include "core/core_globals.h" #include "core/io/dir_access.h" #include "core/os/os.h" #include "core/os/time.h" @@ -41,7 +42,7 @@ #endif bool Logger::should_log(bool p_err) { - return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled); + return (!p_err || CoreGlobals::print_error_enabled) && (p_err || CoreGlobals::print_line_enabled); } bool Logger::_flush_stdout_on_print = true; diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 8ee19f274e..2f69c10218 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -285,6 +285,46 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; + case Variant::VECTOR4: { + Vector4 val; + if (type & ENCODE_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA); + val.x = decode_double(&buf[0]); + val.y = decode_double(&buf[sizeof(double)]); + val.z = decode_double(&buf[sizeof(double) * 2]); + val.w = decode_double(&buf[sizeof(double) * 3]); + + if (r_len) { + (*r_len) += sizeof(double) * 4; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA); + val.x = decode_float(&buf[0]); + val.y = decode_float(&buf[sizeof(float)]); + val.z = decode_float(&buf[sizeof(float) * 2]); + val.w = decode_float(&buf[sizeof(float) * 3]); + + if (r_len) { + (*r_len) += sizeof(float) * 4; + } + } + r_variant = val; + + } break; + case Variant::VECTOR4I: { + ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); + Vector4i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + val.z = decode_uint32(&buf[8]); + val.w = decode_uint32(&buf[12]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 4; + } + + } break; case Variant::TRANSFORM2D: { Transform2D val; if (type & ENCODE_FLAG_64) { @@ -457,6 +497,33 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = val; } break; + case Variant::PROJECTION: { + Projection val; + if (type & ENCODE_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + val.matrix[i][j] = decode_double(&buf[(i * 4 + j) * sizeof(double)]); + } + } + if (r_len) { + (*r_len) += sizeof(double) * 16; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 62, ERR_INVALID_DATA); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + val.matrix[i][j] = decode_float(&buf[(i * 4 + j) * sizeof(float)]); + } + } + + if (r_len) { + (*r_len) += sizeof(float) * 16; + } + } + r_variant = val; + + } break; // misc types case Variant::COLOR: { ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); @@ -1286,6 +1353,30 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 6 * sizeof(real_t); } break; + case Variant::VECTOR4: { + if (buf) { + Vector4 v4 = p_variant; + encode_real(v4.x, &buf[0]); + encode_real(v4.y, &buf[sizeof(real_t)]); + encode_real(v4.z, &buf[sizeof(real_t) * 2]); + encode_real(v4.w, &buf[sizeof(real_t) * 3]); + } + + r_len += 4 * sizeof(real_t); + + } break; + case Variant::VECTOR4I: { + if (buf) { + Vector4i v4 = p_variant; + encode_uint32(v4.x, &buf[0]); + encode_uint32(v4.y, &buf[4]); + encode_uint32(v4.z, &buf[8]); + encode_uint32(v4.w, &buf[12]); + } + + r_len += 4 * 4; + + } break; case Variant::PLANE: { if (buf) { Plane p = p_variant; @@ -1354,6 +1445,19 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 12 * sizeof(real_t); } break; + case Variant::PROJECTION: { + if (buf) { + Projection val = p_variant; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + memcpy(&buf[(i * 4 + j) * sizeof(real_t)], &val.matrix[i][j], sizeof(real_t)); + } + } + } + + r_len += 16 * sizeof(real_t); + + } break; // misc types case Variant::COLOR: { diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 0b12640627..ec9d33aa5a 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -127,4 +127,4 @@ public: PacketPeerStream(); }; -#endif // PACKET_STREAM_H +#endif // PACKET_PEER_H diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index b1c50e829c..b731608b4f 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -81,6 +81,9 @@ enum { VARIANT_VECTOR3I = 47, VARIANT_PACKED_INT64_ARRAY = 48, VARIANT_PACKED_FLOAT64_ARRAY = 49, + VARIANT_VECTOR4 = 50, + VARIANT_VECTOR4I = 51, + VARIANT_PROJECTION = 52, OBJECT_EMPTY = 0, OBJECT_EXTERNAL_RESOURCE = 1, OBJECT_INTERNAL_RESOURCE = 2, @@ -237,6 +240,22 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { v.z = f->get_32(); r_v = v; } break; + case VARIANT_VECTOR4: { + Vector4 v; + v.x = f->get_real(); + v.y = f->get_real(); + v.z = f->get_real(); + v.w = f->get_real(); + r_v = v; + } break; + case VARIANT_VECTOR4I: { + Vector4i v; + v.x = f->get_32(); + v.y = f->get_32(); + v.z = f->get_32(); + v.w = f->get_32(); + r_v = v; + } break; case VARIANT_PLANE: { Plane v; v.normal.x = f->get_real(); @@ -306,6 +325,26 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { v.origin.z = f->get_real(); r_v = v; } break; + case VARIANT_PROJECTION: { + Projection v; + v.matrix[0].x = f->get_real(); + v.matrix[0].y = f->get_real(); + v.matrix[0].z = f->get_real(); + v.matrix[0].w = f->get_real(); + v.matrix[1].x = f->get_real(); + v.matrix[1].y = f->get_real(); + v.matrix[1].z = f->get_real(); + v.matrix[1].w = f->get_real(); + v.matrix[2].x = f->get_real(); + v.matrix[2].y = f->get_real(); + v.matrix[2].z = f->get_real(); + v.matrix[2].w = f->get_real(); + v.matrix[3].x = f->get_real(); + v.matrix[3].y = f->get_real(); + v.matrix[3].z = f->get_real(); + v.matrix[3].w = f->get_real(); + r_v = v; + } break; case VARIANT_COLOR: { Color v; // Colors should always be in single-precision. v.r = f->get_float(); @@ -865,6 +904,22 @@ String ResourceLoaderBinary::get_unicode_string() { return s; } +void ResourceLoaderBinary::get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes) { + open(p_f, false, true); + if (error) { + return; + } + + for (int i = 0; i < internal_resources.size(); i++) { + p_f->seek(internal_resources[i].offset); + String t = get_unicode_string(); + ERR_FAIL_COND(p_f->get_error() != OK); + if (t != String()) { + p_classes->insert(t); + } + } +} + void ResourceLoaderBinary::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) { open(p_f, false, true); if (error) { @@ -1212,7 +1267,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons Ref<Resource> res = loader.get_resource(); ERR_FAIL_COND_V(!res.is_valid(), ERR_FILE_CORRUPT); - return ResourceFormatSaverBinary::singleton->save(p_path, res); + return ResourceFormatSaverBinary::singleton->save(res, p_path); } if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { @@ -1337,6 +1392,16 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons return OK; } +void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'."); + + ResourceLoaderBinary loader; + loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + loader.res_path = loader.local_path; + loader.get_classes_used(f, r_classes); +} + String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); if (f.is_null()) { @@ -1473,6 +1538,24 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V f->store_32(val.z); } break; + case Variant::VECTOR4: { + f->store_32(VARIANT_VECTOR4); + Vector4 val = p_property; + f->store_real(val.x); + f->store_real(val.y); + f->store_real(val.z); + f->store_real(val.w); + + } break; + case Variant::VECTOR4I: { + f->store_32(VARIANT_VECTOR4I); + Vector4i val = p_property; + f->store_32(val.x); + f->store_32(val.y); + f->store_32(val.z); + f->store_32(val.w); + + } break; case Variant::PLANE: { f->store_32(VARIANT_PLANE); Plane val = p_property; @@ -1544,6 +1627,27 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V f->store_real(val.origin.z); } break; + case Variant::PROJECTION: { + f->store_32(VARIANT_PROJECTION); + Projection val = p_property; + f->store_real(val.matrix[0].x); + f->store_real(val.matrix[0].y); + f->store_real(val.matrix[0].z); + f->store_real(val.matrix[0].w); + f->store_real(val.matrix[1].x); + f->store_real(val.matrix[1].y); + f->store_real(val.matrix[1].z); + f->store_real(val.matrix[1].w); + f->store_real(val.matrix[2].x); + f->store_real(val.matrix[2].y); + f->store_real(val.matrix[2].z); + f->store_real(val.matrix[2].w); + f->store_real(val.matrix[3].x); + f->store_real(val.matrix[3].y); + f->store_real(val.matrix[3].z); + f->store_real(val.matrix[3].w); + + } break; case Variant::COLOR: { f->store_32(VARIANT_COLOR); Color val = p_property; @@ -2100,7 +2204,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re return OK; } -Error ResourceFormatSaverBinary::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverBinary::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { String local_path = ProjectSettings::get_singleton()->localize_path(p_path); ResourceFormatSaverBinaryInstance saver; return saver.save(local_path, p_resource, p_flags); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 5da880ddb8..c891a61e99 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -101,6 +101,7 @@ public: void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false); String recognize(Ref<FileAccess> p_f); void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types); + void get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes); ResourceLoaderBinary() {} }; @@ -112,6 +113,7 @@ public: 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; + virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes); virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); @@ -174,7 +176,7 @@ public: class ResourceFormatSaverBinary : public ResourceFormatSaver { public: static ResourceFormatSaverBinary *singleton; - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 934cb780e6..e059fc842b 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -352,6 +352,16 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons return pat.metadata; } +void ResourceFormatImporter::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { + PathAndType pat; + Error err = _get_path_and_type(p_path, pat); + + if (err != OK) { + return; + } + + ResourceLoader::get_classes_used(pat.path, r_classes); +} void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { PathAndType pat; diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 0c7909df06..d0ea98b598 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -65,12 +65,12 @@ public: virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; - virtual Variant get_resource_metadata(const String &p_path) const; virtual bool is_import_valid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); virtual bool is_imported(const String &p_path) const { return recognize_path(p_path); } virtual String get_import_group_file(const String &p_path) const; + virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes); virtual bool exists(const String &p_path) const; virtual int get_import_order(const String &p_path) const; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 2cd455475c..3e595557f9 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -76,6 +76,21 @@ bool ResourceFormatLoader::handles_type(const String &p_type) const { return false; } +void ResourceFormatLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { + Vector<String> ret; + if (GDVIRTUAL_CALL(_get_classes_used, p_path, ret)) { + for (int i = 0; i < ret.size(); i++) { + r_classes->insert(ret[i]); + } + return; + } + + String res = get_resource_type(p_path); + if (!res.is_empty()) { + r_classes->insert(res); + } +} + String ResourceFormatLoader::get_resource_type(const String &p_path) const { String ret; @@ -180,6 +195,7 @@ void ResourceFormatLoader::_bind_methods() { GDVIRTUAL_BIND(_get_dependencies, "path", "add_types"); GDVIRTUAL_BIND(_rename_dependencies, "path", "renames"); GDVIRTUAL_BIND(_exists, "path"); + GDVIRTUAL_BIND(_get_classes_used, "path"); GDVIRTUAL_BIND(_load, "path", "original_path", "use_sub_threads", "cache_mode"); } @@ -730,6 +746,18 @@ Error ResourceLoader::rename_dependencies(const String &p_path, const HashMap<St return OK; // ?? } +void ResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { + String local_path = _validate_local_path(p_path); + + for (int i = 0; i < loader_count; i++) { + if (!loader[i]->recognize_path(local_path)) { + continue; + } + + return loader[i]->get_classes_used(p_path, r_classes); + } +} + String ResourceLoader::get_resource_type(const String &p_path) { String local_path = _validate_local_path(p_path); @@ -791,6 +819,12 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem if (r_translation_remapped) { *r_translation_remapped = true; } + + // Fallback to p_path if new_path does not exist. + if (!FileAccess::exists(new_path)) { + WARN_PRINT(vformat("Translation remap '%s' does not exist. Falling back to '%s'.", new_path, p_path)); + new_path = p_path; + } } if (path_remaps.has(new_path)) { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 815dd1dd72..91ba930176 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -55,6 +55,7 @@ protected: GDVIRTUAL1RC(String, _get_resource_type, String) GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String) GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool) + GDVIRTUAL1RC(Vector<String>, _get_classes_used, String) GDVIRTUAL2RC(int64_t, _rename_dependencies, String, Dictionary) GDVIRTUAL1RC(bool, _exists, String) @@ -67,6 +68,7 @@ public: virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const; virtual bool handles_type(const String &p_type) const; + virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes); virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); @@ -170,6 +172,7 @@ public: static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions); static void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front = false); static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader); + static void get_classes_used(const String &p_path, HashSet<StringName> *r_classes); static String get_resource_type(const String &p_path); static ResourceUID::ID get_resource_uid(const String &p_path); static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 2f5c5b54dd..274316f058 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -41,9 +41,9 @@ bool ResourceSaver::timestamp_on_save = false; ResourceSavedCallback ResourceSaver::save_callback = nullptr; ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr; -Error ResourceFormatSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { int64_t res; - if (GDVIRTUAL_CALL(_save, p_path, p_resource, p_flags, res)) { + if (GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, res)) { return (Error)res; } @@ -75,8 +75,14 @@ void ResourceFormatSaver::_bind_methods() { GDVIRTUAL_BIND(_get_recognized_extensions, "resource"); } -Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { - String extension = p_path.get_extension(); +Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { + String path = p_path; + if (path.is_empty()) { + path = p_resource->get_path(); + } + ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Can't save resource to empty path. Provide non-empty path or a Resource with non-empty resource_path."); + + String extension = path.get_extension(); Error err = ERR_FILE_UNRECOGNIZED; for (int i = 0; i < saver_count; i++) { @@ -100,21 +106,21 @@ Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, String old_path = p_resource->get_path(); - String local_path = ProjectSettings::get_singleton()->localize_path(p_path); + String local_path = ProjectSettings::get_singleton()->localize_path(path); Ref<Resource> rwcopy = p_resource; if (p_flags & FLAG_CHANGE_PATH) { rwcopy->set_path(local_path); } - err = saver[i]->save(p_path, p_resource, p_flags); + err = saver[i]->save(p_resource, path, p_flags); if (err == OK) { #ifdef TOOLS_ENABLED ((Resource *)p_resource.ptr())->set_edited(false); if (timestamp_on_save) { - uint64_t mt = FileAccess::get_modified_time(p_path); + uint64_t mt = FileAccess::get_modified_time(path); ((Resource *)p_resource.ptr())->set_last_modified_time(mt); } @@ -124,8 +130,8 @@ Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, rwcopy->set_path(old_path); } - if (save_callback && p_path.begins_with("res://")) { - save_callback(p_resource, p_path); + if (save_callback && path.begins_with("res://")) { + save_callback(p_resource, path); } return OK; diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 088317bfbe..4fee2bcfd1 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -41,12 +41,12 @@ class ResourceFormatSaver : public RefCounted { protected: static void _bind_methods(); - GDVIRTUAL3R(int64_t, _save, String, Ref<Resource>, uint32_t) + GDVIRTUAL3R(int64_t, _save, Ref<Resource>, String, uint32_t) GDVIRTUAL1RC(bool, _recognize, Ref<Resource>) GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>) public: - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; @@ -81,7 +81,7 @@ public: FLAG_REPLACE_SUBRESOURCE_PATHS = 64, }; - static Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = (uint32_t)FLAG_NONE); + static Error save(const Ref<Resource> &p_resource, const String &p_path = "", uint32_t p_flags = (uint32_t)FLAG_NONE); static void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions); static void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front = false); static void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver); diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h index da42553cf5..0da37e2716 100644 --- a/core/io/resource_uid.h +++ b/core/io/resource_uid.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCE_UUID_H -#define RESOURCE_UUID_H +#ifndef RESOURCE_UID_H +#define RESOURCE_UID_H #include "core/object/ref_counted.h" #include "core/string/string_name.h" @@ -85,4 +85,4 @@ public: ~ResourceUID(); }; -#endif // RESOURCEUUID_H +#endif // RESOURCE_UID_H diff --git a/core/math/basis.cpp b/core/math/basis.cpp index ce5e9aa9b3..f8e7c47107 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -817,14 +817,13 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { #endif */ real_t angle, x, y, z; // variables for result - real_t epsilon = 0.01; // margin to allow for rounding errors - real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees + real_t angle_epsilon = 0.1; // margin to distinguish between 0 and 180 degrees - if ((Math::abs(rows[1][0] - rows[0][1]) < epsilon) && (Math::abs(rows[2][0] - rows[0][2]) < epsilon) && (Math::abs(rows[2][1] - rows[1][2]) < epsilon)) { + if ((Math::abs(rows[1][0] - rows[0][1]) < CMP_EPSILON) && (Math::abs(rows[2][0] - rows[0][2]) < CMP_EPSILON) && (Math::abs(rows[2][1] - rows[1][2]) < CMP_EPSILON)) { // singularity found // first check for identity matrix which must have +1 for all terms // in leading diagonal and zero in other terms - if ((Math::abs(rows[1][0] + rows[0][1]) < epsilon2) && (Math::abs(rows[2][0] + rows[0][2]) < epsilon2) && (Math::abs(rows[2][1] + rows[1][2]) < epsilon2) && (Math::abs(rows[0][0] + rows[1][1] + rows[2][2] - 3) < epsilon2)) { + if ((Math::abs(rows[1][0] + rows[0][1]) < angle_epsilon) && (Math::abs(rows[2][0] + rows[0][2]) < angle_epsilon) && (Math::abs(rows[2][1] + rows[1][2]) < angle_epsilon) && (Math::abs(rows[0][0] + rows[1][1] + rows[2][2] - 3) < angle_epsilon)) { // this singularity is identity matrix so angle = 0 r_axis = Vector3(0, 1, 0); r_angle = 0; @@ -839,7 +838,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { real_t xz = (rows[2][0] + rows[0][2]) / 4; real_t yz = (rows[2][1] + rows[1][2]) / 4; if ((xx > yy) && (xx > zz)) { // rows[0][0] is the largest diagonal term - if (xx < epsilon) { + if (xx < CMP_EPSILON) { x = 0; y = Math_SQRT12; z = Math_SQRT12; @@ -849,7 +848,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { z = xz / x; } } else if (yy > zz) { // rows[1][1] is the largest diagonal term - if (yy < epsilon) { + if (yy < CMP_EPSILON) { x = Math_SQRT12; y = 0; z = Math_SQRT12; @@ -859,7 +858,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { z = yz / y; } } else { // rows[2][2] is the largest diagonal term so base result on this - if (zz < epsilon) { + if (zz < CMP_EPSILON) { x = Math_SQRT12; y = Math_SQRT12; z = 0; diff --git a/core/math/bvh.h b/core/math/bvh.h index 9f6ab9f736..b5f5eda3e6 100644 --- a/core/math/bvh.h +++ b/core/math/bvh.h @@ -302,7 +302,7 @@ public: tree.update(); _check_for_collisions(); #ifdef BVH_INTEGRITY_CHECKS - tree.integrity_check_all(); + tree._integrity_check_all(); #endif } diff --git a/core/math/bvh_public.inc b/core/math/bvh_public.inc index 36b0bfeb13..fc1c67a21b 100644 --- a/core/math/bvh_public.inc +++ b/core/math/bvh_public.inc @@ -2,7 +2,7 @@ public: BVHHandle item_add(T *p_userdata, bool p_active, const BOUNDS &p_aabb, int32_t p_subindex, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_invisible = false) { #ifdef BVH_VERBOSE_TREE VERBOSE_PRINT("\nitem_add BEFORE"); - _debug_recursive_print_tree(0); + _debug_recursive_print_tree(p_tree_id); VERBOSE_PRINT("\n"); #endif @@ -78,8 +78,8 @@ BVHHandle item_add(T *p_userdata, bool p_active, const BOUNDS &p_aabb, int32_t p mem += _nodes.estimate_memory_use(); String sz = _debug_aabb_to_string(abb); - VERBOSE_PRINT("\titem_add [" + itos(ref_id) + "] " + itos(_refs.size()) + " refs,\t" + itos(_nodes.size()) + " nodes " + sz); - VERBOSE_PRINT("mem use : " + itos(mem) + ", num nodes : " + itos(_nodes.size())); + VERBOSE_PRINT("\titem_add [" + itos(ref_id) + "] " + itos(_refs.used_size()) + " refs,\t" + itos(_nodes.used_size()) + " nodes " + sz); + VERBOSE_PRINT("mem use : " + itos(mem) + ", num nodes reserved : " + itos(_nodes.reserved_size())); #endif diff --git a/core/math/color.h b/core/math/color.h index 0afa6006a8..65036f74cc 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -215,12 +215,12 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0f); } _FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(Math::round(a * 255.0f), 0.0f, 255.0f)); } - _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); } - _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); } - _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); } - _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l()); } - _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l()); } - _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l); } + _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); } + _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); } + _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); } + _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l(), a); } + _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); } + _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); } _FORCE_INLINE_ Color() {} diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index 4ab00e1f34..898c3c2d91 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -33,7 +33,7 @@ #include "core/io/file_access.h" #include "core/math/aabb.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/math/vector3.h" #include "core/string/print_string.h" #include "core/templates/local_vector.h" @@ -184,7 +184,7 @@ class Delaunay3D { return true; } - CameraMatrix cm; + Projection cm; cm.matrix[0][0] = p_points[p_simplex.points[0]].x; cm.matrix[0][1] = p_points[p_simplex.points[1]].x; diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp index 4be4809e3f..208f89f449 100644 --- a/core/math/math_fieldwise.cpp +++ b/core/math/math_fieldwise.cpp @@ -76,6 +76,36 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const return target; } + case Variant::VECTOR3I: { + SETUP_TYPE(Vector3i) + + /**/ TRY_TRANSFER_FIELD("x", x) + else TRY_TRANSFER_FIELD("y", y) + else TRY_TRANSFER_FIELD("z", z) + + return target; + } + case Variant::VECTOR4: { + SETUP_TYPE(Vector4) + + /**/ TRY_TRANSFER_FIELD("x", x) + else TRY_TRANSFER_FIELD("y", y) + else TRY_TRANSFER_FIELD("z", z) + else TRY_TRANSFER_FIELD("w", w) + + return target; + } + case Variant::VECTOR4I: { + SETUP_TYPE(Vector4i) + + /**/ TRY_TRANSFER_FIELD("x", x) + else TRY_TRANSFER_FIELD("y", y) + else TRY_TRANSFER_FIELD("z", z) + else TRY_TRANSFER_FIELD("w", w) + + return target; + } + case Variant::PLANE: { SETUP_TYPE(Plane) diff --git a/core/math/plane.h b/core/math/plane.h index 66c1741662..73babfa496 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -52,7 +52,7 @@ struct _NO_DISCARD_ Plane { _FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane _FORCE_INLINE_ real_t distance_to(const Vector3 &p_point) const; - _FORCE_INLINE_ bool has_point(const Vector3 &p_point, real_t _epsilon = CMP_EPSILON) const; + _FORCE_INLINE_ bool has_point(const Vector3 &p_point, real_t p_tolerance = CMP_EPSILON) const; /* intersections */ @@ -97,10 +97,10 @@ real_t Plane::distance_to(const Vector3 &p_point) const { return (normal.dot(p_point) - d); } -bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const { +bool Plane::has_point(const Vector3 &p_point, real_t p_tolerance) const { real_t dist = normal.dot(p_point) - d; dist = ABS(dist); - return (dist <= _epsilon); + return (dist <= p_tolerance); } Plane::Plane(const Vector3 &p_normal, real_t p_d) : diff --git a/core/math/camera_matrix.cpp b/core/math/projection.cpp index 57c53b0adb..edf8bf36cd 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/projection.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_matrix.cpp */ +/* projection.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "camera_matrix.h" +#include "projection.h" #include "core/math/aabb.h" #include "core/math/math_funcs.h" @@ -37,7 +37,7 @@ #include "core/math/transform_3d.h" #include "core/string/print_string.h" -float CameraMatrix::determinant() const { +float Projection::determinant() const { return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] - matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] + matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] - @@ -52,7 +52,7 @@ float CameraMatrix::determinant() const { matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3]; } -void CameraMatrix::set_identity() { +void Projection::set_identity() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrix[i][j] = (i == j) ? 1 : 0; @@ -60,7 +60,7 @@ void CameraMatrix::set_identity() { } } -void CameraMatrix::set_zero() { +void Projection::set_zero() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrix[i][j] = 0; @@ -68,7 +68,7 @@ void CameraMatrix::set_zero() { } } -Plane CameraMatrix::xform4(const Plane &p_vec4) const { +Plane Projection::xform4(const Plane &p_vec4) const { Plane ret; ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d; @@ -78,7 +78,22 @@ Plane CameraMatrix::xform4(const Plane &p_vec4) const { return ret; } -void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) { +Vector4 Projection::xform(const Vector4 &p_vec4) const { + return Vector4( + matrix[0][0] * p_vec4.x + matrix[1][0] * p_vec4.y + matrix[2][0] * p_vec4.z + matrix[3][0] * p_vec4.w, + matrix[0][1] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[2][1] * p_vec4.z + matrix[3][1] * p_vec4.w, + matrix[0][2] * p_vec4.x + matrix[1][2] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[3][2] * p_vec4.w, + matrix[0][3] * p_vec4.x + matrix[1][3] * p_vec4.y + matrix[2][3] * p_vec4.z + matrix[3][3] * p_vec4.w); +} +Vector4 Projection::xform_inv(const Vector4 &p_vec4) const { + return Vector4( + matrix[0][0] * p_vec4.x + matrix[0][1] * p_vec4.y + matrix[0][2] * p_vec4.z + matrix[0][3] * p_vec4.w, + matrix[1][0] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[1][2] * p_vec4.z + matrix[1][3] * p_vec4.w, + matrix[2][0] * p_vec4.x + matrix[2][1] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[2][3] * p_vec4.w, + matrix[3][0] * p_vec4.x + matrix[3][1] * p_vec4.y + matrix[3][2] * p_vec4.z + matrix[3][3] * p_vec4.w); +} + +void Projection::adjust_perspective_znear(real_t p_new_znear) { real_t zfar = get_z_far(); real_t znear = p_new_znear; @@ -87,7 +102,154 @@ void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) { matrix[3][2] = -2 * znear * zfar / deltaZ; } -void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) { +Projection Projection::create_depth_correction(bool p_flip_y) { + Projection proj; + proj.set_depth_correction(p_flip_y); + return proj; +} + +Projection Projection::create_light_atlas_rect(const Rect2 &p_rect) { + Projection proj; + proj.set_light_atlas_rect(p_rect); + return proj; +} + +Projection Projection::create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) { + Projection proj; + proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov); + return proj; +} + +Projection Projection::create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) { + Projection proj; + proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist); + return proj; +} + +Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) { + Projection proj; + proj.set_for_hmd(p_eye, p_aspect, p_intraocular_dist, p_display_width, p_display_to_lens, p_oversample, p_z_near, p_z_far); + return proj; +} + +Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { + Projection proj; + proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar); + return proj; +} + +Projection Projection::create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) { + Projection proj; + proj.set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov); + return proj; +} + +Projection Projection::create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) { + Projection proj; + proj.set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far); + return proj; +} + +Projection Projection::create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) { + Projection proj; + proj.set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov); + return proj; +} + +Projection Projection::create_fit_aabb(const AABB &p_aabb) { + Projection proj; + proj.scale_translate_to_fit(p_aabb); + return proj; +} + +Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const { + Projection proj = *this; + proj.adjust_perspective_znear(p_new_znear); + return proj; +} + +Plane Projection::get_projection_plane(Planes p_plane) const { + const real_t *matrix = (const real_t *)this->matrix; + + switch (p_plane) { + case PLANE_NEAR: { + Plane new_plane = Plane(matrix[3] + matrix[2], + matrix[7] + matrix[6], + matrix[11] + matrix[10], + matrix[15] + matrix[14]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + case PLANE_FAR: { + Plane new_plane = Plane(matrix[3] - matrix[2], + matrix[7] - matrix[6], + matrix[11] - matrix[10], + matrix[15] - matrix[14]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + case PLANE_LEFT: { + Plane new_plane = Plane(matrix[3] + matrix[0], + matrix[7] + matrix[4], + matrix[11] + matrix[8], + matrix[15] + matrix[12]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + case PLANE_TOP: { + Plane new_plane = Plane(matrix[3] - matrix[1], + matrix[7] - matrix[5], + matrix[11] - matrix[9], + matrix[15] - matrix[13]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + case PLANE_RIGHT: { + Plane new_plane = Plane(matrix[3] - matrix[0], + matrix[7] - matrix[4], + matrix[11] - matrix[8], + matrix[15] - matrix[12]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + case PLANE_BOTTOM: { + Plane new_plane = Plane(matrix[3] + matrix[1], + matrix[7] + matrix[5], + matrix[11] + matrix[9], + matrix[15] + matrix[13]); + + new_plane.normal = -new_plane.normal; + new_plane.normalize(); + return new_plane; + } break; + } + + return Plane(); +} + +Projection Projection::flipped_y() const { + Projection proj = *this; + proj.flip_y(); + return proj; +} + +Projection Projection ::jitter_offseted(const Vector2 &p_offset) const { + Projection proj = *this; + proj.add_jitter_offset(p_offset); + return proj; +} + +void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) { if (p_flip_fov) { p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect); } @@ -113,7 +275,7 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_ matrix[3][3] = 0; } -void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) { +void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) { if (p_flip_fov) { p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect); } @@ -145,13 +307,13 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_ set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far); // translate matrix by (modeltranslation, 0.0, 0.0) - CameraMatrix cm; + Projection cm; cm.set_identity(); cm.matrix[3][0] = modeltranslation; *this = *this * cm; } -void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) { +void Projection::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) { // we first calculate our base frustum on our values without taking our lens magnification into account. real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens; real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens; @@ -179,7 +341,7 @@ void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_ } } -void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { +void Projection::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { set_identity(); matrix[0][0] = 2.0 / (p_right - p_left); @@ -191,7 +353,7 @@ void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom matrix[3][3] = 1.0; } -void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) { +void Projection::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) { if (!p_flip_fov) { p_size *= p_aspect; } @@ -199,7 +361,7 @@ void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar); } -void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) { +void Projection::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) { ERR_FAIL_COND(p_right <= p_left); ERR_FAIL_COND(p_top <= p_bottom); ERR_FAIL_COND(p_far <= p_near); @@ -231,7 +393,7 @@ void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, r te[15] = 0; } -void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) { +void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) { if (!p_flip_fov) { p_size *= p_aspect; } @@ -239,7 +401,7 @@ void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far); } -real_t CameraMatrix::get_z_far() const { +real_t Projection::get_z_far() const { const real_t *matrix = (const real_t *)this->matrix; Plane new_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], @@ -252,7 +414,7 @@ real_t CameraMatrix::get_z_far() const { return new_plane.d; } -real_t CameraMatrix::get_z_near() const { +real_t Projection::get_z_near() const { const real_t *matrix = (const real_t *)this->matrix; Plane new_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], @@ -263,7 +425,7 @@ real_t CameraMatrix::get_z_near() const { return new_plane.d; } -Vector2 CameraMatrix::get_viewport_half_extents() const { +Vector2 Projection::get_viewport_half_extents() const { const real_t *matrix = (const real_t *)this->matrix; ///////--- Near Plane ---/////// Plane near_plane = Plane(matrix[3] + matrix[2], @@ -291,7 +453,7 @@ Vector2 CameraMatrix::get_viewport_half_extents() const { return Vector2(res.x, res.y); } -Vector2 CameraMatrix::get_far_plane_half_extents() const { +Vector2 Projection::get_far_plane_half_extents() const { const real_t *matrix = (const real_t *)this->matrix; ///////--- Far Plane ---/////// Plane far_plane = Plane(matrix[3] - matrix[2], @@ -319,7 +481,7 @@ Vector2 CameraMatrix::get_far_plane_half_extents() const { return Vector2(res.x, res.y); } -bool CameraMatrix::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const { +bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const { Vector<Plane> planes = get_projection_planes(Transform3D()); const Planes intersections[8][3] = { { PLANE_FAR, PLANE_LEFT, PLANE_TOP }, @@ -342,7 +504,7 @@ bool CameraMatrix::get_endpoints(const Transform3D &p_transform, Vector3 *p_8poi return true; } -Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform) const { +Vector<Plane> Projection::get_projection_planes(const Transform3D &p_transform) const { /** Fast Plane Extraction from combined modelview/projection matrices. * References: * https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html @@ -425,13 +587,13 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform return planes; } -CameraMatrix CameraMatrix::inverse() const { - CameraMatrix cm = *this; +Projection Projection::inverse() const { + Projection cm = *this; cm.invert(); return cm; } -void CameraMatrix::invert() { +void Projection::invert() { int i, j, k; int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */ real_t pvt_val; /* Value of current pivot element */ @@ -529,18 +691,18 @@ void CameraMatrix::invert() { } } -void CameraMatrix::flip_y() { +void Projection::flip_y() { for (int i = 0; i < 4; i++) { matrix[1][i] = -matrix[1][i]; } } -CameraMatrix::CameraMatrix() { +Projection::Projection() { set_identity(); } -CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const { - CameraMatrix new_matrix; +Projection Projection::operator*(const Projection &p_matrix) const { + Projection new_matrix; for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { @@ -555,7 +717,7 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const { return new_matrix; } -void CameraMatrix::set_depth_correction(bool p_flip_y) { +void Projection::set_depth_correction(bool p_flip_y) { real_t *m = &matrix[0][0]; m[0] = 1; @@ -576,7 +738,7 @@ void CameraMatrix::set_depth_correction(bool p_flip_y) { m[15] = 1.0; } -void CameraMatrix::set_light_bias() { +void Projection::set_light_bias() { real_t *m = &matrix[0][0]; m[0] = 0.5; @@ -597,7 +759,7 @@ void CameraMatrix::set_light_bias() { m[15] = 1.0; } -void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) { +void Projection::set_light_atlas_rect(const Rect2 &p_rect) { real_t *m = &matrix[0][0]; m[0] = p_rect.size.width; @@ -618,7 +780,7 @@ void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) { m[15] = 1.0; } -CameraMatrix::operator String() const { +Projection::operator String() const { String str; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { @@ -629,22 +791,22 @@ CameraMatrix::operator String() const { return str; } -real_t CameraMatrix::get_aspect() const { +real_t Projection::get_aspect() const { Vector2 vp_he = get_viewport_half_extents(); return vp_he.x / vp_he.y; } -int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const { +int Projection::get_pixels_per_meter(int p_for_pixel_width) const { Vector3 result = xform(Vector3(1, 0, -1)); return int((result.x * 0.5 + 0.5) * p_for_pixel_width); } -bool CameraMatrix::is_orthogonal() const { +bool Projection::is_orthogonal() const { return matrix[3][3] == 1.0; } -real_t CameraMatrix::get_fov() const { +real_t Projection::get_fov() const { const real_t *matrix = (const real_t *)this->matrix; Plane right_plane = Plane(matrix[3] - matrix[0], @@ -667,7 +829,7 @@ real_t CameraMatrix::get_fov() const { } } -float CameraMatrix::get_lod_multiplier() const { +float Projection::get_lod_multiplier() const { if (is_orthogonal()) { return get_viewport_half_extents().x; } else { @@ -678,14 +840,14 @@ float CameraMatrix::get_lod_multiplier() const { //usage is lod_size / (lod_distance * multiplier) < threshold } -void CameraMatrix::make_scale(const Vector3 &p_scale) { +void Projection::make_scale(const Vector3 &p_scale) { set_identity(); matrix[0][0] = p_scale.x; matrix[1][1] = p_scale.y; matrix[2][2] = p_scale.z; } -void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) { +void Projection::scale_translate_to_fit(const AABB &p_aabb) { Vector3 min = p_aabb.position; Vector3 max = p_aabb.position + p_aabb.size; @@ -710,12 +872,12 @@ void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) { matrix[3][3] = 1; } -void CameraMatrix::add_jitter_offset(const Vector2 &p_offset) { +void Projection::add_jitter_offset(const Vector2 &p_offset) { matrix[3][0] += p_offset.x; matrix[3][1] += p_offset.y; } -CameraMatrix::operator Transform3D() const { +Projection::operator Transform3D() const { Transform3D tr; const real_t *m = &matrix[0][0]; @@ -737,8 +899,13 @@ CameraMatrix::operator Transform3D() const { return tr; } - -CameraMatrix::CameraMatrix(const Transform3D &p_transform) { +Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) { + matrix[0] = p_x; + matrix[1] = p_y; + matrix[2] = p_z; + matrix[3] = p_w; +} +Projection::Projection(const Transform3D &p_transform) { const Transform3D &tr = p_transform; real_t *m = &matrix[0][0]; @@ -760,5 +927,5 @@ CameraMatrix::CameraMatrix(const Transform3D &p_transform) { m[15] = 1.0; } -CameraMatrix::~CameraMatrix() { +Projection::~Projection() { } diff --git a/core/math/camera_matrix.h b/core/math/projection.h index a4051cee3b..a3d2d7720b 100644 --- a/core/math/camera_matrix.h +++ b/core/math/projection.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_matrix.h */ +/* projection.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERA_MATRIX_H -#define CAMERA_MATRIX_H +#ifndef PROJECTION_H +#define PROJECTION_H #include "core/math/math_defs.h" #include "core/math/vector3.h" +#include "core/math/vector4.h" #include "core/templates/vector.h" struct AABB; @@ -41,7 +42,7 @@ struct Rect2; struct Transform3D; struct Vector2; -struct CameraMatrix { +struct Projection { enum Planes { PLANE_NEAR, PLANE_FAR, @@ -51,13 +52,24 @@ struct CameraMatrix { PLANE_BOTTOM }; - real_t matrix[4][4]; + Vector4 matrix[4]; + + _FORCE_INLINE_ const Vector4 &operator[](const int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 4); + return matrix[p_axis]; + } + + _FORCE_INLINE_ Vector4 &operator[](const int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 4); + return matrix[p_axis]; + } float determinant() const; void set_identity(); void set_zero(); void set_light_bias(); void set_depth_correction(bool p_flip_y = true); + void set_light_atlas_rect(const Rect2 &p_rect); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist); @@ -68,6 +80,21 @@ struct CameraMatrix { void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false); void adjust_perspective_znear(real_t p_new_znear); + static Projection create_depth_correction(bool p_flip_y); + static Projection create_light_atlas_rect(const Rect2 &p_rect); + static Projection create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false); + static Projection create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist); + static Projection create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far); + static Projection create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar); + static Projection create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false); + static Projection create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far); + static Projection create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false); + static Projection create_fit_aabb(const AABB &p_aabb); + Projection perspective_znear_adjusted(real_t p_new_znear) const; + Plane get_projection_plane(Planes p_plane) const; + Projection flipped_y() const; + Projection jitter_offseted(const Vector2 &p_offset) const; + static real_t get_fovy(real_t p_fovx, real_t p_aspect) { return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0); } @@ -85,13 +112,16 @@ struct CameraMatrix { Vector2 get_far_plane_half_extents() const; void invert(); - CameraMatrix inverse() const; + Projection inverse() const; - CameraMatrix operator*(const CameraMatrix &p_matrix) const; + Projection operator*(const Projection &p_matrix) const; Plane xform4(const Plane &p_vec4) const; _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const; + Vector4 xform(const Vector4 &p_vec4) const; + Vector4 xform_inv(const Vector4 &p_vec4) const; + operator String() const; void scale_translate_to_fit(const AABB &p_aabb); @@ -102,7 +132,7 @@ struct CameraMatrix { void flip_y(); - bool operator==(const CameraMatrix &p_cam) const { + bool operator==(const Projection &p_cam) const { for (uint32_t i = 0; i < 4; i++) { for (uint32_t j = 0; j < 4; j++) { if (matrix[i][j] != p_cam.matrix[i][j]) { @@ -113,18 +143,19 @@ struct CameraMatrix { return true; } - bool operator!=(const CameraMatrix &p_cam) const { + bool operator!=(const Projection &p_cam) const { return !(*this == p_cam); } float get_lod_multiplier() const; - CameraMatrix(); - CameraMatrix(const Transform3D &p_transform); - ~CameraMatrix(); + Projection(); + Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w); + Projection(const Transform3D &p_transform); + ~Projection(); }; -Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const { +Vector3 Projection::xform(const Vector3 &p_vec3) const { Vector3 ret; ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0]; ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1]; @@ -133,4 +164,4 @@ Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const { return ret / w; } -#endif // CAMERA_MATRIX_H +#endif // PROJECTION_H diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp index 11bfcc1a6f..c681c60694 100644 --- a/core/math/quaternion.cpp +++ b/core/math/quaternion.cpp @@ -111,7 +111,7 @@ Quaternion Quaternion::log() const { Quaternion Quaternion::exp() const { Quaternion src = *this; Vector3 src_v = Vector3(src.x, src.y, src.z); - float theta = src_v.length(); + real_t theta = src_v.length(); if (theta < CMP_EPSILON) { return Quaternion(0, 0, 0, 1); } @@ -132,15 +132,9 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con // adjust signs (if necessary) if (cosom < 0.0f) { cosom = -cosom; - to1.x = -p_to.x; - to1.y = -p_to.y; - to1.z = -p_to.z; - to1.w = -p_to.w; + to1 = -p_to; } else { - to1.x = p_to.x; - to1.y = p_to.y; - to1.z = p_to.z; - to1.w = p_to.w; + to1 = p_to; } // calculate coefficients @@ -189,16 +183,54 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c invFactor * from.w + newFactor * p_to.w); } -Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const { +Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized."); #endif - //the only way to do slerp :| - real_t t2 = (1.0f - p_weight) * p_weight * 2; - Quaternion sp = this->slerp(p_b, p_weight); - Quaternion sq = p_pre_a.slerpni(p_post_b, p_weight); - return sp.slerpni(sq, t2); + Quaternion from_q = *this; + Quaternion pre_q = p_pre_a; + Quaternion to_q = p_b; + Quaternion post_q = p_post_b; + + // Align flip phases. + from_q = Basis(from_q).get_rotation_quaternion(); + pre_q = Basis(pre_q).get_rotation_quaternion(); + to_q = Basis(to_q).get_rotation_quaternion(); + post_q = Basis(post_q).get_rotation_quaternion(); + + // Flip quaternions to shortest path if necessary. + bool flip1 = signbit(from_q.dot(pre_q)); + pre_q = flip1 ? -pre_q : pre_q; + bool flip2 = signbit(from_q.dot(to_q)); + to_q = flip2 ? -to_q : to_q; + bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q)); + post_q = flip3 ? -post_q : post_q; + + // Calc by Expmap in from_q space. + Quaternion ln_from = Quaternion(0, 0, 0, 0); + Quaternion ln_to = (from_q.inverse() * to_q).log(); + Quaternion ln_pre = (from_q.inverse() * pre_q).log(); + Quaternion ln_post = (from_q.inverse() * post_q).log(); + Quaternion ln = Quaternion(0, 0, 0, 0); + ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight); + ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight); + ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight); + Quaternion q1 = from_q * ln.exp(); + + // Calc by Expmap in to_q space. + ln_from = (to_q.inverse() * from_q).log(); + ln_to = Quaternion(0, 0, 0, 0); + ln_pre = (to_q.inverse() * pre_q).log(); + ln_post = (to_q.inverse() * post_q).log(); + ln = Quaternion(0, 0, 0, 0); + ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight); + ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight); + ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight); + Quaternion q2 = to_q * ln.exp(); + + // To cancel error made by Expmap ambiguity, do blends. + return q1.slerp(q2, p_weight); } Quaternion::operator String() const { @@ -213,7 +245,7 @@ Vector3 Quaternion::get_axis() const { return Vector3(x * r, y * r, z * r); } -float Quaternion::get_angle() const { +real_t Quaternion::get_angle() const { return 2 * Math::acos(w); } diff --git a/core/math/quaternion.h b/core/math/quaternion.h index 9801746659..cb54a6f540 100644 --- a/core/math/quaternion.h +++ b/core/math/quaternion.h @@ -71,10 +71,10 @@ struct _NO_DISCARD_ Quaternion { Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const; Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const; - Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const; + Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const; Vector3 get_axis() const; - float get_angle() const; + real_t get_angle() const; _FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { r_angle = 2 * Math::acos(w); diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index cbd2fd3fa1..226076029b 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -136,11 +136,11 @@ void Transform2D::scale_basis(const Size2 &p_scale) { columns[1][1] *= p_scale.y; } -void Transform2D::translate(const real_t p_tx, const real_t p_ty) { - translate(Vector2(p_tx, p_ty)); +void Transform2D::translate_local(const real_t p_tx, const real_t p_ty) { + translate_local(Vector2(p_tx, p_ty)); } -void Transform2D::translate(const Vector2 &p_translation) { +void Transform2D::translate_local(const Vector2 &p_translation) { columns[2] += basis_xform(p_translation); } @@ -217,18 +217,24 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const { return t; } -Transform2D Transform2D::scaled(const Size2 &p_scale) const { +Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const { Transform2D copy = *this; - copy.scale(p_scale); + copy.scale_basis(p_scale); return copy; } -Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const { +Transform2D Transform2D::scaled(const Size2 &p_scale) const { + // Equivalent to left multiplication Transform2D copy = *this; - copy.scale_basis(p_scale); + copy.scale(p_scale); return copy; } +Transform2D Transform2D::scaled_local(const Size2 &p_scale) const { + // Equivalent to right multiplication + return Transform2D(columns[0] * p_scale.x, columns[1] * p_scale.y, columns[2]); +} + Transform2D Transform2D::untranslated() const { Transform2D copy = *this; copy.columns[2] = Vector2(); @@ -236,15 +242,23 @@ Transform2D Transform2D::untranslated() const { } Transform2D Transform2D::translated(const Vector2 &p_offset) const { - Transform2D copy = *this; - copy.translate(p_offset); - return copy; + // Equivalent to left multiplication + return Transform2D(columns[0], columns[1], columns[2] + p_offset); +} + +Transform2D Transform2D::translated_local(const Vector2 &p_offset) const { + // Equivalent to right multiplication + return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset)); } Transform2D Transform2D::rotated(const real_t p_angle) const { - Transform2D copy = *this; - copy.rotate(p_angle); - return copy; + // Equivalent to left multiplication + return Transform2D(p_angle, Vector2()) * (*this); +} + +Transform2D Transform2D::rotated_local(const real_t p_angle) const { + // Equivalent to right multiplication + return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped. } real_t Transform2D::basis_determinant() const { diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 72d34a5d4c..f23f32867a 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -74,8 +74,8 @@ struct _NO_DISCARD_ Transform2D { void scale(const Size2 &p_scale); void scale_basis(const Size2 &p_scale); - void translate(const real_t p_tx, const real_t p_ty); - void translate(const Vector2 &p_translation); + void translate_local(const real_t p_tx, const real_t p_ty); + void translate_local(const Vector2 &p_translation); real_t basis_determinant() const; @@ -85,10 +85,13 @@ struct _NO_DISCARD_ Transform2D { _FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; } _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; } - Transform2D scaled(const Size2 &p_scale) const; Transform2D basis_scaled(const Size2 &p_scale) const; + Transform2D scaled(const Size2 &p_scale) const; + Transform2D scaled_local(const Size2 &p_scale) const; Transform2D translated(const Vector2 &p_offset) const; + Transform2D translated_local(const Vector2 &p_offset) const; Transform2D rotated(const real_t p_angle) const; + Transform2D rotated_local(const real_t p_angle) const; Transform2D untranslated() const; diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index 76b31daa76..a634faca9a 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -62,7 +62,15 @@ void Transform3D::rotate(const Vector3 &p_axis, real_t p_angle) { } Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_angle) const { - return Transform3D(Basis(p_axis, p_angle), Vector3()) * (*this); + // Equivalent to left multiplication + Basis p_basis(p_axis, p_angle); + return Transform3D(p_basis * basis, p_basis.xform(origin)); +} + +Transform3D Transform3D::rotated_local(const Vector3 &p_axis, real_t p_angle) const { + // Equivalent to right multiplication + Basis p_basis(p_axis, p_angle); + return Transform3D(basis * p_basis, origin); } void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { @@ -70,17 +78,23 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { } Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { +#ifdef MATH_CHECKS + ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal."); +#endif Transform3D t = *this; t.basis = Basis::looking_at(p_target - origin, p_up); return t; } void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { +#ifdef MATH_CHECKS + ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal."); +#endif basis = Basis::looking_at(p_target - p_eye, p_up); origin = p_eye; } -Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const { +Transform3D Transform3D::spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const { /* not sure if very "efficient" but good enough? */ Transform3D interp; @@ -114,29 +128,37 @@ void Transform3D::scale(const Vector3 &p_scale) { } Transform3D Transform3D::scaled(const Vector3 &p_scale) const { - Transform3D t = *this; - t.scale(p_scale); - return t; + // Equivalent to left multiplication + return Transform3D(basis.scaled(p_scale), origin * p_scale); +} + +Transform3D Transform3D::scaled_local(const Vector3 &p_scale) const { + // Equivalent to right multiplication + return Transform3D(basis.scaled_local(p_scale), origin); } void Transform3D::scale_basis(const Vector3 &p_scale) { basis.scale(p_scale); } -void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) { - translate(Vector3(p_tx, p_ty, p_tz)); +void Transform3D::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) { + translate_local(Vector3(p_tx, p_ty, p_tz)); } -void Transform3D::translate(const Vector3 &p_translation) { +void Transform3D::translate_local(const Vector3 &p_translation) { for (int i = 0; i < 3; i++) { origin[i] += basis[i].dot(p_translation); } } Transform3D Transform3D::translated(const Vector3 &p_translation) const { - Transform3D t = *this; - t.translate(p_translation); - return t; + // Equivalent to left multiplication + return Transform3D(basis, origin + p_translation); +} + +Transform3D Transform3D::translated_local(const Vector3 &p_translation) const { + // Equivalent to right multiplication + return Transform3D(basis, origin + basis.xform(p_translation)); } void Transform3D::orthonormalize() { diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index 25832434cd..b572e90859 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -46,6 +46,7 @@ struct _NO_DISCARD_ Transform3D { Transform3D affine_inverse() const; Transform3D rotated(const Vector3 &p_axis, real_t p_angle) const; + Transform3D rotated_local(const Vector3 &p_axis, real_t p_angle) const; void rotate(const Vector3 &p_axis, real_t p_angle); void rotate_basis(const Vector3 &p_axis, real_t p_angle); @@ -55,10 +56,12 @@ struct _NO_DISCARD_ Transform3D { void scale(const Vector3 &p_scale); Transform3D scaled(const Vector3 &p_scale) const; + Transform3D scaled_local(const Vector3 &p_scale) const; void scale_basis(const Vector3 &p_scale); - void translate(real_t p_tx, real_t p_ty, real_t p_tz); - void translate(const Vector3 &p_translation); + void translate_local(real_t p_tx, real_t p_ty, real_t p_tz); + void translate_local(const Vector3 &p_translation); Transform3D translated(const Vector3 &p_translation) const; + Transform3D translated_local(const Vector3 &p_translation) const; const Basis &get_basis() const { return basis; } void set_basis(const Basis &p_basis) { basis = p_basis; } @@ -100,7 +103,7 @@ struct _NO_DISCARD_ Transform3D { void operator*=(const real_t p_val); Transform3D operator*(const real_t p_val) const; - Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const; + Transform3D spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const { diff --git a/core/math/vector3.h b/core/math/vector3.h index 970416234d..4ce01da60e 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -217,16 +217,25 @@ Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { } Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { + // This method seems more complicated than it really is, since we write out + // the internals of some methods for efficiency (mainly, checking length). real_t start_length_sq = length_squared(); real_t end_length_sq = p_to.length_squared(); if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) { // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. return lerp(p_to, p_weight); } + Vector3 axis = cross(p_to); + real_t axis_length_sq = axis.length_squared(); + if (unlikely(axis_length_sq == 0.0f)) { + // Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp. + return lerp(p_to, p_weight); + } + axis /= Math::sqrt(axis_length_sq); real_t start_length = Math::sqrt(start_length_sq); real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight); real_t angle = angle_to(p_to); - return rotated(cross(p_to).normalized(), angle * p_weight) * (result_length / start_length); + return rotated(axis, angle * p_weight) * (result_length / start_length); } Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const { diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp new file mode 100644 index 0000000000..4697c311b4 --- /dev/null +++ b/core/math/vector4.cpp @@ -0,0 +1,172 @@ +/*************************************************************************/ +/* vector4.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "vector4.h" + +#include "core/math/basis.h" +#include "core/string/print_string.h" + +void Vector4::set_axis(const int p_axis, const real_t p_value) { + ERR_FAIL_INDEX(p_axis, 4); + components[p_axis] = p_value; +} + +real_t Vector4::get_axis(const int p_axis) const { + ERR_FAIL_INDEX_V(p_axis, 4, 0); + return operator[](p_axis); +} + +Vector4::Axis Vector4::min_axis_index() const { + uint32_t min_index = 0; + real_t min_value = x; + for (uint32_t i = 1; i < 4; i++) { + if (operator[](i) <= min_value) { + min_index = i; + min_value = operator[](i); + } + } + return Vector4::Axis(min_index); +} + +Vector4::Axis Vector4::max_axis_index() const { + uint32_t max_index = 0; + real_t max_value = x; + for (uint32_t i = 1; i < 4; i++) { + if (operator[](i) > max_value) { + max_index = i; + max_value = operator[](i); + } + } + return Vector4::Axis(max_index); +} + +bool Vector4::is_equal_approx(const Vector4 &p_vec4) const { + return Math::is_equal_approx(x, p_vec4.x) && Math::is_equal_approx(y, p_vec4.y) && Math::is_equal_approx(z, p_vec4.z) && Math::is_equal_approx(w, p_vec4.w); +} + +real_t Vector4::length() const { + return Math::sqrt(length_squared()); +} + +void Vector4::normalize() { + *this /= length(); +} + +Vector4 Vector4::normalized() const { + return *this / length(); +} + +bool Vector4::is_normalized() const { + return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); // Use less epsilon. +} + +real_t Vector4::distance_to(const Vector4 &p_to) const { + return (p_to - *this).length(); +} + +Vector4 Vector4::direction_to(const Vector4 &p_to) const { + Vector4 ret(p_to.x - x, p_to.y - y, p_to.z - z, p_to.w - w); + ret.normalize(); + return ret; +} + +Vector4 Vector4::abs() const { + return Vector4(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w)); +} + +Vector4 Vector4::sign() const { + return Vector4(SIGN(x), SIGN(y), SIGN(z), SIGN(w)); +} + +Vector4 Vector4::floor() const { + return Vector4(Math::floor(x), Math::floor(y), Math::floor(z), Math::floor(w)); +} + +Vector4 Vector4::ceil() const { + return Vector4(Math::ceil(x), Math::ceil(y), Math::ceil(z), Math::ceil(w)); +} + +Vector4 Vector4::round() const { + return Vector4(Math::round(x), Math::round(y), Math::round(z), Math::round(w)); +} + +Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const { + return Vector4( + x + (p_weight * (p_to.x - x)), + y + (p_weight * (p_to.y - y)), + z + (p_weight * (p_to.z - z)), + w + (p_weight * (p_to.w - w))); +} + +Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const { + Vector4 res = *this; + res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight); + res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight); + res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight); + res.w = Math::cubic_interpolate(res.w, p_b.w, p_pre_a.w, p_post_b.w, p_weight); + return res; +} + +Vector4 Vector4::posmod(const real_t p_mod) const { + return Vector4(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod), Math::fposmod(w, p_mod)); +} + +Vector4 Vector4::posmodv(const Vector4 &p_modv) const { + return Vector4(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z), Math::fposmod(w, p_modv.w)); +} + +void Vector4::snap(const Vector4 &p_step) { + x = Math::snapped(x, p_step.x); + y = Math::snapped(y, p_step.y); + z = Math::snapped(z, p_step.z); + w = Math::snapped(w, p_step.w); +} + +Vector4 Vector4::snapped(const Vector4 &p_step) const { + Vector4 v = *this; + v.snap(p_step); + return v; +} + +Vector4 Vector4::inverse() const { + return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w); +} + +Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const { + return Vector4( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y), + CLAMP(z, p_min.z, p_max.z), + CLAMP(w, p_min.w, p_max.w)); +} + +Vector4::operator String() const { + return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")"; +} diff --git a/core/math/vector4.h b/core/math/vector4.h new file mode 100644 index 0000000000..373a6a1218 --- /dev/null +++ b/core/math/vector4.h @@ -0,0 +1,302 @@ +/*************************************************************************/ +/* vector4.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 VECTOR4_H +#define VECTOR4_H + +#include "core/math/math_defs.h" +#include "core/math/math_funcs.h" +#include "core/math/vector3.h" +#include "core/string/ustring.h" + +struct _NO_DISCARD_ Vector4 { + enum Axis { + AXIS_X, + AXIS_Y, + AXIS_Z, + AXIS_W, + }; + + union { + struct { + real_t x; + real_t y; + real_t z; + real_t w; + }; + real_t components[4] = { 0, 0, 0, 0 }; + }; + + _FORCE_INLINE_ real_t &operator[](const int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 4); + return components[p_axis]; + } + _FORCE_INLINE_ const real_t &operator[](const int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 4); + return components[p_axis]; + } + + _FORCE_INLINE_ void set_all(const real_t p_value); + + void set_axis(const int p_axis, const real_t p_value); + real_t get_axis(const int p_axis) const; + + Vector4::Axis min_axis_index() const; + Vector4::Axis max_axis_index() const; + + _FORCE_INLINE_ real_t length_squared() const; + bool is_equal_approx(const Vector4 &p_vec4) const; + real_t length() const; + void normalize(); + Vector4 normalized() const; + bool is_normalized() const; + + real_t distance_to(const Vector4 &p_to) const; + Vector4 direction_to(const Vector4 &p_to) const; + + Vector4 abs() const; + Vector4 sign() const; + Vector4 floor() const; + Vector4 ceil() const; + Vector4 round() const; + Vector4 lerp(const Vector4 &p_to, const real_t p_weight) const; + Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const; + + Vector4 posmod(const real_t p_mod) const; + Vector4 posmodv(const Vector4 &p_modv) const; + void snap(const Vector4 &p_step); + Vector4 snapped(const Vector4 &p_step) const; + Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const; + + Vector4 inverse() const; + _FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const; + + _FORCE_INLINE_ void operator+=(const Vector4 &p_vec4); + _FORCE_INLINE_ void operator-=(const Vector4 &p_vec4); + _FORCE_INLINE_ void operator*=(const Vector4 &p_vec4); + _FORCE_INLINE_ void operator/=(const Vector4 &p_vec4); + _FORCE_INLINE_ void operator*=(const real_t &s); + _FORCE_INLINE_ void operator/=(const real_t &s); + _FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const; + _FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const; + _FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const; + _FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const; + _FORCE_INLINE_ Vector4 operator-() const; + _FORCE_INLINE_ Vector4 operator*(const real_t &s) const; + _FORCE_INLINE_ Vector4 operator/(const real_t &s) const; + + _FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const; + _FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const; + _FORCE_INLINE_ bool operator>(const Vector4 &p_vec4) const; + _FORCE_INLINE_ bool operator<(const Vector4 &p_vec4) const; + _FORCE_INLINE_ bool operator>=(const Vector4 &p_vec4) const; + _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const; + + operator String() const; + + _FORCE_INLINE_ Vector4() {} + + _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : + x(p_x), + y(p_y), + z(p_z), + w(p_w) { + } + + Vector4(const Vector4 &p_vec4) : + x(p_vec4.x), + y(p_vec4.y), + z(p_vec4.z), + w(p_vec4.w) { + } + + void operator=(const Vector4 &p_vec4) { + x = p_vec4.x; + y = p_vec4.y; + z = p_vec4.z; + w = p_vec4.w; + } +}; + +void Vector4::set_all(const real_t p_value) { + x = y = z = p_value; +} + +real_t Vector4::dot(const Vector4 &p_vec4) const { + return x * p_vec4.x + y * p_vec4.y + z * p_vec4.z + w * p_vec4.w; +} + +real_t Vector4::length_squared() const { + return dot(*this); +} + +void Vector4::operator+=(const Vector4 &p_vec4) { + x += p_vec4.x; + y += p_vec4.y; + z += p_vec4.z; + w += p_vec4.w; +} + +void Vector4::operator-=(const Vector4 &p_vec4) { + x -= p_vec4.x; + y -= p_vec4.y; + z -= p_vec4.z; + w -= p_vec4.w; +} + +void Vector4::operator*=(const Vector4 &p_vec4) { + x *= p_vec4.x; + y *= p_vec4.y; + z *= p_vec4.z; + w *= p_vec4.w; +} + +void Vector4::operator/=(const Vector4 &p_vec4) { + x /= p_vec4.x; + y /= p_vec4.y; + z /= p_vec4.z; + w /= p_vec4.w; +} +void Vector4::operator*=(const real_t &s) { + x *= s; + y *= s; + z *= s; + w *= s; +} + +void Vector4::operator/=(const real_t &s) { + *this *= 1.0f / s; +} + +Vector4 Vector4::operator+(const Vector4 &p_vec4) const { + return Vector4(x + p_vec4.x, y + p_vec4.y, z + p_vec4.z, w + p_vec4.w); +} + +Vector4 Vector4::operator-(const Vector4 &p_vec4) const { + return Vector4(x - p_vec4.x, y - p_vec4.y, z - p_vec4.z, w - p_vec4.w); +} + +Vector4 Vector4::operator*(const Vector4 &p_vec4) const { + return Vector4(x * p_vec4.x, y * p_vec4.y, z * p_vec4.z, w * p_vec4.w); +} + +Vector4 Vector4::operator/(const Vector4 &p_vec4) const { + return Vector4(x / p_vec4.x, y / p_vec4.y, z / p_vec4.z, w / p_vec4.w); +} + +Vector4 Vector4::operator-() const { + return Vector4(-x, -y, -z, -w); +} + +Vector4 Vector4::operator*(const real_t &s) const { + return Vector4(x * s, y * s, z * s, w * s); +} + +Vector4 Vector4::operator/(const real_t &s) const { + return *this * (1.0f / s); +} + +bool Vector4::operator==(const Vector4 &p_vec4) const { + return x == p_vec4.x && y == p_vec4.y && z == p_vec4.z && w == p_vec4.w; +} + +bool Vector4::operator!=(const Vector4 &p_vec4) const { + return x != p_vec4.x || y != p_vec4.y || z != p_vec4.z || w != p_vec4.w; +} + +bool Vector4::operator<(const Vector4 &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w < p_v.w; + } + return z < p_v.z; + } + return y < p_v.y; + } + return x < p_v.x; +} + +bool Vector4::operator>(const Vector4 &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w > p_v.w; + } + return z > p_v.z; + } + return y > p_v.y; + } + return x > p_v.x; +} + +bool Vector4::operator<=(const Vector4 &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w <= p_v.w; + } + return z < p_v.z; + } + return y < p_v.y; + } + return x < p_v.x; +} + +bool Vector4::operator>=(const Vector4 &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w >= p_v.w; + } + return z > p_v.z; + } + return y > p_v.y; + } + return x > p_v.x; +} + +_FORCE_INLINE_ Vector4 operator*(const float p_scalar, const Vector4 &p_vec) { + return p_vec * p_scalar; +} + +_FORCE_INLINE_ Vector4 operator*(const double p_scalar, const Vector4 &p_vec) { + return p_vec * p_scalar; +} + +_FORCE_INLINE_ Vector4 operator*(const int32_t p_scalar, const Vector4 &p_vec) { + return p_vec * p_scalar; +} + +_FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) { + return p_vec * p_scalar; +} + +#endif // VECTOR4_H diff --git a/core/templates/thread_work_pool.cpp b/core/math/vector4i.cpp index a75fd06b9b..2dc5b74202 100644 --- a/core/templates/thread_work_pool.cpp +++ b/core/math/vector4i.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* thread_work_pool.cpp */ +/* vector4i.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,54 +28,64 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "thread_work_pool.h" +#include "vector4i.h" -#include "core/os/os.h" +#include "core/math/vector4.h" +#include "core/string/ustring.h" -void ThreadWorkPool::_thread_function(void *p_user) { - ThreadData *thread = static_cast<ThreadData *>(p_user); - while (true) { - thread->start.wait(); - if (thread->exit.load()) { - break; - } - thread->work->work(); - thread->completed.post(); - } +void Vector4i::set_axis(const int p_axis, const int32_t p_value) { + ERR_FAIL_INDEX(p_axis, 4); + coord[p_axis] = p_value; } -void ThreadWorkPool::init(int p_thread_count) { - ERR_FAIL_COND(threads != nullptr); - if (p_thread_count < 0) { - p_thread_count = OS::get_singleton()->get_default_thread_pool_size(); - } - - thread_count = p_thread_count; - threads = memnew_arr(ThreadData, thread_count); +int32_t Vector4i::get_axis(const int p_axis) const { + ERR_FAIL_INDEX_V(p_axis, 4, 0); + return operator[](p_axis); +} - for (uint32_t i = 0; i < thread_count; i++) { - threads[i].exit.store(false); - threads[i].thread.start(&ThreadWorkPool::_thread_function, &threads[i]); +Vector4i::Axis Vector4i::min_axis_index() const { + uint32_t min_index = 0; + int32_t min_value = x; + for (uint32_t i = 1; i < 4; i++) { + if (operator[](i) <= min_value) { + min_index = i; + min_value = operator[](i); + } } + return Vector4i::Axis(min_index); } -void ThreadWorkPool::finish() { - if (threads == nullptr) { - return; +Vector4i::Axis Vector4i::max_axis_index() const { + uint32_t max_index = 0; + int32_t max_value = x; + for (uint32_t i = 1; i < 4; i++) { + if (operator[](i) > max_value) { + max_index = i; + max_value = operator[](i); + } } + return Vector4i::Axis(max_index); +} - for (uint32_t i = 0; i < thread_count; i++) { - threads[i].exit.store(true); - threads[i].start.post(); - } - for (uint32_t i = 0; i < thread_count; i++) { - threads[i].thread.wait_to_finish(); - } +Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const { + return Vector4i( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y), + CLAMP(z, p_min.z, p_max.z), + CLAMP(w, p_min.w, p_max.w)); +} + +Vector4i::operator String() const { + return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; +} - memdelete_arr(threads); - threads = nullptr; +Vector4i::operator Vector4() const { + return Vector4(x, y, z, w); } -ThreadWorkPool::~ThreadWorkPool() { - finish(); +Vector4i::Vector4i(const Vector4 &p_vec4) { + x = p_vec4.x; + y = p_vec4.y; + z = p_vec4.z; + w = p_vec4.w; } diff --git a/core/math/vector4i.h b/core/math/vector4i.h new file mode 100644 index 0000000000..37d905878f --- /dev/null +++ b/core/math/vector4i.h @@ -0,0 +1,338 @@ +/*************************************************************************/ +/* vector4i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 VECTOR4I_H +#define VECTOR4I_H + +#include "core/error/error_macros.h" +#include "core/math/math_funcs.h" + +class String; +struct Vector4; + +struct _NO_DISCARD_ Vector4i { + enum Axis { + AXIS_X, + AXIS_Y, + AXIS_Z, + AXIS_W, + }; + + union { + struct { + int32_t x; + int32_t y; + int32_t z; + int32_t w; + }; + + int32_t coord[4] = { 0 }; + }; + + _FORCE_INLINE_ const int32_t &operator[](const int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 4); + return coord[p_axis]; + } + + _FORCE_INLINE_ int32_t &operator[](const int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 4); + return coord[p_axis]; + } + + void set_axis(const int p_axis, const int32_t p_value); + int32_t get_axis(const int p_axis) const; + + Vector4i::Axis min_axis_index() const; + Vector4i::Axis max_axis_index() const; + + _FORCE_INLINE_ int64_t length_squared() const; + _FORCE_INLINE_ double length() const; + + _FORCE_INLINE_ void zero(); + + _FORCE_INLINE_ Vector4i abs() const; + _FORCE_INLINE_ Vector4i sign() const; + Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; + + /* Operators */ + + _FORCE_INLINE_ Vector4i &operator+=(const Vector4i &p_v); + _FORCE_INLINE_ Vector4i operator+(const Vector4i &p_v) const; + _FORCE_INLINE_ Vector4i &operator-=(const Vector4i &p_v); + _FORCE_INLINE_ Vector4i operator-(const Vector4i &p_v) const; + _FORCE_INLINE_ Vector4i &operator*=(const Vector4i &p_v); + _FORCE_INLINE_ Vector4i operator*(const Vector4i &p_v) const; + _FORCE_INLINE_ Vector4i &operator/=(const Vector4i &p_v); + _FORCE_INLINE_ Vector4i operator/(const Vector4i &p_v) const; + _FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v); + _FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const; + + _FORCE_INLINE_ Vector4i &operator*=(const int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar) const; + _FORCE_INLINE_ Vector4i &operator/=(const int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator/(const int32_t p_scalar) const; + _FORCE_INLINE_ Vector4i &operator%=(const int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator%(const int32_t p_scalar) const; + + _FORCE_INLINE_ Vector4i operator-() const; + + _FORCE_INLINE_ bool operator==(const Vector4i &p_v) const; + _FORCE_INLINE_ bool operator!=(const Vector4i &p_v) const; + _FORCE_INLINE_ bool operator<(const Vector4i &p_v) const; + _FORCE_INLINE_ bool operator<=(const Vector4i &p_v) const; + _FORCE_INLINE_ bool operator>(const Vector4i &p_v) const; + _FORCE_INLINE_ bool operator>=(const Vector4i &p_v) const; + + operator String() const; + operator Vector4() const; + + _FORCE_INLINE_ Vector4i() {} + Vector4i(const Vector4 &p_vec4); + _FORCE_INLINE_ Vector4i(const int32_t p_x, const int32_t p_y, const int32_t p_z, const int32_t p_w) { + x = p_x; + y = p_y; + z = p_z; + w = p_w; + } +}; + +int64_t Vector4i::length_squared() const { + return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z + w * (int64_t)w; +} + +double Vector4i::length() const { + return Math::sqrt((double)length_squared()); +} + +Vector4i Vector4i::abs() const { + return Vector4i(ABS(x), ABS(y), ABS(z), ABS(w)); +} + +Vector4i Vector4i::sign() const { + return Vector4i(SIGN(x), SIGN(y), SIGN(z), SIGN(w)); +} + +/* Operators */ + +Vector4i &Vector4i::operator+=(const Vector4i &p_v) { + x += p_v.x; + y += p_v.y; + z += p_v.z; + w += p_v.w; + return *this; +} + +Vector4i Vector4i::operator+(const Vector4i &p_v) const { + return Vector4i(x + p_v.x, y + p_v.y, z + p_v.z, w + p_v.w); +} + +Vector4i &Vector4i::operator-=(const Vector4i &p_v) { + x -= p_v.x; + y -= p_v.y; + z -= p_v.z; + w -= p_v.w; + return *this; +} + +Vector4i Vector4i::operator-(const Vector4i &p_v) const { + return Vector4i(x - p_v.x, y - p_v.y, z - p_v.z, w - p_v.w); +} + +Vector4i &Vector4i::operator*=(const Vector4i &p_v) { + x *= p_v.x; + y *= p_v.y; + z *= p_v.z; + w *= p_v.w; + return *this; +} + +Vector4i Vector4i::operator*(const Vector4i &p_v) const { + return Vector4i(x * p_v.x, y * p_v.y, z * p_v.z, w * p_v.w); +} + +Vector4i &Vector4i::operator/=(const Vector4i &p_v) { + x /= p_v.x; + y /= p_v.y; + z /= p_v.z; + w /= p_v.w; + return *this; +} + +Vector4i Vector4i::operator/(const Vector4i &p_v) const { + return Vector4i(x / p_v.x, y / p_v.y, z / p_v.z, w / p_v.w); +} + +Vector4i &Vector4i::operator%=(const Vector4i &p_v) { + x %= p_v.x; + y %= p_v.y; + z %= p_v.z; + w %= p_v.w; + return *this; +} + +Vector4i Vector4i::operator%(const Vector4i &p_v) const { + return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w); +} + +Vector4i &Vector4i::operator*=(const int32_t p_scalar) { + x *= p_scalar; + y *= p_scalar; + z *= p_scalar; + w *= p_scalar; + return *this; +} + +Vector4i Vector4i::operator*(const int32_t p_scalar) const { + return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar); +} + +// Multiplication operators required to workaround issues with LLVM using implicit conversion. + +_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar, const Vector4i &p_vector) { + return p_vector * p_scalar; +} + +_FORCE_INLINE_ Vector4i operator*(const int64_t p_scalar, const Vector4i &p_vector) { + return p_vector * p_scalar; +} + +_FORCE_INLINE_ Vector4i operator*(const float p_scalar, const Vector4i &p_vector) { + return p_vector * p_scalar; +} + +_FORCE_INLINE_ Vector4i operator*(const double p_scalar, const Vector4i &p_vector) { + return p_vector * p_scalar; +} + +Vector4i &Vector4i::operator/=(const int32_t p_scalar) { + x /= p_scalar; + y /= p_scalar; + z /= p_scalar; + w /= p_scalar; + return *this; +} + +Vector4i Vector4i::operator/(const int32_t p_scalar) const { + return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar); +} + +Vector4i &Vector4i::operator%=(const int32_t p_scalar) { + x %= p_scalar; + y %= p_scalar; + z %= p_scalar; + w %= p_scalar; + return *this; +} + +Vector4i Vector4i::operator%(const int32_t p_scalar) const { + return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar); +} + +Vector4i Vector4i::operator-() const { + return Vector4i(-x, -y, -z, -w); +} + +bool Vector4i::operator==(const Vector4i &p_v) const { + return (x == p_v.x && y == p_v.y && z == p_v.z && w == p_v.w); +} + +bool Vector4i::operator!=(const Vector4i &p_v) const { + return (x != p_v.x || y != p_v.y || z != p_v.z || w != p_v.w); +} + +bool Vector4i::operator<(const Vector4i &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w < p_v.w; + } else { + return z < p_v.z; + } + } else { + return y < p_v.y; + } + } else { + return x < p_v.x; + } +} + +bool Vector4i::operator>(const Vector4i &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w > p_v.w; + } else { + return z > p_v.z; + } + } else { + return y > p_v.y; + } + } else { + return x > p_v.x; + } +} + +bool Vector4i::operator<=(const Vector4i &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w <= p_v.w; + } else { + return z < p_v.z; + } + } else { + return y < p_v.y; + } + } else { + return x < p_v.x; + } +} + +bool Vector4i::operator>=(const Vector4i &p_v) const { + if (x == p_v.x) { + if (y == p_v.y) { + if (z == p_v.z) { + return w >= p_v.w; + } else { + return z > p_v.z; + } + } else { + return y > p_v.y; + } + } else { + return x > p_v.x; + } +} + +void Vector4i::zero() { + x = y = z = w = 0; +} + +#endif // VECTOR4I_H diff --git a/core/multiplayer/SCsub b/core/multiplayer/SCsub deleted file mode 100644 index 19a6549225..0000000000 --- a/core/multiplayer/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -env.add_source_files(env.core_sources, "*.cpp") diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h deleted file mode 100644 index f4c965b0f8..0000000000 --- a/core/multiplayer/multiplayer.h +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************/ -/* multiplayer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 MULTIPLAYER_H -#define MULTIPLAYER_H - -#include "core/variant/binder_common.h" - -#include "core/string/string_name.h" - -namespace Multiplayer { - -enum TransferMode { - TRANSFER_MODE_UNRELIABLE, - TRANSFER_MODE_UNRELIABLE_ORDERED, - TRANSFER_MODE_RELIABLE -}; - -enum RPCMode { - RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) - RPC_MODE_ANY_PEER, // Any peer can call this RPC - RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC -}; - -struct RPCConfig { - StringName name; - RPCMode rpc_mode = RPC_MODE_DISABLED; - bool call_local = false; - TransferMode transfer_mode = TRANSFER_MODE_RELIABLE; - int channel = 0; - - bool operator==(RPCConfig const &p_other) const { - return name == p_other.name; - } -}; - -struct SortRPCConfig { - StringName::AlphCompare compare; - bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const { - return compare(p_a.name, p_b.name); - } -}; - -}; // namespace Multiplayer - -// This is needed for proper docs generation (i.e. not "Multiplayer."-prefixed). -typedef Multiplayer::RPCMode RPCMode; -typedef Multiplayer::TransferMode TransferMode; - -VARIANT_ENUM_CAST(RPCMode); -VARIANT_ENUM_CAST(TransferMode); - -#endif // MULTIPLAYER_H diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp deleted file mode 100644 index 9605647b3f..0000000000 --- a/core/multiplayer/multiplayer_api.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/*************************************************************************/ -/* multiplayer_api.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 "multiplayer_api.h" - -#include "core/debugger/engine_debugger.h" -#include "core/io/marshalls.h" - -#include <stdint.h> - -#ifdef DEBUG_ENABLED -#include "core/os/os.h" -#endif - -MultiplayerReplicationInterface *(*MultiplayerAPI::create_default_replication_interface)(MultiplayerAPI *p_multiplayer) = nullptr; -MultiplayerRPCInterface *(*MultiplayerAPI::create_default_rpc_interface)(MultiplayerAPI *p_multiplayer) = nullptr; -MultiplayerCacheInterface *(*MultiplayerAPI::create_default_cache_interface)(MultiplayerAPI *p_multiplayer) = nullptr; - -#ifdef DEBUG_ENABLED -void MultiplayerAPI::profile_bandwidth(const String &p_inout, int p_size) { - if (EngineDebugger::is_profiling("multiplayer")) { - Array values; - values.push_back(p_inout); - values.push_back(OS::get_singleton()->get_ticks_msec()); - values.push_back(p_size); - EngineDebugger::profiler_add_frame_data("multiplayer", values); - } -} -#endif - -void MultiplayerAPI::poll() { - if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) { - return; - } - - multiplayer_peer->poll(); - - if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here. - return; - } - - while (multiplayer_peer->get_available_packet_count()) { - int sender = multiplayer_peer->get_packet_peer(); - const uint8_t *packet; - int len; - - Error err = multiplayer_peer->get_packet(&packet, len); - if (err != OK) { - ERR_PRINT("Error getting packet!"); - return; // Something is wrong! - } - - remote_sender_id = sender; - _process_packet(sender, packet, len); - remote_sender_id = 0; - - if (!multiplayer_peer.is_valid()) { - return; // It's also possible that a packet or RPC caused a disconnection, so also check here. - } - } - replicator->on_network_process(); -} - -void MultiplayerAPI::clear() { - connected_peers.clear(); - packet_cache.clear(); - cache->clear(); -} - -void MultiplayerAPI::set_root_path(const NodePath &p_path) { - ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "MultiplayerAPI root path must be absolute."); - root_path = p_path; -} - -NodePath MultiplayerAPI::get_root_path() const { - return root_path; -} - -void MultiplayerAPI::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) { - if (p_peer == multiplayer_peer) { - return; // Nothing to do - } - - ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED, - "Supplied MultiplayerPeer must be connecting or connected."); - - if (multiplayer_peer.is_valid()) { - multiplayer_peer->disconnect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer)); - multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer)); - multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server)); - multiplayer_peer->disconnect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed)); - multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected)); - clear(); - } - - multiplayer_peer = p_peer; - - if (multiplayer_peer.is_valid()) { - multiplayer_peer->connect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer)); - multiplayer_peer->connect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer)); - multiplayer_peer->connect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server)); - multiplayer_peer->connect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed)); - multiplayer_peer->connect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected)); - } - replicator->on_reset(); -} - -Ref<MultiplayerPeer> MultiplayerAPI::get_multiplayer_peer() const { - return multiplayer_peer; -} - -void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via MultiplayerAPI.set_root_path before using it."); - ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small."); - -#ifdef DEBUG_ENABLED - profile_bandwidth("in", p_packet_len); -#endif - - // Extract the `packet_type` from the LSB three bits: - uint8_t packet_type = p_packet[0] & CMD_MASK; - - switch (packet_type) { - case NETWORK_COMMAND_SIMPLIFY_PATH: { - cache->process_simplify_path(p_from, p_packet, p_packet_len); - } break; - - case NETWORK_COMMAND_CONFIRM_PATH: { - cache->process_confirm_path(p_from, p_packet, p_packet_len); - } break; - - case NETWORK_COMMAND_REMOTE_CALL: { - rpc->process_rpc(p_from, p_packet, p_packet_len); - } break; - - case NETWORK_COMMAND_RAW: { - _process_raw(p_from, p_packet, p_packet_len); - } break; - case NETWORK_COMMAND_SPAWN: { - replicator->on_spawn_receive(p_from, p_packet, p_packet_len); - } break; - case NETWORK_COMMAND_DESPAWN: { - replicator->on_despawn_receive(p_from, p_packet, p_packet_len); - } break; - case NETWORK_COMMAND_SYNC: { - replicator->on_sync_receive(p_from, p_packet, p_packet_len); - } break; - } -} - -// The variant is compressed and encoded; The first byte contains all the meta -// information and the format is: -// - The first LSB 5 bits are used for the variant type. -// - The next two bits are used to store the encoding mode. -// - The most significant is used to store the boolean value. -#define VARIANT_META_TYPE_MASK 0x1F -#define VARIANT_META_EMODE_MASK 0x60 -#define VARIANT_META_BOOL_MASK 0x80 -#define ENCODE_8 0 << 5 -#define ENCODE_16 1 << 5 -#define ENCODE_32 2 << 5 -#define ENCODE_64 3 << 5 -Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) { - // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 - CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); - - uint8_t *buf = r_buffer; - r_len = 0; - uint8_t encode_mode = 0; - - switch (p_variant.get_type()) { - case Variant::BOOL: { - if (buf) { - // We still have 1 free bit in the meta, so let's use it. - buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0; - buf[0] |= encode_mode | p_variant.get_type(); - } - r_len += 1; - } break; - case Variant::INT: { - if (buf) { - // Reserve the first byte for the meta. - buf += 1; - } - r_len += 1; - int64_t val = p_variant; - if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) { - // Use 8 bit - encode_mode = ENCODE_8; - if (buf) { - buf[0] = val; - } - r_len += 1; - } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) { - // Use 16 bit - encode_mode = ENCODE_16; - if (buf) { - encode_uint16(val, buf); - } - r_len += 2; - } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) { - // Use 32 bit - encode_mode = ENCODE_32; - if (buf) { - encode_uint32(val, buf); - } - r_len += 4; - } else { - // Use 64 bit - encode_mode = ENCODE_64; - if (buf) { - encode_uint64(val, buf); - } - r_len += 8; - } - // Store the meta - if (buf) { - buf -= 1; - buf[0] = encode_mode | p_variant.get_type(); - } - } break; - default: - // Any other case is not yet compressed. - Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding); - if (err != OK) { - return err; - } - if (r_buffer) { - // The first byte is not used by the marshalling, so store the type - // so we know how to decompress and decode this variant. - r_buffer[0] = p_variant.get_type(); - } - } - - return OK; -} - -Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) { - const uint8_t *buf = p_buffer; - int len = p_len; - - ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); - uint8_t type = buf[0] & VARIANT_META_TYPE_MASK; - uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK; - - ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA); - - switch (type) { - case Variant::BOOL: { - bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0; - r_variant = val; - if (r_len) { - *r_len = 1; - } - } break; - case Variant::INT: { - buf += 1; - len -= 1; - if (r_len) { - *r_len = 1; - } - if (encode_mode == ENCODE_8) { - // 8 bits. - ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); - int8_t val = buf[0]; - r_variant = val; - if (r_len) { - (*r_len) += 1; - } - } else if (encode_mode == ENCODE_16) { - // 16 bits. - ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA); - int16_t val = decode_uint16(buf); - r_variant = val; - if (r_len) { - (*r_len) += 2; - } - } else if (encode_mode == ENCODE_32) { - // 32 bits. - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); - int32_t val = decode_uint32(buf); - r_variant = val; - if (r_len) { - (*r_len) += 4; - } - } else { - // 64 bits. - ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); - int64_t val = decode_uint64(buf); - r_variant = val; - if (r_len) { - (*r_len) += 8; - } - } - } break; - default: - Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding); - if (err != OK) { - return err; - } - } - - return OK; -} - -Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) { - r_len = 0; - int size = 0; - - if (p_count == 0) { - if (r_raw) { - *r_raw = true; - } - return OK; - } - - // Try raw encoding optimization. - if (r_raw && p_count == 1) { - *r_raw = false; - const Variant &v = *(p_variants[0]); - if (v.get_type() == Variant::PACKED_BYTE_ARRAY) { - *r_raw = true; - const PackedByteArray pba = v; - if (p_buffer) { - memcpy(p_buffer, pba.ptr(), pba.size()); - } - r_len += pba.size(); - } else { - encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding); - r_len += size; - } - return OK; - } - - // Regular encoding. - for (int i = 0; i < p_count; i++) { - const Variant &v = *(p_variants[i]); - encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding); - r_len += size; - } - return OK; -} - -Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) { - r_len = 0; - int argc = r_variants.size(); - if (argc == 0 && p_raw) { - return OK; - } - ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA); - if (p_raw) { - r_len = p_len; - PackedByteArray pba; - pba.resize(p_len); - memcpy(pba.ptrw(), p_buffer, p_len); - r_variants.write[0] = pba; - return OK; - } - - Vector<Variant> args; - Vector<const Variant *> argp; - args.resize(argc); - - for (int i = 0; i < argc; i++) { - ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small."); - - int vlen; - Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding); - ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable."); - r_len += vlen; - } - return OK; -} - -void MultiplayerAPI::_add_peer(int p_id) { - connected_peers.insert(p_id); - cache->on_peer_change(p_id, true); - replicator->on_peer_change(p_id, true); - emit_signal(SNAME("peer_connected"), p_id); -} - -void MultiplayerAPI::_del_peer(int p_id) { - replicator->on_peer_change(p_id, false); - cache->on_peer_change(p_id, false); - connected_peers.erase(p_id); - emit_signal(SNAME("peer_disconnected"), p_id); -} - -void MultiplayerAPI::_connected_to_server() { - emit_signal(SNAME("connected_to_server")); -} - -void MultiplayerAPI::_connection_failed() { - emit_signal(SNAME("connection_failed")); -} - -void MultiplayerAPI::_server_disconnected() { - replicator->on_reset(); - emit_signal(SNAME("server_disconnected")); -} - -Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, Multiplayer::TransferMode p_mode, int p_channel) { - ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet."); - ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active."); - ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected."); - - if (packet_cache.size() < p_data.size() + 1) { - packet_cache.resize(p_data.size() + 1); - } - - const uint8_t *r = p_data.ptr(); - packet_cache.write[0] = NETWORK_COMMAND_RAW; - memcpy(&packet_cache.write[1], &r[0], p_data.size()); - - multiplayer_peer->set_target_peer(p_to); - multiplayer_peer->set_transfer_channel(p_channel); - multiplayer_peer->set_transfer_mode(p_mode); - - return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1); -} - -void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); - - Vector<uint8_t> out; - int len = p_packet_len - 1; - out.resize(len); - { - uint8_t *w = out.ptrw(); - memcpy(&w[0], &p_packet[1], len); - } - emit_signal(SNAME("peer_packet"), p_from, out); -} - -bool MultiplayerAPI::is_cache_confirmed(NodePath p_path, int p_peer) { - return cache->is_cache_confirmed(p_path, p_peer); -} - -bool MultiplayerAPI::send_object_cache(Object *p_obj, NodePath p_path, int p_peer_id, int &r_id) { - return cache->send_object_cache(p_obj, p_path, p_peer_id, r_id); -} - -Object *MultiplayerAPI::get_cached_object(int p_from, uint32_t p_cache_id) { - return cache->get_cached_object(p_from, p_cache_id); -} - -int MultiplayerAPI::get_unique_id() const { - ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID."); - return multiplayer_peer->get_unique_id(); -} - -bool MultiplayerAPI::is_server() const { - return multiplayer_peer.is_valid() && multiplayer_peer->is_server(); -} - -void MultiplayerAPI::set_refuse_new_connections(bool p_refuse) { - ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'."); - multiplayer_peer->set_refuse_new_connections(p_refuse); -} - -bool MultiplayerAPI::is_refusing_new_connections() const { - ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'."); - return multiplayer_peer->is_refusing_new_connections(); -} - -Vector<int> MultiplayerAPI::get_peer_ids() const { - ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected."); - - Vector<int> ret; - for (const int &E : connected_peers) { - ret.push_back(E); - } - - return ret; -} - -void MultiplayerAPI::set_allow_object_decoding(bool p_enable) { - allow_object_decoding = p_enable; -} - -bool MultiplayerAPI::is_object_decoding_allowed() const { - return allow_object_decoding; -} - -String MultiplayerAPI::get_rpc_md5(const Object *p_obj) const { - return rpc->get_rpc_md5(p_obj); -} - -void MultiplayerAPI::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { - rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount); -} - -Error MultiplayerAPI::spawn(Object *p_object, Variant p_config) { - return replicator->on_spawn(p_object, p_config); -} - -Error MultiplayerAPI::despawn(Object *p_object, Variant p_config) { - return replicator->on_despawn(p_object, p_config); -} - -Error MultiplayerAPI::replication_start(Object *p_object, Variant p_config) { - return replicator->on_replication_start(p_object, p_config); -} - -Error MultiplayerAPI::replication_stop(Object *p_object, Variant p_config) { - return replicator->on_replication_stop(p_object, p_config); -} - -void MultiplayerAPI::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerAPI::set_root_path); - ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerAPI::get_root_path); - ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &MultiplayerAPI::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer); - ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer); - ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer); - ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id); - ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server); - ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id); - ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll); - ClassDB::bind_method(D_METHOD("clear"), &MultiplayerAPI::clear); - - ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids); - ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &MultiplayerAPI::set_refuse_new_connections); - ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerAPI::is_refusing_new_connections); - ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding); - ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path"); - ADD_PROPERTY_DEFAULT("refuse_new_connections", false); - - ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id"))); - ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id"))); - ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet"))); - ADD_SIGNAL(MethodInfo("connected_to_server")); - ADD_SIGNAL(MethodInfo("connection_failed")); - ADD_SIGNAL(MethodInfo("server_disconnected")); -} - -MultiplayerAPI::MultiplayerAPI() { - if (create_default_replication_interface) { - replicator = Ref<MultiplayerReplicationInterface>(create_default_replication_interface(this)); - } else { - replicator.instantiate(); - } - if (create_default_rpc_interface) { - rpc = Ref<MultiplayerRPCInterface>(create_default_rpc_interface(this)); - } else { - rpc.instantiate(); - } - if (create_default_cache_interface) { - cache = Ref<MultiplayerCacheInterface>(create_default_cache_interface(this)); - } else { - cache.instantiate(); - } -} - -MultiplayerAPI::~MultiplayerAPI() { - clear(); -} diff --git a/core/multiplayer/multiplayer_api.h b/core/multiplayer/multiplayer_api.h deleted file mode 100644 index cc7743ccf8..0000000000 --- a/core/multiplayer/multiplayer_api.h +++ /dev/null @@ -1,194 +0,0 @@ -/*************************************************************************/ -/* multiplayer_api.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 MULTIPLAYER_API_H -#define MULTIPLAYER_API_H - -#include "core/multiplayer/multiplayer.h" -#include "core/multiplayer/multiplayer_peer.h" -#include "core/object/ref_counted.h" - -class MultiplayerAPI; - -class MultiplayerReplicationInterface : public RefCounted { - GDCLASS(MultiplayerReplicationInterface, RefCounted); - -public: - virtual void on_peer_change(int p_id, bool p_connected) {} - virtual void on_reset() {} - virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; } - virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; } - virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; } - virtual Error on_spawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; } - virtual Error on_despawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; } - virtual Error on_replication_start(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; } - virtual Error on_replication_stop(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; } - virtual void on_network_process() {} - - MultiplayerReplicationInterface() {} -}; - -class MultiplayerRPCInterface : public RefCounted { - GDCLASS(MultiplayerRPCInterface, RefCounted); - -public: - // Called by Node.rpc - virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {} - virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) {} - virtual String get_rpc_md5(const Object *p_obj) const { return String(); } - - MultiplayerRPCInterface() {} -}; - -class MultiplayerCacheInterface : public RefCounted { - GDCLASS(MultiplayerCacheInterface, RefCounted); - -public: - virtual void clear() {} - virtual void on_peer_change(int p_id, bool p_connected) {} - virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {} - virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {} - - // Returns true if all peers have cached path. - virtual bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id) { return false; } - virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) { return nullptr; } - virtual bool is_cache_confirmed(NodePath p_path, int p_peer) { return false; } - - MultiplayerCacheInterface() {} -}; - -class MultiplayerAPI : public RefCounted { - GDCLASS(MultiplayerAPI, RefCounted); - -public: - enum NetworkCommands { - NETWORK_COMMAND_REMOTE_CALL = 0, - NETWORK_COMMAND_SIMPLIFY_PATH, - NETWORK_COMMAND_CONFIRM_PATH, - NETWORK_COMMAND_RAW, - NETWORK_COMMAND_SPAWN, - NETWORK_COMMAND_DESPAWN, - NETWORK_COMMAND_SYNC, - }; - - // For each command, the 4 MSB can contain custom flags, as defined by subsystems. - enum { - CMD_FLAG_0_SHIFT = 4, - CMD_FLAG_1_SHIFT = 5, - CMD_FLAG_2_SHIFT = 6, - CMD_FLAG_3_SHIFT = 7, - }; - - // This is the mask that will be used to extract the command. - enum { - CMD_MASK = 7, // 0x7 -> 0b00001111 - }; - -private: - Ref<MultiplayerPeer> multiplayer_peer; - HashSet<int> connected_peers; - int remote_sender_id = 0; - int remote_sender_override = 0; - - Vector<uint8_t> packet_cache; - - NodePath root_path; - bool allow_object_decoding = false; - - Ref<MultiplayerCacheInterface> cache; - Ref<MultiplayerReplicationInterface> replicator; - Ref<MultiplayerRPCInterface> rpc; - -protected: - static void _bind_methods(); - - void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len); - void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len); - -public: - static MultiplayerReplicationInterface *(*create_default_replication_interface)(MultiplayerAPI *p_multiplayer); - static MultiplayerRPCInterface *(*create_default_rpc_interface)(MultiplayerAPI *p_multiplayer); - static MultiplayerCacheInterface *(*create_default_cache_interface)(MultiplayerAPI *p_multiplayer); - - static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding); - static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding); - static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false); - static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false); - - void poll(); - void clear(); - void set_root_path(const NodePath &p_path); - NodePath get_root_path() const; - void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer); - Ref<MultiplayerPeer> get_multiplayer_peer() const; - - Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, Multiplayer::TransferMode p_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); - - // RPC API - void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); - String get_rpc_md5(const Object *p_obj) const; - // Replication API - Error spawn(Object *p_object, Variant p_config); - Error despawn(Object *p_object, Variant p_config); - Error replication_start(Object *p_object, Variant p_config); - Error replication_stop(Object *p_object, Variant p_config); - // Cache API - bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id); - Object *get_cached_object(int p_from, uint32_t p_cache_id); - bool is_cache_confirmed(NodePath p_path, int p_peer); - - void _add_peer(int p_id); - void _del_peer(int p_id); - void _connected_to_server(); - void _connection_failed(); - void _server_disconnected(); - - bool has_multiplayer_peer() const { return multiplayer_peer.is_valid(); } - Vector<int> get_peer_ids() const; - const HashSet<int> get_connected_peers() const { return connected_peers; } - int get_remote_sender_id() const { return remote_sender_override ? remote_sender_override : remote_sender_id; } - void set_remote_sender_override(int p_id) { remote_sender_override = p_id; } - int get_unique_id() const; - bool is_server() const; - void set_refuse_new_connections(bool p_refuse); - bool is_refusing_new_connections() const; - - void set_allow_object_decoding(bool p_enable); - bool is_object_decoding_allowed() const; - -#ifdef DEBUG_ENABLED - void profile_bandwidth(const String &p_inout, int p_size); -#endif - - MultiplayerAPI(); - ~MultiplayerAPI(); -}; - -#endif // MULTIPLAYER_API_H diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ac008dad88..9790cc44e3 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -305,6 +305,13 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam compat_classes[p_class] = p_fallback; } +StringName ClassDB::get_compatibility_class(const StringName &p_class) { + if (compat_classes.has(p_class)) { + return compat_classes[p_class]; + } + return StringName(); +} + Object *ClassDB::instantiate(const StringName &p_class) { ClassInfo *ti; { @@ -956,8 +963,11 @@ void ClassDB::add_linked_property(const StringName &p_class, const String &p_pro ERR_FAIL_COND(!type->property_map.has(p_property)); ERR_FAIL_COND(!type->property_map.has(p_linked_property)); - PropertyInfo &pinfo = type->property_map[p_property]; - pinfo.linked_properties.push_back(p_linked_property); + if (!type->linked_properties.has(p_property)) { + type->linked_properties.insert(p_property, List<StringName>()); + } + type->linked_properties[p_property].push_back(p_linked_property); + #endif } @@ -985,6 +995,25 @@ void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p } } +void ClassDB::get_linked_properties_info(const StringName &p_class, const StringName &p_property, List<StringName> *r_properties, bool p_no_inheritance) { +#ifdef TOOLS_ENABLED + ClassInfo *check = classes.getptr(p_class); + while (check) { + if (!check->linked_properties.has(p_property)) { + return; + } + for (const StringName &E : check->linked_properties[p_property]) { + r_properties->push_back(E); + } + + if (p_no_inheritance) { + break; + } + check = check->inherits_ptr; + } +#endif +} + bool ClassDB::get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) { OBJTYPE_RLOCK; diff --git a/core/object/class_db.h b/core/object/class_db.h index 1d26eb18f1..5fba52e23e 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -120,6 +120,7 @@ public: List<MethodInfo> virtual_methods; HashMap<StringName, MethodInfo> virtual_methods_map; HashMap<StringName, Vector<Error>> method_error_values; + HashMap<StringName, List<StringName>> linked_properties; #endif HashMap<StringName, PropertySetGet> property_setget; @@ -312,6 +313,7 @@ public: static void add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property); static void get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr); static bool get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr); + static void get_linked_properties_info(const StringName &p_class, const StringName &p_property, List<StringName> *r_properties, bool p_no_inheritance = false); static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr); static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value); static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false); @@ -357,6 +359,7 @@ public: static bool is_resource_extension(const StringName &p_extension); static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback); + static StringName get_compatibility_class(const StringName &p_class); static void set_current_api(APIType p_api); static APIType get_current_api(); @@ -418,16 +421,16 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) { #endif -#define GDREGISTER_CLASS(m_class) \ - if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \ - ::ClassDB::register_class<m_class>(); \ +#define GDREGISTER_CLASS(m_class) \ + if (m_class::_class_is_enabled) { \ + ::ClassDB::register_class<m_class>(); \ } -#define GDREGISTER_VIRTUAL_CLASS(m_class) \ - if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \ - ::ClassDB::register_class<m_class>(true); \ +#define GDREGISTER_VIRTUAL_CLASS(m_class) \ + if (m_class::_class_is_enabled) { \ + ::ClassDB::register_class<m_class>(true); \ } #define GDREGISTER_ABSTRACT_CLASS(m_class) \ - if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \ + if (m_class::_class_is_enabled) { \ ::ClassDB::register_abstract_class<m_class>(); \ } diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp index fa1945cf79..13dc921c9f 100644 --- a/core/object/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -226,7 +226,7 @@ void MessageQueue::_call_function(const Callable &p_callable, const Variant *p_a Callable::CallError ce; Variant ret; - p_callable.call(argptrs, p_argcount, ret, ce); + p_callable.callp(argptrs, p_argcount, ret, ce); if (p_show_error && ce.error != Callable::CallError::CALL_OK) { ERR_PRINT("Error calling deferred method: " + Variant::get_callable_error_text(p_callable, argptrs, p_argcount, ce) + "."); } diff --git a/core/object/object.cpp b/core/object/object.cpp index 5f2287c9d3..0fcd1c0e40 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -166,7 +166,6 @@ Object::Connection::operator Variant() const { d["signal"] = signal; d["callable"] = callable; d["flags"] = flags; - d["binds"] = binds; return d; } @@ -189,9 +188,6 @@ Object::Connection::Connection(const Variant &p_variant) { if (d.has("flags")) { flags = d["flags"]; } - if (d.has("binds")) { - binds = d["binds"]; - } } bool Object::_predelete() { @@ -476,7 +472,6 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const { if (script_instance && p_reversed) { - p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); } @@ -507,7 +502,6 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons } if (script_instance && !p_reversed) { - p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); } @@ -973,8 +967,6 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int OBJ_DEBUG_LOCK - Vector<const Variant *> bind_mem; - Error err = OK; for (int i = 0; i < ssize; i++) { @@ -989,28 +981,13 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int const Variant **args = p_args; int argc = p_argcount; - if (c.binds.size()) { - //handle binds - bind_mem.resize(p_argcount + c.binds.size()); - - for (int j = 0; j < p_argcount; j++) { - bind_mem.write[j] = p_args[j]; - } - for (int j = 0; j < c.binds.size(); j++) { - bind_mem.write[p_argcount + j] = &c.binds[j]; - } - - args = (const Variant **)bind_mem.ptr(); - argc = bind_mem.size(); - } - if (c.flags & CONNECT_DEFERRED) { MessageQueue::get_singleton()->push_callablep(c.callable, args, argc, true); } else { Callable::CallError ce; _emitting = true; Variant ret; - c.callable.call(args, argc, ret, ce); + c.callable.callp(args, argc, ret, ce); _emitting = false; if (ce.error != Callable::CallError::CALL_OK) { @@ -1196,7 +1173,7 @@ void Object::get_signals_connected_to_this(List<Connection> *p_connections) cons } } -Error Object::connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { +Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) { ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is null."); Object *target_object = p_callable.get_object(); @@ -1244,7 +1221,6 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, co conn.callable = target; conn.signal = ::Signal(this, p_signal); conn.flags = p_flags; - conn.binds = p_binds; slot.conn = conn; slot.cE = target_object->connections.push_back(conn); if (p_flags & CONNECT_REFERENCE_COUNTED) { @@ -1492,7 +1468,7 @@ void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list); ClassDB::bind_method(D_METHOD("get_incoming_connections"), &Object::_get_incoming_connections); - ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "binds", "flags"), &Object::connect, DEFVAL(Array()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0)); ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect); ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected); diff --git a/core/object/object.h b/core/object/object.h index 87d042dd7e..35d0aaaa7d 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -50,10 +50,8 @@ enum PropertyHint { PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,no_slider][,radians][,degrees][,exp][,suffix:<keyword>] range. PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc" - PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout") - PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "positive_only" to exclude in-out and out-in. (ie: "attenuation,positive_only") PROPERTY_HINT_LINK, - PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, PROPERTY_HINT_LAYERS_2D_PHYSICS, @@ -99,41 +97,39 @@ enum PropertyHint { enum PropertyUsageFlags { PROPERTY_USAGE_NONE = 0, - PROPERTY_USAGE_STORAGE = 1, - PROPERTY_USAGE_EDITOR = 2, - PROPERTY_USAGE_NETWORK = 4, - PROPERTY_USAGE_EDITOR_HELPER = 8, - PROPERTY_USAGE_CHECKABLE = 16, //used for editing global variables - PROPERTY_USAGE_CHECKED = 32, //used for editing global variables - PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings - PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor - PROPERTY_USAGE_CATEGORY = 256, - PROPERTY_USAGE_SUBGROUP = 512, - PROPERTY_USAGE_CLASS_IS_BITFIELD = 1024, - PROPERTY_USAGE_NO_INSTANCE_STATE = 2048, - PROPERTY_USAGE_RESTART_IF_CHANGED = 4096, - PROPERTY_USAGE_SCRIPT_VARIABLE = 8192, - PROPERTY_USAGE_STORE_IF_NULL = 16384, - PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768, - PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 65536, - PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 17, - PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 18, - PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19, - PROPERTY_USAGE_INTERNAL = 1 << 20, - PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated - PROPERTY_USAGE_HIGH_END_GFX = 1 << 22, - PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 23, - PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24, - PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 25, // Used in inspector to increment property when keyed in animation player - PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 26, // when loading, the resource for this property can be set at the end of loading - PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 27, // For Object properties, instantiate them when creating in editor. - PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 28, //for project or editor settings, show when basic settings are selected - PROPERTY_USAGE_READ_ONLY = 1 << 29, // Mark a property as read-only in the inspector. - PROPERTY_USAGE_ARRAY = 1 << 30, // Used in the inspector to group properties as elements of an array. - - PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, - PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, - PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK, + PROPERTY_USAGE_STORAGE = 1 << 1, + PROPERTY_USAGE_EDITOR = 1 << 2, + PROPERTY_USAGE_CHECKABLE = 1 << 3, // Used for editing global variables. + PROPERTY_USAGE_CHECKED = 1 << 4, // Used for editing global variables. + PROPERTY_USAGE_INTERNATIONALIZED = 1 << 5, // Hint for internationalized strings. + PROPERTY_USAGE_GROUP = 1 << 6, // Used for grouping props in the editor. + PROPERTY_USAGE_CATEGORY = 1 << 7, + PROPERTY_USAGE_SUBGROUP = 1 << 8, + PROPERTY_USAGE_CLASS_IS_BITFIELD = 1 << 9, + PROPERTY_USAGE_NO_INSTANCE_STATE = 1 << 10, + PROPERTY_USAGE_RESTART_IF_CHANGED = 1 << 11, + PROPERTY_USAGE_SCRIPT_VARIABLE = 1 << 12, + PROPERTY_USAGE_STORE_IF_NULL = 1 << 13, + PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 1 << 14, + PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 << 15, + PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 16, + PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 17, + PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 18, + PROPERTY_USAGE_INTERNAL = 1 << 19, + PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 20, // If the object is duplicated also this property will be duplicated. + PROPERTY_USAGE_HIGH_END_GFX = 1 << 21, + PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 22, + PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 23, + PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 24, // Used in inspector to increment property when keyed in animation player. + PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // when loading, the resource for this property can be set at the end of loading. + PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor. + PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected. + PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector. + PROPERTY_USAGE_ARRAY = 1 << 29, // Used in the inspector to group properties as elements of an array. + + PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR, + PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNATIONALIZED, + PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE, }; #define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal) @@ -158,9 +154,7 @@ struct PropertyInfo { String hint_string; uint32_t usage = PROPERTY_USAGE_DEFAULT; -#ifdef TOOLS_ENABLED - Vector<String> linked_properties; -#endif + // If you are thinking about adding another member to this class, ask the maintainer (Juan) first. _FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const { PropertyInfo pi = *this; @@ -218,14 +212,11 @@ Array convert_property_list(const List<PropertyInfo> *p_list); enum MethodFlags { METHOD_FLAG_NORMAL = 1, METHOD_FLAG_EDITOR = 2, - METHOD_FLAG_NOSCRIPT = 4, - METHOD_FLAG_CONST = 8, - METHOD_FLAG_REVERSE = 16, // used for events - METHOD_FLAG_VIRTUAL = 32, - METHOD_FLAG_FROM_SCRIPT = 64, - METHOD_FLAG_VARARG = 128, - METHOD_FLAG_STATIC = 256, - METHOD_FLAG_OBJECT_CORE = 512, + METHOD_FLAG_CONST = 4, + METHOD_FLAG_VIRTUAL = 8, + METHOD_FLAG_VARARG = 16, + METHOD_FLAG_STATIC = 32, + METHOD_FLAG_OBJECT_CORE = 64, METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL, }; @@ -365,6 +356,7 @@ private: friend class ::ClassDB; \ \ public: \ + static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \ virtual String get_class() const override { \ if (_get_extension()) { \ return _get_extension()->class_name.operator String(); \ @@ -516,7 +508,6 @@ public: Callable callable; uint32_t flags = 0; - Vector<Variant> binds; bool operator<(const Connection &p_conn) const; operator Variant() const; @@ -674,6 +665,8 @@ public: // Should be protected, but bug in clang++. _FORCE_INLINE_ static void register_custom_data_to_otdb() {} public: + static constexpr bool _class_is_enabled = true; + void notify_property_list_changed(); static void *get_class_ptr_static() { @@ -833,7 +826,7 @@ public: int get_persistent_signal_connection_count() const; void get_signals_connected_to_this(List<Connection> *p_connections) const; - Error connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0); + Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0); void disconnect(const StringName &p_signal, const Callable &p_callable); bool is_connected(const StringName &p_signal, const Callable &p_callable) const; diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 4623d0e525..b06c2e8896 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -101,6 +101,31 @@ Dictionary Script::_get_script_constant_map() { return ret; } +#ifdef TOOLS_ENABLED + +PropertyInfo Script::get_class_category() const { + String path = get_path(); + String name; + + if (is_built_in()) { + if (get_name().is_empty()) { + name = TTR("Built-in script"); + } else { + name = vformat("%s (%s)", get_name(), TTR("Built-in")); + } + } else { + if (get_name().is_empty()) { + name = path.get_file(); + } else { + name = get_name(); + } + } + + return PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY); +} + +#endif // TOOLS_ENABLED + void Script::_bind_methods() { ClassDB::bind_method(D_METHOD("can_instantiate"), &Script::can_instantiate); //ClassDB::bind_method(D_METHOD("instance_create","base_object"),&Script::instance_create); @@ -344,11 +369,14 @@ void ScriptLanguage::get_core_type_words(List<String> *p_core_type_words) const p_core_type_words->push_back("Vector3"); p_core_type_words->push_back("Vector3i"); p_core_type_words->push_back("Transform2D"); + p_core_type_words->push_back("Vector4"); + p_core_type_words->push_back("Vector4i"); p_core_type_words->push_back("Plane"); p_core_type_words->push_back("Quaternion"); p_core_type_words->push_back("AABB"); p_core_type_words->push_back("Basis"); p_core_type_words->push_back("Transform3D"); + p_core_type_words->push_back("Projection"); p_core_type_words->push_back("Color"); p_core_type_words->push_back("StringName"); p_core_type_words->push_back("NodePath"); diff --git a/core/object/script_language.h b/core/object/script_language.h index 686ab5b8d3..f5f052b600 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -33,7 +33,6 @@ #include "core/doc_data.h" #include "core/io/resource.h" -#include "core/multiplayer/multiplayer.h" #include "core/templates/pair.h" #include "core/templates/rb_map.h" @@ -133,6 +132,7 @@ public: #ifdef TOOLS_ENABLED virtual Vector<DocData::ClassDoc> get_documentation() const = 0; + virtual PropertyInfo get_class_category() const; #endif // TOOLS_ENABLED virtual bool has_method(const StringName &p_method) const = 0; @@ -159,7 +159,7 @@ public: virtual bool is_placeholder_fallback_enabled() const { return false; } - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const = 0; + virtual const Variant get_rpc_config() const = 0; Script() {} }; @@ -213,7 +213,7 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid); virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid); - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const { return get_script()->get_rpc_methods(); } + virtual const Variant get_rpc_config() const { return get_script()->get_rpc_config(); } virtual ScriptLanguage *get_language() = 0; virtual ~ScriptInstance(); @@ -469,7 +469,7 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr) override; virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr) override; - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { return Vector<Multiplayer::RPCConfig>(); } + virtual const Variant get_rpc_config() const override { return Variant(); } PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner); ~PlaceHolderScriptInstance(); diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp index ab8dd6d1ee..9de784ea7f 100644 --- a/core/object/script_language_extension.cpp +++ b/core/object/script_language_extension.cpp @@ -74,7 +74,7 @@ void ScriptExtension::_bind_methods() { GDVIRTUAL_BIND(_get_members); GDVIRTUAL_BIND(_is_placeholder_fallback_enabled); - GDVIRTUAL_BIND(_get_rpc_methods); + GDVIRTUAL_BIND(_get_rpc_config); } void ScriptLanguageExtension::_bind_methods() { diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 2c53139ec2..2869f4ad98 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -173,28 +173,12 @@ public: EXBIND0RC(bool, is_placeholder_fallback_enabled) - GDVIRTUAL0RC(TypedArray<Dictionary>, _get_rpc_methods) + GDVIRTUAL0RC(Variant, _get_rpc_config) - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { - TypedArray<Dictionary> ret; - GDVIRTUAL_REQUIRED_CALL(_get_rpc_methods, ret); - Vector<Multiplayer::RPCConfig> rpcret; - for (int i = 0; i < ret.size(); i++) { - Dictionary d = ret[i]; - Multiplayer::RPCConfig rpc; - ERR_CONTINUE(!d.has("name")); - rpc.name = d["name"]; - ERR_CONTINUE(!d.has("rpc_mode")); - rpc.rpc_mode = Multiplayer::RPCMode(int(d["rpc_mode"])); - ERR_CONTINUE(!d.has("call_local")); - rpc.call_local = d["call_local"]; - ERR_CONTINUE(!d.has("transfer_mode")); - rpc.transfer_mode = Multiplayer::TransferMode(int(d["transfer_mode"])); - ERR_CONTINUE(!d.has("channel")); - rpc.channel = d["channel"]; - rpcret.push_back(rpc); - } - return rpcret; + virtual const Variant get_rpc_config() const override { + Variant ret; + GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret); + return ret; } ScriptExtension() {} @@ -679,6 +663,14 @@ public: if (native_info->get_property_list_func) { uint32_t pcount; const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_script(); + if (script->is_valid() && pcount > 0) { + p_list->push_back(script->get_class_category()); + } +#endif // TOOLS_ENABLED + for (uint32_t i = 0; i < pcount; i++) { p_list->push_back(PropertyInfo(pinfo[i])); } diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp new file mode 100644 index 0000000000..c770515b9e --- /dev/null +++ b/core/object/worker_thread_pool.cpp @@ -0,0 +1,474 @@ +/*************************************************************************/ +/* worker_thread_pool.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "worker_thread_pool.h" + +#include "core/os/os.h" + +void WorkerThreadPool::Task::free_template_userdata() { + ERR_FAIL_COND(!template_userdata); + ERR_FAIL_COND(native_func_userdata == nullptr); + BaseTemplateUserdata *btu = (BaseTemplateUserdata *)native_func_userdata; + memdelete(btu); +} + +WorkerThreadPool *WorkerThreadPool::singleton = nullptr; + +void WorkerThreadPool::_process_task_queue() { + task_mutex.lock(); + Task *task = task_queue.first()->self(); + task_queue.remove(task_queue.first()); + task_mutex.unlock(); + _process_task(task); +} + +void WorkerThreadPool::_process_task(Task *p_task) { + bool low_priority = p_task->low_priority; + + if (p_task->group) { + // Handling a group + bool do_post = false; + Callable::CallError ce; + Variant ret; + Variant arg; + Variant *argptr = &arg; + + while (true) { + uint32_t work_index = p_task->group->index.postincrement(); + + if (work_index >= p_task->group->max) { + break; + } + if (p_task->native_group_func) { + p_task->native_group_func(p_task->native_func_userdata, work_index); + } else if (p_task->template_userdata) { + p_task->template_userdata->callback_indexed(work_index); + } else { + arg = work_index; + p_task->callable.callp((const Variant **)&argptr, 1, ret, ce); + } + + // This is the only way to ensure posting is done when all tasks are really complete. + uint32_t completed_amount = p_task->group->completed_index.increment(); + + if (completed_amount == p_task->group->max) { + do_post = true; + } + } + + if (do_post && p_task->template_userdata) { + memdelete(p_task->template_userdata); // This is no longer needed at this point, so get rid of it. + } + + if (low_priority && use_native_low_priority_threads) { + p_task->completed = true; + p_task->done_semaphore.post(); + if (do_post) { + p_task->group->completed.set_to(true); + } + } else { + if (do_post) { + p_task->group->done_semaphore.post(); + p_task->group->completed.set_to(true); + } + uint32_t max_users = p_task->group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment. + uint32_t finished_users = p_task->group->finished.increment(); + + if (finished_users == max_users) { + // Get rid of the group, because nobody else is using it. + task_mutex.lock(); + group_allocator.free(p_task->group); + task_mutex.unlock(); + } + + // For groups, tasks get rid of themselves. + + task_mutex.lock(); + task_allocator.free(p_task); + task_mutex.unlock(); + } + } else { + if (p_task->native_func) { + p_task->native_func(p_task->native_func_userdata); + } else if (p_task->template_userdata) { + p_task->template_userdata->callback(); + memdelete(p_task->template_userdata); + } else { + Callable::CallError ce; + Variant ret; + p_task->callable.callp(nullptr, 0, ret, ce); + } + + p_task->completed = true; + p_task->done_semaphore.post(); + } + + if (!use_native_low_priority_threads && low_priority) { + // A low prioriry task was freed, so see if we can move a pending one to the high priority queue. + bool post = false; + task_mutex.lock(); + if (low_priority_task_queue.first()) { + Task *low_prio_task = low_priority_task_queue.first()->self(); + low_priority_task_queue.remove(low_priority_task_queue.first()); + task_queue.add_last(&low_prio_task->task_elem); + post = true; + } else { + low_priority_threads_used.decrement(); + } + task_mutex.lock(); + if (post) { + task_available_semaphore.post(); + } + } +} + +void WorkerThreadPool::_thread_function(void *p_user) { + while (true) { + singleton->task_available_semaphore.wait(); + if (singleton->exit_threads.is_set()) { + break; + } + singleton->_process_task_queue(); + } +} + +void WorkerThreadPool::_native_low_priority_thread_function(void *p_user) { + Task *task = (Task *)p_user; + singleton->_process_task(task); +} + +void WorkerThreadPool::_post_task(Task *p_task, bool p_high_priority) { + task_mutex.lock(); + p_task->low_priority = !p_high_priority; + if (!p_high_priority && use_native_low_priority_threads) { + task_mutex.unlock(); + p_task->low_priority_thread = native_thread_allocator.alloc(); + p_task->low_priority_thread->start(_native_low_priority_thread_function, p_task); // Pask task directly to thread. + + } else if (p_high_priority || low_priority_threads_used.get() < max_low_priority_threads) { + task_queue.add_last(&p_task->task_elem); + if (!p_high_priority) { + low_priority_threads_used.increment(); + } + task_mutex.unlock(); + task_available_semaphore.post(); + } else { + // Too many threads using low priority, must go to queue. + low_priority_task_queue.add_last(&p_task->task_elem); + task_mutex.unlock(); + } +} + +WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) { + return _add_task(Callable(), p_func, p_userdata, nullptr, p_high_priority, p_description); +} + +WorkerThreadPool::TaskID WorkerThreadPool::_add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description) { + task_mutex.lock(); + // Get a free task + Task *task = task_allocator.alloc(); + TaskID id = last_task++; + task->callable = p_callable; + task->native_func = p_func; + task->native_func_userdata = p_userdata; + task->description = p_description; + task->template_userdata = p_template_userdata; + tasks.insert(id, task); + task_mutex.unlock(); + + _post_task(task, p_high_priority); + + return id; +} + +WorkerThreadPool::TaskID WorkerThreadPool::add_task(const Callable &p_action, bool p_high_priority, const String &p_description) { + return _add_task(p_action, nullptr, nullptr, nullptr, p_high_priority, p_description); +} + +bool WorkerThreadPool::is_task_completed(TaskID p_task_id) const { + task_mutex.lock(); + const Task *const *taskp = tasks.getptr(p_task_id); + if (!taskp) { + task_mutex.unlock(); + ERR_FAIL_V_MSG(false, "Invalid Task ID"); // Invalid task + } + + bool completed = (*taskp)->completed; + task_mutex.unlock(); + + return completed; +} + +void WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) { + task_mutex.lock(); + Task **taskp = tasks.getptr(p_task_id); + if (!taskp) { + task_mutex.unlock(); + ERR_FAIL_MSG("Invalid Task ID"); // Invalid task + } + Task *task = *taskp; + + if (task->waiting) { + String description = task->description; + task_mutex.unlock(); + if (description.is_empty()) { + ERR_FAIL_MSG("Another thread is waiting on this task: " + itos(p_task_id)); // Invalid task + } else { + ERR_FAIL_MSG("Another thread is waiting on this task: " + description + " (" + itos(p_task_id) + ")"); // Invalid task + } + } + + task->waiting = true; + + task_mutex.unlock(); + + if (use_native_low_priority_threads && task->low_priority) { + task->low_priority_thread->wait_to_finish(); + native_thread_allocator.free(task->low_priority_thread); + } else { + int *index = thread_ids.getptr(Thread::get_caller_id()); + + if (index) { + // We are an actual process thread, we must not be blocked so continue processing stuff if available. + while (true) { + if (task->done_semaphore.try_wait()) { + // If done, exit + break; + } + if (task_available_semaphore.try_wait()) { + // Solve tasks while they are around. + _process_task_queue(); + continue; + } + OS::get_singleton()->delay_usec(1); // Microsleep, this could be converted to waiting for multiple objects in supported platforms for a bit more performance. + } + } else { + task->done_semaphore.wait(); + } + } + + task_mutex.lock(); + tasks.erase(p_task_id); + task_allocator.free(task); + task_mutex.unlock(); +} + +WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) { + ERR_FAIL_COND_V(p_elements < 0, INVALID_TASK_ID); + if (p_tasks < 0) { + p_tasks = threads.size(); + } + + task_mutex.lock(); + Group *group = group_allocator.alloc(); + GroupID id = last_task++; + group->max = p_elements; + group->self = id; + + Task **tasks_posted = nullptr; + if (p_elements == 0) { + // Should really not call it with zero Elements, but at least it should work. + group->completed.set_to(true); + group->done_semaphore.post(); + group->tasks_used = 0; + p_tasks = 0; + if (p_template_userdata) { + memdelete(p_template_userdata); + } + + } else { + group->tasks_used = p_tasks; + tasks_posted = (Task **)alloca(sizeof(Task *) * p_tasks); + for (int i = 0; i < p_tasks; i++) { + Task *task = task_allocator.alloc(); + task->native_group_func = p_func; + task->native_func_userdata = p_userdata; + task->description = p_description; + task->group = group; + task->callable = p_callable; + task->template_userdata = p_template_userdata; + tasks_posted[i] = task; + // No task ID is used. + } + } + + groups[id] = group; + task_mutex.unlock(); + + if (!p_high_priority && use_native_low_priority_threads) { + group->low_priority_native_tasks.resize(p_tasks); + } + + for (int i = 0; i < p_tasks; i++) { + _post_task(tasks_posted[i], p_high_priority); + if (!p_high_priority && use_native_low_priority_threads) { + group->low_priority_native_tasks[i] = tasks_posted[i]; + } + } + + return id; +} + +WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) { + return _add_group_task(Callable(), p_func, p_userdata, nullptr, p_elements, p_tasks, p_high_priority, p_description); +} + +WorkerThreadPool::GroupID WorkerThreadPool::add_group_task(const Callable &p_action, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) { + return _add_group_task(p_action, nullptr, nullptr, nullptr, p_elements, p_tasks, p_high_priority, p_description); +} + +uint32_t WorkerThreadPool::get_group_processed_element_count(GroupID p_group) const { + task_mutex.lock(); + const Group *const *groupp = groups.getptr(p_group); + if (!groupp) { + task_mutex.unlock(); + ERR_FAIL_V_MSG(0, "Invalid Group ID"); + } + uint32_t elements = (*groupp)->completed_index.get(); + task_mutex.unlock(); + return elements; +} +bool WorkerThreadPool::is_group_task_completed(GroupID p_group) const { + task_mutex.lock(); + const Group *const *groupp = groups.getptr(p_group); + if (!groupp) { + task_mutex.unlock(); + ERR_FAIL_V_MSG(false, "Invalid Group ID"); + } + bool completed = (*groupp)->completed.is_set(); + task_mutex.unlock(); + return completed; +} + +void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) { + task_mutex.lock(); + Group **groupp = groups.getptr(p_group); + task_mutex.unlock(); + if (!groupp) { + ERR_FAIL_MSG("Invalid Group ID"); + } + Group *group = *groupp; + + if (group->low_priority_native_tasks.size() > 0) { + for (uint32_t i = 0; i < group->low_priority_native_tasks.size(); i++) { + group->low_priority_native_tasks[i]->low_priority_thread->wait_to_finish(); + native_thread_allocator.free(group->low_priority_native_tasks[i]->low_priority_thread); + task_mutex.lock(); + task_allocator.free(group->low_priority_native_tasks[i]); + task_mutex.unlock(); + } + + task_mutex.lock(); + group_allocator.free(group); + task_mutex.unlock(); + } else { + group->done_semaphore.wait(); + + uint32_t max_users = group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment. + uint32_t finished_users = group->finished.increment(); // fetch happens before inc, so increment later. + + if (finished_users == max_users) { + // All tasks using this group are gone (finished before the group), so clear the gorup too. + task_mutex.lock(); + group_allocator.free(group); + task_mutex.unlock(); + } + } + + groups.erase(p_group); // Threads do not access this, so safe to erase here. +} + +void WorkerThreadPool::init(int p_thread_count, bool p_use_native_threads_low_priority, float p_low_priority_task_ratio) { + ERR_FAIL_COND(threads.size() > 0); + if (p_thread_count < 0) { + p_thread_count = OS::get_singleton()->get_default_thread_pool_size(); + } + + if (p_use_native_threads_low_priority) { + max_low_priority_threads = 0; + } else { + max_low_priority_threads = CLAMP(p_thread_count * p_low_priority_task_ratio, 1, p_thread_count); + } + + use_native_low_priority_threads = p_use_native_threads_low_priority; + + threads.resize(p_thread_count); + + for (uint32_t i = 0; i < threads.size(); i++) { + threads[i].index = i; + threads[i].thread.start(&WorkerThreadPool::_thread_function, &threads[i]); + thread_ids.insert(threads[i].thread.get_id(), i); + } +} + +void WorkerThreadPool::finish() { + if (threads.size() == 0) { + return; + } + + task_mutex.lock(); + SelfList<Task> *E = low_priority_task_queue.first(); + while (E) { + print_error("Task waiting was never re-claimed: " + E->self()->description); + E = E->next(); + } + task_mutex.unlock(); + + exit_threads.set_to(true); + + for (uint32_t i = 0; i < threads.size(); i++) { + task_available_semaphore.post(); + } + + for (uint32_t i = 0; i < threads.size(); i++) { + threads[i].thread.wait_to_finish(); + } + + threads.clear(); +} + +void WorkerThreadPool::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_task", "action", "high_priority", "description"), &WorkerThreadPool::add_task, DEFVAL(false), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("is_task_completed", "task_id"), &WorkerThreadPool::is_task_completed); + ClassDB::bind_method(D_METHOD("wait_for_task_completion", "task_id"), &WorkerThreadPool::wait_for_task_completion); + + ClassDB::bind_method(D_METHOD("add_group_task", "action", "elements", "tasks_needed", "high_priority", "description"), &WorkerThreadPool::add_group_task, DEFVAL(-1), DEFVAL(false), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("is_group_task_completed", "group_id"), &WorkerThreadPool::is_group_task_completed); + ClassDB::bind_method(D_METHOD("get_group_processed_element_count", "group_id"), &WorkerThreadPool::get_group_processed_element_count); + ClassDB::bind_method(D_METHOD("wait_for_group_task_completion", "group_id"), &WorkerThreadPool::wait_for_group_task_completion); +} + +WorkerThreadPool::WorkerThreadPool() { + singleton = this; +} + +WorkerThreadPool::~WorkerThreadPool() { + finish(); +} diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h new file mode 100644 index 0000000000..1debd9ca37 --- /dev/null +++ b/core/object/worker_thread_pool.h @@ -0,0 +1,198 @@ +/*************************************************************************/ +/* worker_thread_pool.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 WORKER_THREAD_POOL_H +#define WORKER_THREAD_POOL_H + +#include "core/os/memory.h" +#include "core/os/os.h" +#include "core/os/semaphore.h" +#include "core/os/thread.h" +#include "core/templates/local_vector.h" +#include "core/templates/paged_allocator.h" +#include "core/templates/rid.h" +#include "core/templates/safe_refcount.h" + +class WorkerThreadPool : public Object { + GDCLASS(WorkerThreadPool, Object) +public: + enum { + INVALID_TASK_ID = -1 + }; + + typedef int64_t TaskID; + typedef int64_t GroupID; + +private: + struct Task; + + struct BaseTemplateUserdata { + virtual void callback() {} + virtual void callback_indexed(uint32_t p_index) {} + virtual ~BaseTemplateUserdata() {} + }; + + struct Group { + GroupID self; + SafeNumeric<uint32_t> index; + SafeNumeric<uint32_t> completed_index; + uint32_t max = 0; + Semaphore done_semaphore; + SafeFlag completed; + SafeNumeric<uint32_t> finished; + uint32_t tasks_used = 0; + TightLocalVector<Task *> low_priority_native_tasks; + }; + + struct Task { + Callable callable; + void (*native_func)(void *) = nullptr; + void (*native_group_func)(void *, uint32_t) = nullptr; + void *native_func_userdata = nullptr; + String description; + Semaphore done_semaphore; + bool completed = false; + Group *group = nullptr; + SelfList<Task> task_elem; + bool waiting = false; // Waiting for completion + bool low_priority = false; + BaseTemplateUserdata *template_userdata = nullptr; + Thread *low_priority_thread = nullptr; + + void free_template_userdata(); + Task() : + task_elem(this) {} + }; + + PagedAllocator<Task> task_allocator; + PagedAllocator<Group> group_allocator; + PagedAllocator<Thread> native_thread_allocator; + + SelfList<Task>::List low_priority_task_queue; + SelfList<Task>::List task_queue; + + Mutex task_mutex; + Semaphore task_available_semaphore; + + struct ThreadData { + uint32_t index; + Thread thread; + }; + + TightLocalVector<ThreadData> threads; + SafeFlag exit_threads; + + HashMap<Thread::ID, int> thread_ids; + HashMap<TaskID, Task *> tasks; + HashMap<GroupID, Group *> groups; + + bool use_native_low_priority_threads = false; + uint32_t max_low_priority_threads = 0; + SafeNumeric<uint32_t> low_priority_threads_used; + + uint64_t last_task = 1; + + static void _thread_function(void *p_user); + static void _native_low_priority_thread_function(void *p_user); + + void _process_task_queue(); + void _process_task(Task *task); + + void _post_task(Task *p_task, bool p_high_priority); + + static WorkerThreadPool *singleton; + + TaskID _add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description); + GroupID _add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description); + + template <class C, class M, class U> + struct TaskUserData : public BaseTemplateUserdata { + C *instance; + M method; + U userdata; + virtual void callback() override { + (instance->*method)(userdata); + } + }; + + template <class C, class M, class U> + struct GroupUserData : public BaseTemplateUserdata { + C *instance; + M method; + U userdata; + virtual void callback_indexed(uint32_t p_index) override { + (instance->*method)(p_index, userdata); + } + }; + +protected: + static void _bind_methods(); + +public: + template <class C, class M, class U> + TaskID add_template_task(C *p_instance, M p_method, U p_userdata, bool p_high_priority = false, const String &p_description = String()) { + typedef TaskUserData<C, M, U> TUD; + TUD *ud = memnew(TUD); + ud->instance = p_instance; + ud->method = p_method; + ud->userdata = p_userdata; + return _add_task(Callable(), nullptr, nullptr, ud, p_high_priority, p_description); + } + TaskID add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority = false, const String &p_description = String()); + TaskID add_task(const Callable &p_action, bool p_high_priority = false, const String &p_description = String()); + + bool is_task_completed(TaskID p_task_id) const; + void wait_for_task_completion(TaskID p_task_id); + + template <class C, class M, class U> + GroupID add_template_group_task(C *p_instance, M p_method, U p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()) { + typedef GroupUserData<C, M, U> GUD; + GUD *ud = memnew(GUD); + ud->instance = p_instance; + ud->method = p_method; + ud->userdata = p_userdata; + return _add_group_task(Callable(), nullptr, nullptr, ud, p_elements, p_tasks, p_high_priority, p_description); + } + GroupID add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()); + GroupID add_group_task(const Callable &p_action, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()); + uint32_t get_group_processed_element_count(GroupID p_group) const; + bool is_group_task_completed(GroupID p_group) const; + void wait_for_group_task_completion(GroupID p_group); + + _FORCE_INLINE_ int get_thread_count() const { return threads.size(); } + + static WorkerThreadPool *get_singleton() { return singleton; } + void init(int p_thread_count = -1, bool p_use_native_threads_low_priority = true, float p_low_priority_task_ratio = 0.3); + void finish(); + WorkerThreadPool(); + ~WorkerThreadPool(); +}; + +#endif // WORKER_THREAD_POOL_H diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 3e690991d9..a592791d06 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -61,7 +61,7 @@ static const _KeyCodeText _keycodes[] = { {Key::PAGEDOWN ,"PageDown"}, {Key::SHIFT ,"Shift"}, {Key::CTRL ,"Ctrl"}, -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED {Key::META ,"Command"}, #else {Key::META ,"Meta"}, diff --git a/core/os/memory.h b/core/os/memory.h index 42ba9634e2..0e1afe027e 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -36,6 +36,7 @@ #include <stddef.h> #include <new> +#include <type_traits> #ifndef PAD_ALIGN #define PAD_ALIGN 16 //must always be greater than this at much @@ -104,7 +105,7 @@ void memdelete(T *p_class) { if (!predelete_handler(p_class)) { return; // doesn't want to be deleted } - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { p_class->~T(); } @@ -116,7 +117,7 @@ void memdelete_allocator(T *p_class) { if (!predelete_handler(p_class)) { return; // doesn't want to be deleted } - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { p_class->~T(); } @@ -146,7 +147,7 @@ T *memnew_arr_template(size_t p_elements) { ERR_FAIL_COND_V(!mem, failptr); *(mem - 1) = p_elements; - if (!__has_trivial_constructor(T)) { + if (!std::is_trivially_constructible<T>::value) { T *elems = (T *)mem; /* call operator new */ @@ -173,7 +174,7 @@ template <typename T> void memdelete_arr(T *p_class) { uint64_t *ptr = (uint64_t *)p_class; - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { uint64_t elem_count = *(ptr - 1); for (uint64_t i = 0; i < elem_count; i++) { diff --git a/core/os/os.cpp b/core/os/os.cpp index b9daf6fa53..1358c926d1 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -159,7 +159,7 @@ int OS::get_process_id() const { } void OS::vibrate_handheld(int p_duration_ms) { - WARN_PRINT("vibrate_handheld() only works with Android and iOS"); + WARN_PRINT("vibrate_handheld() only works with Android, iOS and HTML5"); } bool OS::is_stdout_verbose() const { @@ -362,9 +362,10 @@ String OS::get_model_name() const { return "GenericDevice"; } -void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) { +void OS::set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args) { _execpath = String::utf8(p_execpath); _cmdline = p_args; + _user_args = p_user_args; } String OS::get_unique_id() const { diff --git a/core/os/os.h b/core/os/os.h index 0428f6df2a..9152b797ef 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -46,6 +46,7 @@ class OS { static uint64_t target_ticks; String _execpath; List<String> _cmdline; + List<String> _user_args; bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. bool low_processor_usage_mode = false; int low_processor_usage_mode_sleep_usec = 10000; @@ -106,7 +107,7 @@ protected: virtual void finalize() = 0; virtual void finalize_core() = 0; - virtual void set_cmdline(const char *p_execpath, const List<String> &p_args); + virtual void set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args); virtual bool _check_internal_feature_support(const String &p_feature) = 0; @@ -142,6 +143,8 @@ public: virtual void set_low_processor_usage_mode_sleep_usec(int p_usec); virtual int get_low_processor_usage_mode_sleep_usec() const; + virtual Vector<String> get_system_fonts() const { return Vector<String>(); }; + virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const { return String(); }; virtual String get_executable_path() const; virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0; virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0; @@ -160,6 +163,7 @@ public: virtual String get_name() const = 0; virtual List<String> get_cmdline_args() const { return _cmdline; } + virtual List<String> get_cmdline_user_args() const { return _user_args; } virtual List<String> get_cmdline_platform_args() const { return List<String>(); } virtual String get_model_name() const; diff --git a/core/os/spin_lock.h b/core/os/spin_lock.h index 6e8d7f46d5..80eeef3386 100644 --- a/core/os/spin_lock.h +++ b/core/os/spin_lock.h @@ -48,4 +48,5 @@ public: locked.clear(std::memory_order_release); } }; + #endif // SPIN_LOCK_H diff --git a/core/os/thread.h b/core/os/thread.h index 3382dd81f9..0fb283e224 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -123,4 +123,5 @@ public: }; #endif // THREAD_H + #endif // PLATFORM_THREAD_OVERRIDE diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index e60d325f74..9ad6b0ca68 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -69,11 +69,10 @@ #include "core/math/geometry_3d.h" #include "core/math/random_number_generator.h" #include "core/math/triangle_mesh.h" -#include "core/multiplayer/multiplayer_api.h" -#include "core/multiplayer/multiplayer_peer.h" #include "core/object/class_db.h" #include "core/object/script_language_extension.h" #include "core/object/undo_redo.h" +#include "core/object/worker_thread_pool.h" #include "core/os/main_loop.h" #include "core/os/time.h" #include "core/string/optimized_translation.h" @@ -101,6 +100,8 @@ static IP *ip = nullptr; static core_bind::Geometry2D *_geometry_2d = nullptr; static core_bind::Geometry3D *_geometry_3d = nullptr; +static WorkerThreadPool *worker_thread_pool = nullptr; + extern Mutex _global_mutex; static NativeExtensionManager *native_extension_manager = nullptr; @@ -189,6 +190,8 @@ void register_core_types() { GDREGISTER_CLASS(PacketPeerUDP); GDREGISTER_CLASS(UDPServer); + GDREGISTER_ABSTRACT_CLASS(WorkerThreadPool); + ClassDB::register_custom_instance_class<HTTPClient>(); // Crypto @@ -207,9 +210,6 @@ void register_core_types() { resource_format_loader_crypto.instantiate(); ResourceLoader::add_resource_format_loader(resource_format_loader_crypto); - GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer); - GDREGISTER_CLASS(MultiplayerPeerExtension); - GDREGISTER_CLASS(MultiplayerAPI); GDREGISTER_CLASS(MainLoop); GDREGISTER_CLASS(Translation); GDREGISTER_CLASS(OptimizedTranslation); @@ -269,8 +269,11 @@ void register_core_types() { _marshalls = memnew(core_bind::Marshalls); _engine_debugger = memnew(core_bind::EngineDebugger); + GDREGISTER_NATIVE_STRUCT(ObjectID, "uint64_t id = 0"); GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right"); GDREGISTER_NATIVE_STRUCT(ScriptLanguageExtensionProfilingInfo, "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time"); + + worker_thread_pool = memnew(WorkerThreadPool); } void register_core_settings() { @@ -279,9 +282,18 @@ void register_core_settings() { 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)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater")); - GLOBAL_DEF("network/ssl/certificate_bundle_override", ""); ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificate_bundle_override", PropertyInfo(Variant::STRING, "network/ssl/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt")); + + int worker_threads = GLOBAL_DEF("threading/worker_pool/max_threads", -1); + bool low_priority_use_system_threads = GLOBAL_DEF("threading/worker_pool/use_system_threads_for_low_priority_tasks", true); + float low_property_ratio = GLOBAL_DEF("threading/worker_pool/low_priority_thread_ratio", 0.3); + + if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) { + worker_thread_pool->init(); + } else { + worker_thread_pool->init(worker_threads, low_priority_use_system_threads, low_property_ratio); + } } void register_core_singletons() { @@ -319,6 +331,7 @@ void register_core_singletons() { Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("WorkerThreadPool", worker_thread_pool)); } void register_core_extensions() { @@ -350,6 +363,8 @@ void unregister_core_types() { memdelete(_geometry_2d); memdelete(_geometry_3d); + memdelete(worker_thread_pool); + ResourceLoader::remove_resource_format_loader(resource_format_image); resource_format_image.unref(); diff --git a/core/string/char_range.inc b/core/string/char_range.inc new file mode 100644 index 0000000000..c0be9016ad --- /dev/null +++ b/core/string/char_range.inc @@ -0,0 +1,1456 @@ +/*************************************************************************/ +/* char_range.inc */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 CHAR_RANGE_INC +#define CHAR_RANGE_INC + +#include "core/typedefs.h" + +struct CharRange { + char32_t start; + char32_t end; +}; + +static CharRange xid_start[] = { + { 0x41, 0x5a }, + { 0x5f, 0x5f }, + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x370, 0x374 }, + { 0x376, 0x377 }, + { 0x37a, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x386 }, + { 0x388, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x620, 0x64a }, + { 0x66e, 0x66f }, + { 0x671, 0x6d3 }, + { 0x6d5, 0x6d5 }, + { 0x6e5, 0x6e6 }, + { 0x6ee, 0x6ef }, + { 0x6fa, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x710 }, + { 0x712, 0x72f }, + { 0x74d, 0x7a5 }, + { 0x7b1, 0x7b1 }, + { 0x7ca, 0x7ea }, + { 0x7f4, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x800, 0x815 }, + { 0x81a, 0x81a }, + { 0x824, 0x824 }, + { 0x828, 0x828 }, + { 0x840, 0x858 }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x8a0, 0x8c9 }, + { 0x904, 0x939 }, + { 0x93d, 0x93d }, + { 0x950, 0x950 }, + { 0x958, 0x961 }, + { 0x971, 0x980 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bd, 0x9bd }, + { 0x9ce, 0x9ce }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e1 }, + { 0x9f0, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa72, 0xa74 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabd, 0xabd }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae1 }, + { 0xaf9, 0xaf9 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3d, 0xb3d }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb61 }, + { 0xb71, 0xb71 }, + { 0xb83, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbd0, 0xbd0 }, + { 0xc05, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3d, 0xc3d }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc61 }, + { 0xc80, 0xc80 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbd, 0xcbd }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce1 }, + { 0xcf1, 0xcf2 }, + { 0xd04, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd3a }, + { 0xd3d, 0xd3d }, + { 0xd4e, 0xd4e }, + { 0xd54, 0xd56 }, + { 0xd5f, 0xd61 }, + { 0xd7a, 0xd7f }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xe01, 0xe30 }, + { 0xe32, 0xe33 }, + { 0xe40, 0xe46 }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xeb0 }, + { 0xeb2, 0xeb3 }, + { 0xebd, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf40, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf88, 0xf8c }, + { 0x1000, 0x102a }, + { 0x103f, 0x103f }, + { 0x1050, 0x1055 }, + { 0x105a, 0x105d }, + { 0x1061, 0x1061 }, + { 0x1065, 0x1066 }, + { 0x106e, 0x1070 }, + { 0x1075, 0x1081 }, + { 0x108e, 0x108e }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1711 }, + { 0x171f, 0x1731 }, + { 0x1740, 0x1751 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1780, 0x17b3 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dc }, + { 0x1820, 0x1878 }, + { 0x1880, 0x1884 }, + { 0x1887, 0x18a8 }, + { 0x18aa, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1950, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x1a00, 0x1a16 }, + { 0x1a20, 0x1a54 }, + { 0x1aa7, 0x1aa7 }, + { 0x1b05, 0x1b33 }, + { 0x1b45, 0x1b4c }, + { 0x1b83, 0x1ba0 }, + { 0x1bae, 0x1baf }, + { 0x1bba, 0x1be5 }, + { 0x1c00, 0x1c23 }, + { 0x1c4d, 0x1c4f }, + { 0x1c5a, 0x1c7d }, + { 0x1c80, 0x1c88 }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1ce9, 0x1cec }, + { 0x1cee, 0x1cf3 }, + { 0x1cf5, 0x1cf6 }, + { 0x1cfa, 0x1cfa }, + { 0x1d00, 0x1dbf }, + { 0x1e00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2118, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2160, 0x2188 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cee }, + { 0x2cf2, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d80, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x3005, 0x3007 }, + { 0x3021, 0x3029 }, + { 0x3031, 0x3035 }, + { 0x3038, 0x303c }, + { 0x3041, 0x3096 }, + { 0x309b, 0x309f }, + { 0x30a1, 0x30fa }, + { 0x30fc, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa61f }, + { 0xa62a, 0xa62b }, + { 0xa640, 0xa66e }, + { 0xa67f, 0xa69d }, + { 0xa6a0, 0xa6ef }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7ca }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7d9 }, + { 0xa7f2, 0xa801 }, + { 0xa803, 0xa805 }, + { 0xa807, 0xa80a }, + { 0xa80c, 0xa822 }, + { 0xa840, 0xa873 }, + { 0xa882, 0xa8b3 }, + { 0xa8f2, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa8fe }, + { 0xa90a, 0xa925 }, + { 0xa930, 0xa946 }, + { 0xa960, 0xa97c }, + { 0xa984, 0xa9b2 }, + { 0xa9cf, 0xa9cf }, + { 0xa9e0, 0xa9e4 }, + { 0xa9e6, 0xa9ef }, + { 0xa9fa, 0xa9fe }, + { 0xaa00, 0xaa28 }, + { 0xaa40, 0xaa42 }, + { 0xaa44, 0xaa4b }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaa7a }, + { 0xaa7e, 0xaaaf }, + { 0xaab1, 0xaab1 }, + { 0xaab5, 0xaab6 }, + { 0xaab9, 0xaabd }, + { 0xaac0, 0xaac0 }, + { 0xaac2, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaea }, + { 0xaaf2, 0xaaf4 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabe2 }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb1d }, + { 0xfb1f, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdfb }, + { 0xfe70, 0xfe74 }, + { 0xfe76, 0xfefc }, + { 0xff21, 0xff3a }, + { 0xff41, 0xff5a }, + { 0xff66, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x10375 }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, + { 0x10400, 0x1049d }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a00 }, + { 0x10a10, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae4 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d23 }, + { 0x10e80, 0x10ea9 }, + { 0x10eb0, 0x10eb1 }, + { 0x10f00, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f45 }, + { 0x10f70, 0x10f81 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11003, 0x11037 }, + { 0x11071, 0x11072 }, + { 0x11075, 0x11075 }, + { 0x11083, 0x110af }, + { 0x110d0, 0x110e8 }, + { 0x11103, 0x11126 }, + { 0x11144, 0x11144 }, + { 0x11147, 0x11147 }, + { 0x11150, 0x11172 }, + { 0x11176, 0x11176 }, + { 0x11183, 0x111b2 }, + { 0x111c1, 0x111c4 }, + { 0x111da, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x1122b }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112de }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133d, 0x1133d }, + { 0x11350, 0x11350 }, + { 0x1135d, 0x11361 }, + { 0x11400, 0x11434 }, + { 0x11447, 0x1144a }, + { 0x1145f, 0x11461 }, + { 0x11480, 0x114af }, + { 0x114c4, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x11580, 0x115ae }, + { 0x115d8, 0x115db }, + { 0x11600, 0x1162f }, + { 0x11644, 0x11644 }, + { 0x11680, 0x116aa }, + { 0x116b8, 0x116b8 }, + { 0x11700, 0x1171a }, + { 0x11740, 0x11746 }, + { 0x11800, 0x1182b }, + { 0x118a0, 0x118df }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x1192f }, + { 0x1193f, 0x1193f }, + { 0x11941, 0x11941 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d0 }, + { 0x119e1, 0x119e1 }, + { 0x119e3, 0x119e3 }, + { 0x11a00, 0x11a00 }, + { 0x11a0b, 0x11a32 }, + { 0x11a3a, 0x11a3a }, + { 0x11a50, 0x11a50 }, + { 0x11a5c, 0x11a89 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c2e }, + { 0x11c40, 0x11c40 }, + { 0x11c72, 0x11c8f }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d30 }, + { 0x11d46, 0x11d46 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d89 }, + { 0x11d98, 0x11d98 }, + { 0x11ee0, 0x11ef2 }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342e }, + { 0x14400, 0x14646 }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a70, 0x16abe }, + { 0x16ad0, 0x16aed }, + { 0x16b00, 0x16b2f }, + { 0x16b40, 0x16b43 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f50, 0x16f50 }, + { 0x16f93, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe3 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18d00, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b150, 0x1b152 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1df00, 0x1df1e }, + { 0x1e100, 0x1e12c }, + { 0x1e137, 0x1e13d }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ad }, + { 0x1e2c0, 0x1e2eb }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e900, 0x1e943 }, + { 0x1e94b, 0x1e94b }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b738 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0x0, 0x0 }, +}; + +static CharRange xid_continue[] = { + { 0x30, 0x39 }, + { 0x41, 0x5a }, + { 0x5f, 0x5f }, + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xb7, 0xb7 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x300, 0x374 }, + { 0x376, 0x377 }, + { 0x37a, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x483, 0x487 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x591, 0x5bd }, + { 0x5bf, 0x5bf }, + { 0x5c1, 0x5c2 }, + { 0x5c4, 0x5c5 }, + { 0x5c7, 0x5c7 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x610, 0x61a }, + { 0x620, 0x669 }, + { 0x66e, 0x6d3 }, + { 0x6d5, 0x6dc }, + { 0x6df, 0x6e8 }, + { 0x6ea, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x74a }, + { 0x74d, 0x7b1 }, + { 0x7c0, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x7fd, 0x7fd }, + { 0x800, 0x82d }, + { 0x840, 0x85b }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x898, 0x8e1 }, + { 0x8e3, 0x963 }, + { 0x966, 0x96f }, + { 0x971, 0x983 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bc, 0x9c4 }, + { 0x9c7, 0x9c8 }, + { 0x9cb, 0x9ce }, + { 0x9d7, 0x9d7 }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e3 }, + { 0x9e6, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0x9fe, 0x9fe }, + { 0xa01, 0xa03 }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa3c, 0xa3c }, + { 0xa3e, 0xa42 }, + { 0xa47, 0xa48 }, + { 0xa4b, 0xa4d }, + { 0xa51, 0xa51 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa66, 0xa75 }, + { 0xa81, 0xa83 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabc, 0xac5 }, + { 0xac7, 0xac9 }, + { 0xacb, 0xacd }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae3 }, + { 0xae6, 0xaef }, + { 0xaf9, 0xaff }, + { 0xb01, 0xb03 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3c, 0xb44 }, + { 0xb47, 0xb48 }, + { 0xb4b, 0xb4d }, + { 0xb55, 0xb57 }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb63 }, + { 0xb66, 0xb6f }, + { 0xb71, 0xb71 }, + { 0xb82, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbbe, 0xbc2 }, + { 0xbc6, 0xbc8 }, + { 0xbca, 0xbcd }, + { 0xbd0, 0xbd0 }, + { 0xbd7, 0xbd7 }, + { 0xbe6, 0xbef }, + { 0xc00, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3c, 0xc44 }, + { 0xc46, 0xc48 }, + { 0xc4a, 0xc4d }, + { 0xc55, 0xc56 }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc63 }, + { 0xc66, 0xc6f }, + { 0xc80, 0xc83 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbc, 0xcc4 }, + { 0xcc6, 0xcc8 }, + { 0xcca, 0xccd }, + { 0xcd5, 0xcd6 }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce3 }, + { 0xce6, 0xcef }, + { 0xcf1, 0xcf2 }, + { 0xd00, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd44 }, + { 0xd46, 0xd48 }, + { 0xd4a, 0xd4e }, + { 0xd54, 0xd57 }, + { 0xd5f, 0xd63 }, + { 0xd66, 0xd6f }, + { 0xd7a, 0xd7f }, + { 0xd81, 0xd83 }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xdca, 0xdca }, + { 0xdcf, 0xdd4 }, + { 0xdd6, 0xdd6 }, + { 0xdd8, 0xddf }, + { 0xde6, 0xdef }, + { 0xdf2, 0xdf3 }, + { 0xe01, 0xe3a }, + { 0xe40, 0xe4e }, + { 0xe50, 0xe59 }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xec8, 0xecd }, + { 0xed0, 0xed9 }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf18, 0xf19 }, + { 0xf20, 0xf29 }, + { 0xf35, 0xf35 }, + { 0xf37, 0xf37 }, + { 0xf39, 0xf39 }, + { 0xf3e, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf71, 0xf84 }, + { 0xf86, 0xf97 }, + { 0xf99, 0xfbc }, + { 0xfc6, 0xfc6 }, + { 0x1000, 0x1049 }, + { 0x1050, 0x109d }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x135d, 0x135f }, + { 0x1369, 0x1369 }, + { 0x1371, 0x1371 }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1715 }, + { 0x171f, 0x1734 }, + { 0x1740, 0x1753 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1772, 0x1773 }, + { 0x1780, 0x17d3 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dd }, + { 0x17e0, 0x17e9 }, + { 0x180b, 0x180d }, + { 0x180f, 0x1819 }, + { 0x1820, 0x1878 }, + { 0x1880, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1920, 0x192b }, + { 0x1930, 0x193b }, + { 0x1946, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x19d0, 0x19da }, + { 0x1a00, 0x1a1b }, + { 0x1a20, 0x1a5e }, + { 0x1a60, 0x1a7c }, + { 0x1a7f, 0x1a89 }, + { 0x1a90, 0x1a99 }, + { 0x1aa7, 0x1aa7 }, + { 0x1ab0, 0x1abd }, + { 0x1abf, 0x1ace }, + { 0x1b00, 0x1b4c }, + { 0x1b50, 0x1b59 }, + { 0x1b6b, 0x1b73 }, + { 0x1b80, 0x1bf3 }, + { 0x1c00, 0x1c37 }, + { 0x1c40, 0x1c49 }, + { 0x1c4d, 0x1c7d }, + { 0x1c80, 0x1c88 }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1cd0, 0x1cd2 }, + { 0x1cd4, 0x1cfa }, + { 0x1d00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x203f, 0x2040 }, + { 0x2054, 0x2054 }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x20d0, 0x20dc }, + { 0x20e1, 0x20e1 }, + { 0x20e5, 0x20f0 }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2118, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2160, 0x2188 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d7f, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x2de0, 0x2dff }, + { 0x3005, 0x3007 }, + { 0x3021, 0x302f }, + { 0x3031, 0x3035 }, + { 0x3038, 0x303c }, + { 0x3041, 0x3096 }, + { 0x3099, 0x309f }, + { 0x30a1, 0x30fa }, + { 0x30fc, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa62b }, + { 0xa640, 0xa66f }, + { 0xa674, 0xa67d }, + { 0xa67f, 0xa6f1 }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7ca }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7d9 }, + { 0xa7f2, 0xa827 }, + { 0xa82c, 0xa82c }, + { 0xa840, 0xa873 }, + { 0xa880, 0xa8c5 }, + { 0xa8d0, 0xa8d9 }, + { 0xa8e0, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa92d }, + { 0xa930, 0xa953 }, + { 0xa960, 0xa97c }, + { 0xa980, 0xa9c0 }, + { 0xa9cf, 0xa9d9 }, + { 0xa9e0, 0xa9fe }, + { 0xaa00, 0xaa36 }, + { 0xaa40, 0xaa4d }, + { 0xaa50, 0xaa59 }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaef }, + { 0xaaf2, 0xaaf6 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabea }, + { 0xabec, 0xabed }, + { 0xabf0, 0xabf9 }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdfb }, + { 0xfe00, 0xfe0f }, + { 0xfe20, 0xfe2f }, + { 0xfe33, 0xfe34 }, + { 0xfe4d, 0xfe4f }, + { 0xfe70, 0xfe74 }, + { 0xfe76, 0xfefc }, + { 0xff10, 0xff19 }, + { 0xff21, 0xff3a }, + { 0xff3f, 0xff3f }, + { 0xff41, 0xff5a }, + { 0xff66, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, + { 0x101fd, 0x101fd }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x102e0, 0x102e0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x1037a }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, + { 0x10400, 0x1049d }, + { 0x104a0, 0x104a9 }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a03 }, + { 0x10a05, 0x10a06 }, + { 0x10a0c, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a38, 0x10a3a }, + { 0x10a3f, 0x10a3f }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae6 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d27 }, + { 0x10d30, 0x10d39 }, + { 0x10e80, 0x10ea9 }, + { 0x10eab, 0x10eac }, + { 0x10eb0, 0x10eb1 }, + { 0x10f00, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f50 }, + { 0x10f70, 0x10f85 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11000, 0x11046 }, + { 0x11066, 0x11075 }, + { 0x1107f, 0x110ba }, + { 0x110c2, 0x110c2 }, + { 0x110d0, 0x110e8 }, + { 0x110f0, 0x110f9 }, + { 0x11100, 0x11134 }, + { 0x11136, 0x1113f }, + { 0x11144, 0x11147 }, + { 0x11150, 0x11173 }, + { 0x11176, 0x11176 }, + { 0x11180, 0x111c4 }, + { 0x111c9, 0x111cc }, + { 0x111ce, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x11237 }, + { 0x1123e, 0x1123e }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112ea }, + { 0x112f0, 0x112f9 }, + { 0x11300, 0x11303 }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133b, 0x11344 }, + { 0x11347, 0x11348 }, + { 0x1134b, 0x1134d }, + { 0x11350, 0x11350 }, + { 0x11357, 0x11357 }, + { 0x1135d, 0x11363 }, + { 0x11366, 0x1136c }, + { 0x11370, 0x11374 }, + { 0x11400, 0x1144a }, + { 0x11450, 0x11459 }, + { 0x1145e, 0x11461 }, + { 0x11480, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x114d0, 0x114d9 }, + { 0x11580, 0x115b5 }, + { 0x115b8, 0x115c0 }, + { 0x115d8, 0x115dd }, + { 0x11600, 0x11640 }, + { 0x11644, 0x11644 }, + { 0x11650, 0x11659 }, + { 0x11680, 0x116b8 }, + { 0x116c0, 0x116c9 }, + { 0x11700, 0x1171a }, + { 0x1171d, 0x1172b }, + { 0x11730, 0x11739 }, + { 0x11740, 0x11746 }, + { 0x11800, 0x1183a }, + { 0x118a0, 0x118e9 }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x11935 }, + { 0x11937, 0x11938 }, + { 0x1193b, 0x11943 }, + { 0x11950, 0x11959 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d7 }, + { 0x119da, 0x119e1 }, + { 0x119e3, 0x119e4 }, + { 0x11a00, 0x11a3e }, + { 0x11a47, 0x11a47 }, + { 0x11a50, 0x11a99 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c36 }, + { 0x11c38, 0x11c40 }, + { 0x11c50, 0x11c59 }, + { 0x11c72, 0x11c8f }, + { 0x11c92, 0x11ca7 }, + { 0x11ca9, 0x11cb6 }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d36 }, + { 0x11d3a, 0x11d3a }, + { 0x11d3c, 0x11d3d }, + { 0x11d3f, 0x11d47 }, + { 0x11d50, 0x11d59 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d8e }, + { 0x11d90, 0x11d91 }, + { 0x11d93, 0x11d98 }, + { 0x11da0, 0x11da9 }, + { 0x11ee0, 0x11ef6 }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342e }, + { 0x14400, 0x14646 }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a60, 0x16a69 }, + { 0x16a70, 0x16abe }, + { 0x16ac0, 0x16ac9 }, + { 0x16ad0, 0x16aed }, + { 0x16af0, 0x16af4 }, + { 0x16b00, 0x16b36 }, + { 0x16b40, 0x16b43 }, + { 0x16b50, 0x16b59 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f4f, 0x16f87 }, + { 0x16f8f, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe4 }, + { 0x16ff0, 0x16ff1 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18d00, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b150, 0x1b152 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1bc9d, 0x1bc9e }, + { 0x1cf00, 0x1cf2d }, + { 0x1cf30, 0x1cf46 }, + { 0x1d165, 0x1d169 }, + { 0x1d16d, 0x1d172 }, + { 0x1d17b, 0x1d182 }, + { 0x1d185, 0x1d18b }, + { 0x1d1aa, 0x1d1ad }, + { 0x1d242, 0x1d244 }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1d7ce, 0x1d7ff }, + { 0x1da00, 0x1da36 }, + { 0x1da3b, 0x1da6c }, + { 0x1da75, 0x1da75 }, + { 0x1da84, 0x1da84 }, + { 0x1da9b, 0x1da9f }, + { 0x1daa1, 0x1daaf }, + { 0x1df00, 0x1df1e }, + { 0x1e000, 0x1e006 }, + { 0x1e008, 0x1e018 }, + { 0x1e01b, 0x1e021 }, + { 0x1e023, 0x1e024 }, + { 0x1e026, 0x1e02a }, + { 0x1e100, 0x1e12c }, + { 0x1e130, 0x1e13d }, + { 0x1e140, 0x1e149 }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ae }, + { 0x1e2c0, 0x1e2f9 }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e8d0, 0x1e8d6 }, + { 0x1e900, 0x1e94b }, + { 0x1e950, 0x1e959 }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x1fbf0, 0x1fbf9 }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b738 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0xe0100, 0xe01ef }, + { 0x0, 0x0 }, +}; + +#endif // CHAR_RANGE_INC diff --git a/core/string/char_utils.h b/core/string/char_utils.h index 0afd058f01..67147a4327 100644 --- a/core/string/char_utils.h +++ b/core/string/char_utils.h @@ -33,6 +33,26 @@ #include "core/typedefs.h" +#include "char_range.inc" + +static _FORCE_INLINE_ bool is_unicode_identifier_start(char32_t c) { + for (int i = 0; xid_start[i].start != 0; i++) { + if (c >= xid_start[i].start && c <= xid_start[i].end) { + return true; + } + } + return false; +} + +static _FORCE_INLINE_ bool is_unicode_identifier_continue(char32_t c) { + for (int i = 0; xid_continue[i].start != 0; i++) { + if (c >= xid_continue[i].start && c <= xid_continue[i].end) { + return true; + } + } + return false; +} + static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) { return (c >= 'A' && c <= 'Z'); } diff --git a/core/string/print_string.cpp b/core/string/print_string.cpp index f58486e0a5..592da58fe7 100644 --- a/core/string/print_string.cpp +++ b/core/string/print_string.cpp @@ -30,13 +30,12 @@ #include "print_string.h" +#include "core/core_globals.h" #include "core/os/os.h" #include <stdio.h> static PrintHandlerList *print_handler_list = nullptr; -bool _print_line_enabled = true; -bool _print_error_enabled = true; void add_print_handler(PrintHandlerList *p_handler) { _global_lock(); @@ -70,7 +69,7 @@ void remove_print_handler(const PrintHandlerList *p_handler) { } void __print_line(String p_string) { - if (!_print_line_enabled) { + if (!CoreGlobals::print_line_enabled) { return; } @@ -87,7 +86,7 @@ void __print_line(String p_string) { } void __print_line_rich(String p_string) { - if (!_print_line_enabled) { + if (!CoreGlobals::print_line_enabled) { return; } @@ -178,7 +177,7 @@ void __print_line_rich(String p_string) { } void print_error(String p_string) { - if (!_print_error_enabled) { + if (!CoreGlobals::print_error_enabled) { return; } diff --git a/core/string/print_string.h b/core/string/print_string.h index 823e2c29e8..ca930a3a0f 100644 --- a/core/string/print_string.h +++ b/core/string/print_string.h @@ -56,8 +56,6 @@ String stringify_variants(Variant p_var, Args... p_args) { void add_print_handler(PrintHandlerList *p_handler); void remove_print_handler(const PrintHandlerList *p_handler); -extern bool _print_line_enabled; -extern bool _print_error_enabled; extern void __print_line(String p_string); extern void __print_line_rich(String p_string); extern void print_error(String p_string); diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index beefe54faf..e93375bff7 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1656,7 +1656,7 @@ String String::utf8(const char *p_utf8, int p_len) { return ret; } -Error String::parse_utf8(const char *p_utf8, int p_len) { +Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) { if (!p_utf8) { return ERR_INVALID_DATA; } @@ -1689,6 +1689,10 @@ Error String::parse_utf8(const char *p_utf8, int p_len) { uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp); if (skip == 0) { + if (p_skip_cr && c == '\r') { + ptrtmp++; + continue; + } /* Determine the number of characters in sequence */ if ((c & 0x80) == 0) { skip = 0; @@ -1753,6 +1757,10 @@ Error String::parse_utf8(const char *p_utf8, int p_len) { uint8_t c = *p_utf8 >= 0 ? *p_utf8 : uint8_t(256 + *p_utf8); if (skip == 0) { + if (p_skip_cr && c == '\r') { + p_utf8++; + continue; + } /* Determine the number of characters in sequence */ if ((c & 0x80) == 0) { *(dst++) = c; diff --git a/core/string/ustring.h b/core/string/ustring.h index 1b8bf3d234..6c3169f136 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -28,9 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +// Note: _GODOT suffix added to avoid conflict with ICU header with the same guard. + #ifndef USTRING_GODOT_H #define USTRING_GODOT_H -// Note: Renamed to avoid conflict with ICU header with the same name. #include "core/string/char_utils.h" #include "core/templates/cowdata.h" @@ -376,7 +377,7 @@ public: CharString ascii(bool p_allow_extended = false) const; CharString utf8() const; - Error parse_utf8(const char *p_utf8, int p_len = -1); + Error parse_utf8(const char *p_utf8, int p_len = -1, bool p_skip_cr = false); static String utf8(const char *p_utf8, int p_len = -1); Char16String utf16() const; diff --git a/core/templates/bin_sorted_array.h b/core/templates/bin_sorted_array.h index d928bd7a82..38beb9c04d 100644 --- a/core/templates/bin_sorted_array.h +++ b/core/templates/bin_sorted_array.h @@ -178,4 +178,4 @@ public: } }; -#endif //BIN_SORTED_ARRAY_H +#endif // BIN_SORTED_ARRAY_H diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h index e760fc2176..f98b2308c9 100644 --- a/core/templates/cowdata.h +++ b/core/templates/cowdata.h @@ -36,6 +36,7 @@ #include "core/templates/safe_refcount.h" #include <string.h> +#include <type_traits> template <class T> class Vector; @@ -158,6 +159,7 @@ public: return _ptr[p_index]; } + template <bool p_ensure_zero = false> Error resize(int p_size); _FORCE_INLINE_ void remove_at(int p_index) { @@ -204,7 +206,7 @@ void CowData<T>::_unref(void *p_data) { } // clean up - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { uint32_t *count = _get_size(); T *data = (T *)(count + 1); @@ -239,7 +241,7 @@ uint32_t CowData<T>::_copy_on_write() { T *_data = (T *)(mem_new); // initialize new elements - if (__has_trivial_copy(T)) { + if (std::is_trivially_copyable<T>::value) { memcpy(mem_new, _ptr, current_size * sizeof(T)); } else { @@ -257,6 +259,7 @@ uint32_t CowData<T>::_copy_on_write() { } template <class T> +template <bool p_ensure_zero> Error CowData<T>::resize(int p_size) { ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); @@ -302,16 +305,18 @@ Error CowData<T>::resize(int p_size) { // construct the newly created elements - if (!__has_trivial_constructor(T)) { + if (!std::is_trivially_constructible<T>::value) { for (int i = *_get_size(); i < p_size; i++) { memnew_placement(&_ptr[i], T); } + } else if (p_ensure_zero) { + memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T)); } *_get_size() = p_size; } else if (p_size < current_size) { - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { // deinitialize no longer needed elements for (uint32_t i = p_size; i < *_get_size(); i++) { T *t = &_ptr[i]; diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 547534f26a..d85cdf7adc 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -40,6 +40,8 @@ #include "core/math/vector2i.h" #include "core/math/vector3.h" #include "core/math/vector3i.h" +#include "core/math/vector4.h" +#include "core/math/vector4i.h" #include "core/object/object_id.h" #include "core/string/node_path.h" #include "core/string/string_name.h" @@ -332,6 +334,13 @@ struct HashMapHasherDefault { h = hash_murmur3_one_32(p_vec.z, h); return hash_fmix32(h); } + static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) { + uint32_t h = hash_murmur3_one_32(p_vec.x); + h = hash_murmur3_one_32(p_vec.y, h); + h = hash_murmur3_one_32(p_vec.z, h); + h = hash_murmur3_one_32(p_vec.w, h); + return hash_fmix32(h); + } static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { uint32_t h = hash_murmur3_one_real(p_vec.x); h = hash_murmur3_one_real(p_vec.y, h); @@ -343,6 +352,13 @@ struct HashMapHasherDefault { h = hash_murmur3_one_real(p_vec.z, h); return hash_fmix32(h); } + static _FORCE_INLINE_ uint32_t hash(const Vector4 &p_vec) { + uint32_t h = hash_murmur3_one_real(p_vec.x); + h = hash_murmur3_one_real(p_vec.y, h); + h = hash_murmur3_one_real(p_vec.z, h); + h = hash_murmur3_one_real(p_vec.w, h); + return hash_fmix32(h); + } static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { uint32_t h = hash_murmur3_one_32(p_rect.position.x); h = hash_murmur3_one_32(p_rect.position.y, h); diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h index 8d687effcf..49690f2373 100644 --- a/core/templates/local_vector.h +++ b/core/templates/local_vector.h @@ -37,6 +37,7 @@ #include "core/templates/vector.h" #include <initializer_list> +#include <type_traits> // If tight, it grows strictly as much as needed. // Otherwise, it grows exponentially (the default and what you want in most cases). @@ -67,7 +68,7 @@ public: CRASH_COND_MSG(!data, "Out of memory"); } - if (!__has_trivial_constructor(T) && !force_trivial) { + if (!std::is_trivially_constructible<T>::value && !force_trivial) { memnew_placement(&data[count++], T(p_elem)); } else { data[count++] = p_elem; @@ -80,7 +81,7 @@ public: for (U i = p_index; i < count; i++) { data[i] = data[i + 1]; } - if (!__has_trivial_destructor(T) && !force_trivial) { + if (!std::is_trivially_destructible<T>::value && !force_trivial) { data[count].~T(); } } @@ -93,7 +94,7 @@ public: if (count > p_index) { data[p_index] = data[count]; } - if (!__has_trivial_destructor(T) && !force_trivial) { + if (!std::is_trivially_destructible<T>::value && !force_trivial) { data[count].~T(); } } @@ -134,7 +135,7 @@ public: _FORCE_INLINE_ U size() const { return count; } void resize(U p_size) { if (p_size < count) { - if (!__has_trivial_destructor(T) && !force_trivial) { + if (!std::is_trivially_destructible<T>::value && !force_trivial) { for (U i = p_size; i < count; i++) { data[i].~T(); } @@ -151,7 +152,7 @@ public: data = (T *)memrealloc(data, capacity * sizeof(T)); CRASH_COND_MSG(!data, "Out of memory"); } - if (!__has_trivial_constructor(T) && !force_trivial) { + if (!std::is_trivially_constructible<T>::value && !force_trivial) { for (U i = count; i < p_size; i++) { memnew_placement(&data[i], T); } diff --git a/core/templates/lru.h b/core/templates/lru.h index b08b6455b6..3a78de61db 100644 --- a/core/templates/lru.h +++ b/core/templates/lru.h @@ -124,4 +124,4 @@ public: } }; -#endif +#endif // LRU_H diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h index cf5911a847..43aab052fd 100644 --- a/core/templates/paged_allocator.h +++ b/core/templates/paged_allocator.h @@ -31,11 +31,14 @@ #ifndef PAGED_ALLOCATOR_H #define PAGED_ALLOCATOR_H +#include "core/core_globals.h" #include "core/os/memory.h" #include "core/os/spin_lock.h" +#include "core/string/ustring.h" #include "core/typedefs.h" #include <type_traits> +#include <typeinfo> template <class T, bool thread_safe = false> class PagedAllocator { @@ -132,7 +135,12 @@ public: } ~PagedAllocator() { - ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, "Pages in use exist at exit in PagedAllocator"); + if (allocs_available < pages_allocated * page_size) { + if (CoreGlobals::leak_reporting_enabled) { + ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, String("Pages in use exist at exit in PagedAllocator: ") + String(typeid(T).name())); + } + return; + } reset(); } }; diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h index 33d2757bec..f1ede556e6 100644 --- a/core/templates/paged_array.h +++ b/core/templates/paged_array.h @@ -35,6 +35,8 @@ #include "core/os/spin_lock.h" #include "core/typedefs.h" +#include <type_traits> + // PagedArray is used mainly for filling a very large array from multiple threads efficiently and without causing major fragmentation // PageArrayPool manages central page allocation in a thread safe matter @@ -197,7 +199,7 @@ public: uint32_t page = count >> page_size_shift; uint32_t offset = count & page_size_mask; - if (!__has_trivial_constructor(T)) { + if (!std::is_trivially_constructible<T>::value) { memnew_placement(&page_data[page][offset], T(p_value)); } else { page_data[page][offset] = p_value; @@ -209,7 +211,7 @@ public: _FORCE_INLINE_ void pop_back() { ERR_FAIL_COND(count == 0); - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { uint32_t page = (count - 1) >> page_size_shift; uint32_t offset = (count - 1) & page_size_mask; page_data[page][offset].~T(); @@ -226,7 +228,7 @@ public: void clear() { //destruct if needed - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { for (uint64_t i = 0; i < count; i++) { uint32_t page = i >> page_size_shift; uint32_t offset = i & page_size_mask; @@ -309,13 +311,13 @@ public: uint32_t to_copy = MIN(page_size - new_remainder, remainder); for (uint32_t i = 0; i < to_copy; i++) { - if (!__has_trivial_constructor(T)) { + if (!std::is_trivially_constructible<T>::value) { memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy])); } else { dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy]; } - if (!__has_trivial_destructor(T)) { + if (!std::is_trivially_destructible<T>::value) { remainder_page[i + remainder - to_copy].~T(); } } diff --git a/core/templates/rb_map.h b/core/templates/rb_map.h index c732ccd485..3393e6dd3e 100644 --- a/core/templates/rb_map.h +++ b/core/templates/rb_map.h @@ -758,4 +758,4 @@ public: } }; -#endif // MAP_H +#endif // RB_MAP_H diff --git a/core/templates/rb_set.h b/core/templates/rb_set.h index 226ea979c9..e87ea544fd 100644 --- a/core/templates/rb_set.h +++ b/core/templates/rb_set.h @@ -708,4 +708,4 @@ public: } }; -#endif // SET_H +#endif // RB_SET_H diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h index 9c74b41818..320faebe98 100644 --- a/core/templates/rid_owner.h +++ b/core/templates/rid_owner.h @@ -79,7 +79,7 @@ class RID_Alloc : public RID_AllocBase { const char *description = nullptr; - SpinLock spin_lock; + mutable SpinLock spin_lock; _FORCE_INLINE_ RID _allocate_rid() { if (THREAD_SAFE) { @@ -220,7 +220,7 @@ public: memnew_placement(mem, T(p_value)); } - _FORCE_INLINE_ bool owns(const RID &p_rid) { + _FORCE_INLINE_ bool owns(const RID &p_rid) const { if (THREAD_SAFE) { spin_lock.lock(); } @@ -292,7 +292,7 @@ public: _FORCE_INLINE_ uint32_t get_rid_count() const { return alloc_count; } - void get_owned_list(List<RID> *p_owned) { + void get_owned_list(List<RID> *p_owned) const { if (THREAD_SAFE) { spin_lock.lock(); } @@ -308,7 +308,7 @@ public: } //used for fast iteration in the elements or RIDs - void fill_owned_buffer(RID *p_rid_buffer) { + void fill_owned_buffer(RID *p_rid_buffer) const { if (THREAD_SAFE) { spin_lock.lock(); } @@ -402,7 +402,7 @@ public: *ptr = p_new_ptr; } - _FORCE_INLINE_ bool owns(const RID &p_rid) { + _FORCE_INLINE_ bool owns(const RID &p_rid) const { return alloc.owns(p_rid); } @@ -414,11 +414,11 @@ public: return alloc.get_rid_count(); } - _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) { + _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const { return alloc.get_owned_list(p_owned); } - void fill_owned_buffer(RID *p_rid_buffer) { + void fill_owned_buffer(RID *p_rid_buffer) const { alloc.fill_owned_buffer(p_rid_buffer); } @@ -458,7 +458,7 @@ public: return alloc.get_or_null(p_rid); } - _FORCE_INLINE_ bool owns(const RID &p_rid) { + _FORCE_INLINE_ bool owns(const RID &p_rid) const { return alloc.owns(p_rid); } @@ -470,10 +470,10 @@ public: return alloc.get_rid_count(); } - _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) { + _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const { return alloc.get_owned_list(p_owned); } - void fill_owned_buffer(RID *p_rid_buffer) { + void fill_owned_buffer(RID *p_rid_buffer) const { alloc.fill_owned_buffer(p_rid_buffer); } diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h index 76f76be96a..1f6551762e 100644 --- a/core/templates/safe_refcount.h +++ b/core/templates/safe_refcount.h @@ -111,7 +111,8 @@ public: if (tmp >= p_value) { return tmp; // already greater, or equal } - if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) { + + if (value.compare_exchange_weak(tmp, p_value, std::memory_order_acq_rel)) { return p_value; } } @@ -123,7 +124,7 @@ public: if (c == 0) { return 0; } - if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) { + if (value.compare_exchange_weak(c, c + 1, std::memory_order_acq_rel)) { return c + 1; } } diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h deleted file mode 100644 index b0cebf04f1..0000000000 --- a/core/templates/thread_work_pool.h +++ /dev/null @@ -1,157 +0,0 @@ -/*************************************************************************/ -/* thread_work_pool.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 THREAD_WORK_POOL_H -#define THREAD_WORK_POOL_H - -#include "core/os/memory.h" -#include "core/os/semaphore.h" -#include "core/os/thread.h" - -#include <atomic> - -class ThreadWorkPool { - std::atomic<uint32_t> index; - - struct BaseWork { - std::atomic<uint32_t> *index = nullptr; - uint32_t max_elements = 0; - virtual void work() = 0; - virtual ~BaseWork() = default; - }; - - template <class C, class M, class U> - struct Work : public BaseWork { - C *instance; - M method; - U userdata; - virtual void work() override { - while (true) { - uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed); - if (work_index >= max_elements) { - break; - } - (instance->*method)(work_index, userdata); - } - } - }; - - struct ThreadData { - Thread thread; - Semaphore start; - Semaphore completed; - std::atomic<bool> exit; - BaseWork *work = nullptr; - }; - - ThreadData *threads = nullptr; - uint32_t thread_count = 0; - uint32_t threads_working = 0; - BaseWork *current_work = nullptr; - - static void _thread_function(void *p_user); - -public: - template <class C, class M, class U> - void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - ERR_FAIL_COND(!threads); //never initialized - ERR_FAIL_COND(current_work != nullptr); - - index.store(0, std::memory_order_release); - - Work<C, M, U> *w = memnew((Work<C, M, U>)); - w->instance = p_instance; - w->userdata = p_userdata; - w->method = p_method; - w->index = &index; - w->max_elements = p_elements; - - current_work = w; - - threads_working = MIN(p_elements, thread_count); - - for (uint32_t i = 0; i < threads_working; i++) { - threads[i].work = w; - threads[i].start.post(); - } - } - - bool is_working() const { - return current_work != nullptr; - } - - bool is_done_dispatching() const { - ERR_FAIL_COND_V(current_work == nullptr, true); - return index.load(std::memory_order_acquire) >= current_work->max_elements; - } - - uint32_t get_work_index() const { - ERR_FAIL_COND_V(current_work == nullptr, 0); - uint32_t idx = index.load(std::memory_order_acquire); - return MIN(idx, current_work->max_elements); - } - - void end_work() { - ERR_FAIL_COND(current_work == nullptr); - for (uint32_t i = 0; i < threads_working; i++) { - threads[i].completed.wait(); - threads[i].work = nullptr; - } - - threads_working = 0; - memdelete(current_work); - current_work = nullptr; - } - - template <class C, class M, class U> - void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - switch (p_elements) { - case 0: - // Nothing to do, so do nothing. - break; - case 1: - // No value in pushing the work to another thread if it's a single job - // and we're going to wait for it to finish. Just run it right here. - (p_instance->*p_method)(0, p_userdata); - break; - default: - // Multiple jobs to do; commence threaded business. - begin_work(p_elements, p_instance, p_method, p_userdata); - end_work(); - } - } - - _FORCE_INLINE_ int get_thread_count() const { return thread_count; } - void init(int p_thread_count = -1); - void finish(); - ~ThreadWorkPool(); -}; - -#endif // THREAD_POOL_H diff --git a/core/templates/vector.h b/core/templates/vector.h index f3f5ed76a7..51595a75f5 100644 --- a/core/templates/vector.h +++ b/core/templates/vector.h @@ -89,6 +89,7 @@ public: _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); } + Error resize_zeroed(int p_size) { return _cowdata.template resize<true>(p_size); } _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); } Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); } diff --git a/core/variant/array.cpp b/core/variant/array.cpp index af166e09a3..c1bdd6a6bc 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -441,7 +441,7 @@ Array Array::filter(const Callable &p_callable) const { Variant result; Callable::CallError ce; - p_callable.call(argptrs, 1, result, ce); + p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); } @@ -467,7 +467,7 @@ Array Array::map(const Callable &p_callable) const { Variant result; Callable::CallError ce; - p_callable.call(argptrs, 1, result, ce); + p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); } @@ -493,7 +493,7 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const Variant result; Callable::CallError ce; - p_callable.call(argptrs, 2, result, ce); + p_callable.callp(argptrs, 2, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce)); } @@ -510,7 +510,7 @@ bool Array::any(const Callable &p_callable) const { Variant result; Callable::CallError ce; - p_callable.call(argptrs, 1, result, ce); + p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); } @@ -532,7 +532,7 @@ bool Array::all(const Callable &p_callable) const { Variant result; Callable::CallError ce; - p_callable.call(argptrs, 1, result, ce); + p_callable.callp(argptrs, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); } diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 84f894dcbf..f0c3b1ce38 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -136,7 +136,10 @@ VARIANT_ENUM_CAST(Vector2::Axis); VARIANT_ENUM_CAST(Vector2i::Axis); VARIANT_ENUM_CAST(Vector3::Axis); VARIANT_ENUM_CAST(Vector3i::Axis); +VARIANT_ENUM_CAST(Vector4::Axis); +VARIANT_ENUM_CAST(Vector4i::Axis); VARIANT_ENUM_CAST(Basis::EulerOrder); +VARIANT_ENUM_CAST(Projection::Planes); VARIANT_ENUM_CAST(Error); VARIANT_ENUM_CAST(Side); diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 5453f0d5c6..28efb43fc5 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -36,11 +36,11 @@ #include "core/object/ref_counted.h" #include "core/object/script_language.h" -void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const { +void Callable::call_deferredp(const Variant **p_arguments, int p_argcount) const { MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount); } -void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const { +void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const { if (is_null()) { r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; r_call_error.argument = 0; @@ -63,21 +63,23 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu } } -void Callable::rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const { +Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const { if (is_null()) { r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; r_call_error.argument = 0; r_call_error.expected = 0; + return ERR_UNCONFIGURED; } else if (!is_custom()) { r_call_error.error = CallError::CALL_ERROR_INVALID_METHOD; r_call_error.argument = 0; r_call_error.expected = 0; + return ERR_UNCONFIGURED; } else { - custom->rpc(p_id, p_arguments, p_argcount, r_call_error); + return custom->rpc(p_id, p_arguments, p_argcount, r_call_error); } } -Callable Callable::bind(const Variant **p_arguments, int p_argcount) const { +Callable Callable::bindp(const Variant **p_arguments, int p_argcount) const { Vector<Variant> args; args.resize(p_argcount); for (int i = 0; i < p_argcount; i++) { @@ -316,10 +318,11 @@ StringName CallableCustom::get_method() const { ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text())); } -void CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { +Error CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_call_error.argument = 0; r_call_error.expected = 0; + return ERR_UNCONFIGURED; } const Callable *CallableCustom::get_base_comparator() const { @@ -387,7 +390,7 @@ Error Signal::connect(const Callable &p_callable, uint32_t p_flags) { Object *object = get_object(); ERR_FAIL_COND_V(!object, ERR_UNCONFIGURED); - return object->connect(name, p_callable, varray(), p_flags); + return object->connect(name, p_callable, p_flags); } void Signal::disconnect(const Callable &p_callable) { @@ -435,8 +438,8 @@ bool CallableComparator::operator()(const Variant &p_l, const Variant &p_r) cons const Variant *args[2] = { &p_l, &p_r }; Callable::CallError err; Variant res; - func.call(args, 2, res, err); + func.callp(args, 2, res, err); ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false, - "Error calling compare method: " + Variant::get_callable_error_text(func, args, 1, err)); + "Error calling compare method: " + Variant::get_callable_error_text(func, args, 2, err)); return res; } diff --git a/core/variant/callable.h b/core/variant/callable.h index bbcf5427ba..1f1c983eb3 100644 --- a/core/variant/callable.h +++ b/core/variant/callable.h @@ -45,6 +45,7 @@ class CallableCustom; // but can be optimized or customized. // Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7. + class Callable { alignas(8) StringName method; union { @@ -68,10 +69,10 @@ public: int expected = 0; }; - void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const; - void call_deferred(const Variant **p_arguments, int p_argcount) const; + void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const; + void call_deferredp(const Variant **p_arguments, int p_argcount) const; - void rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const; + Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const; _FORCE_INLINE_ bool is_null() const { return method == StringName() && object == 0; @@ -84,7 +85,10 @@ public: } bool is_valid() const; - Callable bind(const Variant **p_arguments, int p_argcount) const; + template <typename... VarArgs> + Callable bind(VarArgs... p_args); + + Callable bindp(const Variant **p_arguments, int p_argcount) const; Callable unbind(int p_argcount) const; Object *get_object() const; @@ -129,7 +133,7 @@ public: virtual StringName get_method() const; virtual ObjectID get_object() const = 0; //must always be able to provide an object virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0; - virtual void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const; + virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const; virtual const Callable *get_base_comparator() const; CallableCustom(); diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp index 1a400b4360..d26aa2ae46 100644 --- a/core/variant/callable_bind.cpp +++ b/core/variant/callable_bind.cpp @@ -96,7 +96,7 @@ void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Varia args[i + p_argcount] = (const Variant *)&binds[i]; } - callable.call(args, p_argcount + binds.size(), r_return_value, r_call_error); + callable.callp(args, p_argcount + binds.size(), r_return_value, r_call_error); } CallableCustomBind::CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds) { @@ -171,7 +171,7 @@ void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Var r_call_error.expected = argcount; return; } - callable.call(p_arguments, p_argcount - argcount, r_return_value, r_call_error); + callable.callp(p_arguments, p_argcount - argcount, r_return_value, r_call_error); } CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_argcount) { @@ -181,28 +181,3 @@ CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_arg CallableCustomUnbind::~CallableCustomUnbind() { } - -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1) { - const Variant *args[1] = { &p_arg1 }; - return p_callable.bind(args, 1); -} - -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2) { - const Variant *args[2] = { &p_arg1, &p_arg2 }; - return p_callable.bind(args, 2); -} - -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3) { - const Variant *args[3] = { &p_arg1, &p_arg2, &p_arg3 }; - return p_callable.bind(args, 3); -} - -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4) { - const Variant *args[4] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4 }; - return p_callable.bind(args, 4); -} - -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5) { - const Variant *args[5] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5 }; - return p_callable.bind(args, 5); -} diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h index a5c830e109..f7351d29e0 100644 --- a/core/variant/callable_bind.h +++ b/core/variant/callable_bind.h @@ -84,10 +84,4 @@ public: virtual ~CallableCustomUnbind(); }; -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1); -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2); -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3); -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4); -Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5); - #endif // CALLABLE_BIND_H diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index d0acf60c22..0ed70a5504 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -125,7 +125,10 @@ MAKE_PTRARG(Rect2); MAKE_PTRARG(Rect2i); MAKE_PTRARG_BY_REFERENCE(Vector3); MAKE_PTRARG_BY_REFERENCE(Vector3i); +MAKE_PTRARG_BY_REFERENCE(Vector4); +MAKE_PTRARG_BY_REFERENCE(Vector4i); MAKE_PTRARG(Transform2D); +MAKE_PTRARG(Projection); MAKE_PTRARG_BY_REFERENCE(Plane); MAKE_PTRARG(Quaternion); MAKE_PTRARG_BY_REFERENCE(AABB); diff --git a/core/variant/type_info.h b/core/variant/type_info.h index 794274dd77..7372c60754 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -144,12 +144,15 @@ MAKE_TYPE_INFO(Vector3, Variant::VECTOR3) MAKE_TYPE_INFO(Vector2i, Variant::VECTOR2I) MAKE_TYPE_INFO(Rect2i, Variant::RECT2I) MAKE_TYPE_INFO(Vector3i, Variant::VECTOR3I) +MAKE_TYPE_INFO(Vector4, Variant::VECTOR4) +MAKE_TYPE_INFO(Vector4i, Variant::VECTOR4I) MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D) MAKE_TYPE_INFO(Plane, Variant::PLANE) MAKE_TYPE_INFO(Quaternion, Variant::QUATERNION) MAKE_TYPE_INFO(AABB, Variant::AABB) MAKE_TYPE_INFO(Basis, Variant::BASIS) MAKE_TYPE_INFO(Transform3D, Variant::TRANSFORM3D) +MAKE_TYPE_INFO(Projection, Variant::PROJECTION) MAKE_TYPE_INFO(Color, Variant::COLOR) MAKE_TYPE_INFO(StringName, Variant::STRING_NAME) MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH) @@ -289,6 +292,7 @@ public: _FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; } _FORCE_INLINE_ BitField(uint32_t p_value) { value = p_value; } _FORCE_INLINE_ operator uint32_t() const { return value; } + _FORCE_INLINE_ operator Variant() const { return value; } }; #define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \ diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index ae92d7b5c4..a5bc6c229d 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -39,6 +39,10 @@ #include "core/string/print_string.h" #include "core/variant/variant_parser.h" +PagedAllocator<Variant::Pools::BucketSmall, true> Variant::Pools::_bucket_small; +PagedAllocator<Variant::Pools::BucketMedium, true> Variant::Pools::_bucket_medium; +PagedAllocator<Variant::Pools::BucketLarge, true> Variant::Pools::_bucket_large; + String Variant::get_type_name(Variant::Type p_type) { switch (p_type) { case NIL: { @@ -83,6 +87,12 @@ String Variant::get_type_name(Variant::Type p_type) { case VECTOR3I: { return "Vector3i"; } break; + case VECTOR4: { + return "Vector4"; + } break; + case VECTOR4I: { + return "Vector4i"; + } break; case PLANE: { return "Plane"; @@ -102,6 +112,10 @@ String Variant::get_type_name(Variant::Type p_type) { return "Transform3D"; } break; + case PROJECTION: { + return "Projection"; + + } break; // misc types case COLOR: { @@ -298,6 +312,24 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; + case VECTOR4: { + static const Type valid[] = { + VECTOR4I, + NIL, + }; + + valid_types = valid; + + } break; + case VECTOR4I: { + static const Type valid[] = { + VECTOR4, + NIL, + }; + + valid_types = valid; + + } break; case QUATERNION: { static const Type valid[] = { @@ -322,6 +354,16 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { TRANSFORM2D, QUATERNION, BASIS, + PROJECTION, + NIL + }; + + valid_types = valid; + + } break; + case PROJECTION: { + static const Type valid[] = { + TRANSFORM3D, NIL }; @@ -604,6 +646,24 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; + case VECTOR4: { + static const Type valid[] = { + VECTOR4I, + NIL, + }; + + valid_types = valid; + + } break; + case VECTOR4I: { + static const Type valid[] = { + VECTOR4, + NIL, + }; + + valid_types = valid; + + } break; case QUATERNION: { static const Type valid[] = { @@ -628,6 +688,16 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type TRANSFORM2D, QUATERNION, BASIS, + PROJECTION, + NIL + }; + + valid_types = valid; + + } break; + case PROJECTION: { + static const Type valid[] = { + TRANSFORM3D, NIL }; @@ -858,6 +928,14 @@ bool Variant::is_zero() const { return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(); } break; + case VECTOR4: { + return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4(); + + } break; + case VECTOR4I: { + return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i(); + + } break; case PLANE: { return *reinterpret_cast<const Plane *>(_data._mem) == Plane(); @@ -877,6 +955,10 @@ bool Variant::is_zero() const { return *_data._transform3d == Transform3D(); } break; + case PROJECTION: { + return *_data._projection == Projection(); + + } break; // misc types case COLOR: { @@ -998,6 +1080,14 @@ bool Variant::is_one() const { return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1); } break; + case VECTOR4: { + return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4(1, 1, 1, 1); + + } break; + case VECTOR4I: { + return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i(1, 1, 1, 1); + + } break; case PLANE: { return *reinterpret_cast<const Plane *>(_data._mem) == Plane(1, 1, 1, 1); @@ -1076,7 +1166,8 @@ void Variant::reference(const Variant &p_variant) { memnew_placement(_data._mem, Rect2i(*reinterpret_cast<const Rect2i *>(p_variant._data._mem))); } break; case TRANSFORM2D: { - _data._transform2d = memnew(Transform2D(*p_variant._data._transform2d)); + _data._transform2d = (Transform2D *)Pools::_bucket_small.alloc(); + memnew_placement(_data._transform2d, Transform2D(*p_variant._data._transform2d)); } break; case VECTOR3: { memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem))); @@ -1084,23 +1175,33 @@ void Variant::reference(const Variant &p_variant) { case VECTOR3I: { memnew_placement(_data._mem, Vector3i(*reinterpret_cast<const Vector3i *>(p_variant._data._mem))); } break; + case VECTOR4: { + memnew_placement(_data._mem, Vector4(*reinterpret_cast<const Vector4 *>(p_variant._data._mem))); + } break; + case VECTOR4I: { + memnew_placement(_data._mem, Vector4i(*reinterpret_cast<const Vector4i *>(p_variant._data._mem))); + } break; case PLANE: { memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem))); } break; - case AABB: { - _data._aabb = memnew(::AABB(*p_variant._data._aabb)); + _data._aabb = (::AABB *)Pools::_bucket_small.alloc(); + memnew_placement(_data._aabb, ::AABB(*p_variant._data._aabb)); } break; case QUATERNION: { memnew_placement(_data._mem, Quaternion(*reinterpret_cast<const Quaternion *>(p_variant._data._mem))); - } break; case BASIS: { - _data._basis = memnew(Basis(*p_variant._data._basis)); - + _data._basis = (Basis *)Pools::_bucket_medium.alloc(); + memnew_placement(_data._basis, Basis(*p_variant._data._basis)); } break; case TRANSFORM3D: { - _data._transform3d = memnew(Transform3D(*p_variant._data._transform3d)); + _data._transform3d = (Transform3D *)Pools::_bucket_medium.alloc(); + memnew_placement(_data._transform3d, Transform3D(*p_variant._data._transform3d)); + } break; + case PROJECTION: { + _data._projection = (Projection *)Pools::_bucket_large.alloc(); + memnew_placement(_data._projection, Projection(*p_variant._data._projection)); } break; // misc types @@ -1250,6 +1351,12 @@ void Variant::zero() { case VECTOR3I: *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); break; + case VECTOR4: + *reinterpret_cast<Vector4 *>(this->_data._mem) = Vector4(); + break; + case VECTOR4I: + *reinterpret_cast<Vector4i *>(this->_data._mem) = Vector4i(); + break; case PLANE: *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); break; @@ -1280,18 +1387,40 @@ void Variant::_clear_internal() { RECT2 */ case TRANSFORM2D: { - memdelete(_data._transform2d); + if (_data._transform2d) { + _data._transform2d->~Transform2D(); + Pools::_bucket_small.free((Pools::BucketSmall *)_data._transform2d); + _data._transform2d = nullptr; + } } break; case AABB: { - memdelete(_data._aabb); + if (_data._aabb) { + _data._aabb->~AABB(); + Pools::_bucket_small.free((Pools::BucketSmall *)_data._aabb); + _data._aabb = nullptr; + } } break; case BASIS: { - memdelete(_data._basis); + if (_data._basis) { + _data._basis->~Basis(); + Pools::_bucket_medium.free((Pools::BucketMedium *)_data._basis); + _data._basis = nullptr; + } } break; case TRANSFORM3D: { - memdelete(_data._transform3d); + if (_data._transform3d) { + _data._transform3d->~Transform3D(); + Pools::_bucket_medium.free((Pools::BucketMedium *)_data._transform3d); + _data._transform3d = nullptr; + } + } break; + case PROJECTION: { + if (_data._projection) { + _data._projection->~Projection(); + Pools::_bucket_large.free((Pools::BucketLarge *)_data._projection); + _data._projection = nullptr; + } } break; - // misc types case STRING_NAME: { reinterpret_cast<StringName *>(_data._mem)->~StringName(); @@ -1681,6 +1810,10 @@ String Variant::stringify(int recursion_count) const { return operator Vector3(); case VECTOR3I: return operator Vector3i(); + case VECTOR4: + return operator Vector4(); + case VECTOR4I: + return operator Vector4i(); case PLANE: return operator Plane(); case AABB: @@ -1691,6 +1824,8 @@ String Variant::stringify(int recursion_count) const { return operator Basis(); case TRANSFORM3D: return operator Transform3D(); + case PROJECTION: + return operator Projection(); case STRING_NAME: return operator StringName(); case NODE_PATH: @@ -1812,6 +1947,10 @@ Variant::operator Vector2() const { return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y); } else if (type == VECTOR3I) { return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y); + } else if (type == VECTOR4) { + return Vector2(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y); + } else if (type == VECTOR4I) { + return Vector2(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y); } else { return Vector2(); } @@ -1826,6 +1965,10 @@ Variant::operator Vector2i() const { return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y); } else if (type == VECTOR3I) { return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y); + } else if (type == VECTOR4) { + return Vector2(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y); + } else if (type == VECTOR4I) { + return Vector2(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y); } else { return Vector2i(); } @@ -1860,6 +2003,10 @@ Variant::operator Vector3() const { return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0); } else if (type == VECTOR2I) { return Vector3(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0); + } else if (type == VECTOR4) { + return Vector3(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y, reinterpret_cast<const Vector4 *>(_data._mem)->z); + } else if (type == VECTOR4I) { + return Vector3(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y, reinterpret_cast<const Vector4i *>(_data._mem)->z); } else { return Vector3(); } @@ -1874,11 +2021,52 @@ Variant::operator Vector3i() const { return Vector3i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0); } else if (type == VECTOR2I) { return Vector3i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0); + } else if (type == VECTOR4) { + return Vector3i(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y, reinterpret_cast<const Vector4 *>(_data._mem)->z); + } else if (type == VECTOR4I) { + return Vector3i(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y, reinterpret_cast<const Vector4i *>(_data._mem)->z); } else { return Vector3i(); } } +Variant::operator Vector4() const { + if (type == VECTOR4) { + return *reinterpret_cast<const Vector4 *>(_data._mem); + } else if (type == VECTOR4I) { + return *reinterpret_cast<const Vector4i *>(_data._mem); + } else if (type == VECTOR2) { + return Vector4(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0, 0.0); + } else if (type == VECTOR2I) { + return Vector4(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0, 0.0); + } else if (type == VECTOR3) { + return Vector4(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y, reinterpret_cast<const Vector3 *>(_data._mem)->z, 0.0); + } else if (type == VECTOR3I) { + return Vector4(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y, reinterpret_cast<const Vector3i *>(_data._mem)->z, 0.0); + } else { + return Vector4(); + } +} + +Variant::operator Vector4i() const { + if (type == VECTOR4I) { + return *reinterpret_cast<const Vector4i *>(_data._mem); + } else if (type == VECTOR4) { + const Vector4 &v4 = *reinterpret_cast<const Vector4 *>(_data._mem); + return Vector4i(v4.x, v4.y, v4.z, v4.w); + } else if (type == VECTOR2) { + return Vector4i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0, 0.0); + } else if (type == VECTOR2I) { + return Vector4i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0, 0.0); + } else if (type == VECTOR3) { + return Vector4i(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y, reinterpret_cast<const Vector3 *>(_data._mem)->z, 0.0); + } else if (type == VECTOR3I) { + return Vector4i(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y, reinterpret_cast<const Vector3i *>(_data._mem)->z, 0.0); + } else { + return Vector4i(); + } +} + Variant::operator Plane() const { if (type == PLANE) { return *reinterpret_cast<const Plane *>(_data._mem); @@ -1936,11 +2124,37 @@ Variant::operator Transform3D() const { m.origin[0] = t.columns[2][0]; m.origin[1] = t.columns[2][1]; return m; + } else if (type == PROJECTION) { + return *_data._projection; } else { return Transform3D(); } } +Variant::operator Projection() const { + if (type == TRANSFORM3D) { + return *_data._transform3d; + } else if (type == BASIS) { + return Transform3D(*_data._basis, Vector3()); + } else if (type == QUATERNION) { + return Transform3D(Basis(*reinterpret_cast<const Quaternion *>(_data._mem)), Vector3()); + } else if (type == TRANSFORM2D) { + const Transform2D &t = *_data._transform2d; + Transform3D m; + m.basis.rows[0][0] = t.columns[0][0]; + m.basis.rows[1][0] = t.columns[0][1]; + m.basis.rows[0][1] = t.columns[1][0]; + m.basis.rows[1][1] = t.columns[1][1]; + m.origin[0] = t.columns[2][0]; + m.origin[1] = t.columns[2][1]; + return m; + } else if (type == PROJECTION) { + return *_data._projection; + } else { + return Projection(); + } +} + Variant::operator Transform2D() const { if (type == TRANSFORM2D) { return *_data._transform2d; @@ -2384,6 +2598,16 @@ Variant::Variant(const Vector3i &p_vector3i) { memnew_placement(_data._mem, Vector3i(p_vector3i)); } +Variant::Variant(const Vector4 &p_vector4) { + type = VECTOR4; + memnew_placement(_data._mem, Vector4(p_vector4)); +} + +Variant::Variant(const Vector4i &p_vector4i) { + type = VECTOR4I; + memnew_placement(_data._mem, Vector4i(p_vector4i)); +} + Variant::Variant(const Vector2 &p_vector2) { type = VECTOR2; memnew_placement(_data._mem, Vector2(p_vector2)); @@ -2411,12 +2635,14 @@ Variant::Variant(const Plane &p_plane) { Variant::Variant(const ::AABB &p_aabb) { type = AABB; - _data._aabb = memnew(::AABB(p_aabb)); + _data._aabb = (::AABB *)Pools::_bucket_small.alloc(); + memnew_placement(_data._aabb, ::AABB(p_aabb)); } Variant::Variant(const Basis &p_matrix) { type = BASIS; - _data._basis = memnew(Basis(p_matrix)); + _data._basis = (Basis *)Pools::_bucket_medium.alloc(); + memnew_placement(_data._basis, Basis(p_matrix)); } Variant::Variant(const Quaternion &p_quaternion) { @@ -2426,12 +2652,20 @@ Variant::Variant(const Quaternion &p_quaternion) { Variant::Variant(const Transform3D &p_transform) { type = TRANSFORM3D; - _data._transform3d = memnew(Transform3D(p_transform)); + _data._transform3d = (Transform3D *)Pools::_bucket_medium.alloc(); + memnew_placement(_data._transform3d, Transform3D(p_transform)); +} + +Variant::Variant(const Projection &pp_projection) { + type = PROJECTION; + _data._projection = (Projection *)Pools::_bucket_large.alloc(); + memnew_placement(_data._projection, Projection(pp_projection)); } Variant::Variant(const Transform2D &p_transform) { type = TRANSFORM2D; - _data._transform2d = memnew(Transform2D(p_transform)); + _data._transform2d = (Transform2D *)Pools::_bucket_small.alloc(); + memnew_placement(_data._transform2d, Transform2D(p_transform)); } Variant::Variant(const Color &p_color) { @@ -2656,6 +2890,12 @@ void Variant::operator=(const Variant &p_variant) { case VECTOR3I: { *reinterpret_cast<Vector3i *>(_data._mem) = *reinterpret_cast<const Vector3i *>(p_variant._data._mem); } break; + case VECTOR4: { + *reinterpret_cast<Vector4 *>(_data._mem) = *reinterpret_cast<const Vector4 *>(p_variant._data._mem); + } break; + case VECTOR4I: { + *reinterpret_cast<Vector4i *>(_data._mem) = *reinterpret_cast<const Vector4i *>(p_variant._data._mem); + } break; case PLANE: { *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem); } break; @@ -2672,6 +2912,9 @@ void Variant::operator=(const Variant &p_variant) { case TRANSFORM3D: { *_data._transform3d = *(p_variant._data._transform3d); } break; + case PROJECTION: { + *_data._projection = *(p_variant._data._projection); + } break; // misc types case COLOR: { @@ -2817,6 +3060,12 @@ uint32_t Variant::recursive_hash(int recursion_count) const { case VECTOR3I: { return HashMapHasherDefault::hash(*reinterpret_cast<const Vector3i *>(_data._mem)); } break; + case VECTOR4: { + return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4 *>(_data._mem)); + } break; + case VECTOR4I: { + return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4i *>(_data._mem)); + } break; case PLANE: { uint32_t h = HASH_MURMUR3_SEED; const Plane &p = *reinterpret_cast<const Plane *>(_data._mem); @@ -2869,6 +3118,27 @@ uint32_t Variant::recursive_hash(int recursion_count) const { h = hash_murmur3_one_real(t.origin.z, h); return hash_fmix32(h); } break; + case PROJECTION: { + uint32_t h = HASH_MURMUR3_SEED; + const Projection &t = *_data._projection; + h = hash_murmur3_one_real(t.matrix[0].x, h); + h = hash_murmur3_one_real(t.matrix[0].y, h); + h = hash_murmur3_one_real(t.matrix[0].z, h); + h = hash_murmur3_one_real(t.matrix[0].w, h); + h = hash_murmur3_one_real(t.matrix[1].x, h); + h = hash_murmur3_one_real(t.matrix[1].y, h); + h = hash_murmur3_one_real(t.matrix[1].z, h); + h = hash_murmur3_one_real(t.matrix[1].w, h); + h = hash_murmur3_one_real(t.matrix[2].x, h); + h = hash_murmur3_one_real(t.matrix[2].y, h); + h = hash_murmur3_one_real(t.matrix[2].z, h); + h = hash_murmur3_one_real(t.matrix[2].w, h); + h = hash_murmur3_one_real(t.matrix[3].x, h); + h = hash_murmur3_one_real(t.matrix[3].y, h); + h = hash_murmur3_one_real(t.matrix[3].z, h); + h = hash_murmur3_one_real(t.matrix[3].w, h); + return hash_fmix32(h); + } break; // misc types case COLOR: { uint32_t h = HASH_MURMUR3_SEED; @@ -3062,6 +3332,11 @@ uint32_t Variant::recursive_hash(int recursion_count) const { (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \ (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \ (hash_compare_scalar((p_lhs).z, (p_rhs).z)) +#define hash_compare_vector4(p_lhs, p_rhs) \ + (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \ + (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \ + (hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \ + (hash_compare_scalar((p_lhs).w, (p_rhs).w)) #define hash_compare_quaternion(p_lhs, p_rhs) \ (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \ @@ -3165,6 +3440,18 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const return *l == *r; } break; + case VECTOR4: { + const Vector4 *l = reinterpret_cast<const Vector4 *>(_data._mem); + const Vector4 *r = reinterpret_cast<const Vector4 *>(p_variant._data._mem); + + return hash_compare_vector4(*l, *r); + } break; + case VECTOR4I: { + const Vector4i *l = reinterpret_cast<const Vector4i *>(_data._mem); + const Vector4i *r = reinterpret_cast<const Vector4i *>(p_variant._data._mem); + + return *l == *r; + } break; case PLANE: { const Plane *l = reinterpret_cast<const Plane *>(_data._mem); @@ -3215,6 +3502,18 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const return hash_compare_vector3(l->origin, r->origin); } break; + case PROJECTION: { + const Projection *l = _data._projection; + const Projection *r = p_variant._data._projection; + + for (int i = 0; i < 4; i++) { + if (!(hash_compare_vector4(l->matrix[i], r->matrix[i]))) { + return false; + } + } + + return true; + } break; case COLOR: { const Color *l = reinterpret_cast<const Color *>(_data._mem); diff --git a/core/variant/variant.h b/core/variant/variant.h index 872b374b13..212f94a9a8 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -38,6 +38,7 @@ #include "core/math/color.h" #include "core/math/face3.h" #include "core/math/plane.h" +#include "core/math/projection.h" #include "core/math/quaternion.h" #include "core/math/rect2.h" #include "core/math/rect2i.h" @@ -47,10 +48,13 @@ #include "core/math/vector2i.h" #include "core/math/vector3.h" #include "core/math/vector3i.h" +#include "core/math/vector4.h" +#include "core/math/vector4i.h" #include "core/object/object_id.h" #include "core/os/keyboard.h" #include "core/string/node_path.h" #include "core/string/ustring.h" +#include "core/templates/paged_allocator.h" #include "core/templates/rid.h" #include "core/variant/array.h" #include "core/variant/callable.h" @@ -91,11 +95,14 @@ public: VECTOR3, VECTOR3I, TRANSFORM2D, + VECTOR4, + VECTOR4I, PLANE, QUATERNION, AABB, BASIS, TRANSFORM3D, + PROJECTION, // misc types COLOR, @@ -128,6 +135,30 @@ public: }; private: + struct Pools { + union BucketSmall { + BucketSmall() {} + ~BucketSmall() {} + Transform2D _transform2d; + ::AABB _aabb; + }; + union BucketMedium { + BucketMedium() {} + ~BucketMedium() {} + Basis _basis; + Transform3D _transform3d; + }; + union BucketLarge { + BucketLarge() {} + ~BucketLarge() {} + Projection _projection; + }; + + static PagedAllocator<BucketSmall, true> _bucket_small; + static PagedAllocator<BucketMedium, true> _bucket_medium; + static PagedAllocator<BucketLarge, true> _bucket_large; + }; + friend struct _VariantCall; friend class VariantInternal; // Variant takes 20 bytes when real_t is float, and 36 if double @@ -210,6 +241,7 @@ private: ::AABB *_aabb; Basis *_basis; Transform3D *_transform3d; + Projection *_projection; PackedArrayRefBase *packed_array; void *_ptr; //generic pointer uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 }; @@ -234,11 +266,14 @@ private: false, //VECTOR3, false, //VECTOR3I, true, //TRANSFORM2D, + false, //VECTOR4, + false, //VECTOR4I, false, //PLANE, false, //QUATERNION, true, //AABB, true, //BASIS, true, //TRANSFORM, + true, //PROJECTION, // misc types false, //COLOR, @@ -339,12 +374,15 @@ public: operator Rect2i() const; operator Vector3() const; operator Vector3i() const; + operator Vector4() const; + operator Vector4i() const; operator Plane() const; operator ::AABB() const; operator Quaternion() const; operator Basis() const; operator Transform2D() const; operator Transform3D() const; + operator Projection() const; operator Color() const; operator NodePath() const; @@ -409,12 +447,15 @@ public: Variant(const Rect2i &p_rect2i); Variant(const Vector3 &p_vector3); Variant(const Vector3i &p_vector3i); + Variant(const Vector4 &p_vector4); + Variant(const Vector4i &p_vector4i); Variant(const Plane &p_plane); Variant(const ::AABB &p_aabb); Variant(const Quaternion &p_quat); Variant(const Basis &p_matrix); Variant(const Transform2D &p_transform); Variant(const Transform3D &p_transform); + Variant(const Projection &p_projection); Variant(const Color &p_color); Variant(const NodePath &p_node_path); Variant(const ::RID &p_rid); @@ -768,4 +809,14 @@ const Variant::ObjData &Variant::_get_obj() const { String vformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant()); +template <typename... VarArgs> +Callable Callable::bind(VarArgs... p_args) { + Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. + const Variant *argptrs[sizeof...(p_args) + 1]; + for (uint32_t i = 0; i < sizeof...(p_args); i++) { + argptrs[i] = &args[i]; + } + return bindp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); +} + #endif // VARIANT_H diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 8e16a767cf..5c298f9b3b 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -895,17 +895,17 @@ struct _VariantCall { static void func_Callable_call(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); - callable->call(p_args, p_argcount, r_ret, r_error); + callable->callp(p_args, p_argcount, r_ret, r_error); } static void func_Callable_call_deferred(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); - callable->call_deferred(p_args, p_argcount); + callable->call_deferredp(p_args, p_argcount); } static void func_Callable_rpc(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); - callable->rpc(0, p_args, p_argcount, r_error); + callable->rpcp(0, p_args, p_argcount, r_error); } static void func_Callable_rpc_id(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { @@ -920,13 +920,13 @@ struct _VariantCall { r_error.expected = Variant::INT; } else { Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); - callable->rpc(*p_args[0], &p_args[1], p_argcount - 1, r_error); + callable->rpcp(*p_args[0], &p_args[1], p_argcount - 1, r_error); } } static void func_Callable_bind(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); - r_ret = callable->bind(p_args, p_argcount); + r_ret = callable->bindp(p_args, p_argcount); } static void func_Signal_emit(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { @@ -1725,14 +1725,49 @@ static void _register_variant_builtin_methods() { bind_method(Vector3i, abs, sarray(), varray()); bind_method(Vector3i, clamp, sarray("min", "max"), varray()); + /* Vector4 */ + + bind_method(Vector4, min_axis_index, sarray(), varray()); + bind_method(Vector4, max_axis_index, sarray(), varray()); + bind_method(Vector4, length, sarray(), varray()); + bind_method(Vector4, length_squared, sarray(), varray()); + bind_method(Vector4, abs, sarray(), varray()); + bind_method(Vector4, sign, sarray(), varray()); + bind_method(Vector4, floor, sarray(), varray()); + bind_method(Vector4, ceil, sarray(), varray()); + bind_method(Vector4, round, sarray(), varray()); + bind_method(Vector4, lerp, sarray("to", "weight"), varray()); + bind_method(Vector4, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); + bind_method(Vector4, posmod, sarray("mod"), varray()); + bind_method(Vector4, posmodv, sarray("modv"), varray()); + bind_method(Vector4, snapped, sarray("step"), varray()); + bind_method(Vector4, clamp, sarray("min", "max"), varray()); + bind_method(Vector4, normalized, sarray(), varray()); + bind_method(Vector4, is_normalized, sarray(), varray()); + bind_method(Vector4, direction_to, sarray("to"), varray()); + bind_method(Vector4, distance_to, sarray("to"), varray()); + bind_method(Vector4, dot, sarray("with"), varray()); + bind_method(Vector4, inverse, sarray(), varray()); + bind_method(Vector4, is_equal_approx, sarray("with"), varray()); + + /* Vector4i */ + + bind_method(Vector4i, min_axis_index, sarray(), varray()); + bind_method(Vector4i, max_axis_index, sarray(), varray()); + bind_method(Vector4i, length, sarray(), varray()); + bind_method(Vector4i, length_squared, sarray(), varray()); + bind_method(Vector4i, sign, sarray(), varray()); + bind_method(Vector4i, abs, sarray(), varray()); + bind_method(Vector4i, clamp, sarray("min", "max"), varray()); + /* Plane */ bind_method(Plane, normalized, sarray(), varray()); bind_method(Plane, center, sarray(), varray()); bind_method(Plane, is_equal_approx, sarray("to_plane"), varray()); - bind_method(Plane, is_point_over, sarray("plane"), varray()); + bind_method(Plane, is_point_over, sarray("point"), varray()); bind_method(Plane, distance_to, sarray("point"), varray()); - bind_method(Plane, has_point, sarray("point", "epsilon"), varray(CMP_EPSILON)); + bind_method(Plane, has_point, sarray("point", "tolerance"), varray(CMP_EPSILON)); bind_method(Plane, project, sarray("point"), varray()); bind_methodv(Plane, intersect_3, &Plane::intersect_3_bind, sarray("b", "c"), varray()); bind_methodv(Plane, intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray()); @@ -1752,7 +1787,7 @@ static void _register_variant_builtin_methods() { bind_method(Quaternion, dot, sarray("with"), varray()); bind_method(Quaternion, slerp, sarray("to", "weight"), varray()); bind_method(Quaternion, slerpni, sarray("to", "weight"), varray()); - bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray()); + bind_method(Quaternion, spherical_cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); bind_method(Quaternion, get_euler, sarray(), varray()); bind_method(Quaternion, get_axis, sarray(), varray()); bind_method(Quaternion, get_angle, sarray(), varray()); @@ -1853,8 +1888,11 @@ static void _register_variant_builtin_methods() { bind_method(Transform2D, get_skew, sarray(), varray()); bind_method(Transform2D, orthonormalized, sarray(), varray()); bind_method(Transform2D, rotated, sarray("angle"), varray()); + bind_method(Transform2D, rotated_local, sarray("angle"), varray()); bind_method(Transform2D, scaled, sarray("scale"), varray()); + bind_method(Transform2D, scaled_local, sarray("scale"), varray()); bind_method(Transform2D, translated, sarray("offset"), varray()); + bind_method(Transform2D, translated_local, sarray("offset"), varray()); bind_method(Transform2D, basis_xform, sarray("v"), varray()); bind_method(Transform2D, basis_xform_inv, sarray("v"), varray()); bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray()); @@ -1918,13 +1956,50 @@ static void _register_variant_builtin_methods() { bind_method(Transform3D, affine_inverse, sarray(), varray()); bind_method(Transform3D, orthonormalized, sarray(), varray()); bind_method(Transform3D, rotated, sarray("axis", "angle"), varray()); + bind_method(Transform3D, rotated_local, sarray("axis", "angle"), varray()); bind_method(Transform3D, scaled, sarray("scale"), varray()); + bind_method(Transform3D, scaled_local, sarray("scale"), varray()); bind_method(Transform3D, translated, sarray("offset"), varray()); + bind_method(Transform3D, translated_local, sarray("offset"), varray()); bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0))); - bind_method(Transform3D, sphere_interpolate_with, sarray("xform", "weight"), varray()); + bind_method(Transform3D, spherical_interpolate_with, sarray("xform", "weight"), varray()); bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray()); bind_method(Transform3D, is_equal_approx, sarray("xform"), varray()); + /* Projection */ + + bind_static_method(Projection, create_depth_correction, sarray("flip_y"), varray()); + bind_static_method(Projection, create_light_atlas_rect, sarray("rect"), varray()); + bind_static_method(Projection, create_perspective, sarray("fovy", "aspect", "z_near", "z_far", "flip_fov"), varray(false)); + bind_static_method(Projection, create_perspective_hmd, sarray("fovy", "aspect", "z_near", "z_far", "flip_fov", "eye", "intraocular_dist", " convergence_dist"), varray()); + bind_static_method(Projection, create_for_hmd, sarray("eye", "aspect", "intraocular_dist", "display_width", "display_to_lens", "oversample", "z_near", "z_far"), varray()); + bind_static_method(Projection, create_orthogonal, sarray("left", "right", "bottom", "top", "z_near", "z_far"), varray()); + bind_static_method(Projection, create_orthogonal_aspect, sarray("size", "aspect", "z_near", "z_far", "flip_fov"), varray(false)); + bind_static_method(Projection, create_frustum, sarray("left", "right", "bottom", "top", "z_near", "z_far"), varray()); + bind_static_method(Projection, create_frustum_aspect, sarray("size", "aspect", "offset", "z_near", "z_far", "flip_fov"), varray(false)); + bind_static_method(Projection, create_fit_aabb, sarray("aabb"), varray()); + + bind_method(Projection, determinant, sarray(), varray()); + bind_method(Projection, perspective_znear_adjusted, sarray("new_znear"), varray()); + bind_method(Projection, get_projection_plane, sarray("plane"), varray()); + bind_method(Projection, flipped_y, sarray(), varray()); + bind_method(Projection, jitter_offseted, sarray("offset"), varray()); + + bind_static_method(Projection, get_fovy, sarray("fovx", "aspect"), varray()); + + bind_method(Projection, get_z_far, sarray(), varray()); + bind_method(Projection, get_z_near, sarray(), varray()); + bind_method(Projection, get_aspect, sarray(), varray()); + bind_method(Projection, get_fov, sarray(), varray()); + bind_method(Projection, is_orthogonal, sarray(), varray()); + + bind_method(Projection, get_viewport_half_extents, sarray(), varray()); + bind_method(Projection, get_far_plane_half_extents, sarray(), varray()); + + bind_method(Projection, inverse, sarray(), varray()); + bind_method(Projection, get_pixels_per_meter, sarray("for_pixel_width"), varray()); + bind_method(Projection, get_lod_multiplier, sarray(), varray()); + /* Dictionary */ bind_method(Dictionary, size, sarray(), varray()); @@ -1991,7 +2066,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedByteArray, remove_at, sarray("index"), varray()); bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedByteArray, fill, sarray("value"), varray()); - bind_method(PackedByteArray, resize, sarray("new_size"), varray()); + bind_methodv(PackedByteArray, resize, &PackedByteArray::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedByteArray, has, sarray("value"), varray()); bind_method(PackedByteArray, reverse, sarray(), varray()); bind_method(PackedByteArray, slice, sarray("begin", "end"), varray(INT_MAX)); @@ -2055,7 +2130,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt32Array, remove_at, sarray("index"), varray()); bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedInt32Array, fill, sarray("value"), varray()); - bind_method(PackedInt32Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedInt32Array, resize, &PackedInt32Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedInt32Array, has, sarray("value"), varray()); bind_method(PackedInt32Array, reverse, sarray(), varray()); bind_method(PackedInt32Array, slice, sarray("begin", "end"), varray(INT_MAX)); @@ -2078,7 +2153,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt64Array, remove_at, sarray("index"), varray()); bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedInt64Array, fill, sarray("value"), varray()); - bind_method(PackedInt64Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedInt64Array, resize, &PackedInt64Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedInt64Array, has, sarray("value"), varray()); bind_method(PackedInt64Array, reverse, sarray(), varray()); bind_method(PackedInt64Array, slice, sarray("begin", "end"), varray(INT_MAX)); @@ -2101,7 +2176,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat32Array, remove_at, sarray("index"), varray()); bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedFloat32Array, fill, sarray("value"), varray()); - bind_method(PackedFloat32Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedFloat32Array, resize, &PackedFloat32Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedFloat32Array, has, sarray("value"), varray()); bind_method(PackedFloat32Array, reverse, sarray(), varray()); bind_method(PackedFloat32Array, slice, sarray("begin", "end"), varray(INT_MAX)); @@ -2124,7 +2199,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat64Array, remove_at, sarray("index"), varray()); bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedFloat64Array, fill, sarray("value"), varray()); - bind_method(PackedFloat64Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedFloat64Array, resize, &PackedFloat64Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedFloat64Array, has, sarray("value"), varray()); bind_method(PackedFloat64Array, reverse, sarray(), varray()); bind_method(PackedFloat64Array, slice, sarray("begin", "end"), varray(INT_MAX)); @@ -2253,6 +2328,19 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1)); _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); + _VariantCall::add_constant(Variant::VECTOR4, "AXIS_X", Vector4::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Y", Vector4::AXIS_Y); + _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Z", Vector4::AXIS_Z); + _VariantCall::add_constant(Variant::VECTOR4, "AXIS_W", Vector4::AXIS_W); + + _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_X", Vector4::AXIS_X); + _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Y", Vector4::AXIS_Y); + _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Z", Vector4::AXIS_Z); + _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_W", Vector4::AXIS_W); + _VariantCall::add_variant_constant(Variant::VECTOR4, "ZERO", Vector4(0, 0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR4, "ONE", Vector4(1, 1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR4, "INF", Vector4(INFINITY, INFINITY, INFINITY, INFINITY)); + _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X); _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y); _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z); @@ -2261,6 +2349,19 @@ static void _register_variant_builtin_methods() { _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Y", Vector3i::AXIS_Y); _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Z", Vector3i::AXIS_Z); + _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_X", Vector4i::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Y", Vector4i::AXIS_Y); + _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Z", Vector4i::AXIS_Z); + _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_W", Vector4i::AXIS_W); + + _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_X", Vector4i::AXIS_X); + _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Y", Vector4i::AXIS_Y); + _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Z", Vector4i::AXIS_Z); + _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_W", Vector4i::AXIS_W); + + _VariantCall::add_variant_constant(Variant::VECTOR4I, "ZERO", Vector4i(0, 0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR4I, "ONE", Vector4i(1, 1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0)); @@ -2338,6 +2439,25 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0)); _VariantCall::add_variant_constant(Variant::QUATERNION, "IDENTITY", Quaternion(0, 0, 0, 1)); + + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_NEAR", Projection::PLANE_NEAR); + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_FAR", Projection::PLANE_FAR); + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_LEFT", Projection::PLANE_LEFT); + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_TOP", Projection::PLANE_TOP); + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_RIGHT", Projection::PLANE_RIGHT); + _VariantCall::add_constant(Variant::PROJECTION, "PLANE_BOTTOM", Projection::PLANE_BOTTOM); + + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_NEAR", Projection::PLANE_NEAR); + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_FAR", Projection::PLANE_FAR); + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_LEFT", Projection::PLANE_LEFT); + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_TOP", Projection::PLANE_TOP); + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_RIGHT", Projection::PLANE_RIGHT); + _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_BOTTOM", Projection::PLANE_BOTTOM); + + Projection p; + _VariantCall::add_variant_constant(Variant::PROJECTION, "IDENTITY", p); + p.set_zero(); + _VariantCall::add_variant_constant(Variant::PROJECTION, "ZERO", p); } void Variant::_register_variant_methods() { diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp index 78d5433d8c..3a0b6c1bb9 100644 --- a/core/variant/variant_construct.cpp +++ b/core/variant/variant_construct.cpp @@ -111,6 +111,16 @@ void Variant::_register_variant_constructors() { add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from")); add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z")); + add_constructor<VariantConstructNoArgs<Vector4>>(sarray()); + add_constructor<VariantConstructor<Vector4, Vector4>>(sarray("from")); + add_constructor<VariantConstructor<Vector4, Vector4i>>(sarray("from")); + add_constructor<VariantConstructor<Vector4, double, double, double, double>>(sarray("x", "y", "z", "w")); + + add_constructor<VariantConstructNoArgs<Vector4i>>(sarray()); + add_constructor<VariantConstructor<Vector4i, Vector4i>>(sarray("from")); + add_constructor<VariantConstructor<Vector4i, Vector4>>(sarray("from")); + add_constructor<VariantConstructor<Vector4i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "z", "w")); + add_constructor<VariantConstructNoArgs<Transform2D>>(sarray()); add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from")); add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position")); @@ -147,6 +157,11 @@ void Variant::_register_variant_constructors() { add_constructor<VariantConstructor<Transform3D, Transform3D>>(sarray("from")); add_constructor<VariantConstructor<Transform3D, Basis, Vector3>>(sarray("basis", "origin")); add_constructor<VariantConstructor<Transform3D, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin")); + add_constructor<VariantConstructor<Transform3D, Projection>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<Projection>>(sarray()); + add_constructor<VariantConstructor<Projection, Projection>>(sarray("from")); + add_constructor<VariantConstructor<Projection, Transform3D>>(sarray("from")); add_constructor<VariantConstructNoArgs<Color>>(sarray()); add_constructor<VariantConstructor<Color, Color>>(sarray("from")); diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h index 638c0136f3..58a0f34c1e 100644 --- a/core/variant/variant_construct.h +++ b/core/variant/variant_construct.h @@ -63,12 +63,15 @@ MAKE_PTRCONSTRUCT(Rect2); MAKE_PTRCONSTRUCT(Rect2i); MAKE_PTRCONSTRUCT(Vector3); MAKE_PTRCONSTRUCT(Vector3i); +MAKE_PTRCONSTRUCT(Vector4); +MAKE_PTRCONSTRUCT(Vector4i); MAKE_PTRCONSTRUCT(Transform2D); MAKE_PTRCONSTRUCT(Plane); MAKE_PTRCONSTRUCT(Quaternion); MAKE_PTRCONSTRUCT(AABB); MAKE_PTRCONSTRUCT(Basis); MAKE_PTRCONSTRUCT(Transform3D); +MAKE_PTRCONSTRUCT(Projection); MAKE_PTRCONSTRUCT(Color); MAKE_PTRCONSTRUCT(StringName); MAKE_PTRCONSTRUCT(NodePath); diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index e0cfb42e1e..874a183d29 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -36,6 +36,8 @@ // For use when you want to access the internal pointer of a Variant directly. // Use with caution. You need to be sure that the type is correct. class VariantInternal { + friend class Variant; + public: // Set type. _FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) { @@ -138,6 +140,10 @@ public: _FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return reinterpret_cast<const Vector3 *>(v->_data._mem); } _FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return reinterpret_cast<Vector3i *>(v->_data._mem); } _FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return reinterpret_cast<const Vector3i *>(v->_data._mem); } + _FORCE_INLINE_ static Vector4 *get_vector4(Variant *v) { return reinterpret_cast<Vector4 *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector4 *get_vector4(const Variant *v) { return reinterpret_cast<const Vector4 *>(v->_data._mem); } + _FORCE_INLINE_ static Vector4i *get_vector4i(Variant *v) { return reinterpret_cast<Vector4i *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector4i *get_vector4i(const Variant *v) { return reinterpret_cast<const Vector4i *>(v->_data._mem); } _FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return v->_data._transform2d; } _FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return v->_data._transform2d; } _FORCE_INLINE_ static Plane *get_plane(Variant *v) { return reinterpret_cast<Plane *>(v->_data._mem); } @@ -150,6 +156,8 @@ public: _FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return v->_data._basis; } _FORCE_INLINE_ static Transform3D *get_transform(Variant *v) { return v->_data._transform3d; } _FORCE_INLINE_ static const Transform3D *get_transform(const Variant *v) { return v->_data._transform3d; } + _FORCE_INLINE_ static Projection *get_projection(Variant *v) { return v->_data._projection; } + _FORCE_INLINE_ static const Projection *get_projection(const Variant *v) { return v->_data._projection; } // Misc types. _FORCE_INLINE_ static Color *get_color(Variant *v) { return reinterpret_cast<Color *>(v->_data._mem); } @@ -209,21 +217,30 @@ public: } _FORCE_INLINE_ static void init_transform2d(Variant *v) { - v->_data._transform2d = memnew(Transform2D); + v->_data._transform2d = (Transform2D *)Variant::Pools::_bucket_small.alloc(); + memnew_placement(v->_data._transform2d, Transform2D); v->type = Variant::TRANSFORM2D; } _FORCE_INLINE_ static void init_aabb(Variant *v) { - v->_data._aabb = memnew(AABB); + v->_data._aabb = (AABB *)Variant::Pools::_bucket_small.alloc(); + memnew_placement(v->_data._aabb, AABB); v->type = Variant::AABB; } _FORCE_INLINE_ static void init_basis(Variant *v) { - v->_data._basis = memnew(Basis); + v->_data._basis = (Basis *)Variant::Pools::_bucket_medium.alloc(); + memnew_placement(v->_data._basis, Basis); v->type = Variant::BASIS; } _FORCE_INLINE_ static void init_transform(Variant *v) { - v->_data._transform3d = memnew(Transform3D); + v->_data._transform3d = (Transform3D *)Variant::Pools::_bucket_medium.alloc(); + memnew_placement(v->_data._transform3d, Transform3D); v->type = Variant::TRANSFORM3D; } + _FORCE_INLINE_ static void init_projection(Variant *v) { + v->_data._projection = (Projection *)Variant::Pools::_bucket_large.alloc(); + memnew_placement(v->_data._projection, Projection); + v->type = Variant::PROJECTION; + } _FORCE_INLINE_ static void init_string_name(Variant *v) { memnew_placement(v->_data._mem, StringName); v->type = Variant::STRING_NAME; @@ -331,12 +348,18 @@ public: return get_vector3(v); case Variant::VECTOR3I: return get_vector3i(v); + case Variant::VECTOR4: + return get_vector4(v); + case Variant::VECTOR4I: + return get_vector4i(v); case Variant::RECT2: return get_rect2(v); case Variant::RECT2I: return get_rect2i(v); case Variant::TRANSFORM3D: return get_transform(v); + case Variant::PROJECTION: + return get_projection(v); case Variant::TRANSFORM2D: return get_transform2d(v); case Variant::QUATERNION: @@ -409,12 +432,18 @@ public: return get_vector3(v); case Variant::VECTOR3I: return get_vector3i(v); + case Variant::VECTOR4: + return get_vector4(v); + case Variant::VECTOR4I: + return get_vector4i(v); case Variant::RECT2: return get_rect2(v); case Variant::RECT2I: return get_rect2i(v); case Variant::TRANSFORM3D: return get_transform(v); + case Variant::PROJECTION: + return get_projection(v); case Variant::TRANSFORM2D: return get_transform2d(v); case Variant::QUATERNION: @@ -599,6 +628,17 @@ struct VariantGetInternalPtr<Vector3i> { }; template <> +struct VariantGetInternalPtr<Vector4> { + static Vector4 *get_ptr(Variant *v) { return VariantInternal::get_vector4(v); } + static const Vector4 *get_ptr(const Variant *v) { return VariantInternal::get_vector4(v); } +}; + +template <> +struct VariantGetInternalPtr<Vector4i> { + static Vector4i *get_ptr(Variant *v) { return VariantInternal::get_vector4i(v); } + static const Vector4i *get_ptr(const Variant *v) { return VariantInternal::get_vector4i(v); } +}; +template <> struct VariantGetInternalPtr<Transform2D> { static Transform2D *get_ptr(Variant *v) { return VariantInternal::get_transform2d(v); } static const Transform2D *get_ptr(const Variant *v) { return VariantInternal::get_transform2d(v); } @@ -611,6 +651,12 @@ struct VariantGetInternalPtr<Transform3D> { }; template <> +struct VariantGetInternalPtr<Projection> { + static Projection *get_ptr(Variant *v) { return VariantInternal::get_projection(v); } + static const Projection *get_ptr(const Variant *v) { return VariantInternal::get_projection(v); } +}; + +template <> struct VariantGetInternalPtr<Plane> { static Plane *get_ptr(Variant *v) { return VariantInternal::get_plane(v); } static const Plane *get_ptr(const Variant *v) { return VariantInternal::get_plane(v); } @@ -772,6 +818,10 @@ VARIANT_ACCESSOR_NUMBER(Vector2::Axis) VARIANT_ACCESSOR_NUMBER(Vector2i::Axis) VARIANT_ACCESSOR_NUMBER(Vector3::Axis) VARIANT_ACCESSOR_NUMBER(Vector3i::Axis) +VARIANT_ACCESSOR_NUMBER(Vector4::Axis) +VARIANT_ACCESSOR_NUMBER(Vector4i::Axis) + +VARIANT_ACCESSOR_NUMBER(Projection::Planes) template <> struct VariantInternalAccessor<Basis::EulerOrder> { @@ -840,6 +890,17 @@ struct VariantInternalAccessor<Vector3i> { }; template <> +struct VariantInternalAccessor<Vector4> { + static _FORCE_INLINE_ const Vector4 &get(const Variant *v) { return *VariantInternal::get_vector4(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector4 &p_value) { *VariantInternal::get_vector4(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector4i> { + static _FORCE_INLINE_ const Vector4i &get(const Variant *v) { return *VariantInternal::get_vector4i(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector4i &p_value) { *VariantInternal::get_vector4i(v) = p_value; } +}; +template <> struct VariantInternalAccessor<Transform2D> { static _FORCE_INLINE_ const Transform2D &get(const Variant *v) { return *VariantInternal::get_transform2d(v); } static _FORCE_INLINE_ void set(Variant *v, const Transform2D &p_value) { *VariantInternal::get_transform2d(v) = p_value; } @@ -852,6 +913,12 @@ struct VariantInternalAccessor<Transform3D> { }; template <> +struct VariantInternalAccessor<Projection> { + static _FORCE_INLINE_ const Projection &get(const Variant *v) { return *VariantInternal::get_projection(v); } + static _FORCE_INLINE_ void set(Variant *v, const Projection &p_value) { *VariantInternal::get_projection(v) = p_value; } +}; + +template <> struct VariantInternalAccessor<Plane> { static _FORCE_INLINE_ const Plane &get(const Variant *v) { return *VariantInternal::get_plane(v); } static _FORCE_INLINE_ void set(Variant *v, const Plane &p_value) { *VariantInternal::get_plane(v) = p_value; } @@ -1041,6 +1108,8 @@ INITIALIZER_INT(Vector2::Axis) INITIALIZER_INT(Vector2i::Axis) INITIALIZER_INT(Vector3::Axis) INITIALIZER_INT(Vector3i::Axis) +INITIALIZER_INT(Vector4::Axis) +INITIALIZER_INT(Vector4i::Axis) template <> struct VariantInitializer<double> { @@ -1086,8 +1155,16 @@ template <> struct VariantInitializer<Vector3i> { static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3i>(v); } }; +template <> +struct VariantInitializer<Vector4> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector4>(v); } +}; template <> +struct VariantInitializer<Vector4i> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector4i>(v); } +}; +template <> struct VariantInitializer<Transform2D> { static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform2d(v); } }; @@ -1116,6 +1193,10 @@ template <> struct VariantInitializer<Transform3D> { static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); } }; +template <> +struct VariantInitializer<Projection> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_projection(v); } +}; template <> struct VariantInitializer<Color> { @@ -1267,6 +1348,16 @@ struct VariantZeroAssigner<Vector3i> { }; template <> +struct VariantZeroAssigner<Vector4> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector4(v) = Vector4(); } +}; + +template <> +struct VariantZeroAssigner<Vector4i> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector4i(v) = Vector4i(); } +}; + +template <> struct VariantZeroAssigner<Transform2D> { static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform2d(v) = Transform2D(); } }; @@ -1297,6 +1388,11 @@ struct VariantZeroAssigner<Transform3D> { }; template <> +struct VariantZeroAssigner<Projection> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_projection(v) = Projection(); } +}; + +template <> struct VariantZeroAssigner<Color> { static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color(v) = Color(); } }; diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index adace2b534..6cca7955ae 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -165,6 +165,70 @@ public: static Variant::Type get_return_type() { return GetTypeInfo<Vector3>::VARIANT_TYPE; } }; +// + +template <> +class OperatorEvaluatorMul<Vector4, Vector4i, double> { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_right); + *r_ret = Vector4(a.x, a.y, a.z, a.w) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(left)->x, VariantGetInternalPtr<Vector4i>::get_ptr(left)->y, VariantGetInternalPtr<Vector4i>::get_ptr(left)->z, VariantGetInternalPtr<Vector4i>::get_ptr(left)->w) * *VariantGetInternalPtr<double>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(left).x, PtrToArg<Vector4i>::convert(left).y, PtrToArg<Vector4i>::convert(left).z, PtrToArg<Vector4i>::convert(left).w) * PtrToArg<double>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorMul<Vector4, double, Vector4i> { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right); + const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_left); + *r_ret = Vector4(a.x, a.y, a.z, a.w) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(right)->x, VariantGetInternalPtr<Vector4i>::get_ptr(right)->y, VariantGetInternalPtr<Vector4i>::get_ptr(right)->z, VariantGetInternalPtr<Vector4i>::get_ptr(right)->w) * *VariantGetInternalPtr<double>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(right).x, PtrToArg<Vector4i>::convert(right).y, PtrToArg<Vector4i>::convert(right).z, PtrToArg<Vector4i>::convert(right).w) * PtrToArg<double>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorDivNZ<Vector4, Vector4i, double> { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_right); + if (unlikely(b == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = Vector4(a.x, a.y, a.z, a.w) / b; + r_valid = true; + } + + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(left)->x, VariantGetInternalPtr<Vector4i>::get_ptr(left)->y, VariantGetInternalPtr<Vector4i>::get_ptr(left)->z, VariantGetInternalPtr<Vector4i>::get_ptr(left)->w) / *VariantGetInternalPtr<double>::get_ptr(right); + } + + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(left).x, PtrToArg<Vector4i>::convert(left).y, PtrToArg<Vector4i>::convert(left).z, PtrToArg<Vector4i>::convert(left).w) / PtrToArg<double>::convert(right), r_ret); + } + + static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; } +}; + void Variant::_register_variant_operators() { memset(operator_return_type_table, 0, sizeof(operator_return_type_table)); memset(operator_evaluator_table, 0, sizeof(operator_evaluator_table)); @@ -182,6 +246,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorAdd<Vector3i, Vector3i, Vector3i>>(Variant::OP_ADD, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorAdd<Vector4, Vector4, Vector4>>(Variant::OP_ADD, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorAdd<Vector4i, Vector4i, Vector4i>>(Variant::OP_ADD, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorAdd<Quaternion, Quaternion, Quaternion>>(Variant::OP_ADD, Variant::QUATERNION, Variant::QUATERNION); register_op<OperatorEvaluatorAdd<Color, Color, Color>>(Variant::OP_ADD, Variant::COLOR, Variant::COLOR); register_op<OperatorEvaluatorAddArray>(Variant::OP_ADD, Variant::ARRAY, Variant::ARRAY); @@ -203,6 +269,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorSub<Vector2i, Vector2i, Vector2i>>(Variant::OP_SUBTRACT, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorSub<Vector3, Vector3, Vector3>>(Variant::OP_SUBTRACT, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorSub<Vector3i, Vector3i, Vector3i>>(Variant::OP_SUBTRACT, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorSub<Vector4, Vector4, Vector4>>(Variant::OP_SUBTRACT, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorSub<Vector4i, Vector4i, Vector4i>>(Variant::OP_SUBTRACT, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorSub<Quaternion, Quaternion, Quaternion>>(Variant::OP_SUBTRACT, Variant::QUATERNION, Variant::QUATERNION); register_op<OperatorEvaluatorSub<Color, Color, Color>>(Variant::OP_SUBTRACT, Variant::COLOR, Variant::COLOR); @@ -212,6 +280,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorMul<Vector2i, int64_t, Vector2i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR2I); register_op<OperatorEvaluatorMul<Vector3, int64_t, Vector3>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3); register_op<OperatorEvaluatorMul<Vector3i, int64_t, Vector3i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3I); + register_op<OperatorEvaluatorMul<Vector4, int64_t, Vector4>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR4); + register_op<OperatorEvaluatorMul<Vector4i, int64_t, Vector4i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR4I); register_op<OperatorEvaluatorMul<double, double, double>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::FLOAT); register_op<OperatorEvaluatorMul<double, double, int64_t>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::INT); @@ -219,6 +289,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorMul<Vector2, double, Vector2i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I); register_op<OperatorEvaluatorMul<Vector3, double, Vector3>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3); register_op<OperatorEvaluatorMul<Vector3, double, Vector3i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I); + register_op<OperatorEvaluatorMul<Vector4, double, Vector4>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR4); + register_op<OperatorEvaluatorMul<Vector4, double, Vector4i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR4I); register_op<OperatorEvaluatorMul<Vector2, Vector2, Vector2>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::VECTOR2); register_op<OperatorEvaluatorMul<Vector2, Vector2, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::INT); @@ -236,6 +308,14 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorMul<Vector3i, Vector3i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT); register_op<OperatorEvaluatorMul<Vector3, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT); + register_op<OperatorEvaluatorMul<Vector4, Vector4, Vector4>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorMul<Vector4, Vector4, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::INT); + register_op<OperatorEvaluatorMul<Vector4, Vector4, double>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Vector4i, Vector4i, Vector4i>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::VECTOR4I); + register_op<OperatorEvaluatorMul<Vector4i, Vector4i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::INT); + register_op<OperatorEvaluatorMul<Vector4, Vector4i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::FLOAT); + register_op<OperatorEvaluatorMul<Quaternion, Quaternion, Quaternion>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION); register_op<OperatorEvaluatorMul<Quaternion, Quaternion, int64_t>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT); register_op<OperatorEvaluatorMul<Quaternion, Quaternion, double>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::FLOAT); @@ -261,9 +341,16 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform3D>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM3D); register_op<OperatorEvaluatorXForm<::AABB, Transform3D, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::AABB); register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform3D>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM3D); + register_op<OperatorEvaluatorXForm<Plane, Transform3D, Plane>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PLANE); + register_op<OperatorEvaluatorXFormInv<Plane, Plane, Transform3D>>(Variant::OP_MULTIPLY, Variant::PLANE, Variant::TRANSFORM3D); register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform3D, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform3D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM3D); + register_op<OperatorEvaluatorXForm<Vector4, Projection, Vector4>>(Variant::OP_MULTIPLY, Variant::PROJECTION, Variant::VECTOR4); + register_op<OperatorEvaluatorXFormInv<Vector4, Vector4, Projection>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::PROJECTION); + + register_op<OperatorEvaluatorMul<Projection, Projection, Projection>>(Variant::OP_MULTIPLY, Variant::PROJECTION, Variant::PROJECTION); + register_op<OperatorEvaluatorMul<Basis, Basis, Basis>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::BASIS); register_op<OperatorEvaluatorMul<Basis, Basis, int64_t>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::INT); register_op<OperatorEvaluatorMul<Basis, Basis, double>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::FLOAT); @@ -309,6 +396,14 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorDivNZ<Vector3, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT); register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT); + register_op<OperatorEvaluatorDiv<Vector4, Vector4, Vector4>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorDiv<Vector4, Vector4, double>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Vector4, Vector4, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::INT); + + register_op<OperatorEvaluatorDivNZ<Vector4i, Vector4i, Vector4i>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::VECTOR4I); + register_op<OperatorEvaluatorDivNZ<Vector4, Vector4i, double>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::FLOAT); + register_op<OperatorEvaluatorDivNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::INT); + register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, double>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT); register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, int64_t>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::INT); @@ -323,6 +418,9 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorModNZ<Vector3i, Vector3i, Vector3i>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::VECTOR3I); register_op<OperatorEvaluatorModNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::INT); + register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, Vector4i>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::VECTOR4I); + register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::INT); + register_op<OperatorEvaluatorStringModNil>(Variant::OP_MODULE, Variant::STRING, Variant::NIL); register_op<OperatorEvaluatorStringModT<bool>>(Variant::OP_MODULE, Variant::STRING, Variant::BOOL); @@ -335,12 +433,15 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorStringModT<Rect2i>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2I); register_op<OperatorEvaluatorStringModT<Vector3>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3); register_op<OperatorEvaluatorStringModT<Vector3i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3I); + register_op<OperatorEvaluatorStringModT<Vector4>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4); + register_op<OperatorEvaluatorStringModT<Vector4i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4I); register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D); register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE); register_op<OperatorEvaluatorStringModT<Quaternion>>(Variant::OP_MODULE, Variant::STRING, Variant::QUATERNION); register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB); register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS); register_op<OperatorEvaluatorStringModT<Transform3D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM3D); + register_op<OperatorEvaluatorStringModT<Projection>>(Variant::OP_MODULE, Variant::STRING, Variant::PROJECTION); register_op<OperatorEvaluatorStringModT<Color>>(Variant::OP_MODULE, Variant::STRING, Variant::COLOR); register_op<OperatorEvaluatorStringModT<StringName>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING_NAME); @@ -372,6 +473,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNeg<Vector2i, Vector2i>>(Variant::OP_NEGATE, Variant::VECTOR2I, Variant::NIL); register_op<OperatorEvaluatorNeg<Vector3, Vector3>>(Variant::OP_NEGATE, Variant::VECTOR3, Variant::NIL); register_op<OperatorEvaluatorNeg<Vector3i, Vector3i>>(Variant::OP_NEGATE, Variant::VECTOR3I, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector4, Vector4>>(Variant::OP_NEGATE, Variant::VECTOR4, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector4i, Vector4i>>(Variant::OP_NEGATE, Variant::VECTOR4I, Variant::NIL); register_op<OperatorEvaluatorNeg<Quaternion, Quaternion>>(Variant::OP_NEGATE, Variant::QUATERNION, Variant::NIL); register_op<OperatorEvaluatorNeg<Plane, Plane>>(Variant::OP_NEGATE, Variant::PLANE, Variant::NIL); register_op<OperatorEvaluatorNeg<Color, Color>>(Variant::OP_NEGATE, Variant::COLOR, Variant::NIL); @@ -382,6 +485,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorPos<Vector2i, Vector2i>>(Variant::OP_POSITIVE, Variant::VECTOR2I, Variant::NIL); register_op<OperatorEvaluatorPos<Vector3, Vector3>>(Variant::OP_POSITIVE, Variant::VECTOR3, Variant::NIL); register_op<OperatorEvaluatorPos<Vector3i, Vector3i>>(Variant::OP_POSITIVE, Variant::VECTOR3I, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector4, Vector4>>(Variant::OP_POSITIVE, Variant::VECTOR4, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector4i, Vector4i>>(Variant::OP_POSITIVE, Variant::VECTOR4I, Variant::NIL); register_op<OperatorEvaluatorPos<Quaternion, Quaternion>>(Variant::OP_POSITIVE, Variant::QUATERNION, Variant::NIL); register_op<OperatorEvaluatorPos<Plane, Plane>>(Variant::OP_POSITIVE, Variant::PLANE, Variant::NIL); register_op<OperatorEvaluatorPos<Color, Color>>(Variant::OP_POSITIVE, Variant::COLOR, Variant::NIL); @@ -409,11 +514,14 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorEqual<Vector3, Vector3>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorEqual<Vector3i, Vector3i>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorEqual<Vector4, Vector4>>(Variant::OP_EQUAL, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorEqual<Vector4i, Vector4i>>(Variant::OP_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE); register_op<OperatorEvaluatorEqual<Quaternion, Quaternion>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::QUATERNION); register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB); register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS); register_op<OperatorEvaluatorEqual<Transform3D, Transform3D>>(Variant::OP_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D); + register_op<OperatorEvaluatorEqual<Projection, Projection>>(Variant::OP_EQUAL, Variant::PROJECTION, Variant::PROJECTION); register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR); register_op<OperatorEvaluatorEqual<StringName, String>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING); @@ -451,6 +559,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL>>(Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR4, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR4, Variant::NIL); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR4I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR4I, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_EQUAL, Variant::PLANE, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL); @@ -485,6 +595,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4I); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_EQUAL, Variant::NIL, Variant::PLANE); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION); @@ -522,12 +634,15 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNotEqual<Rect2i, Rect2i>>(Variant::OP_NOT_EQUAL, Variant::RECT2I, Variant::RECT2I); register_op<OperatorEvaluatorNotEqual<Vector3, Vector3>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorNotEqual<Vector3i, Vector3i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorNotEqual<Vector4, Vector4>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorNotEqual<Vector4i, Vector4i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D); register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE); register_op<OperatorEvaluatorNotEqual<Quaternion, Quaternion>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::QUATERNION); register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB); register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS); register_op<OperatorEvaluatorNotEqual<Transform3D, Transform3D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D); + register_op<OperatorEvaluatorNotEqual<Projection, Projection>>(Variant::OP_NOT_EQUAL, Variant::PROJECTION, Variant::PROJECTION); register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR); register_op<OperatorEvaluatorNotEqual<StringName, String>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING); @@ -566,6 +681,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::NIL); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL); @@ -599,6 +716,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4I); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION); @@ -634,6 +753,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorLess<Vector2i, Vector2i>>(Variant::OP_LESS, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorLess<Vector3, Vector3>>(Variant::OP_LESS, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorLess<Vector3i, Vector3i>>(Variant::OP_LESS, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorLess<Vector4, Vector4>>(Variant::OP_LESS, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorLess<Vector4i, Vector4i>>(Variant::OP_LESS, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorLess<::RID, ::RID>>(Variant::OP_LESS, Variant::RID, Variant::RID); register_op<OperatorEvaluatorLess<Array, Array>>(Variant::OP_LESS, Variant::ARRAY, Variant::ARRAY); @@ -647,6 +768,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorLessEqual<Vector2i, Vector2i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorLessEqual<Vector3, Vector3>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorLessEqual<Vector3i, Vector3i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorLessEqual<Vector4, Vector4>>(Variant::OP_LESS_EQUAL, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorLessEqual<Vector4i, Vector4i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorLessEqual<::RID, ::RID>>(Variant::OP_LESS_EQUAL, Variant::RID, Variant::RID); register_op<OperatorEvaluatorLessEqual<Array, Array>>(Variant::OP_LESS_EQUAL, Variant::ARRAY, Variant::ARRAY); @@ -661,6 +784,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorGreater<Vector2i, Vector2i>>(Variant::OP_GREATER, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorGreater<Vector3, Vector3>>(Variant::OP_GREATER, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorGreater<Vector3i, Vector3i>>(Variant::OP_GREATER, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorGreater<Vector4, Vector4>>(Variant::OP_GREATER, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorGreater<Vector4i, Vector4i>>(Variant::OP_GREATER, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorGreater<::RID, ::RID>>(Variant::OP_GREATER, Variant::RID, Variant::RID); register_op<OperatorEvaluatorGreater<Array, Array>>(Variant::OP_GREATER, Variant::ARRAY, Variant::ARRAY); @@ -674,6 +799,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorGreaterEqual<Vector2i, Vector2i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorGreaterEqual<Vector3, Vector3>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3, Variant::VECTOR3); register_op<OperatorEvaluatorGreaterEqual<Vector3i, Vector3i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorGreaterEqual<Vector4, Vector4>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR4, Variant::VECTOR4); + register_op<OperatorEvaluatorGreaterEqual<Vector4i, Vector4i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorGreaterEqual<::RID, ::RID>>(Variant::OP_GREATER_EQUAL, Variant::RID, Variant::RID); register_op<OperatorEvaluatorGreaterEqual<Array, Array>>(Variant::OP_GREATER_EQUAL, Variant::ARRAY, Variant::ARRAY); @@ -788,12 +915,15 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInDictionaryHas<Rect2i>>(Variant::OP_IN, Variant::RECT2I, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Vector3>>(Variant::OP_IN, Variant::VECTOR3, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Vector3i>>(Variant::OP_IN, Variant::VECTOR3I, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector4>>(Variant::OP_IN, Variant::VECTOR4, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector4i>>(Variant::OP_IN, Variant::VECTOR4I, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Quaternion>>(Variant::OP_IN, Variant::QUATERNION, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Transform3D>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Projection>>(Variant::OP_IN, Variant::PROJECTION, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<Color>>(Variant::OP_IN, Variant::COLOR, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::DICTIONARY); @@ -825,12 +955,15 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInArrayFind<Rect2i, Array>>(Variant::OP_IN, Variant::RECT2I, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Vector3, Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Vector3i, Array>>(Variant::OP_IN, Variant::VECTOR3I, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector4, Array>>(Variant::OP_IN, Variant::VECTOR4, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector4i, Array>>(Variant::OP_IN, Variant::VECTOR4I, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Quaternion, Array>>(Variant::OP_IN, Variant::QUATERNION, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Transform3D, Array>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Projection, Array>>(Variant::OP_IN, Variant::PROJECTION, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<Color, Array>>(Variant::OP_IN, Variant::COLOR, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<StringName, Array>>(Variant::OP_IN, Variant::STRING_NAME, Variant::ARRAY); diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index 3e9bae1078..ec1ce67445 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -234,6 +234,30 @@ public: static Variant::Type get_return_type() { return GetTypeInfo<Vector3i>::VARIANT_TYPE; } }; +template <> +class OperatorEvaluatorDivNZ<Vector4i, Vector4i, Vector4i> { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left); + const Vector4i &b = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0 || b.z == 0 || b.w == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = a / b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<Vector4i>::change(r_ret); + *VariantGetInternalPtr<Vector4i>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector4i>::get_ptr(left) / *VariantGetInternalPtr<Vector4i>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<Vector4i>::encode(PtrToArg<Vector4i>::convert(left) / PtrToArg<Vector4i>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; } +}; + template <class R, class A, class B> class OperatorEvaluatorMod { public: @@ -323,6 +347,30 @@ public: static Variant::Type get_return_type() { return GetTypeInfo<Vector3i>::VARIANT_TYPE; } }; +template <> +class OperatorEvaluatorModNZ<Vector4i, Vector4i, Vector4i> { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left); + const Vector4i &b = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0 || b.z == 0 || b.w == 0)) { + r_valid = false; + *r_ret = "Module by zero error"; + return; + } + *r_ret = a % b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<Vector4i>::change(r_ret); + *VariantGetInternalPtr<Vector4i>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector4i>::get_ptr(left) % *VariantGetInternalPtr<Vector4i>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<Vector4i>::encode(PtrToArg<Vector4i>::convert(left) % PtrToArg<Vector4i>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; } +}; + template <class R, class A> class OperatorEvaluatorNeg { public: diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 259ca8a60d..34653310b1 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -649,6 +649,32 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = Vector3i(args[0], args[1], args[2]); + } else if (id == "Vector4") { + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); + if (err) { + return err; + } + + if (args.size() != 4) { + r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; + } + + value = Vector4(args[0], args[1], args[2], args[3]); + } else if (id == "Vector4i") { + Vector<int32_t> args; + Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str); + if (err) { + return err; + } + + if (args.size() != 4) { + r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; + } + + value = Vector4i(args[0], args[1], args[2], args[3]); } else if (id == "Transform2D" || id == "Matrix32") { //compatibility Vector<real_t> args; Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); @@ -731,6 +757,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = Transform3D(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11])); + } else if (id == "Projection") { // "Transform" kept for compatibility with Godot <4. + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); + if (err) { + return err; + } + + if (args.size() != 16) { + r_err_str = "Expected 16 arguments for constructor"; + return ERR_PARSE_ERROR; + } + + value = Projection(Vector4(args[0], args[1], args[2], args[3]), Vector4(args[4], args[5], args[6], args[7]), Vector4(args[8], args[9], args[10], args[11]), Vector4(args[12], args[13], args[14], args[15])); } else if (id == "Color") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); @@ -1534,6 +1573,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str Vector3i v = p_variant; p_store_string_func(p_store_string_ud, "Vector3i(" + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + ")"); } break; + case Variant::VECTOR4: { + Vector4 v = p_variant; + p_store_string_func(p_store_string_ud, "Vector4(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ", " + rtos_fix(v.z) + ", " + rtos_fix(v.w) + ")"); + } break; + case Variant::VECTOR4I: { + Vector4i v = p_variant; + p_store_string_func(p_store_string_ud, "Vector4i(" + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + ", " + itos(v.w) + ")"); + } break; case Variant::PLANE: { Plane p = p_variant; p_store_string_func(p_store_string_ud, "Plane(" + rtos_fix(p.normal.x) + ", " + rtos_fix(p.normal.y) + ", " + rtos_fix(p.normal.z) + ", " + rtos_fix(p.d) + ")"); @@ -1596,6 +1643,20 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, s + ")"); } break; + case Variant::PROJECTION: { + String s = "Projection("; + Projection t = p_variant; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i != 0 || j != 0) { + s += ", "; + } + s += rtos_fix(t.matrix[i][j]); + } + } + + p_store_string_func(p_store_string_ud, s + ")"); + } break; // misc types case Variant::COLOR: { diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 3839da495f..57b953f7f0 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -77,6 +77,16 @@ void register_named_setters_getters() { REGISTER_MEMBER(Vector3i, y); REGISTER_MEMBER(Vector3i, z); + REGISTER_MEMBER(Vector4, x); + REGISTER_MEMBER(Vector4, y); + REGISTER_MEMBER(Vector4, z); + REGISTER_MEMBER(Vector4, w); + + REGISTER_MEMBER(Vector4i, x); + REGISTER_MEMBER(Vector4i, y); + REGISTER_MEMBER(Vector4i, z); + REGISTER_MEMBER(Vector4i, w); + REGISTER_MEMBER(Rect2, position); REGISTER_MEMBER(Rect2, size); REGISTER_MEMBER(Rect2, end); @@ -111,6 +121,11 @@ void register_named_setters_getters() { REGISTER_MEMBER(Transform3D, basis); REGISTER_MEMBER(Transform3D, origin); + REGISTER_MEMBER(Projection, x); + REGISTER_MEMBER(Projection, y); + REGISTER_MEMBER(Projection, z); + REGISTER_MEMBER(Projection, w); + REGISTER_MEMBER(Color, r); REGISTER_MEMBER(Color, g); REGISTER_MEMBER(Color, b); @@ -804,11 +819,14 @@ INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2) INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2) INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3) INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4, double, real_t, 4) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4i, int64_t, int32_t, 4) INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quaternion, double, real_t, 4) INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4) INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .columns, 3) INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_column, get_column, 3) +INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Projection, Vector4, .matrix, 4) INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t) INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t) @@ -867,10 +885,13 @@ void register_indexed_setters_getters() { REGISTER_INDEXED_MEMBER(Vector2i); REGISTER_INDEXED_MEMBER(Vector3); REGISTER_INDEXED_MEMBER(Vector3i); + REGISTER_INDEXED_MEMBER(Vector4); + REGISTER_INDEXED_MEMBER(Vector4i); REGISTER_INDEXED_MEMBER(Quaternion); REGISTER_INDEXED_MEMBER(Color); REGISTER_INDEXED_MEMBER(Transform2D); REGISTER_INDEXED_MEMBER(Basis); + REGISTER_INDEXED_MEMBER(Projection); REGISTER_INDEXED_MEMBER(PackedByteArray); REGISTER_INDEXED_MEMBER(PackedInt32Array); diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h index bc4dc4b408..570277dc7a 100644 --- a/core/variant/variant_setget.h +++ b/core/variant/variant_setget.h @@ -281,6 +281,16 @@ SETGET_NUMBER_STRUCT(Vector3i, int64_t, x) SETGET_NUMBER_STRUCT(Vector3i, int64_t, y) SETGET_NUMBER_STRUCT(Vector3i, int64_t, z) +SETGET_NUMBER_STRUCT(Vector4, double, x) +SETGET_NUMBER_STRUCT(Vector4, double, y) +SETGET_NUMBER_STRUCT(Vector4, double, z) +SETGET_NUMBER_STRUCT(Vector4, double, w) + +SETGET_NUMBER_STRUCT(Vector4i, int64_t, x) +SETGET_NUMBER_STRUCT(Vector4i, int64_t, y) +SETGET_NUMBER_STRUCT(Vector4i, int64_t, z) +SETGET_NUMBER_STRUCT(Vector4i, int64_t, w) + SETGET_STRUCT(Rect2, Vector2, position) SETGET_STRUCT(Rect2, Vector2, size) SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end) @@ -315,6 +325,11 @@ SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_column, get_column, 2) SETGET_STRUCT(Transform3D, Basis, basis) SETGET_STRUCT(Transform3D, Vector3, origin) +SETGET_STRUCT_CUSTOM(Projection, Vector4, x, matrix[0]) +SETGET_STRUCT_CUSTOM(Projection, Vector4, y, matrix[1]) +SETGET_STRUCT_CUSTOM(Projection, Vector4, z, matrix[2]) +SETGET_STRUCT_CUSTOM(Projection, Vector4, w, matrix[3]) + SETGET_NUMBER_STRUCT(Color, double, r) SETGET_NUMBER_STRUCT(Color, double, g) SETGET_NUMBER_STRUCT(Color, double, b) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 2bca5f8284..1f1439ab24 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -99,18 +99,105 @@ struct VariantUtilityFunctions { return Math::posmod(b, r); } - static inline double floor(double x) { + static inline Variant floor(Variant x, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + switch (x.get_type()) { + case Variant::INT: { + return VariantInternalAccessor<int64_t>::get(&x); + } break; + case Variant::FLOAT: { + return Math::floor(VariantInternalAccessor<double>::get(&x)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).floor(); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).floor(); + } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).floor(); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double floorf(double x) { return Math::floor(x); } - static inline double ceil(double x) { + static inline int floori(double x) { + return int(x); + } + + static inline Variant ceil(Variant x, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + switch (x.get_type()) { + case Variant::INT: { + return VariantInternalAccessor<int64_t>::get(&x); + } break; + case Variant::FLOAT: { + return Math::ceil(VariantInternalAccessor<double>::get(&x)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).ceil(); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).ceil(); + } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).ceil(); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double ceilf(double x) { return Math::ceil(x); } - static inline double round(double x) { + static inline int ceili(double x) { + return int(Math::ceil(x)); + } + + static inline Variant round(Variant x, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + switch (x.get_type()) { + case Variant::INT: { + return VariantInternalAccessor<int64_t>::get(&x); + } break; + case Variant::FLOAT: { + return Math::round(VariantInternalAccessor<double>::get(&x)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).round(); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).round(); + } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).round(); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double roundf(double x) { return Math::round(x); } + static inline int roundi(double x) { + return int(Math::round(x)); + } + static inline Variant abs(const Variant &x, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { @@ -132,6 +219,12 @@ struct VariantUtilityFunctions { case Variant::VECTOR3I: { return VariantInternalAccessor<Vector3i>::get(&x).abs(); } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).abs(); + } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x).abs(); + } break; default: { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); @@ -168,6 +261,12 @@ struct VariantUtilityFunctions { case Variant::VECTOR3I: { return VariantInternalAccessor<Vector3i>::get(&x).sign(); } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).sign(); + } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x).sign(); + } break; default: { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); @@ -223,7 +322,44 @@ struct VariantUtilityFunctions { return Math::snapped(value, step); } - static inline double lerp(double from, double to, double weight) { + static inline Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + if (from.get_type() != to.get_type()) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + return Variant(); + } + + switch (from.get_type()) { + case Variant::FLOAT: { + return lerpf(VariantInternalAccessor<double>::get(&from), to, weight); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&from).lerp(VariantInternalAccessor<Vector2>::get(&to), weight); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&from).lerp(VariantInternalAccessor<Vector3>::get(&to), weight); + } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&from).lerp(VariantInternalAccessor<Vector4>::get(&to), weight); + } break; + case Variant::QUATERNION: { + return VariantInternalAccessor<Quaternion>::get(&from).slerp(VariantInternalAccessor<Quaternion>::get(&to), weight); + } break; + case Variant::BASIS: { + return VariantInternalAccessor<Basis>::get(&from).slerp(VariantInternalAccessor<Basis>::get(&to), weight); + } break; + case Variant::COLOR: { + return VariantInternalAccessor<Color>::get(&from).lerp(VariantInternalAccessor<Color>::get(&to), weight); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double lerpf(double from, double to, double weight) { return Math::lerp(from, to, weight); } @@ -1240,17 +1376,24 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(posmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDVR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(floorf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(floori, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(ceilf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(ceili, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDVR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(roundf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(roundi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(absf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(absi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVR(sign, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1268,7 +1411,8 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1288,12 +1432,10 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVARARG(max, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(maxi, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(maxf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVARARG(min, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(mini, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(minf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 1943221309..658a13d05b 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -134,15 +134,32 @@ </description> </method> <method name="ceil"> - <return type="float" /> - <argument index="0" name="x" type="float" /> + <return type="Variant" /> + <argument index="0" name="x" type="Variant" /> <description> - Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code]. + Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code]. Supported types: [int], [float], [Vector2], [Vector3], [Vector4]. [codeblock] var i = ceil(1.45) # i is 2.0 i = ceil(1.001) # i is 2.0 [/codeblock] See also [method floor], [method round], and [method snapped]. + [b]Note:[/b] For better type safety, you can use [method ceilf], [method ceili], [method Vector2.ceil], [method Vector3.ceil] or [method Vector4.ceil] instead. + </description> + </method> + <method name="ceilf"> + <return type="float" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code]. + A type-safe version of [method ceil], specialzied in floats. + </description> + </method> + <method name="ceili"> + <return type="int" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code]. + A type-safe version of [method ceil] that returns integer. </description> </method> <method name="clamp"> @@ -300,10 +317,10 @@ </description> </method> <method name="floor"> - <return type="float" /> - <argument index="0" name="x" type="float" /> + <return type="Variant" /> + <argument index="0" name="x" type="Variant" /> <description> - Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code]. + Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code]. Supported types: [int], [float], [Vector2], [Vector3], [Vector4]. [codeblock] # a is 2.0 var a = floor(2.99) @@ -311,7 +328,23 @@ a = floor(-2.99) [/codeblock] See also [method ceil], [method round], and [method snapped]. - [b]Note:[/b] This method returns a float. If you need an integer, you can use [code]int(x)[/code] directly. + [b]Note:[/b] For better type safety, you can use [method floorf], [method floori], [method Vector2.floor], [method Vector3.floor] or [method Vector4.floor] instead. + </description> + </method> + <method name="floorf"> + <return type="float" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code]. + A type-safe version of [method floor], specialzied in floats. + </description> + </method> + <method name="floori"> + <return type="int" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code]. + Equivalent of doing [code]int(x)[/code]. </description> </method> <method name="fmod"> @@ -380,7 +413,7 @@ <argument index="1" name="to" type="float" /> <argument index="2" name="weight" type="float" /> <description> - Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]). + Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]). Use [method clamp] on the result of [method inverse_lerp] if this is not desired. [codeblock] # The interpolation ratio in the `lerp()` call below is 0.75. var middle = lerp(20, 30, 0.75) @@ -389,7 +422,7 @@ var ratio = inverse_lerp(20, 30, 27.5) # `ratio` is now 0.75. [/codeblock] - See also [method lerp] which performs the reverse of this operation. + See also [method lerp] which performs the reverse of this operation, and [method range_lerp] to map a continuous series of values to another. </description> </method> <method name="is_equal_approx"> @@ -439,16 +472,18 @@ </description> </method> <method name="lerp"> - <return type="float" /> - <argument index="0" name="from" type="float" /> - <argument index="1" name="to" type="float" /> - <argument index="2" name="weight" type="float" /> + <return type="Variant" /> + <argument index="0" name="from" type="Variant" /> + <argument index="1" name="to" type="Variant" /> + <argument index="2" name="weight" type="Variant" /> <description> - Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. + Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. Use [method clamp] on the result of [method lerp] if this is not desired. + Both [code]from[/code] and [code]to[/code] must have matching types. Supported types: [float], [Vector2], [Vector3], [Vector4], [Color], [Quaternion], [Basis]. [codeblock] lerp(0, 4, 0.75) # Returns 3.0 [/codeblock] - See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. + See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. See also [method range_lerp] to map a continuous series of values to another. + [b]Note:[/b] For better type safety, you can use [method lerpf], [method Vector2.lerp], [method Vector3.lerp], [method Vector4.lerp], [method Color.lerp], [method Quaternion.slerp] or [method Basis.slerp] instead. </description> </method> <method name="lerp_angle"> @@ -471,6 +506,19 @@ [b]Note:[/b] This method lerps through the shortest path between [code]from[/code] and [code]to[/code]. However, when these two angles are approximately [code]PI + k * TAU[/code] apart for any integer [code]k[/code], it's not obvious which way they lerp due to floating-point precision errors. For example, [code]lerp_angle(0, PI, weight)[/code] lerps counter-clockwise, while [code]lerp_angle(0, PI + 5 * TAU, weight)[/code] lerps clockwise. </description> </method> + <method name="lerpf"> + <return type="float" /> + <argument index="0" name="from" type="float" /> + <argument index="1" name="to" type="float" /> + <argument index="2" name="weight" type="float" /> + <description> + Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. + [codeblock] + lerp(0, 4, 0.75) # Returns 3.0 + [/codeblock] + See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. + </description> + </method> <method name="linear2db"> <return type="float" /> <argument index="0" name="lin" type="float" /> @@ -807,10 +855,11 @@ <argument index="3" name="ostart" type="float" /> <argument index="4" name="ostop" type="float" /> <description> - Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. + Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. See also [method lerp] and [method inverse_lerp]. If [code]value[/code] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. Use [method clamp] on the result of [method range_lerp] if this is not desired. [codeblock] range_lerp(75, 0, 100, -1, 1) # Returns 0.5 [/codeblock] + For complex use cases where you need multiple ranges, consider using [Curve] or [Gradient] instead. </description> </method> <method name="rid_allocate_id"> @@ -827,14 +876,33 @@ </description> </method> <method name="round"> - <return type="float" /> - <argument index="0" name="x" type="float" /> + <return type="Variant" /> + <argument index="0" name="x" type="Variant" /> <description> - Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero. + Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero. Supported types: [int], [float], [Vector2], [Vector3], [Vector4]. [codeblock] + round(2.4) # Returns 2 + round(2.5) # Returns 3 round(2.6) # Returns 3 [/codeblock] See also [method floor], [method ceil], and [method snapped]. + [b]Note:[/b] For better type safety, you can use [method roundf], [method roundi], [method Vector2.round], [method Vector3.round] or [method Vector4.round] instead. + </description> + </method> + <method name="roundf"> + <return type="float" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero. + A type-safe version of [method round], specialzied in floats. + </description> + </method> + <method name="roundi"> + <return type="int" /> + <argument index="0" name="x" type="float" /> + <description> + Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero. + A type-safe version of [method round] that returns integer. </description> </method> <method name="seed"> @@ -1209,6 +1277,7 @@ The [ResourceSaver] singleton. </member> <member name="ResourceUID" type="ResourceUID" setter="" getter=""> + The [ResourceUID] singleton. </member> <member name="TextServerManager" type="TextServerManager" setter="" getter=""> The [TextServerManager] singleton. @@ -1222,6 +1291,8 @@ <member name="VisualScriptCustomNodes" type="VisualScriptCustomNodes" setter="" getter=""> The [VisualScriptCustomNodes] singleton. </member> + <member name="WorkerThreadPool" type="WorkerThreadPool" setter="" getter=""> + </member> <member name="XRServer" type="XRServer" setter="" getter=""> The [XRServer] singleton. </member> @@ -2515,72 +2586,66 @@ <constant name="PROPERTY_HINT_EXP_EASING" value="4" enum="PropertyHint"> Hints that a float property should be edited via an exponential easing function. The hint string can include [code]"attenuation"[/code] to flip the curve horizontally and/or [code]"inout"[/code] to also include in/out easing. </constant> - <constant name="PROPERTY_HINT_LENGTH" value="5" enum="PropertyHint"> - Deprecated hint, unused. - </constant> - <constant name="PROPERTY_HINT_LINK" value="6" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LINK" value="5" enum="PropertyHint"> Hints that a vector property should allow linking values (e.g. to edit both [code]x[/code] and [code]y[/code] together). </constant> - <constant name="PROPERTY_HINT_KEY_ACCEL" value="7" enum="PropertyHint"> - Deprecated hint, unused. - </constant> - <constant name="PROPERTY_HINT_FLAGS" value="8" enum="PropertyHint"> + <constant name="PROPERTY_HINT_FLAGS" value="6" enum="PropertyHint"> Hints that an integer property is a bitmask with named bit flags. For example, to allow toggling bits 0, 1, 2 and 4, the hint could be something like [code]"Bit0,Bit1,Bit2,,Bit4"[/code]. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="9" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="7" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D render layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="10" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="8" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D physics layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="11" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="9" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 2D navigation layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="12" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="10" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D render layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="13" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="11" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D physics layers. </constant> - <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="14" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="12" enum="PropertyHint"> Hints that an integer property is a bitmask using the optionally named 3D navigation layers. </constant> - <constant name="PROPERTY_HINT_FILE" value="15" enum="PropertyHint"> + <constant name="PROPERTY_HINT_FILE" value="13" enum="PropertyHint"> Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_DIR" value="16" enum="PropertyHint"> + <constant name="PROPERTY_HINT_DIR" value="14" enum="PropertyHint"> Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_GLOBAL_FILE" value="17" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_FILE" value="15" enum="PropertyHint"> Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code]. </constant> - <constant name="PROPERTY_HINT_GLOBAL_DIR" value="18" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_DIR" value="16" enum="PropertyHint"> Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path. </constant> - <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="19" enum="PropertyHint"> + <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="17" enum="PropertyHint"> Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate. </constant> - <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="20" enum="PropertyHint"> + <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="18" enum="PropertyHint"> Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed. </constant> - <constant name="PROPERTY_HINT_EXPRESSION" value="21" enum="PropertyHint"> + <constant name="PROPERTY_HINT_EXPRESSION" value="19" enum="PropertyHint"> Hints that a string property is an [Expression]. </constant> - <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="22" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint"> Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use. </constant> - <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="23" enum="PropertyHint"> + <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint"> Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="24" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint"> Hints that an image is compressed using lossy compression. </constant> - <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="25" enum="PropertyHint"> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint"> Hints that an image is compressed using lossless compression. </constant> - <constant name="PROPERTY_HINT_OBJECT_ID" value="26" enum="PropertyHint"> + <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_TYPE_STRING" value="27" enum="PropertyHint"> + <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint"> Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance: [codeblock] hint_string = "%s:" % [TYPE_INT] # Array of inteters. @@ -2590,128 +2655,124 @@ [/codeblock] [b]Note:[/b] The final colon is required to specify for properly detecting built-in types. </constant> - <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="28" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="29" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="30" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="31" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="32" enum="PropertyHint"> + <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="33" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="34" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="35" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="36" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="37" enum="PropertyHint"> + <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="38" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_SAVE_FILE" value="39" enum="PropertyHint"> + <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="40" enum="PropertyHint"> + <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="38" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="41" enum="PropertyHint"> + <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="39" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_INT_IS_POINTER" value="43" enum="PropertyHint"> + <constant name="PROPERTY_HINT_INT_IS_POINTER" value="41" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_ARRAY_TYPE" value="42" enum="PropertyHint"> + <constant name="PROPERTY_HINT_ARRAY_TYPE" value="40" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_LOCALE_ID" value="44" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALE_ID" value="42" enum="PropertyHint"> Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country. </constant> - <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="45" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="43" enum="PropertyHint"> Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings. </constant> - <constant name="PROPERTY_HINT_NODE_TYPE" value="46" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_TYPE" value="44" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint"> + <constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_STORAGE" value="1" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_STORAGE" value="2" enum="PropertyUsageFlags"> The property is serialized and saved in the scene file (default). </constant> - <constant name="PROPERTY_USAGE_EDITOR" value="2" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_EDITOR" value="4" enum="PropertyUsageFlags"> The property is shown in the editor inspector (default). </constant> - <constant name="PROPERTY_USAGE_NETWORK" value="4" enum="PropertyUsageFlags"> - Deprecated usage flag, unused. - </constant> - <constant name="PROPERTY_USAGE_EDITOR_HELPER" value="8" enum="PropertyUsageFlags"> - Deprecated usage flag, unused. - </constant> - <constant name="PROPERTY_USAGE_CHECKABLE" value="16" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_CHECKABLE" value="8" enum="PropertyUsageFlags"> The property can be checked in the editor inspector. </constant> - <constant name="PROPERTY_USAGE_CHECKED" value="32" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_CHECKED" value="16" enum="PropertyUsageFlags"> The property is checked in the editor inspector. </constant> - <constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="64" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="32" enum="PropertyUsageFlags"> The property is a translatable string. </constant> - <constant name="PROPERTY_USAGE_GROUP" value="128" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_GROUP" value="64" enum="PropertyUsageFlags"> Used to group properties together in the editor. See [EditorInspector]. </constant> - <constant name="PROPERTY_USAGE_CATEGORY" value="256" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_CATEGORY" value="128" enum="PropertyUsageFlags"> Used to categorize properties together in the editor. </constant> - <constant name="PROPERTY_USAGE_SUBGROUP" value="512" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_SUBGROUP" value="256" enum="PropertyUsageFlags"> Used to group properties together in the editor in a subgroup (under a group). See [EditorInspector]. </constant> - <constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="2048" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_CLASS_IS_BITFIELD" value="512" enum="PropertyUsageFlags"> + </constant> + <constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="1024" enum="PropertyUsageFlags"> The property does not save its state in [PackedScene]. </constant> - <constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="4096" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="2048" enum="PropertyUsageFlags"> Editing the property prompts the user for restarting the editor. </constant> - <constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="8192" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="4096" enum="PropertyUsageFlags"> The property is a script variable which should be serialized and saved in the scene file. </constant> - <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="16384" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="32768" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="16384" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="65536" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="32768" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="131072" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="65536" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="262144" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="131072" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="524288" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="262144" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_INTERNAL" value="1048576" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_INTERNAL" value="524288" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="2097152" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="1048576" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="4194304" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="2097152" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="8388608" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="4194304" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="16777216" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="8388608" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="33554432" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="16777216" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="67108864" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="33554432" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="134217728" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="67108864" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="268435456" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="134217728" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_ARRAY" value="1073741824" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_ARRAY" value="536870912" enum="PropertyUsageFlags"> </constant> - <constant name="PROPERTY_USAGE_DEFAULT" value="7" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_DEFAULT" value="6" enum="PropertyUsageFlags"> Default usage (storage, editor and network). </constant> - <constant name="PROPERTY_USAGE_DEFAULT_INTL" value="71" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_DEFAULT_INTL" value="38" enum="PropertyUsageFlags"> Default usage for translatable strings (storage, editor, network and internationalized). </constant> - <constant name="PROPERTY_USAGE_NO_EDITOR" value="5" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_NO_EDITOR" value="2" enum="PropertyUsageFlags"> Default usage but without showing the property in the editor (storage, network). </constant> <constant name="METHOD_FLAG_NORMAL" value="1" enum="MethodFlags"> @@ -2720,49 +2781,22 @@ <constant name="METHOD_FLAG_EDITOR" value="2" enum="MethodFlags"> Flag for an editor method. </constant> - <constant name="METHOD_FLAG_NOSCRIPT" value="4" enum="MethodFlags"> - Deprecated method flag, unused. - </constant> - <constant name="METHOD_FLAG_CONST" value="8" enum="MethodFlags"> + <constant name="METHOD_FLAG_CONST" value="4" enum="MethodFlags"> Flag for a constant method. </constant> - <constant name="METHOD_FLAG_REVERSE" value="16" enum="MethodFlags"> - Deprecated method flag, unused. - </constant> - <constant name="METHOD_FLAG_VIRTUAL" value="32" enum="MethodFlags"> + <constant name="METHOD_FLAG_VIRTUAL" value="8" enum="MethodFlags"> Flag for a virtual method. </constant> - <constant name="METHOD_FLAG_FROM_SCRIPT" value="64" enum="MethodFlags"> - Deprecated method flag, unused. - </constant> - <constant name="METHOD_FLAG_VARARG" value="128" enum="MethodFlags"> + <constant name="METHOD_FLAG_VARARG" value="16" enum="MethodFlags"> </constant> - <constant name="METHOD_FLAG_STATIC" value="256" enum="MethodFlags"> + <constant name="METHOD_FLAG_STATIC" value="32" enum="MethodFlags"> </constant> - <constant name="METHOD_FLAG_OBJECT_CORE" value="512" enum="MethodFlags"> + <constant name="METHOD_FLAG_OBJECT_CORE" value="64" enum="MethodFlags"> Used internally. Allows to not dump core virtuals such as [code]_notification[/code] to the JSON API. </constant> <constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags"> Default method flags. </constant> - <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode"> - Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods. - </constant> - <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode"> - Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not. - </constant> - <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode"> - Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority]. - </constant> - <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode"> - Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters. - </constant> - <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode"> - Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data. - </constant> - <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode"> - Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly. - </constant> <constant name="TYPE_NIL" value="0" enum="Variant.Type"> Variable is [code]null[/code]. </constant> @@ -2799,76 +2833,82 @@ <constant name="TYPE_TRANSFORM2D" value="11" enum="Variant.Type"> Variable is of type [Transform2D]. </constant> - <constant name="TYPE_PLANE" value="12" enum="Variant.Type"> + <constant name="TYPE_VECTOR4" value="12" enum="Variant.Type"> + </constant> + <constant name="TYPE_VECTOR4I" value="13" enum="Variant.Type"> + </constant> + <constant name="TYPE_PLANE" value="14" enum="Variant.Type"> Variable is of type [Plane]. </constant> - <constant name="TYPE_QUATERNION" value="13" enum="Variant.Type"> + <constant name="TYPE_QUATERNION" value="15" enum="Variant.Type"> Variable is of type [Quaternion]. </constant> - <constant name="TYPE_AABB" value="14" enum="Variant.Type"> + <constant name="TYPE_AABB" value="16" enum="Variant.Type"> Variable is of type [AABB]. </constant> - <constant name="TYPE_BASIS" value="15" enum="Variant.Type"> + <constant name="TYPE_BASIS" value="17" enum="Variant.Type"> Variable is of type [Basis]. </constant> - <constant name="TYPE_TRANSFORM3D" value="16" enum="Variant.Type"> + <constant name="TYPE_TRANSFORM3D" value="18" enum="Variant.Type"> Variable is of type [Transform3D]. </constant> - <constant name="TYPE_COLOR" value="17" enum="Variant.Type"> + <constant name="TYPE_PROJECTION" value="19" enum="Variant.Type"> + </constant> + <constant name="TYPE_COLOR" value="20" enum="Variant.Type"> Variable is of type [Color]. </constant> - <constant name="TYPE_STRING_NAME" value="18" enum="Variant.Type"> + <constant name="TYPE_STRING_NAME" value="21" enum="Variant.Type"> Variable is of type [StringName]. </constant> - <constant name="TYPE_NODE_PATH" value="19" enum="Variant.Type"> + <constant name="TYPE_NODE_PATH" value="22" enum="Variant.Type"> Variable is of type [NodePath]. </constant> - <constant name="TYPE_RID" value="20" enum="Variant.Type"> + <constant name="TYPE_RID" value="23" enum="Variant.Type"> Variable is of type [RID]. </constant> - <constant name="TYPE_OBJECT" value="21" enum="Variant.Type"> + <constant name="TYPE_OBJECT" value="24" enum="Variant.Type"> Variable is of type [Object]. </constant> - <constant name="TYPE_CALLABLE" value="22" enum="Variant.Type"> + <constant name="TYPE_CALLABLE" value="25" enum="Variant.Type"> Variable is of type [Callable]. </constant> - <constant name="TYPE_SIGNAL" value="23" enum="Variant.Type"> + <constant name="TYPE_SIGNAL" value="26" enum="Variant.Type"> Variable is of type [Signal]. </constant> - <constant name="TYPE_DICTIONARY" value="24" enum="Variant.Type"> + <constant name="TYPE_DICTIONARY" value="27" enum="Variant.Type"> Variable is of type [Dictionary]. </constant> - <constant name="TYPE_ARRAY" value="25" enum="Variant.Type"> + <constant name="TYPE_ARRAY" value="28" enum="Variant.Type"> Variable is of type [Array]. </constant> - <constant name="TYPE_PACKED_BYTE_ARRAY" value="26" enum="Variant.Type"> + <constant name="TYPE_PACKED_BYTE_ARRAY" value="29" enum="Variant.Type"> Variable is of type [PackedByteArray]. </constant> - <constant name="TYPE_PACKED_INT32_ARRAY" value="27" enum="Variant.Type"> + <constant name="TYPE_PACKED_INT32_ARRAY" value="30" enum="Variant.Type"> Variable is of type [PackedInt32Array]. </constant> - <constant name="TYPE_PACKED_INT64_ARRAY" value="28" enum="Variant.Type"> + <constant name="TYPE_PACKED_INT64_ARRAY" value="31" enum="Variant.Type"> Variable is of type [PackedInt64Array]. </constant> - <constant name="TYPE_PACKED_FLOAT32_ARRAY" value="29" enum="Variant.Type"> + <constant name="TYPE_PACKED_FLOAT32_ARRAY" value="32" enum="Variant.Type"> Variable is of type [PackedFloat32Array]. </constant> - <constant name="TYPE_PACKED_FLOAT64_ARRAY" value="30" enum="Variant.Type"> + <constant name="TYPE_PACKED_FLOAT64_ARRAY" value="33" enum="Variant.Type"> Variable is of type [PackedFloat64Array]. </constant> - <constant name="TYPE_PACKED_STRING_ARRAY" value="31" enum="Variant.Type"> + <constant name="TYPE_PACKED_STRING_ARRAY" value="34" enum="Variant.Type"> Variable is of type [PackedStringArray]. </constant> - <constant name="TYPE_PACKED_VECTOR2_ARRAY" value="32" enum="Variant.Type"> + <constant name="TYPE_PACKED_VECTOR2_ARRAY" value="35" enum="Variant.Type"> Variable is of type [PackedVector2Array]. </constant> - <constant name="TYPE_PACKED_VECTOR3_ARRAY" value="33" enum="Variant.Type"> + <constant name="TYPE_PACKED_VECTOR3_ARRAY" value="36" enum="Variant.Type"> Variable is of type [PackedVector3Array]. </constant> - <constant name="TYPE_PACKED_COLOR_ARRAY" value="34" enum="Variant.Type"> + <constant name="TYPE_PACKED_COLOR_ARRAY" value="37" enum="Variant.Type"> Variable is of type [PackedColorArray]. </constant> - <constant name="TYPE_MAX" value="35" enum="Variant.Type"> + <constant name="TYPE_MAX" value="38" enum="Variant.Type"> Represents the size of the [enum Variant.Type] enum. </constant> <constant name="OP_EQUAL" value="0" enum="Variant.Operator"> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index a92b237624..f40f11944d 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -391,13 +391,13 @@ </description> </method> <method name="track_insert_key"> - <return type="void" /> + <return type="int" /> <argument index="0" name="track_idx" type="int" /> <argument index="1" name="time" type="float" /> <argument index="2" name="key" type="Variant" /> <argument index="3" name="transition" type="float" default="1" /> <description> - Insert a generic key in a given track. + Inserts a generic key in a given track. Returns the key index. </description> </method> <method name="track_is_compressed" qualifiers="const"> diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml index 9026aa6a34..189e30b5f2 100644 --- a/doc/classes/AnimationNode.xml +++ b/doc/classes/AnimationNode.xml @@ -88,7 +88,7 @@ <argument index="3" name="seek_root" type="bool" /> <argument index="4" name="blend" type="float" /> <argument index="5" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> - <argument index="6" name="optimize" type="bool" default="true" /> + <argument index="6" name="sync" type="bool" default="true" /> <description> Blend an input. This is only useful for nodes created for an [AnimationNodeBlendTree]. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute. A filter mode may be optionally passed (see [enum FilterAction] for options). </description> @@ -102,7 +102,7 @@ <argument index="4" name="seek_root" type="bool" /> <argument index="5" name="blend" type="float" /> <argument index="6" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> - <argument index="7" name="optimize" type="bool" default="true" /> + <argument index="7" name="sync" type="bool" default="true" /> <description> Blend another animation node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition. </description> diff --git a/doc/classes/AnimationNodeAdd2.xml b/doc/classes/AnimationNodeAdd2.xml index ca117e3ecd..e6ac1dd963 100644 --- a/doc/classes/AnimationNodeAdd2.xml +++ b/doc/classes/AnimationNodeAdd2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeAdd2" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeAdd2" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Blends two animations additively inside of an [AnimationNodeBlendTree]. </brief_description> @@ -9,9 +9,4 @@ <tutorials> <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> - <members> - <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> - If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame. - </member> - </members> </class> diff --git a/doc/classes/AnimationNodeAdd3.xml b/doc/classes/AnimationNodeAdd3.xml index 91e030a6ae..f290032e11 100644 --- a/doc/classes/AnimationNodeAdd3.xml +++ b/doc/classes/AnimationNodeAdd3.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeAdd3" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeAdd3" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Blends two of three animations additively inside of an [AnimationNodeBlendTree]. </brief_description> @@ -14,9 +14,4 @@ <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> - <members> - <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> - If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame. - </member> - </members> </class> diff --git a/doc/classes/AnimationNodeBlend2.xml b/doc/classes/AnimationNodeBlend2.xml index f17163e155..5001e3ba24 100644 --- a/doc/classes/AnimationNodeBlend2.xml +++ b/doc/classes/AnimationNodeBlend2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeBlend2" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeBlend2" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Blends two animations linearly inside of an [AnimationNodeBlendTree]. </brief_description> @@ -11,9 +11,4 @@ <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> - <members> - <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> - If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame. - </member> - </members> </class> diff --git a/doc/classes/AnimationNodeBlend3.xml b/doc/classes/AnimationNodeBlend3.xml index 6bc7a20823..93947c2462 100644 --- a/doc/classes/AnimationNodeBlend3.xml +++ b/doc/classes/AnimationNodeBlend3.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeBlend3" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeBlend3" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Blends two of three animations linearly inside of an [AnimationNodeBlendTree]. </brief_description> @@ -13,9 +13,4 @@ <tutorials> <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> - <members> - <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> - If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame. - </member> - </members> </class> diff --git a/doc/classes/AnimationNodeBlendSpace1D.xml b/doc/classes/AnimationNodeBlendSpace1D.xml index 6ded3a7ff9..7bb136308d 100644 --- a/doc/classes/AnimationNodeBlendSpace1D.xml +++ b/doc/classes/AnimationNodeBlendSpace1D.xml @@ -76,6 +76,10 @@ <member name="snap" type="float" setter="set_snap" getter="get_snap" default="0.1"> Position increment to snap to when moving a point on the axis. </member> + <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> + If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code]. + If [code]true[/code], forcing the blended animations to advance frame. + </member> <member name="value_label" type="String" setter="set_value_label" getter="get_value_label" default=""value""> Label of the virtual axis of the blend space. </member> diff --git a/doc/classes/AnimationNodeBlendSpace2D.xml b/doc/classes/AnimationNodeBlendSpace2D.xml index 9e0e408ac5..eb2249d2d2 100644 --- a/doc/classes/AnimationNodeBlendSpace2D.xml +++ b/doc/classes/AnimationNodeBlendSpace2D.xml @@ -113,6 +113,10 @@ <member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0.1, 0.1)"> Position increment to snap to when moving a point. </member> + <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> + If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code]. + If [code]true[/code], forcing the blended animations to advance frame. + </member> <member name="x_label" type="String" setter="set_x_label" getter="get_x_label" default=""x""> Name of the blend space's X axis. </member> diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml index de2414cd43..14abc34992 100644 --- a/doc/classes/AnimationNodeOneShot.xml +++ b/doc/classes/AnimationNodeOneShot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeOneShot" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeOneShot" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Plays an animation once in [AnimationNodeBlendTree]. </brief_description> @@ -26,8 +26,6 @@ </member> <member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0"> </member> - <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> - </member> </members> <constants> <constant name="MIX_MODE_BLEND" value="0" enum="MixMode"> diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml index 206164d675..0badb831de 100644 --- a/doc/classes/AnimationNodeStateMachineTransition.xml +++ b/doc/classes/AnimationNodeStateMachineTransition.xml @@ -23,7 +23,7 @@ Use an expression as a condition for state machine transitions. It is possible to create complex animation advance conditions for switching between states and gives much greater flexibility for creating complex state machines by directly interfacing with the script code. </member> <member name="advance_expression_base_node" type="NodePath" setter="set_advance_expression_base_node" getter="get_advance_expression_base_node" default="NodePath("")"> - The path to the [Node] used to evaluate an [Expression] if one is not explictly specified internally. + The path to the [Node] used to evaluate an [Expression] if one is not explicitly specified internally. </member> <member name="auto_advance" type="bool" setter="set_auto_advance" getter="has_auto_advance" default="false"> Turn on the transition automatically when this state is reached. This works best with [constant SWITCH_MODE_AT_END]. diff --git a/doc/classes/AnimationNodeSync.xml b/doc/classes/AnimationNodeSync.xml new file mode 100644 index 0000000000..21cac11d50 --- /dev/null +++ b/doc/classes/AnimationNodeSync.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="AnimationNodeSync" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <members> + <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> + If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code]. + If [code]true[/code], forcing the blended animations to advance frame. + </member> + </members> +</class> diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml index 70c874d251..7e757d4640 100644 --- a/doc/classes/AnimationNodeTransition.xml +++ b/doc/classes/AnimationNodeTransition.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationNodeTransition" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimationNodeTransition" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A generic animation transition node for [AnimationTree]. </brief_description> @@ -40,6 +40,9 @@ </method> </methods> <members> + <member name="from_start" type="bool" setter="set_from_start" getter="is_from_start" default="true"> + If [code]true[/code], the destination animation is played back from the beginning when switched. + </member> <member name="input_count" type="int" setter="set_enabled_inputs" getter="get_enabled_inputs" default="0"> The number of available input ports for this node. </member> diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 653607610d..d3c8bdac3a 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AnimationPlayer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Container and player of [Animation] resources. + Player of [Animation] resources. </brief_description> <description> - An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in different channels. - [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween] node, but it requires doing everything by code. + An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of [AnimationLibrary] resources and custom blend times between animation transitions. + Some methods and properties use a single key to refence an animation directly. These keys are formatted as the key for the library, followed by a forward slash, then the key for the animation whithin the library, for example [code]"movement/run"[/code]. If the library's key is an empty string (known as the default library), the forward slash is omitted, being the same key used by the library. + [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween], but it requires doing everything by code. Updating the target properties of animations occurs at process time. </description> <tutorials> @@ -19,6 +20,7 @@ <argument index="0" name="name" type="StringName" /> <argument index="1" name="library" type="AnimationLibrary" /> <description> + Adds [code]library[/code] to the animation player, under the key [code]name[/code]. </description> </method> <method name="advance"> @@ -32,7 +34,7 @@ <return type="StringName" /> <argument index="0" name="anim_from" type="StringName" /> <description> - Returns the name of the next animation in the queue. + Returns the key of the animation which is queued to play after the [code]anim_from[/code] animation. </description> </method> <method name="animation_set_next"> @@ -59,13 +61,14 @@ <return type="StringName" /> <argument index="0" name="animation" type="Animation" /> <description> - Returns the name of [code]animation[/code] or an empty string if not found. + Returns the key of [code]animation[/code] or an empty [StringName] if not found. </description> </method> <method name="find_animation_library" qualifiers="const"> <return type="StringName" /> <argument index="0" name="animation" type="Animation" /> <description> + Returns the key for the [AnimationLibrary] that contains [code]animation[/code] or an empty [StringName] if not found. </description> </method> <method name="get_animation" qualifiers="const"> @@ -79,17 +82,19 @@ <return type="AnimationLibrary" /> <argument index="0" name="name" type="StringName" /> <description> + Returns the first [AnimationLibrary] with key [code]name[/code] or [code]null[/code] if not found. </description> </method> <method name="get_animation_library_list" qualifiers="const"> <return type="StringName[]" /> <description> + Returns the list of stored library keys. </description> </method> <method name="get_animation_list" qualifiers="const"> <return type="PackedStringArray" /> <description> - Returns the list of stored animation names. + Returns the list of stored animation keys. </description> </method> <method name="get_blend_time" qualifiers="const"> @@ -97,7 +102,7 @@ <argument index="0" name="anim_from" type="StringName" /> <argument index="1" name="anim_to" type="StringName" /> <description> - Gets the blend time (in seconds) between two animations, referenced by their names. + Gets the blend time (in seconds) between two animations, referenced by their keys. </description> </method> <method name="get_playing_speed" qualifiers="const"> @@ -109,7 +114,7 @@ <method name="get_queue"> <return type="PackedStringArray" /> <description> - Returns a list of the animation names that are currently queued to play. + Returns a list of the animation keys that are currently queued to play. </description> </method> <method name="has_animation" qualifiers="const"> @@ -123,6 +128,7 @@ <return type="bool" /> <argument index="0" name="name" type="StringName" /> <description> + Returns [code]true[/code] if the [AnimationPlayer] stores an [AnimationLibrary] with key [code]name[/code]. </description> </method> <method name="is_playing" qualifiers="const"> @@ -164,6 +170,7 @@ <return type="void" /> <argument index="0" name="name" type="StringName" /> <description> + Removes the [AnimationLibrary] assosiated with the key [code]name[/code]. </description> </method> <method name="rename_animation_library"> @@ -171,6 +178,7 @@ <argument index="0" name="name" type="StringName" /> <argument index="1" name="newname" type="StringName" /> <description> + Moves the [AnimationLibrary] associated with the key [code]name[/code] to the key [code]newname[/code]. </description> </method> <method name="seek"> @@ -188,7 +196,7 @@ <argument index="1" name="anim_to" type="StringName" /> <argument index="2" name="sec" type="float" /> <description> - Specifies a blend time (in seconds) between two animations, referenced by their names. + Specifies a blend time (in seconds) between two animations, referenced by their keys. </description> </method> <method name="stop"> @@ -202,17 +210,17 @@ </methods> <members> <member name="assigned_animation" type="String" setter="set_assigned_animation" getter="get_assigned_animation"> - If playing, the current animation; otherwise, the animation last played. When set, would change the animation, but would not play it unless currently playing. See also [member current_animation]. + If playing, the the current animation's key, otherwise, the animation last played. When set, this changes the animation, but will not play it unless already playing. See also [member current_animation]. </member> <member name="autoplay" type="String" setter="set_autoplay" getter="get_autoplay" default=""""> - The name of the animation to play when the scene loads. + The key of the animation to play when the scene loads. </member> <member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation" default=""""> - The name of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations. + The key of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations. [b]Note:[/b] while this property appears in the inspector, it's not meant to be edited, and it's not saved in the scene. This property is mainly used to get the currently playing animation, and internally for animation playback tracks. For more information, see [Animation]. </member> <member name="current_animation_length" type="float" setter="" getter="get_current_animation_length"> - The length (in seconds) of the currently being played animation. + The length (in seconds) of the currently playing animation. </member> <member name="current_animation_position" type="float" setter="" getter="get_current_animation_position"> The position (in seconds) of the currently playing animation. @@ -220,6 +228,10 @@ <member name="method_call_mode" type="int" setter="set_method_call_mode" getter="get_method_call_mode" enum="AnimationPlayer.AnimationMethodCallMode" default="0"> The call mode to use for Call Method tracks. </member> + <member name="movie_quit_on_finish" type="bool" setter="set_movie_quit_on_finish_enabled" getter="is_movie_quit_on_finish_enabled" default="false"> + If [code]true[/code] and the engine is running in Movie Maker mode (see [MovieWriter]), exits the engine with [method SceneTree.quit] as soon as an animation is done playing in this [AnimationPlayer]. A message is printed when the engine quits for this reason. + [b]Note:[/b] This obeys the same logic as the [signal animation_finished] signal, so it will not quit the engine if the animation is set to be looping. + </member> <member name="playback_active" type="bool" setter="set_active" getter="is_active"> If [code]true[/code], updates animations in response to process-related notifications. </member> @@ -233,8 +245,8 @@ The speed scaling ratio. For instance, if this value is 1, then the animation plays at normal speed. If it's 0.5, then it plays at half speed. If it's 2, then it plays at double speed. </member> <member name="reset_on_save" type="bool" setter="set_reset_on_save_enabled" getter="is_reset_on_save_enabled" default="true"> - This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation applied (as if it had been seeked to time 0), then reverted after saving. - In other words, the saved scene file will contain the "default pose", as defined by the reset animation, if any, with the editor keeping the values that the nodes had before saving. + This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving. + This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation. </member> <member name="root_node" type="NodePath" setter="set_root" getter="get_root" default="NodePath("..")"> The node from which node path references will travel. @@ -245,14 +257,15 @@ <argument index="0" name="old_name" type="StringName" /> <argument index="1" name="new_name" type="StringName" /> <description> - Emitted when a queued animation plays after the previous animation was finished. See [method queue]. - [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or from [AnimationTree]. + Emitted when a queued animation plays after the previous animation finished. See [method queue]. + [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or by an [AnimationTree]. </description> </signal> <signal name="animation_finished"> <argument index="0" name="anim_name" type="StringName" /> <description> Notifies when an animation finished playing. + [b]Note:[/b] This signal is not emitted if an animation is looping. </description> </signal> <signal name="animation_started"> diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml index ecac228a26..45d9152564 100644 --- a/doc/classes/AnimationTree.xml +++ b/doc/classes/AnimationTree.xml @@ -38,7 +38,7 @@ If [code]true[/code], the [AnimationTree] will be processing. </member> <member name="advance_expression_base_node" type="NodePath" setter="set_advance_expression_base_node" getter="get_advance_expression_base_node" default="NodePath(".")"> - The path to the [Node] used to evaluate the AnimationNode [Expression] if one is not explictly specified internally. + The path to the [Node] used to evaluate the AnimationNode [Expression] if one is not explicitly specified internally. </member> <member name="anim_player" type="NodePath" setter="set_animation_player" getter="get_animation_player" default="NodePath("")"> The path to the [AnimationPlayer] used for animating. diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index 0f2dd6587a..f5c799d4de 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -67,7 +67,7 @@ <description> Creates a new surface. Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface. - The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used. + The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array (or be an exact multiple of the vertex array's length, when multiple elements of a sub-array correspond to a single vertex) or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used. </description> </method> <method name="clear_blend_shapes"> diff --git a/doc/classes/AudioEffectRecord.xml b/doc/classes/AudioEffectRecord.xml index 9728011bb2..32a6aea340 100644 --- a/doc/classes/AudioEffectRecord.xml +++ b/doc/classes/AudioEffectRecord.xml @@ -14,7 +14,7 @@ </tutorials> <methods> <method name="get_recording" qualifiers="const"> - <return type="AudioStreamSample" /> + <return type="AudioStreamWAV" /> <description> Returns the recorded sample. </description> @@ -34,8 +34,8 @@ </method> </methods> <members> - <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="1"> - Specifies the format in which the sample will be recorded. See [enum AudioStreamSample.Format] for available formats. + <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="1"> + Specifies the format in which the sample will be recorded. See [enum AudioStreamWAV.Format] for available formats. </member> </members> </class> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 1e076654fb..28dcd2794e 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -275,6 +275,12 @@ Sets the volume of the bus at index [code]bus_idx[/code] to [code]volume_db[/code]. </description> </method> + <method name="set_enable_tagging_used_audio_streams"> + <return type="void" /> + <argument index="0" name="enable" type="bool" /> + <description> + </description> + </method> <method name="swap_bus_effects"> <return type="void" /> <argument index="0" name="bus_idx" type="int" /> diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index 6343da6eed..7645cafe86 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -4,7 +4,7 @@ Base class for audio streams. </brief_description> <description> - Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamSample]) and OGG (via [AudioStreamOGGVorbis]) file formats. + Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamWAV]) and Ogg (via [AudioStreamOggVorbis]) file formats. </description> <tutorials> <link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link> @@ -13,6 +13,16 @@ <link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link> </tutorials> <methods> + <method name="_get_beat_count" qualifiers="virtual const"> + <return type="int" /> + <description> + </description> + </method> + <method name="_get_bpm" qualifiers="virtual const"> + <return type="float" /> + <description> + </description> + </method> <method name="_get_length" qualifiers="virtual const"> <return type="float" /> <description> @@ -23,7 +33,7 @@ <description> </description> </method> - <method name="_instance_playback" qualifiers="virtual const"> + <method name="_instantiate_playback" qualifiers="virtual const"> <return type="AudioStreamPlayback" /> <description> </description> @@ -39,10 +49,10 @@ Returns the length of the audio stream in seconds. </description> </method> - <method name="instance_playback"> + <method name="instantiate_playback"> <return type="AudioStreamPlayback" /> <description> - Returns an AudioStreamPlayback. Useful for when you want to extend `_instance_playback` but call `instance_playback` from an internally held AudioStream subresource. An example of this can be found in the source files for `AudioStreamRandomPitch::instance_playback`. + Returns an AudioStreamPlayback. Useful for when you want to extend [method _instantiate_playback] but call [method instantiate_playback] from an internally held AudioStream subresource. An example of this can be found in the source files for [code]AudioStreamRandomPitch::instantiate_playback[/code]. </description> </method> <method name="is_monophonic" qualifiers="const"> diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml index 1909c4b621..f1a1c18c1c 100644 --- a/doc/classes/AudioStreamPlayback.xml +++ b/doc/classes/AudioStreamPlayback.xml @@ -4,7 +4,7 @@ Meta class for playing back audio. </brief_description> <description> - Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOGGVorbis] for usage. + Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOggVorbis] for usage. </description> <tutorials> <link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link> @@ -50,5 +50,10 @@ <description> </description> </method> + <method name="_tag_used_streams" qualifiers="virtual"> + <return type="void" /> + <description> + </description> + </method> </methods> </class> diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamWAV.xml index 62f27ce876..17595aec2f 100644 --- a/doc/classes/AudioStreamSample.xml +++ b/doc/classes/AudioStreamWAV.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamSample" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AudioStreamWAV" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Stores audio data loaded from WAV files. </brief_description> <description> - AudioStreamSample stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped. + AudioStreamWAV stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped. This class can also be used to store dynamically-generated PCM audio data. See also [AudioStreamGenerator] for procedural audio generation. </description> <tutorials> @@ -14,7 +14,7 @@ <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> <description> - Saves the AudioStreamSample as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved. + Saves the AudioStreamWAV as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved. [b]Note:[/b] A [code].wav[/code] extension is automatically appended to [code]path[/code] if it is missing. </description> </method> @@ -24,7 +24,7 @@ Contains the audio data in bytes. [b]Note:[/b] This property expects signed PCM8 data. To convert unsigned PCM8 to signed PCM8, subtract 128 from each byte. </member> - <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="0"> + <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="0"> Audio format. See [enum Format] constants for values. </member> <member name="loop_begin" type="int" setter="set_loop_begin" getter="get_loop_begin" default="0"> @@ -33,7 +33,7 @@ <member name="loop_end" type="int" setter="set_loop_end" getter="get_loop_end" default="0"> The loop end point (in number of samples, relative to the beginning of the sample). This information will be imported automatically from the WAV file if present. </member> - <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamSample.LoopMode" default="0"> + <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamWAV.LoopMode" default="0"> The loop mode. This information will be imported automatically from the WAV file if present. See [enum LoopMode] constants for values. </member> <member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate" default="44100"> diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index d3ae85101d..d0290ff5fd 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -218,30 +218,44 @@ Grows object vertices in the direction of their normals. </member> <member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled" default="false"> + If [code]true[/code], uses parallax occlusion mapping to represent depth in the material instead of simple offset mapping (see [member heightmap_enabled]). This results in a more convincing depth effect, but is much more expensive on the GPU. Only enable this on materials where it makes a significant visual difference. </member> <member name="heightmap_enabled" type="bool" setter="set_feature" getter="get_feature" default="false"> - If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled]. + If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled]. Height mapping is a demanding feature on the GPU, so it should only be used on materials where it makes a significant visual difference. [b]Note:[/b] Height mapping is not supported if triplanar mapping is used on the same material. The value of [member heightmap_enabled] will be ignored if [member uv1_triplanar] is enabled. </member> <member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal" default="false"> + If [code]true[/code], flips the mesh's binormal vectors when interpreting the height map. If the heightmap effect looks strange when the camera moves (even with a reasonable [member heightmap_scale]), try setting this to [code]true[/code]. </member> <member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent" default="false"> + If [code]true[/code], flips the mesh's tangent vectors when interpreting the height map. If the heightmap effect looks strange when the camera moves (even with a reasonable [member heightmap_scale]), try setting this to [code]true[/code]. </member> <member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag" default="false"> + If [code]true[/code], interprets the height map texture as a depth map, with brighter values appearing to be "lower" in altitude compared to darker values. + This can be enabled for compatibility with some materials authored for Godot 3.x. This is not necessary if the Invert import option was used to invert the depth map in Godot 3.x, in which case [member heightmap_flip_texture] should remain [code]false[/code]. </member> <member name="heightmap_max_layers" type="int" setter="set_heightmap_deep_parallax_max_layers" getter="get_heightmap_deep_parallax_max_layers"> + The number of layers to use for parallax occlusion mapping when the camera is up close to the material. Higher values result in a more convincing depth effect, especially in materials that have steep height changes. Higher values have a significant cost on the GPU, so it should only be increased on materials where it makes a significant visual difference. + [b]Note:[/b] Only effective if [member heightmap_deep_parallax] is [code]true[/code]. </member> <member name="heightmap_min_layers" type="int" setter="set_heightmap_deep_parallax_min_layers" getter="get_heightmap_deep_parallax_min_layers"> + The number of layers to use for parallax occlusion mapping when the camera is far away from the material. Higher values result in a more convincing depth effect, especially in materials that have steep height changes. Higher values have a significant cost on the GPU, so it should only be increased on materials where it makes a significant visual difference. + [b]Note:[/b] Only effective if [member heightmap_deep_parallax] is [code]true[/code]. </member> - <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="0.05"> + <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="5.0"> + The heightmap scale to use for the parallax effect (see [member heightmap_enabled]). The default value is tuned so that the highest point (value = 255) appears to be 5 cm higher than the lowest point (value = 0). Higher values result in a deeper appearance, but may result in artifacts appearing when looking at the material from oblique angles, especially when the camera moves. Negative values can be used to invert the parallax effect, but this is different from inverting the texture using [member heightmap_flip_texture] as the material will also appear to be "closer" to the camera. In most cases, [member heightmap_scale] should be kept to a positive value. + [b]Note:[/b] If the height map effect looks strange regardless of this value, try adjusting [member heightmap_flip_binormal] and [member heightmap_flip_tangent]. See also [member heightmap_texture] for recommendations on authoring heightmap textures, as the way the heightmap texture is authored affects how [member heightmap_scale] behaves. </member> <member name="heightmap_texture" type="Texture2D" setter="set_texture" getter="get_texture"> + The texture to use as a height map. See also [member heightmap_enabled]. + For best results, the texture should be normalized (with [member heightmap_scale] reduced to compensate). In [url=https://gimp.org]GIMP[/url], this can be done using [b]Colors > Auto > Equalize[/b]. If the texture only uses a small part of its available range, the parallax effect may look strange, especially when the camera moves. + [b]Note:[/b] To reduce memory usage and improve loading times, you may be able to use a lower-resolution heightmap texture as most heightmaps are only comprised of low-frequency data. </member> <member name="metallic" type="float" setter="set_metallic" getter="get_metallic" default="0.0"> A high value makes the material appear more like a metal. Non-metals use their albedo as the diffuse color and add diffuse to the specular reflection. With non-metals, the reflection appears on top of the albedo color. Metals use their albedo as a multiplier to the specular reflection and set the diffuse color to black resulting in a tinted reflection. Materials work better when fully metal or fully non-metal, values between [code]0[/code] and [code]1[/code] should only be used for blending between metal and non-metal sections. To alter the amount of reflection use [member roughness]. </member> <member name="metallic_specular" type="float" setter="set_specular" getter="get_specular" default="0.5"> - Sets the size of the specular lobe. The specular lobe is the bright spot that is reflected from light sources. + Adjusts the strength of specular reflections. Specular reflections are composed of scene reflections and the specular lobe which is the bright spot that is reflected from light sources. When set to [code]0.0[/code], no specular reflections will be visible. This differs from the [constant SPECULAR_DISABLED] [enum SpecularMode] as [constant SPECULAR_DISABLED] only applies to the specular lobe from the light source. [b]Note:[/b] Unlike [member metallic], this is not energy-conserving, so it should be left at [code]0.5[/code] in most cases. See also [member roughness]. </member> <member name="metallic_texture" type="Texture2D" setter="set_texture" getter="get_texture"> @@ -374,10 +388,10 @@ [b]Note:[/b] This is only effective for objects whose geometry is point-based rather than triangle-based. See also [member point_size]. </member> <member name="uv1_offset" type="Vector3" setter="set_uv1_offset" getter="get_uv1_offset" default="Vector3(0, 0, 0)"> - How much to offset the [code]UV[/code] coordinates. This amount will be added to [code]UV[/code] in the vertex function. This can be used to offset a texture. + How much to offset the [code]UV[/code] coordinates. This amount will be added to [code]UV[/code] in the vertex function. This can be used to offset a texture. The Z component is used when [member uv1_triplanar] is enabled, but it is not used anywhere else. </member> <member name="uv1_scale" type="Vector3" setter="set_uv1_scale" getter="get_uv1_scale" default="Vector3(1, 1, 1)"> - How much to scale the [code]UV[/code] coordinates. This is multiplied by [code]UV[/code] in the vertex function. + How much to scale the [code]UV[/code] coordinates. This is multiplied by [code]UV[/code] in the vertex function. The Z component is used when [member uv1_triplanar] is enabled, but it is not used anywhere else. </member> <member name="uv1_triplanar" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], instead of using [code]UV[/code] textures will use a triplanar texture lookup to determine how to apply textures. Triplanar uses the orientation of the object's surface to blend between texture coordinates. It reads from the source texture 3 times, once for each axis and then blends between the results based on how closely the pixel aligns with each axis. This is often used for natural features to get a realistic blend of materials. Because triplanar texturing requires many more texture reads per-pixel it is much slower than normal UV texturing. Additionally, because it is blending the texture between the three axes, it is unsuitable when you are trying to achieve crisp texturing. @@ -389,10 +403,10 @@ If [code]true[/code], triplanar mapping for [code]UV[/code] is calculated in world space rather than object local space. See also [member uv1_triplanar]. </member> <member name="uv2_offset" type="Vector3" setter="set_uv2_offset" getter="get_uv2_offset" default="Vector3(0, 0, 0)"> - How much to offset the [code]UV2[/code] coordinates. This amount will be added to [code]UV2[/code] in the vertex function. This can be used to offset a texture. + How much to offset the [code]UV2[/code] coordinates. This amount will be added to [code]UV2[/code] in the vertex function. This can be used to offset a texture. The Z component is used when [member uv2_triplanar] is enabled, but it is not used anywhere else. </member> <member name="uv2_scale" type="Vector3" setter="set_uv2_scale" getter="get_uv2_scale" default="Vector3(1, 1, 1)"> - How much to scale the [code]UV2[/code] coordinates. This is multiplied by [code]UV2[/code] in the vertex function. + How much to scale the [code]UV2[/code] coordinates. This is multiplied by [code]UV2[/code] in the vertex function. The Z component is used when [member uv2_triplanar] is enabled, but it is not used anywhere else. </member> <member name="uv2_triplanar" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], instead of using [code]UV2[/code] textures will use a triplanar texture lookup to determine how to apply textures. Triplanar uses the orientation of the object's surface to blend between texture coordinates. It reads from the source texture 3 times, once for each axis and then blends between the results based on how closely the pixel aligns with each axis. This is often used for natural features to get a realistic blend of materials. Because triplanar texturing requires many more texture reads per-pixel it is much slower than normal UV texturing. Additionally, because it is blending the texture between the three axes, it is unsuitable when you are trying to achieve crisp texturing. diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index dacdca1cee..b0282e4107 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -192,8 +192,8 @@ </member> <member name="linear_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> </member> - <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true"> - If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates. + <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false"> + If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [CPUParticles2D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [CPUParticles2D] node (and its parents) when it is moved or rotated. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false"> If [code]true[/code], only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end. diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml index f2a0040ed4..d8faf8e91d 100644 --- a/doc/classes/CPUParticles3D.xml +++ b/doc/classes/CPUParticles3D.xml @@ -224,8 +224,8 @@ <member name="linear_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> Minimum linear acceleration. </member> - <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true"> - If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates. + <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false"> + If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [CPUParticles3D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [CPUParticles3D] node (and its parents) when it is moved or rotated. </member> <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> The [Mesh] used for each particle. If [code]null[/code], particles will be spheres. diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 56e5ce1522..643351efc0 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -113,7 +113,7 @@ <argument index="2" name="z_near" type="float" /> <argument index="3" name="z_far" type="float" /> <description> - Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units. + Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units. See also [member frustum_offset]. </description> </method> <method name="set_orthogonal"> @@ -144,7 +144,7 @@ # This code block is part of a script that inherits from Node3D. # `control` is a reference to a node inheriting from Control. control.visible = not get_viewport().get_camera_3d().is_position_behind(global_transform.origin) - control.rect_position = get_viewport().get_camera_3d().unproject_position(global_transform.origin) + control.position = get_viewport().get_camera_3d().unproject_position(global_transform.origin) [/codeblock] </description> </method> @@ -155,6 +155,7 @@ </member> <member name="current" type="bool" setter="set_current" getter="is_current" default="false"> If [code]true[/code], the ancestor [Viewport] is currently using this camera. + If multiple cameras are in the scene, one will always be made current. For example, if two [Camera3D] nodes are present in the scene and only one is current, setting one camera's [member current] to [code]false[/code] will cause the other camera to be made current. </member> <member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera3D.DopplerTracking" default="0"> If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values. @@ -178,6 +179,7 @@ </member> <member name="frustum_offset" type="Vector2" setter="set_frustum_offset" getter="get_frustum_offset" default="Vector2(0, 0)"> The camera's frustum offset. This can be changed from the default to create "tilted frustum" effects such as [url=https://zdoom.org/wiki/Y-shearing]Y-shearing[/url]. + [b]Note:[/b] Only effective if [member projection] is [constant PROJECTION_FRUSTUM]. </member> <member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0"> The horizontal (X) offset of the camera viewport. @@ -188,7 +190,7 @@ <member name="near" type="float" setter="set_near" getter="get_near" default="0.05"> The distance to the near culling boundary for this camera relative to its local Z axis. </member> - <member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.Projection" default="0"> + <member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.ProjectionType" default="0"> The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size. </member> <member name="size" type="float" setter="set_size" getter="get_size" default="1.0"> @@ -199,13 +201,13 @@ </member> </members> <constants> - <constant name="PROJECTION_PERSPECTIVE" value="0" enum="Projection"> + <constant name="PROJECTION_PERSPECTIVE" value="0" enum="ProjectionType"> Perspective projection. Objects on the screen becomes smaller when they are far away. </constant> - <constant name="PROJECTION_ORTHOGONAL" value="1" enum="Projection"> + <constant name="PROJECTION_ORTHOGONAL" value="1" enum="ProjectionType"> Orthogonal projection, also known as orthographic projection. Objects remain the same size on the screen no matter how far away they are. </constant> - <constant name="PROJECTION_FRUSTUM" value="2" enum="Projection"> + <constant name="PROJECTION_FRUSTUM" value="2" enum="ProjectionType"> Frustum projection. This mode allows adjusting [member frustum_offset] to create "tilted frustum" effects. </constant> <constant name="KEEP_WIDTH" value="0" enum="KeepAspect"> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index acf08414d0..2d68ae6902 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -169,9 +169,10 @@ <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="max_lines" type="int" default="-1" /> <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="8" name="flags" type="int" default="99" /> - <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" /> - <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> + <argument index="8" name="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> + <argument index="9" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> + <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" /> + <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Breaks [code]text[/code] to the lines and draws it using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width. </description> @@ -187,9 +188,10 @@ <argument index="6" name="max_lines" type="int" default="-1" /> <argument index="7" name="size" type="int" default="1" /> <argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="9" name="flags" type="int" default="99" /> - <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" /> - <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> + <argument index="9" name="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> + <argument index="10" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> + <argument index="11" name="direction" type="int" enum="TextServer.Direction" default="0" /> + <argument index="12" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Breaks [code]text[/code] to the lines and draws text outline using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width. </description> @@ -279,7 +281,7 @@ <argument index="4" name="width" type="float" default="-1" /> <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="7" name="flags" type="int" default="3" /> + <argument index="7" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> @@ -316,7 +318,7 @@ <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="size" type="int" default="1" /> <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="8" name="flags" type="int" default="3" /> + <argument index="8" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 6c5cd62fe1..795bd7a429 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -159,10 +159,10 @@ Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum MovingPlatformApplyVelocityOnLeave] constants for available behavior. </member> <member name="moving_platform_floor_layers" type="int" setter="set_moving_platform_floor_layers" getter="get_moving_platform_floor_layers" default="4294967295"> - Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all floor bodies are detected and propagate their velocity. + Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all floor bodies are detected and propagate their velocity. </member> <member name="moving_platform_wall_layers" type="int" setter="set_moving_platform_wall_layers" getter="get_moving_platform_wall_layers" default="0"> - Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all wall bodies are ignored. + Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all wall bodies are ignored. </member> <member name="slide_on_ceiling" type="bool" setter="set_slide_on_ceiling_enabled" getter="is_slide_on_ceiling_enabled" default="true"> If [code]true[/code], during a jump against the ceiling, the body will slide, if [code]false[/code] it will be stopped and will fall vertically. diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index 5d025985cc..95d99855f6 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -16,7 +16,8 @@ <argument index="1" name="event" type="InputEvent" /> <argument index="2" name="shape_idx" type="int" /> <description> - Accepts unhandled [InputEvent]s. Requires [member input_pickable] to be [code]true[/code]. [code]shape_idx[/code] is the child index of the clicked [Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up these events. + Accepts unhandled [InputEvent]s. [code]shape_idx[/code] is the child index of the clicked [Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up these events. + [b]Note:[/b] [method _input_event] requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. </description> </method> <method name="create_shape_owner"> @@ -218,17 +219,19 @@ <argument index="1" name="event" type="InputEvent" /> <argument index="2" name="shape_idx" type="int" /> <description> - Emitted when an input event occurs. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set. See [method _input_event] for details. + Emitted when an input event occurs. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. See [method _input_event] for details. </description> </signal> <signal name="mouse_entered"> <description> Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted. + [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question. </description> </signal> <signal name="mouse_exited"> <description> Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted. + [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question. </description> </signal> <signal name="mouse_shape_entered"> diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml index 2aac5528f4..7284a7e341 100644 --- a/doc/classes/CollisionObject3D.xml +++ b/doc/classes/CollisionObject3D.xml @@ -18,6 +18,7 @@ <argument index="4" name="shape_idx" type="int" /> <description> Receives unhandled [InputEvent]s. [code]position[/code] is the location in world space of the mouse pointer on the surface of the shape with index [code]shape_idx[/code] and [code]normal[/code] is the normal vector of the surface at that point. Connect to the [signal input_event] signal to easily pick up these events. + [b]Note:[/b] [method _input_event] requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. </description> </method> <method name="create_shape_owner"> @@ -199,12 +200,14 @@ </signal> <signal name="mouse_entered"> <description> - Emitted when the mouse pointer enters any of this object's shapes. + Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. + [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question. </description> </signal> <signal name="mouse_exited"> <description> - Emitted when the mouse pointer exits all this object's shapes. + Emitted when the mouse pointer exits all this object's shapes. Requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. + [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question. </description> </signal> </signals> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 2846b564b4..9fc80e1aab 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -1281,8 +1281,8 @@ <constant name="PRESET_HCENTER_WIDE" value="14" enum="LayoutPreset"> Snap all 4 anchors to a horizontal line that cuts the parent control in half. Use with [method set_anchors_preset]. </constant> - <constant name="PRESET_WIDE" value="15" enum="LayoutPreset"> - Snap all 4 anchors to the respective corners of the parent control. Set all 4 offsets to 0 after you applied this preset and the [Control] will fit its parent control. This is equivalent to the "Full Rect" layout option in the editor. Use with [method set_anchors_preset]. + <constant name="PRESET_FULL_RECT" value="15" enum="LayoutPreset"> + Snap all 4 anchors to the respective corners of the parent control. Set all 4 offsets to 0 after you applied this preset and the [Control] will fit its parent control. Use with [method set_anchors_preset]. </constant> <constant name="PRESET_MODE_MINSIZE" value="0" enum="LayoutPresetMode"> The control will be resized to its minimum size. diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml index 383d33532b..179b0344c2 100644 --- a/doc/classes/Curve.xml +++ b/doc/classes/Curve.xml @@ -5,6 +5,7 @@ </brief_description> <description> A curve that can be saved and re-used for other objects. By default, it ranges between [code]0[/code] and [code]1[/code] on the Y axis and positions points relative to the [code]0.5[/code] Y position. + See also [Gradient] which is designed for color interpolation. See also [Curve2D] and [Curve3D]. </description> <tutorials> </tutorials> diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml index 861b4b480c..3322ab4c66 100644 --- a/doc/classes/Decal.xml +++ b/doc/classes/Decal.xml @@ -58,34 +58,35 @@ </methods> <members> <member name="albedo_mix" type="float" setter="set_albedo_mix" getter="get_albedo_mix" default="1.0"> - Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. + Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. This can be set to [code]0.0[/code] to create a decal that only affects normal or ORM. In this case, an albedo texture is still required as its alpha channel will determine where the normal and ORM will be overridden. See also [member modulate]. </member> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575"> Specifies which [member VisualInstance3D.layers] this decal will project on. By default, Decals affect all layers. This is used so you can specify which types of objects receive the Decal and which do not. This is especially useful so you can ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them. </member> - <member name="distance_fade_begin" type="float" setter="set_distance_fade_begin" getter="get_distance_fade_begin" default="10.0"> - Distance from the camera at which the Decal begins to fade away. + <member name="distance_fade_begin" type="float" setter="set_distance_fade_begin" getter="get_distance_fade_begin" default="40.0"> + The distance from the camera at which the Decal begins to fade away (in 3D units). </member> <member name="distance_fade_enabled" type="bool" setter="set_enable_distance_fade" getter="is_distance_fade_enabled" default="false"> - If [code]true[/code], decals will smoothly fade away when far from the active [Camera3D] starting at [member distance_fade_begin]. The Decal will fade out over [member distance_fade_length], after which it will be culled and not sent to the shader at all. Use this to reduce the number of active Decals in a scene and thus improve performance. + If [code]true[/code], decals will smoothly fade away when far from the active [Camera3D] starting at [member distance_fade_begin]. The Decal will fade out over [member distance_fade_begin] + [member distance_fade_length], after which it will be culled and not sent to the shader at all. Use this to reduce the number of active Decals in a scene and thus improve performance. </member> - <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="1.0"> - Distance over which the Decal fades. The Decal becomes slowly more transparent over this distance and is completely invisible at the end. + <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0"> + The distance over which the Decal fades (in 3D units). The Decal becomes slowly more transparent over this distance and is completely invisible at the end. Higher values result in a smoother fade-out transition, which is more suited when the camera moves fast. </member> <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0"> - Energy multiplier for the emission texture. This will make the decal emit light at a higher intensity. + Energy multiplier for the emission texture. This will make the decal emit light at a higher or lower intensity, independently of the albedo color. See also [member modulate]. </member> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> Sets the size of the [AABB] used by the decal. The AABB goes from [code]-extents[/code] to [code]extents[/code]. </member> <member name="lower_fade" type="float" setter="set_lower_fade" getter="get_lower_fade" default="0.3"> - Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). + Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). See also [member upper_fade]. </member> <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)"> - Changes the [Color] of the Decal by multiplying it with this value. + Changes the [Color] of the Decal by multiplying the albedo and emission colors with this value. The alpha component is only taken into account when multiplying the albedo color, not the emission color. See also [member emission_energy] and [member albedo_mix] to change the emission and albedo intensity independently of each other. </member> <member name="normal_fade" type="float" setter="set_normal_fade" getter="get_normal_fade" default="0.0"> Fades the Decal if the angle between the Decal's [AABB] and the target surface becomes too large. A value of [code]0[/code] projects the Decal regardless of angle, a value of [code]1[/code] limits the Decal to surfaces that are nearly perpendicular. + [b]Note:[/b] Setting [member normal_fade] to a value greater than [code]0.0[/code] has a small performance cost due to the added normal angle computations. </member> <member name="texture_albedo" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] with the base [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object. @@ -98,13 +99,15 @@ <member name="texture_normal" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] with the per-pixel normal map for the decal. Use this to add extra detail to decals. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. + [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a normal-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's normal map should be overridden (and its intensity). </member> <member name="texture_orm" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] storing ambient occlusion, roughness, and metallic for the decal. Use this to add extra detail to decals. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. + [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a ORM-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's ORM map should be overridden (and its intensity). </member> <member name="upper_fade" type="float" setter="set_upper_fade" getter="get_upper_fade" default="0.3"> - Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). + Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). See also [member lower_fade]. </member> </members> <constants> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index cec504584c..bc6cd88fa5 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -930,7 +930,7 @@ <return type="void" /> <argument index="0" name="existing_text" type="String" /> <argument index="1" name="position" type="Rect2" default="Rect2(0, 0, 0, 0)" /> - <argument index="2" name="multiline" type="bool" default="false" /> + <argument index="2" name="type" type="int" enum="DisplayServer.VirtualKeyboardType" default="0" /> <argument index="3" name="max_length" type="int" default="-1" /> <argument index="4" name="cursor_start" type="int" default="-1" /> <argument index="5" name="cursor_end" type="int" default="-1" /> @@ -938,11 +938,11 @@ Shows the virtual keyboard if the platform has one. [code]existing_text[/code] parameter is useful for implementing your own [LineEdit] or [TextEdit], as it tells the virtual keyboard what text has already been typed (the virtual keyboard uses it for auto-correct and predictions). [code]position[/code] parameter is the screen space [Rect2] of the edited text. - [code]multiline[/code] parameter needs to be set to [code]true[/code] to be able to enter multiple lines of text, as in [TextEdit]. + [code]type[/code] parameter allows configuring which type of virtual keyboard to show. [code]max_length[/code] limits the number of characters that can be entered if different from [code]-1[/code]. [code]cursor_start[/code] can optionally define the current text cursor position if [code]cursor_end[/code] is not set. [code]cursor_start[/code] and [code]cursor_end[/code] can optionally define the current text selection. - [b]Note:[/b] This method is implemented on Android, iOS and UWP. + [b]Note:[/b] This method is implemented on Android, iOS and HTML5. </description> </method> <method name="warp_mouse"> @@ -1049,7 +1049,7 @@ <return type="int" enum="DisplayServer.VSyncMode" /> <argument index="0" name="window_id" type="int" default="0" /> <description> - Returns the VSync mode of the given window. + Returns the V-Sync mode of the given window. </description> </method> <method name="window_move_to_foreground"> @@ -1234,7 +1234,7 @@ <argument index="0" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode" /> <argument index="1" name="window_id" type="int" default="0" /> <description> - Sets the VSync mode of the given window. + Sets the V-Sync mode of the given window. See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application. Depending on the platform and used renderer, the engine will fall back to [constant VSYNC_ENABLED], if the desired mode is not supported. </description> @@ -1323,6 +1323,31 @@ </constant> <constant name="SCREEN_SENSOR" value="6" enum="ScreenOrientation"> </constant> + <constant name="KEYBOARD_TYPE_DEFAULT" value="0" enum="VirtualKeyboardType"> + Default text virtual keyboard. + </constant> + <constant name="KEYBOARD_TYPE_MULTILINE" value="1" enum="VirtualKeyboardType"> + Multiline virtual keyboard. + </constant> + <constant name="KEYBOARD_TYPE_NUMBER" value="2" enum="VirtualKeyboardType"> + Virtual number keypad, useful for PIN entry. + </constant> + <constant name="KEYBOARD_TYPE_NUMBER_DECIMAL" value="3" enum="VirtualKeyboardType"> + Virtual number keypad, useful for entering fractional numbers. + </constant> + <constant name="KEYBOARD_TYPE_PHONE" value="4" enum="VirtualKeyboardType"> + Virtual phone number keypad. + </constant> + <constant name="KEYBOARD_TYPE_EMAIL_ADDRESS" value="5" enum="VirtualKeyboardType"> + Virtual keyboard with additional keys to assist with typing email addresses. + </constant> + <constant name="KEYBOARD_TYPE_PASSWORD" value="6" enum="VirtualKeyboardType"> + Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization. + [b]Note:[/b] This is not supported on HTML5. Instead, this behaves identically to [constant KEYBOARD_TYPE_DEFAULT]. + </constant> + <constant name="KEYBOARD_TYPE_URL" value="7" enum="VirtualKeyboardType"> + Virtual keyboard with additional keys to assist with typing URLs. + </constant> <constant name="CURSOR_ARROW" value="0" enum="CursorShape"> </constant> <constant name="CURSOR_IBEAM" value="1" enum="CursorShape"> diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index 8aa2db2cf8..f217fbaf48 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -96,7 +96,7 @@ Adds a static lib from the given [code]path[/code] to the iOS project. </description> </method> - <method name="add_osx_plugin_file"> + <method name="add_macos_plugin_file"> <return type="void" /> <argument index="0" name="path" type="String" /> <description> diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml index 2ab87b0dd1..a6bdc294ac 100644 --- a/doc/classes/EditorFeatureProfile.xml +++ b/doc/classes/EditorFeatureProfile.xml @@ -57,7 +57,7 @@ <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> <description> - Saves the editor feature profile to a file in JSON format. It can then be imported using the feature profile manager's [b]Import[/b] button or the [method load_from_file] button. + Saves the editor feature profile to a file in JSON format. It can then be imported using the feature profile manager's [b]Import[/b] button or the [method load_from_file] method. </description> </method> <method name="set_disable_class"> diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml index d44c08cb0f..2975ea6d75 100644 --- a/doc/classes/EditorPaths.xml +++ b/doc/classes/EditorPaths.xml @@ -48,6 +48,12 @@ [/codeblock] </description> </method> + <method name="get_project_settings_dir" qualifiers="const"> + <return type="String" /> + <description> + Returns the project-specific editor settings path. Projects all have a unique subdirectory inside the settings path where project-specific editor settings are saved. + </description> + </method> <method name="get_self_contained_file" qualifiers="const"> <return type="String" /> <description> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 1514b82ff8..2930c2ec22 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -296,6 +296,28 @@ <return type="bool" /> <description> Returns [code]true[/code] if this is a main screen editor plugin (it goes in the workspace selector together with [b]2D[/b], [b]3D[/b], [b]Script[/b] and [b]AssetLib[/b]). + When the plugin's workspace is selected, other main screen plugins will be hidden, but your plugin will not appear automatically. It needs to be added as a child of [method EditorInterface.get_base_control] and made visible inside [method _make_visible]. + Use [method _get_plugin_name] and [method _get_plugin_icon] to customize the plugin button's appearance. + [codeblock] + var plugin_control + + func _enter_tree(): + plugin_control = preload("my_plugin_control.tscn").instantiate() + get_editor_interface().get_editor_main_control().add_child(plugin_control) + plugin_control.hide() + + func _has_main_screen(): + return true + + func _make_visible(visible): + plugin_control.visible = visible + + func _get_plugin_name(): + return "My Super Cool Plugin 3000" + + func _get_plugin_icon(): + return get_editor_interface().get_base_control().get_theme_icon("Node", "EditorIcons") + [/codeblock] </description> </method> <method name="_make_visible" qualifiers="virtual"> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 84f8523da3..586458bd28 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -101,6 +101,13 @@ Used by sub-inspectors. Emit it if what was selected was an Object ID. </description> </signal> + <signal name="property_can_revert_changed"> + <argument index="0" name="property" type="StringName" /> + <argument index="1" name="can_revert" type="bool" /> + <description> + Emitted when the revertability (i.e., whether it has a non-default value and thus is displayed with a revert icon) of a property has changed. + </description> + </signal> <signal name="property_changed"> <argument index="0" name="property" type="StringName" /> <argument index="1" name="value" type="Variant" /> diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml index 93fd5e46ba..44d644411d 100644 --- a/doc/classes/EditorScenePostImportPlugin.xml +++ b/doc/classes/EditorScenePostImportPlugin.xml @@ -88,7 +88,7 @@ <argument index="2" name="default_value" type="Variant" /> <argument index="3" name="hint" type="int" enum="PropertyHint" default="0" /> <argument index="4" name="hint_string" type="String" default="""" /> - <argument index="5" name="usage_flags" type="int" default="7" /> + <argument index="5" name="usage_flags" type="int" default="6" /> <description> Add a specific import option. This function can only be called from [method _get_import_options] and [method _get_internal_import_options]. </description> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index ac2250ab6d..ade7bc1256 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -105,12 +105,6 @@ Returns project-specific metadata for the [code]section[/code] and [code]key[/code] specified. If the metadata doesn't exist, [code]default[/code] will be returned instead. See also [method set_project_metadata]. </description> </method> - <method name="get_project_settings_dir" qualifiers="const"> - <return type="String" /> - <description> - Returns the project-specific settings path. Projects all have a unique subdirectory inside the settings path where project-specific settings are saved. - </description> - </method> <method name="get_recent_dirs" qualifiers="const"> <return type="PackedStringArray" /> <description> @@ -157,6 +151,7 @@ <argument index="0" name="name" type="String" /> <argument index="1" name="actions_list" type="Array" /> <description> + Overrides the built-in editor action [code]name[/code] with the input actions defined in [code]actions_list[/code]. </description> </method> <method name="set_favorites"> @@ -200,6 +195,730 @@ </description> </method> </methods> + <members> + <member name="debugger/profiler_frame_history_size" type="int" setter="" getter=""> + The size of the profiler's frame history. The default value (3600) allows seeing up to 60 seconds of profiling if the project renders at a constant 60 FPS. Higher values allow viewing longer periods of profiling in the graphs, especially when the project is running at high framerates. + </member> + <member name="docks/filesystem/always_show_folders" type="bool" setter="" getter=""> + If [code]true[/code], displays folders in the FileSystem dock's bottom pane when split mode is enabled. If [code]false[/code], only files will be displayed in the bottom pane. Split mode can be toggled by pressing the icon next to the [code]res://[/code] folder path. + [b]Note:[/b] This setting has no effect when split mode is disabled (which is the default). + </member> + <member name="docks/filesystem/textfile_extensions" type="String" setter="" getter=""> + List of file extensions to consider as editable text files in the FileSystem dock (by double-clicking on the files). + </member> + <member name="docks/filesystem/thumbnail_size" type="int" setter="" getter=""> + The thumbnail size to use in the FileSystem dock (in pixels). See also [member filesystem/file_dialog/thumbnail_size]. + </member> + <member name="docks/property_editor/auto_refresh_interval" type="float" setter="" getter=""> + The refresh interval to use for the inspector dock's properties. The effect of this setting is mainly noticeable when adjusting gizmos in the 2D/3D editor and looking at the inspector at the same time. Lower values make the inspector more often, but take up more CPU time. + </member> + <member name="docks/property_editor/subresource_hue_tint" type="float" setter="" getter=""> + The tint intensity to use for the subresources background in the inspector dock. The tint is used to distinguish between different subresources in the inspector. Higher values result in a more noticeable background color difference. + </member> + <member name="docks/scene_tree/auto_expand_to_selected" type="bool" setter="" getter=""> + If [code]true[/code], the scene tree dock will automatically unfold nodes when a node that has folded parents is selected. + </member> + <member name="docks/scene_tree/start_create_dialog_fully_expanded" type="bool" setter="" getter=""> + If [code]true[/code], the Create dialog (Create New Node/Create New Resource) will start with all its sections expanded. Otherwise, sections will be collapsed until the user starts searching (which will automatically expand sections as needed). + </member> + <member name="editors/2d/bone_color1" type="Color" setter="" getter=""> + The "start" stop of the color gradient to use for bones in the 2D skeleton editor. + </member> + <member name="editors/2d/bone_color2" type="Color" setter="" getter=""> + The "end" stop of the color gradient to use for bones in the 2D skeleton editor. + </member> + <member name="editors/2d/bone_ik_color" type="Color" setter="" getter=""> + The color to use for inverse kinematics-enabled bones in the 2D skeleton editor. + </member> + <member name="editors/2d/bone_outline_color" type="Color" setter="" getter=""> + The outline color to use for non-selected bones in the 2D skeleton editor. See also [member editors/2d/bone_selected_color]. + </member> + <member name="editors/2d/bone_outline_size" type="int" setter="" getter=""> + The outline size in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_width]. + </member> + <member name="editors/2d/bone_selected_color" type="Color" setter="" getter=""> + The color to use for selected bones in the 2D skeleton editor. See also [member editors/2d/bone_outline_color]. + </member> + <member name="editors/2d/bone_width" type="int" setter="" getter=""> + The bone width in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_outline_size]. + </member> + <member name="editors/2d/constrain_editor_view" type="bool" setter="" getter=""> + If [code]true[/code], prevents the 2D editor viewport from leaving the scene. Limits are calculated dynamically based on nodes present in the current scene. If [code]false[/code], the 2D editor viewport will be able to move freely, but you risk getting lost when zooming out too far. You can refocus on the scene by selecting a node then pressing [kbd]F[/kbd]. + </member> + <member name="editors/2d/grid_color" type="Color" setter="" getter=""> + The grid color to use in the 2D editor. + </member> + <member name="editors/2d/guides_color" type="Color" setter="" getter=""> + The guides color to use in the 2D editor. Guides can be created by dragging the mouse cursor from the rulers. + </member> + <member name="editors/2d/smart_snapping_line_color" type="Color" setter="" getter=""> + The color to use when drawing smart snapping lines in the 2D editor. The smart snapping lines will automatically display when moving 2D nodes if smart snapping is enabled in the Snapping Options menu at the top of the 2D editor viewport. + </member> + <member name="editors/2d/viewport_border_color" type="Color" setter="" getter=""> + The color of the viewport border in the 2D editor. This border represents the viewport's size at the base resolution defined in the Project Settings. Objects placed outside this border will not be visible unless a [Camera2D] node is used, or unless the window is resized and the stretch mode is set to [code]disabled[/code]. + </member> + <member name="editors/3d/default_fov" type="float" setter="" getter=""> + The default camera field of view to use in the 3D editor (in degrees). The camera field of view can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera field of view adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor. + </member> + <member name="editors/3d/default_z_far" type="float" setter="" getter=""> + The default camera far clip distance to use in the 3D editor (in degrees). Higher values make it possible to view objects placed further away from the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera far clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera far clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor. + </member> + <member name="editors/3d/default_z_near" type="float" setter="" getter=""> + The default camera near clip distance to use in the 3D editor (in degrees). Lower values make it possible to view objects placed closer to the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera near clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera near clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor. + </member> + <member name="editors/3d/freelook/freelook_activation_modifier" type="int" setter="" getter=""> + The modifier key to use to enable freelook in the 3D editor (on top of pressing the right mouse button). + [b]Note:[/b] Regardless of this setting, the freelook toggle keyboard shortcut ([kbd]Shift + F[/kbd] by default) is always available. + [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed. + </member> + <member name="editors/3d/freelook/freelook_base_speed" type="float" setter="" getter=""> + The base 3D freelook speed in units per second. This can be adjusted by using the mouse wheel while in freelook mode, or by holding down the "fast" or "slow" modifier keys ([kbd]Shift[/kbd] and [kbd]Alt[/kbd] by default, respectively). + </member> + <member name="editors/3d/freelook/freelook_inertia" type="float" setter="" getter=""> + The inertia of the 3D freelook camera. Higher values make the camera start and stop slower, which looks smoother but adds latency. + </member> + <member name="editors/3d/freelook/freelook_navigation_scheme" type="int" setter="" getter=""> + The navigation scheme to use when freelook is enabled in the 3D editor. Some of the navigation schemes below may be more convenient when designing specific levels in the 3D editor. + - [b]Default:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move relative to the camera, taking its pitch angle into account for the movement. + - [b]Partially Axis-Locked:[/b] The "Freelook Forward" and "Freelook Backward" keys will move relative to the camera, taking its pitch angle into account for the movement. The "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement. + - [b]Fully Axis-Locked:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement. + See also [member editors/3d/navigation/navigation_scheme]. + </member> + <member name="editors/3d/freelook/freelook_sensitivity" type="float" setter="" getter=""> + The mouse sensitivity to use while freelook mode is active in the 3D editor. See also [member editors/3d/navigation_feel/orbit_sensitivity]. + </member> + <member name="editors/3d/freelook/freelook_speed_zoom_link" type="bool" setter="" getter=""> + If [code]true[/code], freelook speed is linked to the zoom value used in the camera orbit mode in the 3D editor. + </member> + <member name="editors/3d/grid_division_level_bias" type="float" setter="" getter=""> + The grid division bias to use in the 3D editor. Negative values will cause small grid divisions to appear earlier, whereas positive values will cause small grid divisions to appear later. + </member> + <member name="editors/3d/grid_division_level_max" type="int" setter="" getter=""> + The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get larger than [code]1 ^ grid_division_level_max[/code] units. By default, this means grid divisions cannot get smaller than 100 units each, no matter how far away the camera is from the grid. + </member> + <member name="editors/3d/grid_division_level_min" type="int" setter="" getter=""> + The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get smaller than [code]1 ^ grid_division_level_min[/code] units. By default, this means grid divisions cannot get smaller than 1 unit each, no matter how close the camera is from the grid. + </member> + <member name="editors/3d/grid_size" type="int" setter="" getter=""> + The grid size in units. Higher values prevent the grid from appearing "cut off" at certain angles, but make the grid more demanding to render. Depending on the camera's position, the grid may not be fully visible since a shader is used to fade it progressively. + </member> + <member name="editors/3d/grid_xy_plane" type="bool" setter="" getter=""> + If [code]true[/code], render the grid on an XY plane. This can be useful for 3D side-scrolling games. + </member> + <member name="editors/3d/grid_xz_plane" type="bool" setter="" getter=""> + If [code]true[/code], render the grid on an XZ plane. + </member> + <member name="editors/3d/grid_yz_plane" type="bool" setter="" getter=""> + If [code]true[/code], render the grid on an YZ plane. This can be useful for 3D side-scrolling games. + </member> + <member name="editors/3d/navigation/emulate_3_button_mouse" type="bool" setter="" getter=""> + If [code]true[/code], enables 3-button mouse emulation mode. This is useful on laptops when using a trackpad. + When 3-button mouse emulation mode is enabled, the pan, zoom and orbit modifiers can always be used in the 3D editor viewport, even when not holding down any mouse button. + [b]Note:[/b] No matter the orbit modifier configured in [member editors/3d/navigation/orbit_modifier], [kbd]Alt[/kbd] will always remain usable for orbiting in this mode to improve usability with graphics tablets. + </member> + <member name="editors/3d/navigation/emulate_numpad" type="bool" setter="" getter=""> + If [code]true[/code], allows using the top row [kbd]0[/kbd]-[kbd]9[/kbd] keys to function as their equivalent numpad keys for 3D editor navigation. This should be enabled on keyboards that have no numeric keypad available. + </member> + <member name="editors/3d/navigation/invert_x_axis" type="bool" setter="" getter=""> + If [code]true[/code], invert the horizontal mouse axis when panning or orbiting in the 3D editor. This setting does [i]not[/i] apply to freelook mode. + </member> + <member name="editors/3d/navigation/invert_y_axis" type="bool" setter="" getter=""> + If [code]true[/code], invert the vertical mouse axis when panning, orbiting, or using freelook mode in the 3D editor. + </member> + <member name="editors/3d/navigation/navigation_scheme" type="int" setter="" getter=""> + The navigation scheme to use in the 3D editor. Changing this setting will affect the mouse buttons that must be held down to perform certain operations in the 3D editor viewport. + - [b]Godot[/b] Middle mouse button to orbit, [kbd]Shift + Middle mouse button[/kbd] to pan. [kbd]Mouse wheel[/kbd] to zoom. + - [b]Maya:[/b] [kbd]Alt + Left mouse buttton[/kbd] to orbit. [kbd]Middle mouse button[/kbd] to pan, [kbd]Shift + Middle mouse button[/kbd] to pan 10 times faster. [kbd]Mouse wheel[/kbd] to zoom. + - [b]Modo:[/b] [kbd]Alt + Left mouse buttton[/kbd] to orbit. [kbd]Alt + Shift + Left mouse button[/kbd] to pan. [kbd]Ctrl + Alt + Left mouse button[/kbd] to zoom. + See also [member editors/3d/freelook/freelook_navigation_scheme]. + [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed. + </member> + <member name="editors/3d/navigation/orbit_modifier" type="int" setter="" getter=""> + The modifier key that must be held to orbit in the 3D editor. + [b]Note:[/b] If [member editors/3d/navigation/emulate_3_button_mouse] is [code]true[/code], [kbd]Alt[/kbd] will always remain usable for orbiting to improve usability with graphics tablets. + [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed. + </member> + <member name="editors/3d/navigation/pan_modifier" type="int" setter="" getter=""> + The modifier key that must be held to pan in the 3D editor. + [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed. + </member> + <member name="editors/3d/navigation/warped_mouse_panning" type="bool" setter="" getter=""> + If [code]true[/code], warps the mouse around the 3D viewport while panning in the 3D editor. This makes it possible to pan over a large area without having to exit panning then mouse the mouse back constantly. + </member> + <member name="editors/3d/navigation/zoom_modifier" type="int" setter="" getter=""> + The modifier key that must be held to zoom in the 3D editor. + [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed. + </member> + <member name="editors/3d/navigation/zoom_style" type="int" setter="" getter=""> + The mouse cursor movement direction to use when zooming by moving the mouse. This does not affect zooming with the mouse wheel. + </member> + <member name="editors/3d/navigation_feel/orbit_inertia" type="float" setter="" getter=""> + The inertia to use when orbiting in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency. + </member> + <member name="editors/3d/navigation_feel/orbit_sensitivity" type="float" setter="" getter=""> + The mouse sensitivity to use when orbiting in the 3D editor. See also [member editors/3d/freelook/freelook_sensitivity]. + </member> + <member name="editors/3d/navigation_feel/translation_inertia" type="float" setter="" getter=""> + The inertia to use when panning in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency. + </member> + <member name="editors/3d/navigation_feel/zoom_inertia" type="float" setter="" getter=""> + The inertia to use when zooming in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency. + </member> + <member name="editors/3d/primary_grid_color" type="Color" setter="" getter=""> + The color to use for the primary 3D grid. The color's alpha channel affects the grid's opacity. + </member> + <member name="editors/3d/primary_grid_steps" type="int" setter="" getter=""> + If set above 0, where a primary grid line should be drawn. By default, primary lines are configured to be more visible than secondary lines. This helps with measurements in the 3D editor. See also [member editors/3d/primary_grid_color] and [member editors/3d/secondary_grid_color]. + </member> + <member name="editors/3d/secondary_grid_color" type="Color" setter="" getter=""> + The color to use for the secondary 3D grid. This is generally a less visible color than [member editors/3d/primary_grid_color]. The color's alpha channel affects the grid's opacity. + </member> + <member name="editors/3d/selection_box_color" type="Color" setter="" getter=""> + The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity. + </member> + <member name="editors/3d_gizmos/gizmo_colors/instantiated" type="Color" setter="" getter=""> + The color override to use for 3D editor gizmos if the [Node3D] in question is part of an instanced scene file (from the perspective of the current scene). + </member> + <member name="editors/3d_gizmos/gizmo_colors/joint" type="Color" setter="" getter=""> + The 3D editor gizmo color for [Joint3D]s and [PhysicalBone3D]s. + </member> + <member name="editors/3d_gizmos/gizmo_colors/shape" type="Color" setter="" getter=""> + The 3D editor gizmo color for [CollisionShape3D]s, [VehicleWheel3D]s, [RayCast3D]s and [SpringArm3D]s. + </member> + <member name="editors/animation/autorename_animation_tracks" type="bool" setter="" getter=""> + If [code]true[/code], automatically updates animation tracks' target paths when renaming or reparenting nodes in the Scene tree dock. + </member> + <member name="editors/animation/confirm_insert_track" type="bool" setter="" getter=""> + If [code]true[/code], display a confirmation dialog when adding a new track to an animation by pressing the "key" icon next to a property. + </member> + <member name="editors/animation/default_create_bezier_tracks" type="bool" setter="" getter=""> + If [code]true[/code], create a Bezier track instead of a standard track when pressing the "key" icon next to a property. Bezier tracks provide more control over animation curves, but are more difficult to adjust quickly. + </member> + <member name="editors/animation/default_create_reset_tracks" type="bool" setter="" getter=""> + If [code]true[/code], create a [code]RESET[/code] track when creating a new animation track. This track can be used to restore the animation to a "default" state. + </member> + <member name="editors/animation/onion_layers_future_color" type="Color" setter="" getter=""> + The modulate color to use for "future" frames displayed in the animation editor's onion skinning feature. + </member> + <member name="editors/animation/onion_layers_past_color" type="Color" setter="" getter=""> + The modulate color to use for "past" frames displayed in the animation editor's onion skinning feature. + </member> + <member name="editors/grid_map/pick_distance" type="float" setter="" getter=""> + The maximum distance at which tiles can be placed on a GridMap, relative to the camera position (in 3D units). + </member> + <member name="editors/panning/2d_editor_pan_speed" type="int" setter="" getter=""> + The panning speed when using the mouse wheel or touchscreen events in the 2D editor. This setting does not apply to panning by holding down the middle or right mouse buttons. + </member> + <member name="editors/panning/2d_editor_panning_scheme" type="int" setter="" getter=""> + Controls whether the mouse wheel scroll zooms or pans in the 2D editor. See also [member editors/panning/sub_editors_panning_scheme] and [member editors/panning/animation_editors_panning_scheme]. + </member> + <member name="editors/panning/animation_editors_panning_scheme" type="int" setter="" getter=""> + Controls whether the mouse wheel scroll zooms or pans in the animation track and Bezier editors. See also [member editors/panning/2d_editor_panning_scheme] and [member editors/panning/sub_editors_panning_scheme] (which controls the animation blend tree editor's pan behavior). + </member> + <member name="editors/panning/simple_panning" type="bool" setter="" getter=""> + If [code]true[/code], allows panning by holding down [kbd]Space[/kbd] in the 2D editor viewport (in addition to panning with the middle or right mouse buttons). If [code]false[/code], the left mouse button must be held down while holding down [kbd]Space[/kbd] to pan in the 2D editor viewport. + </member> + <member name="editors/panning/sub_editors_panning_scheme" type="int" setter="" getter=""> + Controls whether the mouse wheel scroll zooms or pans in subeditors. The list of affected subeditors is: animation blend tree editor, [Polygon2D] editor, tileset editor, texture region editor, visual shader editor and visual script editor. See also [member editors/panning/2d_editor_panning_scheme] and [member editors/panning/animation_editors_panning_scheme]. + </member> + <member name="editors/panning/warped_mouse_panning" type="bool" setter="" getter=""> + If [code]true[/code], warps the mouse around the 2D viewport while panning in the 2D editor. This makes it possible to pan over a large area without having to exit panning then mouse the mouse back constantly. + </member> + <member name="editors/polygon_editor/point_grab_radius" type="int" setter="" getter=""> + The radius in which points can be selected in the [Polygon2D] and [CollisionPolygon2D] editors (in pixels). Higher values make it easier to select points quickly, but can make it more difficult to select the expected point when several points are located close to each other. + </member> + <member name="editors/polygon_editor/show_previous_outline" type="bool" setter="" getter=""> + If [code]true[/code], displays the polygon's previous shape in the 2D polygon editors with an opaque gray outline. This outline is displayed while dragging a point until the left mouse button is released. + </member> + <member name="editors/tiles_editor/display_grid" type="bool" setter="" getter=""> + If [code]true[/code], displays a grid while the TileMap editor is active. See also [member editors/tiles_editor/grid_color]. + </member> + <member name="editors/tiles_editor/grid_color" type="Color" setter="" getter=""> + The color to use for the TileMap editor's grid. + [b]Note:[/b] Only effective if [member editors/tiles_editor/display_grid] is [code]true[/code]. + </member> + <member name="editors/visual_editors/lines_curvature" type="float" setter="" getter=""> + The curvature to use for connection lines in the visual script and visual shader editors. Higher values will make connection lines appear more curved, with values above [code]0.5[/code] resulting in more "angular" turns in the middle of connection lines. + </member> + <member name="editors/visual_editors/minimap_opacity" type="float" setter="" getter=""> + The opacity of the minimap displayed in the bottom-right corner of the visual script and visual shader editors. + </member> + <member name="editors/visual_editors/visual_shader/port_preview_size" type="int" setter="" getter=""> + The size to use for port previews in the visual shader uniforms (toggled by clicking the "eye" icon next to an output). The value is defined in pixels at 100% zoom, and will scale with zoom automatically. + </member> + <member name="filesystem/directories/autoscan_project_path" type="String" setter="" getter=""> + The folder where projects should be scanned for (recursively), in a way similar to the project manager's [b]Scan[/b]button. This can be set to the same value as [member filesystem/directories/default_project_path] for convenience. + [b]Note:[/b] Setting this path to a folder with very large amounts of files/folders can slow down the project manager startup significantly. To keep the project manager quick to start up, it is recommended to set this value to a folder as "specific" as possible. + </member> + <member name="filesystem/directories/default_project_path" type="String" setter="" getter=""> + The folder where new projects should be created by default when clicking the project manager's [b]New Project[/b] button. This can be set to the same value as [member filesystem/directories/autoscan_project_path] for convenience. + </member> + <member name="filesystem/file_dialog/display_mode" type="int" setter="" getter=""> + The display mode to use in the editor's file dialogs. + - [b]Thumbnails[/b] takes more space, but displays dynamic resource thumbnails, making resources easier to preview without having to open them. + - [b]List[/b] is more compact but doesn't display dynamic resource thumbnails. Instead, it displays static icons based on the file extension. + </member> + <member name="filesystem/file_dialog/show_hidden_files" type="bool" setter="" getter=""> + If [code]true[/code], display hidden files in the editor's file dialogs. Files that have names starting with [code].[/code] are considered hidden (e.g. [code].hidden_file[/code]). + </member> + <member name="filesystem/file_dialog/thumbnail_size" type="int" setter="" getter=""> + The thumbnail size to use in the editor's file dialogs (in pixels). See also [member docks/filesystem/thumbnail_size]. + </member> + <member name="filesystem/on_save/compress_binary_resources" type="bool" setter="" getter=""> + If [code]true[/code], uses lossless compression for binary resources. + </member> + <member name="filesystem/on_save/safe_save_on_backup_then_rename" type="bool" setter="" getter=""> + If [code]true[/code], when saving a file, the editor will rename the old file to a different name, save a new file, then only remove the old file once the new file has been saved. This makes loss of data less likely to happen if the editor or operating system exits unexpectedly while saving (e.g. due to a crash or power outage). + [b]Note:[/b] On Windows, this feature can interact negatively with certain antivirus programs. In this case, you may have to set this to [code]false[/code] to prevent file locking issues. + </member> + <member name="interface/editor/automatically_open_screenshots" type="bool" setter="" getter=""> + If [code]true[/code], automatically opens screenshots with the default program associated to [code].png[/code] files after a screenshot is taken using the [b]Editor > Take Screenshot[/b] action. + </member> + <member name="interface/editor/code_font" type="String" setter="" getter=""> + The font to use for the script editor. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file. + </member> + <member name="interface/editor/code_font_contextual_ligatures" type="int" setter="" getter=""> + The font ligatures to enable for the currently configured code font. Not all fonts include support for ligatures. + [b]Note:[/b] The default editor code font (Hack) does not have contextual ligatures in its font file. + </member> + <member name="interface/editor/code_font_custom_opentype_features" type="String" setter="" getter=""> + List of custom OpenType features to use, if supported by the currently configured code font. Not all fonts include support for custom OpenType features. The string should follow the OpenType specification. + [b]Note:[/b] The default editor code font (Hack) does not have custom OpenType features in its font file. + </member> + <member name="interface/editor/code_font_custom_variations" type="String" setter="" getter=""> + List of alternative characters to use, if supported by the currently configured code font. Not all fonts include support for custom variations. The string should follow the OpenType specification. + [b]Note:[/b] The default editor code font (Hack) does not have alternate characters in its font file. + </member> + <member name="interface/editor/code_font_size" type="int" setter="" getter=""> + The size of the font in the script editor. This setting does not impact the font size of the Output panel (see [member run/output/font_size]). + </member> + <member name="interface/editor/custom_display_scale" type="float" setter="" getter=""> + The custom editor scale factor to use. This can be used for displays with very high DPI where a scale factor of 200% is not sufficient. + [b]Note:[/b] Only effective if [member interface/editor/display_scale] is set to [b]Custom[/b]. + </member> + <member name="interface/editor/debug/enable_pseudolocalization" type="bool" setter="" getter=""> + If [code]true[/code], lengthens the editor's localizable strings and replaces their characters with accented variants. This allows spotting non-localizable strings easily, while also ensuring the UI layout doesn't break when strings are made longer (as many languages require strings to be longer). + This is a debugging feature and should only be enabled when working on the editor itself. + </member> + <member name="interface/editor/display_scale" type="int" setter="" getter=""> + The display scale factor to use for the editor interface. Higher values are more suited to hiDPI/Retina displays. + If set to [b]Auto[/b], the editor scale is automatically determined based on the screen resolution and reported display DPI. This heuristic is not always ideal, which means you can get better results by setting the editor scale manually. + If set to [b]Custom[/b], the scaling value in [member interface/editor/custom_display_scale] will be used. + </member> + <member name="interface/editor/editor_language" type="String" setter="" getter=""> + The language to use for the editor interface. + Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url] + </member> + <member name="interface/editor/font_antialiased" type="bool" setter="" getter=""> + If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. + </member> + <member name="interface/editor/font_hinting" type="int" setter="" getter=""> + The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes: + - [b]None:[/b] Don't use font hinting when rasterizing the font. This results in a smooth font, but it can look blurry. + - [b]Light:[/b] Use hinting on the X axis only. This is a compromise between font sharpness and smoothness. + - [b]Normal:[/b] Use hinting on both X and Y axes. This results in a sharp font, but it doesn't look very smooth. + If set to [b]Auto[/b], the font hinting mode will be set to match the current operating system in use. This means the [b]Light[/b] hinting mode will be used on Windows and Linux, and the [b]None[/b] hinting mode will be used on macOS. + </member> + <member name="interface/editor/font_subpixel_positioning" type="int" setter="" getter=""> + The subpixel positioning mode to use when rendering editor font glyphs. This affects both the main and code fonts. [b]Disabled[/b] is the fastest to render and uses the least memory. [b]Auto[/b] only uses subpixel positioning for small font sizes (where the benefit is the most noticeable). [b]One half of a pixel[/b] and [b]One quarter of a pixel[/b] force the same subpixel positioning mode for all editor fonts, regardless of their size (with [b]One quarter of a pixel[/b] being the highest-quality option). + </member> + <member name="interface/editor/low_processor_mode_sleep_usec" type="float" setter="" getter=""> + The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops. However, higher values will result in a less responsive editor. The default value is set to allow for maximum smoothness on monitors up to 144 Hz. See also [member interface/editor/unfocused_low_processor_mode_sleep_usec]. + </member> + <member name="interface/editor/main_font" type="String" setter="" getter=""> + The font to use for the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file. + </member> + <member name="interface/editor/main_font_bold" type="String" setter="" getter=""> + The font to use for bold text in the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file. + </member> + <member name="interface/editor/main_font_size" type="int" setter="" getter=""> + The size of the font in the editor interface. + </member> + <member name="interface/editor/mouse_extra_buttons_navigate_history" type="bool" setter="" getter=""> + If [code]true[/code], the mouse's additional side buttons will be usable to navigate in the script editor's file history. Set this to [code]false[/code] if you're using the side buttons for other purposes (such as a push-to-talk button in a VoIP program). + </member> + <member name="interface/editor/save_each_scene_on_quit" type="bool" setter="" getter=""> + If [code]true[/code], the editor will save all scenes when confirming the [b]Save[/b] action when quitting the editor or quitting to the project list. If [code]false[/code], the editor will ask to save each scene individually. + </member> + <member name="interface/editor/separate_distraction_mode" type="bool" setter="" getter=""> + If [code]true[/code], the editor's Script tab will have a separate distraction mode setting from the 2D/3D/AssetLib tabs. If [code]false[/code], the distraction-free mode toggle is shared between all tabs. + </member> + <member name="interface/editor/show_internal_errors_in_toast_notifications" type="int" setter="" getter=""> + If enabled, displays internal engine errors in toast notifications (toggleable by clicking the "bell" icon at the bottom of the editor). No matter the value of this setting, non-internal engine errors will always be visible in toast notifications. + The default [b]Auto[/b] value will only enable this if the editor was compiled with the [code]dev=yes[/code] option (the default is [code]dev=no[/code]). + </member> + <member name="interface/editor/single_window_mode" type="bool" setter="" getter=""> + If [code]true[/code], embed modal windows such as docks inside the main editor window. When single-window mode is enabled, tooltips will also be embedded inside the main editor window, which means they can't be displayed outside of the editor window. + </member> + <member name="interface/editor/unfocused_low_processor_mode_sleep_usec" type="float" setter="" getter=""> + When the editor window is unfocused, the amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops (in addition to improving the running project's performance if the editor has to redraw continuously). However, higher values will result in a less responsive editor. The default value is set to limit the editor to 20 FPS when the editor window is unfocused. See also [member interface/editor/low_processor_mode_sleep_usec]. + </member> + <member name="interface/inspector/max_array_dictionary_items_per_page" type="int" setter="" getter=""> + The number of [Array] or [Dictionary] items to display on each "page" in the inspector. Higher values allow viewing more values per page, but take more time to load. This increased load time is noticeable when selecting nodes that have array or dictionary properties in the editor. + </member> + <member name="interface/inspector/show_low_level_opentype_features" type="bool" setter="" getter=""> + If [code]true[/code], display OpenType features marked as [code]hidden[/code] by the font file in the [Font] editor. + </member> + <member name="interface/scene_tabs/display_close_button" type="int" setter="" getter=""> + Controls when the Close (X) button is displayed on scene tabs at the top of the editor. + </member> + <member name="interface/scene_tabs/maximum_width" type="int" setter="" getter=""> + The maximum width of each scene tab at the top editor (in pixels). + </member> + <member name="interface/scene_tabs/show_script_button" type="bool" setter="" getter=""> + If [code]true[/code], show a button next to each scene tab that opens the scene's "dominant" script when clicked. The "dominant" script is the one that is at the highest level in the scene's hierarchy. + </member> + <member name="interface/scene_tabs/show_thumbnail_on_hover" type="bool" setter="" getter=""> + If [code]true[/code], display an automatically-generated thumbnail when hovering scene tabs with the mouse. Scene thumbnails are generated when saving the scene. + </member> + <member name="interface/theme/accent_color" type="Color" setter="" getter=""> + The color to use for "highlighted" user interface elements in the editor (pressed and hovered items). + </member> + <member name="interface/theme/additional_spacing" type="float" setter="" getter=""> + The spacing to add for buttons and list items in the editor (in pixels). Increasing this value is useful to improve usability on touch screens, at the cost of reducing the amount of usable screen real estate. + </member> + <member name="interface/theme/base_color" type="Color" setter="" getter=""> + The base color to use for user interface elements in the editor. Secondary colors (such as darker/lighter variants) are derived from this color. + </member> + <member name="interface/theme/border_size" type="int" setter="" getter=""> + The border size to use for interface elements (in pixels). + </member> + <member name="interface/theme/contrast" type="float" setter="" getter=""> + The contrast factor to use when deriving the editor theme's base color (see [member interface/theme/base_color]). When using a positive values, the derived colors will be [i]darker[/i] than the base color. This contrast factor can be set to a negative value, which will make the derived colors [i]brighter[/i] than the base color. Negative contrast rates often look better for light themes. + </member> + <member name="interface/theme/corner_radius" type="int" setter="" getter=""> + The corner radius to use for interface elements (in pixels). [code]0[/code] is square. + </member> + <member name="interface/theme/custom_theme" type="String" setter="" getter=""> + The custom theme resource to use for the editor. Must be a Godot theme resource in [code].tres[/code] or [code].res[/code] format. + </member> + <member name="interface/theme/icon_and_font_color" type="int" setter="" getter=""> + The icon and font color scheme to use in the editor. + - [b]Auto[/b] determines the color scheme to use automatically based on [member interface/theme/base_color]. + - [b]Dark[/b] makes fonts and icons light (suitable for dark themes). + - [b]Light[/b] makes fonts and icons dark (suitable for light themes). Icon colors are automatically converted by the editor following [url=https://github.com/godotengine/godot/blob/master/editor/editor_themes.cpp#L135]this set of rules[/url]. + </member> + <member name="interface/theme/icon_saturation" type="float" setter="" getter=""> + The saturation to use for editor icons. Higher values result in more vibrant colors. + [b]Note:[/b] The default editor icon saturation was increased by 30% in Godot 4.0 and later. To get Godot 3.x's icon saturation back, set [member interface/theme/icon_saturation] to [code]0.77[/code]. + </member> + <member name="interface/theme/preset" type="String" setter="" getter=""> + The editor theme preset to use. + </member> + <member name="interface/theme/relationship_line_opacity" type="float" setter="" getter=""> + The opacity to use when drawing relationship lines in the editor's [Tree]-based GUIs (such as the Scene tree dock). + </member> + <member name="network/debug/remote_host" type="String" setter="" getter=""> + The address to listen to when starting the remote debugger. This can be set to [code]0.0.0.0[/code] to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]). + </member> + <member name="network/debug/remote_port" type="int" setter="" getter=""> + The port to listen to when starting the remote debugger. Godot will try to use port numbers above the configured number if the configured number is already taken by another application. + </member> + <member name="network/http_proxy/host" type="String" setter="" getter=""> + The host to use to contact the HTTP and HTTPS proxy in the editor (for the asset library and export template downloads). See also [member network/http_proxy/port]. + [b]Note:[/b] Godot currently doesn't automatically use system proxy settings, so you have to enter them manually here if needed. + </member> + <member name="network/http_proxy/port" type="int" setter="" getter=""> + The port number to use to contact the HTTP and HTTPS proxy in the editor (for the asset library and export template downloads). See also [member network/http_proxy/host]. + [b]Note:[/b] Godot currently doesn't automatically use system proxy settings, so you have to enter them manually here if needed. + </member> + <member name="network/ssl/editor_ssl_certificates" type="String" setter="" getter=""> + The SSL certificate bundle to use for HTTP requests made within the editor (e.g. from the AssetLib tab). If left empty, the [url=https://github.com/godotengine/godot/blob/master/thirdparty/certs/ca-certificates.crt]included Mozilla certificate bundle[/url] will be used. + </member> + <member name="project_manager/sorting_order" type="int" setter="" getter=""> + The sorting order to use in the project manager. When changing the sorting order in the project manager, this setting is set permanently in the editor settings. + </member> + <member name="run/auto_save/save_before_running" type="bool" setter="" getter=""> + If [code]true[/code], saves all scenes and scripts automatically before running the project. Setting this to [code]false[/code] prevents the editor from saving if there are no changes which can speed up the project startup slightly, but it makes it possible to run a project that has unsaved changes. (Unsaved changes will not be visible in the running project.) + </member> + <member name="run/output/always_clear_output_on_play" type="bool" setter="" getter=""> + If [code]true[/code], the editor will clear the Output panel when running the project. + </member> + <member name="run/output/always_close_output_on_stop" type="bool" setter="" getter=""> + If [code]true[/code], the editor will collapse the Output panel when stopping the project. + </member> + <member name="run/output/always_open_output_on_play" type="bool" setter="" getter=""> + If [code]true[/code], the editor will expand the Output panel when running the project. + </member> + <member name="run/output/font_size" type="int" setter="" getter=""> + The size of the font in the [b]Output[/b] panel at the bottom of the editor. This setting does not impact the font size of the script editor (see [member interface/editor/code_font_size]). + </member> + <member name="run/window_placement/rect" type="int" setter="" getter=""> + The window mode to use to display the project when starting the project from the editor. + </member> + <member name="run/window_placement/rect_custom_position" type="Vector2" setter="" getter=""> + The custom position to use when starting the project from the editor (in pixels from the top-left corner). Only effective if [member run/window_placement/rect] is set to [b]Custom Position[/b]. + </member> + <member name="run/window_placement/screen" type="int" setter="" getter=""> + The monitor to display the project on when starting the project from the editor. + </member> + <member name="text_editor/appearance/caret/caret_blink" type="bool" setter="" getter=""> + If [code]true[/code], makes the caret blink according to [member text_editor/appearance/caret/caret_blink_speed]. Disabling this setting can improve battery life on laptops if you spend long amounts of time in the script editor, since it will reduce the frequency at which the editor needs to be redrawn. + </member> + <member name="text_editor/appearance/caret/caret_blink_speed" type="float" setter="" getter=""> + The interval at which to blink the caret (in seconds). See also [member text_editor/appearance/caret/caret_blink]. + </member> + <member name="text_editor/appearance/caret/highlight_all_occurrences" type="bool" setter="" getter=""> + If [code]true[/code], highlights all occurrences of the currently selected text in the script editor. See also [member text_editor/theme/highlighting/word_highlighted_color]. + </member> + <member name="text_editor/appearance/caret/highlight_current_line" type="bool" setter="" getter=""> + If [code]true[/code], colors the background of the line the caret is currently on with [member text_editor/theme/highlighting/current_line_color]. + </member> + <member name="text_editor/appearance/caret/type" type="int" setter="" getter=""> + The shape of the caret to use in the script editor. [b]Line[/b] displays a vertical line to the left of the current character, whereas [b]Block[/b] displays a outline over the current character. + </member> + <member name="text_editor/appearance/guidelines/line_length_guideline_hard_column" type="int" setter="" getter=""> + The column at which to display a subtle line as a line length guideline for scripts. This should generally be greater than [member text_editor/appearance/guidelines/line_length_guideline_soft_column]. + </member> + <member name="text_editor/appearance/guidelines/line_length_guideline_soft_column" type="int" setter="" getter=""> + The column at which to display a [i]very[/i] subtle line as a line length guideline for scripts. This should generally be lower than [member text_editor/appearance/guidelines/line_length_guideline_hard_column]. + </member> + <member name="text_editor/appearance/guidelines/show_line_length_guidelines" type="bool" setter="" getter=""> + If [code]true[/code], displays line length guidelines to help you keep line lengths in check. See also [member text_editor/appearance/guidelines/line_length_guideline_soft_column] and [member text_editor/appearance/guidelines/line_length_guideline_hard_column]. + </member> + <member name="text_editor/appearance/gutters/highlight_type_safe_lines" type="bool" setter="" getter=""> + If [code]true[/code], highlights type-safe lines by displaying their line number color with [member text_editor/theme/highlighting/safe_line_number_color] instead of [member text_editor/theme/highlighting/line_number_color]. Type-safe lines are lines of code where the type of all variables is known at compile-time. These type-safe lines will run faster in Godot 4.0 and later thanks to typed instructions. + </member> + <member name="text_editor/appearance/gutters/line_numbers_zero_padded" type="bool" setter="" getter=""> + If [code]true[/code], displays line numbers with zero padding (e.g. [code]007[/code] instead of [code]7[/code]). + </member> + <member name="text_editor/appearance/gutters/show_bookmark_gutter" type="bool" setter="" getter=""> + If [code]true[/code], displays a gutter at the left containing icons for bookmarks. + </member> + <member name="text_editor/appearance/gutters/show_info_gutter" type="bool" setter="" getter=""> + If [code]true[/code], displays a gutter at the left containing icons for methods with signal connections. + </member> + <member name="text_editor/appearance/gutters/show_line_numbers" type="bool" setter="" getter=""> + If [code]true[/code], displays line numbers in the gutter at the left. + </member> + <member name="text_editor/appearance/lines/code_folding" type="bool" setter="" getter=""> + If [code]true[/code], displays the folding arrows next to indented code sections and allows code folding. If [code]false[/code], hides the folding arrows next to indented code sections and disallows code folding. + </member> + <member name="text_editor/appearance/lines/word_wrap" type="int" setter="" getter=""> + If [code]true[/code], wraps long lines over multiple lines to avoid horizontal scrolling. This is a display-only feature; it does not actually insert line breaks in your scripts. + </member> + <member name="text_editor/appearance/minimap/minimap_width" type="int" setter="" getter=""> + The width of the minimap in the script editor (in pixels). + </member> + <member name="text_editor/appearance/minimap/show_minimap" type="bool" setter="" getter=""> + If [code]true[/code], draws an overview of the script near the scroll bar. The minimap can be left-clicked to scroll directly to a location in an "absolute" manner. + </member> + <member name="text_editor/appearance/whitespace/draw_spaces" type="bool" setter="" getter=""> + If [code]true[/code], draws space characters as centered points. + </member> + <member name="text_editor/appearance/whitespace/draw_tabs" type="bool" setter="" getter=""> + If [code]true[/code], draws tab characters as chevrons. + </member> + <member name="text_editor/appearance/whitespace/line_spacing" type="int" setter="" getter=""> + The space to add between lines (in pixels). Greater line spacing can help improve readability at the cost of displaying less lines on screen. + </member> + <member name="text_editor/behavior/files/auto_reload_scripts_on_external_change" type="bool" setter="" getter=""> + If [code]true[/code], automatically reloads scripts in the editor when they have been modified and saved by external editors. + </member> + <member name="text_editor/behavior/files/autosave_interval_secs" type="int" setter="" getter=""> + If set to a value greater than [code]0[/code], automatically saves the current script following the specified interval (in seconds). This can be used to prevent data loss if the editor crashes. + </member> + <member name="text_editor/behavior/files/convert_indent_on_save" type="bool" setter="" getter=""> + If [code]true[/code], converts indentation to match the script editor's indentation settings when saving a script. See also [member text_editor/behavior/indent/type]. + </member> + <member name="text_editor/behavior/files/restore_scripts_on_load" type="bool" setter="" getter=""> + If [code]true[/code], reopens scripts that were opened in the last session when the editor is reopened on a given project. + </member> + <member name="text_editor/behavior/files/trim_trailing_whitespace_on_save" type="bool" setter="" getter=""> + If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy. + </member> + <member name="text_editor/behavior/indent/auto_indent" type="bool" setter="" getter=""> + If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line. + </member> + <member name="text_editor/behavior/indent/size" type="int" setter="" getter=""> + When using tab indentation, determines the length of each tab. When using space indentation, determines how many spaces are inserted when pressing [kbd]Tab[/kbd] and when automatic indentation is performed. + </member> + <member name="text_editor/behavior/indent/type" type="int" setter="" getter=""> + The indentation style to use (tabs or spaces). + [b]Note:[/b] The [url=https://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url] recommends using tabs for indentation. It is advised to change this setting only if you need to work on a project that currently uses spaces for indentation. + </member> + <member name="text_editor/behavior/navigation/drag_and_drop_selection" type="bool" setter="" getter=""> + If [code]true[/code], allows drag-and-dropping text in the script editor to move text. Disable this if you find yourself accidentally drag-and-dropping text in the script editor. + </member> + <member name="text_editor/behavior/navigation/move_caret_on_right_click" type="bool" setter="" getter=""> + If [code]true[/code], the caret will be moved when right-clicking somewhere in the script editor (like when left-clicking or middle-clicking). If [code]false[/code], the caret will only be moved when left-clicking or middle-clicking somewhere. + </member> + <member name="text_editor/behavior/navigation/scroll_past_end_of_file" type="bool" setter="" getter=""> + If [code]true[/code], allows scrolling past the end of the file. + </member> + <member name="text_editor/behavior/navigation/smooth_scrolling" type="bool" setter="" getter=""> + If [code]true[/code], allows scrolling in sub-line intervals and enables a smooth scrolling animation when using the mouse wheel to scroll. + [b]Note:[/b] [member text_editor/behavior/navigation/smooth_scrolling] currently behaves poorly in projects where [member ProjectSettings.physics/common/physics_ticks_per_second] has been increased significantly from its default value ([code]60[/code]). In this case, it is recommended to disable this setting. + </member> + <member name="text_editor/behavior/navigation/stay_in_script_editor_on_node_selected" type="bool" setter="" getter=""> + If [code]true[/code], prevents automatically switching between the Script and 2D/3D screens when selecting a node in the Scene tree dock. + </member> + <member name="text_editor/behavior/navigation/v_scroll_speed" type="int" setter="" getter=""> + The number of pixels to scroll with every mouse wheel increment. Higher values make the script scroll by faster when using the mouse wheel. + [b]Note:[/b] You can hold down [kbd]Alt[/kbd] while using the mouse wheel to temporarily scroll 5 times faster. + </member> + <member name="text_editor/completion/add_type_hints" type="bool" setter="" getter=""> + If [code]true[/code], adds static typing hints such as [code]-> void[/code] and [code]: int[/code] when performing method definition autocompletion. + </member> + <member name="text_editor/completion/auto_brace_complete" type="bool" setter="" getter=""> + If [code]true[/code], automatically completes braces when making use of code completion. + </member> + <member name="text_editor/completion/code_complete_delay" type="float" setter="" getter=""> + The delay in seconds after which autocompletion suggestions should be displayed when the user stops typing. + </member> + <member name="text_editor/completion/complete_file_paths" type="bool" setter="" getter=""> + If [code]true[/code], provides autocompletion suggestions for file paths in methods such as [code]load()[/code] and [code]preload()[/code]. + </member> + <member name="text_editor/completion/idle_parse_delay" type="float" setter="" getter=""> + The delay in seconds after which the script editor should check for errors when the user stops typing. + </member> + <member name="text_editor/completion/put_callhint_tooltip_below_current_line" type="bool" setter="" getter=""> + If [code]true[/code], the code completion tooltip will appear below the current line unless there is no space on screen below the current line. If [code]false[/code], the code completion tooltip will appear above the current line. + </member> + <member name="text_editor/completion/use_single_quotes" type="bool" setter="" getter=""> + If [code]true[/code], performs string autocompletion with single quotes. If [code]false[/code], performs string autocompletion with double quotes (which matches the [url=https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url]). + </member> + <member name="text_editor/help/class_reference_examples" type="int" setter="" getter=""> + Controls which multi-line code blocks should be displayed in the editor help. This setting does not affect single-line code literals in the editor help. + </member> + <member name="text_editor/help/help_font_size" type="int" setter="" getter=""> + The font size to use for the editor help (built-in class reference). + </member> + <member name="text_editor/help/help_source_font_size" type="int" setter="" getter=""> + The font size to use for code samples in the editor help (built-in class reference). + </member> + <member name="text_editor/help/help_title_font_size" type="int" setter="" getter=""> + The font size to use for headings in the editor help (built-in class reference). + </member> + <member name="text_editor/help/show_help_index" type="bool" setter="" getter=""> + If [code]true[/code], displays a table of contents at the left of the editor help (at the location where the members overview would appear when editing a script). + </member> + <member name="text_editor/script_list/show_members_overview" type="bool" setter="" getter=""> + If [code]true[/code], displays an overview of the current script's member variables and functions at the left of the script editor. See also [member text_editor/script_list/sort_members_outline_alphabetically]. + </member> + <member name="text_editor/script_list/sort_members_outline_alphabetically" type="bool" setter="" getter=""> + If [code]true[/code], sorts the members outline (located at the left of the script editor) using alphabetical order. If [code]false[/code], sorts the members outline depending on the order in which members are found in the script. + [b]Note:[/b] Only effective if [member text_editor/script_list/show_members_overview] is [code]true[/code]. + </member> + <member name="text_editor/theme/color_theme" type="String" setter="" getter=""> + The syntax theme to use in the script editor. + You can save your own syntax theme from your current settings by using [b]File > Theme > Save As...[/b] at the top of the script editor. The syntax theme will then be available locally in the list of color themes. + You can find additional syntax themes to install in the [url=https://github.com/godotengine/godot-syntax-themes]godot-syntax-themes[/url] repository. + </member> + <member name="text_editor/theme/highlighting/background_color" type="Color" setter="" getter=""> + The script editor's background color. If set to a translucent color, the editor theme's base color will be visible behind. + </member> + <member name="text_editor/theme/highlighting/base_type_color" type="Color" setter="" getter=""> + The script editor's base type color (used for types like [Vector2], [Vector3], ...). + </member> + <member name="text_editor/theme/highlighting/bookmark_color" type="Color" setter="" getter=""> + The script editor's bookmark icon color (displayed in the gutter). + </member> + <member name="text_editor/theme/highlighting/brace_mismatch_color" type="Color" setter="" getter=""> + The script editor's brace mismatch color. Used when the caret is currently on a mismatched brace, parenthesis or bracket character. + </member> + <member name="text_editor/theme/highlighting/breakpoint_color" type="Color" setter="" getter=""> + The script editor's breakpoint icon color (displayed in the gutter). + </member> + <member name="text_editor/theme/highlighting/caret_background_color" type="Color" setter="" getter=""> + The script editor's caret background color. + [b]Note:[/b] This setting has no effect as it's currently unused. + </member> + <member name="text_editor/theme/highlighting/caret_color" type="Color" setter="" getter=""> + The script editor's caret color. + </member> + <member name="text_editor/theme/highlighting/code_folding_color" type="Color" setter="" getter=""> + The script editor's color for the code folding icon (displayed in the gutter). + </member> + <member name="text_editor/theme/highlighting/comment_color" type="Color" setter="" getter=""> + The script editor's comment color. + [b]Note:[/b] In GDScript, unlike Python, multiline strings are not considered to be comments, and will use the string highlighting color instead. + </member> + <member name="text_editor/theme/highlighting/completion_background_color" type="Color" setter="" getter=""> + The script editor's autocompletion box background color. + </member> + <member name="text_editor/theme/highlighting/completion_existing_color" type="Color" setter="" getter=""> + The script editor's autocompletion box background color to highlight existing characters in the completion results. This should be a translucent color so that [member text_editor/theme/highlighting/completion_selected_color] can be seen behind. + </member> + <member name="text_editor/theme/highlighting/completion_font_color" type="Color" setter="" getter=""> + The script editor's autocompletion box text color. + </member> + <member name="text_editor/theme/highlighting/completion_scroll_color" type="Color" setter="" getter=""> + The script editor's autocompletion box scroll bar color. + </member> + <member name="text_editor/theme/highlighting/completion_scroll_hovered_color" type="Color" setter="" getter=""> + The script editor's autocompletion box scroll bar color when hovered or pressed with the mouse. + </member> + <member name="text_editor/theme/highlighting/completion_selected_color" type="Color" setter="" getter=""> + The script editor's autocompletion box background color for the currently selected line. + </member> + <member name="text_editor/theme/highlighting/control_flow_keyword_color" type="Color" setter="" getter=""> + The script editor's control flow keyword color (used for keywords like [code]if[/code], [code]for[/code], [code]return[/code], ...). + </member> + <member name="text_editor/theme/highlighting/current_line_color" type="Color" setter="" getter=""> + The script editor's background color for the line the caret is currently on. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/mark_color]. + </member> + <member name="text_editor/theme/highlighting/engine_type_color" type="Color" setter="" getter=""> + The script editor's engine type color ([Vector2], [Vector3], [Color], ...). + </member> + <member name="text_editor/theme/highlighting/executing_line_color" type="Color" setter="" getter=""> + The script editor's color for the debugger's executing line icon (displayed in the gutter). + </member> + <member name="text_editor/theme/highlighting/function_color" type="Color" setter="" getter=""> + The script editor's function call color. + [b]Note:[/b] When using the GDScript syntax highlighter, this is replaced by the function declaration color configured in the syntax theme for function declarations (e.g. [code]func _ready():[/code]). + </member> + <member name="text_editor/theme/highlighting/keyword_color" type="Color" setter="" getter=""> + The script editor's non-control flow keyword color (used for keywords like [code]var[/code], [code]func[/code], some built-in methods, ...). + </member> + <member name="text_editor/theme/highlighting/line_length_guideline_color" type="Color" setter="" getter=""> + The script editor's color for the line length guideline. The "hard" line length guideline will be drawn with this color, whereas the "soft" line length guideline will be drawn with an opacity twice as low. + </member> + <member name="text_editor/theme/highlighting/line_number_color" type="Color" setter="" getter=""> + The script editor's color for line numbers. See also [member text_editor/theme/highlighting/safe_line_number_color]. + </member> + <member name="text_editor/theme/highlighting/mark_color" type="Color" setter="" getter=""> + The script editor's background color for lines with errors. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/current_line_color]. + </member> + <member name="text_editor/theme/highlighting/member_variable_color" type="Color" setter="" getter=""> + The script editor's color for member variables on objects (e.g. [code]self.some_property[/code]). + [b]Note:[/b] This color is not used for local variable declaration and access. + </member> + <member name="text_editor/theme/highlighting/number_color" type="Color" setter="" getter=""> + The script editor's color for numbers (integer and floating-point). + </member> + <member name="text_editor/theme/highlighting/safe_line_number_color" type="Color" setter="" getter=""> + The script editor's color for type-safe line numbers. See also [member text_editor/theme/highlighting/line_number_color]. + [b]Note:[/b] Only displayed if [member text_editor/appearance/gutters/highlight_type_safe_lines] is [code]true[/code]. + </member> + <member name="text_editor/theme/highlighting/search_result_border_color" type="Color" setter="" getter=""> + The script editor's color for the border of search results. This border helps bring further attention to the search result. Set this color's opacity to 0 to disable the border. + </member> + <member name="text_editor/theme/highlighting/search_result_color" type="Color" setter="" getter=""> + The script editor's background color for search results. + </member> + <member name="text_editor/theme/highlighting/selection_color" type="Color" setter="" getter=""> + The script editor's background color for the currently selected text. + </member> + <member name="text_editor/theme/highlighting/string_color" type="Color" setter="" getter=""> + The script editor's color for strings (single-line and multi-line). + </member> + <member name="text_editor/theme/highlighting/symbol_color" type="Color" setter="" getter=""> + The script editor's color for operators ([code]( ) [ ] { } + - * /[/code], ...). + </member> + <member name="text_editor/theme/highlighting/text_color" type="Color" setter="" getter=""> + The script editor's color for text not highlighted by any syntax highlighting rule. + </member> + <member name="text_editor/theme/highlighting/text_selected_color" type="Color" setter="" getter=""> + The script editor's background color for text. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/current_line_color]. + </member> + <member name="text_editor/theme/highlighting/user_type_color" type="Color" setter="" getter=""> + The script editor's color for user-defined types (using [code]@class_name[/code]). + </member> + <member name="text_editor/theme/highlighting/word_highlighted_color" type="Color" setter="" getter=""> + The script editor's color for words highlighted by selecting them. Only visible if [member text_editor/appearance/caret/highlight_all_occurrences] is [code]true[/code]. + </member> + </members> <signals> <signal name="settings_changed"> <description> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index 506992e3af..36dfee833b 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -151,6 +151,12 @@ [/codeblocks] </description> </method> + <method name="get_write_movie_path" qualifiers="const"> + <return type="String" /> + <description> + Returns the path to the [MovieWriter]'s output file, or an empty string if the engine wasn't started in Movie Maker mode. This path can be absolute or relative depending on how the user specified it. + </description> + </method> <method name="has_singleton" qualifiers="const"> <return type="bool" /> <argument index="0" name="name" type="StringName" /> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 9da360915b..f662a07825 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -97,7 +97,7 @@ Blend factor between the fog's color and the color of the background [Sky]. Must have [member background_mode] set to [constant BG_SKY]. This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled. </member> - <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.001"> + <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01"> The exponential fog density to use. Higher values result in a more dense fog. </member> <member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false"> @@ -109,7 +109,7 @@ <member name="fog_height_density" type="float" setter="set_fog_height_density" getter="get_fog_height_density" default="0.0"> The density used to increase fog as height decreases. To make fog increase as height increases, use a negative value. </member> - <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.5, 0.6, 0.7, 1)"> + <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.518, 0.553, 0.608, 1)"> The fog's color. </member> <member name="fog_light_energy" type="float" setter="set_fog_light_energy" getter="get_fog_light_energy" default="1.0"> @@ -320,8 +320,9 @@ <member name="volumetric_fog_enabled" type="bool" setter="set_volumetric_fog_enabled" getter="is_volumetric_fog_enabled" default="false"> Enables the volumetric fog effect. Volumetric fog uses a screen-aligned froxel buffer to calculate accurate volumetric scattering in the short to medium range. Volumetric fog interacts with [FogVolume]s and lights to calculate localized and global fog. Volumetric fog uses a PBR single-scattering model based on extinction, scattering, and emission which it exposes to users as density, albedo, and emission. </member> - <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="0.0"> - Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0[/code] means that Global Illumination will not impact the volumetric fog. + <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="1.0"> + Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0.0[/code] means that Global Illumination will not impact the volumetric fog. + [b]Note:[/b] Only [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) are taken into account when using [member volumetric_fog_gi_inject]. Global illumination from [LightmapGI], [ReflectionProbe] and SSIL (see [member ssil_enabled]) will be ignored by volumetric fog. </member> <member name="volumetric_fog_length" type="float" setter="set_volumetric_fog_length" getter="get_volumetric_fog_length" default="64.0"> The distance over which the volumetric fog is computed. Increase to compute fog over a greater range, decrease to add more detail when a long range is not needed. For best quality fog, keep this as low as possible. diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 0b4a8fa46e..3a2776ff21 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -115,9 +115,10 @@ </method> <method name="get_as_text" qualifiers="const"> <return type="String" /> + <argument index="0" name="skip_cr" type="bool" default="false" /> <description> - Returns the whole file as a [String]. - Text is interpreted as being UTF-8 encoded. + Returns the whole file as a [String]. Text is interpreted as being UTF-8 encoded. + If [code]skip_cr[/code] is [code]true[/code], carriage return characters ([code]\r[/code], CR) will be ignored when parsing the UTF-8, so that only line feed characters ([code]\n[/code], LF) represent a new line (Unix convention). </description> </method> <method name="get_buffer" qualifiers="const"> diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml index b19386b398..ec2776f636 100644 --- a/doc/classes/Font.xml +++ b/doc/classes/Font.xml @@ -14,8 +14,8 @@ <argument index="0" name="canvas_item" type="RID" /> <argument index="1" name="pos" type="Vector2" /> <argument index="2" name="char" type="int" /> - <argument index="3" name="modulate" type="int" /> - <argument index="4" name="arg4" type="Color" default="Color(1, 1, 1, 1)" /> + <argument index="3" name="font_size" type="int" /> + <argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> <description> Draw a single Unicode character [code]char[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. [b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead. @@ -26,9 +26,9 @@ <argument index="0" name="canvas_item" type="RID" /> <argument index="1" name="pos" type="Vector2" /> <argument index="2" name="char" type="int" /> - <argument index="3" name="size" type="int" /> - <argument index="4" name="modulate" type="int" default="-1" /> - <argument index="5" name="arg5" type="Color" default="Color(1, 1, 1, 1)" /> + <argument index="3" name="font_size" type="int" /> + <argument index="4" name="size" type="int" default="-1" /> + <argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> <description> Draw a single Unicode character [code]char[/code] outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. [b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead. @@ -44,9 +44,10 @@ <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="max_lines" type="int" default="-1" /> <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="8" name="flags" type="int" default="99" /> - <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" /> - <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> + <argument index="8" name="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> + <argument index="9" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> + <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" /> + <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws it into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. See also [method CanvasItem.draw_multiline_string]. @@ -63,9 +64,10 @@ <argument index="6" name="max_lines" type="int" default="-1" /> <argument index="7" name="size" type="int" default="1" /> <argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="9" name="flags" type="int" default="99" /> - <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" /> - <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> + <argument index="9" name="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> + <argument index="10" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> + <argument index="11" name="direction" type="int" enum="TextServer.Direction" default="0" /> + <argument index="12" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws text outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. See also [method CanvasItem.draw_multiline_string_outline]. @@ -80,7 +82,7 @@ <argument index="4" name="width" type="float" default="-1" /> <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="7" name="flags" type="int" default="3" /> + <argument index="7" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> @@ -98,7 +100,7 @@ <argument index="5" name="font_size" type="int" default="16" /> <argument index="6" name="size" type="int" default="1" /> <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> - <argument index="8" name="flags" type="int" default="3" /> + <argument index="8" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> @@ -127,7 +129,7 @@ <method name="get_char_size" qualifiers="const"> <return type="Vector2" /> <argument index="0" name="char" type="int" /> - <argument index="1" name="arg1" type="int" /> + <argument index="1" name="font_size" type="int" /> <description> Returns the size of a character, optionally taking kerning into account if the next character is provided. [b]Note:[/b] Do not use this function to calculate width of the string character by character, use [method get_string_size] or [TextLine] instead. The height returned is the font height (see also [method get_height]) and has no relation to the glyph height. @@ -160,7 +162,7 @@ </description> </method> <method name="get_font_style" qualifiers="const"> - <return type="int" /> + <return type="int" enum="TextServer.FontStyle" /> <description> Returns font style flags, see [enum TextServer.FontStyle]. </description> @@ -186,9 +188,10 @@ <argument index="2" name="width" type="float" default="-1" /> <argument index="3" name="font_size" type="int" default="16" /> <argument index="4" name="max_lines" type="int" default="-1" /> - <argument index="5" name="flags" type="int" default="96" /> - <argument index="6" name="direction" type="int" enum="TextServer.Direction" default="0" /> - <argument index="7" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> + <argument index="5" name="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> + <argument index="6" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> + <argument index="7" name="direction" type="int" enum="TextServer.Direction" default="0" /> + <argument index="8" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> Returns the size of a bounding box of a string broken into the lines, taking kerning and advance into account. See also [method draw_multiline_string]. @@ -219,13 +222,16 @@ <argument index="1" name="alignment" type="int" enum="HorizontalAlignment" default="0" /> <argument index="2" name="width" type="float" default="-1" /> <argument index="3" name="font_size" type="int" default="16" /> - <argument index="4" name="flags" type="int" default="3" /> + <argument index="4" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <argument index="5" name="direction" type="int" enum="TextServer.Direction" default="0" /> <argument index="6" name="orientation" type="int" enum="TextServer.Orientation" default="0" /> <description> - Returns the size of a bounding box of a string, taking kerning and advance into account. + Returns the size of a bounding box of a single-line string, taking kerning and advance into account. See also [method get_multiline_string_size] and [method draw_string]. + For example, to get the string size as displayed by a single-line Label, use: + [codeblock] + var string_size = $Label.get_theme_font("font").get_string_size($Label.text, HORIZONTAL_ALIGNMENT_LEFT, -1, $Label.get_theme_font_size("font_size")) + [/codeblock] [b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by [method get_height]. - See also [method draw_string]. </description> </method> <method name="get_supported_chars" qualifiers="const"> diff --git a/doc/classes/FontFile.xml b/doc/classes/FontFile.xml index 98abc87b84..dc2cbdde63 100644 --- a/doc/classes/FontFile.xml +++ b/doc/classes/FontFile.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="FontFile" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - FontFile source data and prerendered glyph cache, imported from dynamic or bitmap font. + Font source data and prerendered glyph cache, imported from dynamic or bitmap font. </brief_description> <description> [FontFile] contains a set of glyphs to represent Unicode characters imported from a font file, as well as a cache of rasterized glyphs, and a set of fallback [Font]s to use. @@ -558,7 +558,7 @@ <member name="font_name" type="String" setter="set_font_name" getter="get_font_name" default=""""> Font family name. </member> - <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" default="0"> + <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" enum="TextServer.FontStyle" default="0"> Font style flags, see [enum TextServer.FontStyle]. </member> <member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false"> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 53894bad87..e60ab094c6 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -63,8 +63,8 @@ <member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0"> Amount of time each particle will exist. </member> - <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true"> - If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates. + <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false"> + If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [GPUParticles2D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [GPUParticles2D] node (and its parents) when it is moved or rotated. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false"> If [code]true[/code], only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end. diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index c4bd18db69..b415c56154 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -95,8 +95,8 @@ <member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0"> Amount of time each particle will exist. </member> - <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true"> - If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates. + <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false"> + If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [GPUParticles3D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [GPUParticles3D] node (and its parents) when it is moved or rotated. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false"> If [code]true[/code], only [code]amount[/code] particles will be emitted. diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml index c9af07288e..bc8b3c7c11 100644 --- a/doc/classes/GPUParticlesCollisionSDF3D.xml +++ b/doc/classes/GPUParticlesCollisionSDF3D.xml @@ -13,7 +13,27 @@ </description> <tutorials> </tutorials> + <methods> + <method name="get_bake_mask_value" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="layer_number" type="int" /> + <description> + Returns whether or not the specified layer of the [member bake_mask] is enabled, given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + <method name="set_bake_mask_value"> + <return type="void" /> + <argument index="0" name="layer_number" type="int" /> + <argument index="1" name="value" type="bool" /> + <description> + Based on [code]value[/code], enables or disables the specified layer in the [member bake_mask], given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + </methods> <members> + <member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295"> + The visual layers to account for when baking the particle collision SDF. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated particle collision SDF. By default, all objects are taken into account for the particle collision SDF baking. + </member> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> The collision SDF's extents in 3D units. To improve SDF quality, the [member extents] should be set as small as possible while covering the parts of the scene you need. </member> diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml index b84e221d1c..a4cfa1ddff 100644 --- a/doc/classes/Geometry2D.xml +++ b/doc/classes/Geometry2D.xml @@ -126,7 +126,7 @@ <return type="Dictionary" /> <argument index="0" name="sizes" type="PackedVector2Array" /> <description> - Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is a vector of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2]. + Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is an array of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2]. </description> </method> <method name="merge_polygons"> @@ -188,6 +188,16 @@ Returns if [code]point[/code] is inside the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. </description> </method> + <method name="segment_intersects_circle"> + <return type="float" /> + <argument index="0" name="segment_from" type="Vector2" /> + <argument index="1" name="segment_to" type="Vector2" /> + <argument index="2" name="circle_position" type="Vector2" /> + <argument index="3" name="circle_radius" type="float" /> + <description> + Given the 2D segment ([code]segment_from[/code], [code]segment_to[/code]), returns the position on the segment (as a number between 0 and 1) at which the segment hits the circle that is located at position [code]circle_position[/code] and has radius [code]circle_radius[/code]. If the segment does not intersect the circle, -1 is returned (this is also the case if the line extending the segment would intersect the circle, but the segment does not). + </description> + </method> <method name="segment_intersects_segment"> <return type="Variant" /> <argument index="0" name="from_a" type="Vector2" /> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index c803f43fb0..365efa6761 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -9,7 +9,7 @@ <tutorials> </tutorials> <methods> - <method name="get_shader_instance_uniform" qualifiers="const"> + <method name="get_instance_shader_uniform" qualifiers="const"> <return type="Variant" /> <argument index="0" name="uniform" type="StringName" /> <description> @@ -22,7 +22,7 @@ Overrides the bounding box of this node with a custom one. To remove it, set an [AABB] with all fields set to zero. </description> </method> - <method name="set_shader_instance_uniform"> + <method name="set_instance_shader_uniform"> <return type="void" /> <argument index="0" name="uniform" type="StringName" /> <argument index="1" name="value" type="Variant" /> diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml index 89c968cc9e..8c5373216a 100644 --- a/doc/classes/Gradient.xml +++ b/doc/classes/Gradient.xml @@ -5,6 +5,7 @@ </brief_description> <description> Given a set of colors, this resource will interpolate them in order. This means that if you have color 1, color 2 and color 3, the gradient will interpolate from color 1 to color 2 and from color 2 to color 3. The gradient will initially have 2 colors (black and white), one (black) at gradient lower offset 0 and the other (white) at the gradient higher offset 1. + See also [Curve] which supports more complex easing methods, but does not support colors. </description> <tutorials> </tutorials> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 965dbe7449..33145dccd0 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -55,6 +55,29 @@ [/codeblock] </description> </method> + <method name="_is_node_hover_valid" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="from" type="StringName" /> + <argument index="1" name="from_slot" type="int" /> + <argument index="2" name="to" type="StringName" /> + <argument index="3" name="to_slot" type="int" /> + <description> + This virtual method can be used to insert additional error detection while the user is dragging a connection over a valid port. + Return [code]true[/code] if the connection is indeed valid or return [code]false[/code] if the connection is impossible. If the connection is impossible, no snapping to the port and thus no connection request to that port will happen. + In this example a connection to same node is suppressed: + [codeblocks] + [gdscript] + func _is_node_hover_valid(from, from_slot, to, to_slot): + return from != to + [/gdscript] + [csharp] + public override bool _IsNodeHoverValid(String from, int fromSlot, String to, int toSlot) { + return from != to; + } + [/csharp] + [/codeblocks] + </description> + </method> <method name="add_valid_connection_type"> <return type="void" /> <argument index="0" name="from_type" type="int" /> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 5a9d12d01b..fb437b6d8e 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -4,7 +4,8 @@ Low-level hyper-text transfer protocol client. </brief_description> <description> - Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. [b]See the [HTTPRequest] node for a higher-level alternative.[/b] + Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. + See the [HTTPRequest] node for a higher-level alternative. [b]Note:[/b] This client only needs to connect to a host once (see [method connect_to_host]) to send multiple requests. Because of this, methods that take URLs usually take just the part after the host instead of the full URL, as the client is already connected to a host. See [method request] for a full example and to get started. A [HTTPClient] should be reused between multiple requests or to connect to different hosts instead of creating one client per request. Supports SSL and SSL server certificate verification. HTTP status codes in the 2xx range indicate success, 3xx redirection (i.e. "try again, but over here"), 4xx something was wrong with the request, and 5xx something went wrong on the server's side. For more information on HTTP, see https://developer.mozilla.org/en-US/docs/Web/HTTP (or read RFC 2616 to get it straight from the source: https://tools.ietf.org/html/rfc2616). diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index f138b9087b..3d2e9449e2 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -251,6 +251,7 @@ Maximum number of allowed redirects. </member> <member name="timeout" type="float" setter="set_timeout" getter="get_timeout" default="0.0"> + If set to a value greater than [code]0.0[/code] before the request starts, the HTTP request will time out after [code]timeout[/code] seconds have passed and the request is not [i]completed[/i] yet. For small HTTP requests such as REST API usage, set [member timeout] to a value between [code]10.0[/code] and [code]30.0[/code] to prevent the application from getting stuck if the request fails to get a response in a timely manner. For file downloads, leave this to [code]0.0[/code] to prevent the download from failing if it takes too much time. </member> <member name="use_threads" type="bool" setter="set_use_threads" getter="is_using_threads" default="false"> If [code]true[/code], multithreading is used to improve performance. diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 31bd938c40..754d1ae68a 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -23,8 +23,8 @@ <method name="blend_rect"> <return type="void" /> <argument index="0" name="src" type="Image" /> - <argument index="1" name="src_rect" type="Rect2" /> - <argument index="2" name="dst" type="Vector2" /> + <argument index="1" name="src_rect" type="Rect2i" /> + <argument index="2" name="dst" type="Vector2i" /> <description> Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dest[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty. </description> @@ -33,8 +33,8 @@ <return type="void" /> <argument index="0" name="src" type="Image" /> <argument index="1" name="mask" type="Image" /> - <argument index="2" name="src_rect" type="Rect2" /> - <argument index="3" name="dst" type="Vector2" /> + <argument index="2" name="src_rect" type="Rect2i" /> + <argument index="3" name="dst" type="Vector2i" /> <description> Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image using [code]mask[/code] image at coordinates [code]dst[/code], clipped accordingly to both image bounds. Alpha channels are required for both [code]src[/code] and [code]mask[/code]. [code]dst[/code] pixels and [code]src[/code] pixels will blend if the corresponding mask pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty. </description> @@ -42,8 +42,8 @@ <method name="blit_rect"> <return type="void" /> <argument index="0" name="src" type="Image" /> - <argument index="1" name="src_rect" type="Rect2" /> - <argument index="2" name="dst" type="Vector2" /> + <argument index="1" name="src_rect" type="Rect2i" /> + <argument index="2" name="dst" type="Vector2i" /> <description> Copies [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dst[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty. </description> @@ -52,8 +52,8 @@ <return type="void" /> <argument index="0" name="src" type="Image" /> <argument index="1" name="mask" type="Image" /> - <argument index="2" name="src_rect" type="Rect2" /> - <argument index="3" name="dst" type="Vector2" /> + <argument index="2" name="src_rect" type="Rect2i" /> + <argument index="3" name="dst" type="Vector2i" /> <description> Blits [code]src_rect[/code] area from [code]src[/code] image to this image at the coordinates given by [code]dst[/code], clipped accordingly to both image bounds. [code]src[/code] pixel is copied onto [code]dst[/code] if the corresponding [code]mask[/code] pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty. </description> @@ -168,7 +168,7 @@ </method> <method name="fill_rect"> <return type="void" /> - <argument index="0" name="rect" type="Rect2" /> + <argument index="0" name="rect" type="Rect2i" /> <argument index="1" name="color" type="Color" /> <description> Fills [code]rect[/code] with [code]color[/code]. @@ -244,21 +244,21 @@ </method> <method name="get_rect" qualifiers="const"> <return type="Image" /> - <argument index="0" name="rect" type="Rect2" /> + <argument index="0" name="rect" type="Rect2i" /> <description> Returns a new image that is a copy of the image's area specified with [code]rect[/code]. </description> </method> <method name="get_size" qualifiers="const"> - <return type="Vector2" /> + <return type="Vector2i" /> <description> Returns the image's size (width and height). </description> </method> <method name="get_used_rect" qualifiers="const"> - <return type="Rect2" /> + <return type="Rect2i" /> <description> - Returns a [Rect2] enclosing the visible portion of the image, considering each pixel with a non-zero alpha channel as visible. + Returns a [Rect2i] enclosing the visible portion of the image, considering each pixel with a non-zero alpha channel as visible. </description> </method> <method name="get_width" qualifiers="const"> @@ -378,6 +378,19 @@ Converts a standard RGBE (Red Green Blue Exponent) image to an sRGB image. </description> </method> + <method name="rotate_180"> + <return type="void" /> + <description> + Rotates the image by [code]180[/code] degrees. The width and height of the image must be greater than [code]1[/code]. + </description> + </method> + <method name="rotate_90"> + <return type="void" /> + <argument index="0" name="direction" type="int" enum="ClockDirection" /> + <description> + Rotates the image in the specified [code]direction[/code] by [code]90[/code] degrees. The width and height of the image must be greater than [code]1[/code]. If the width and height are not equal, the image will be resized. + </description> + </method> <method name="save_exr" qualifiers="const"> <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index e668e2e7fd..084bf7e809 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -42,9 +42,17 @@ Returns the format of the texture, one of [enum Image.Format]. </description> </method> + <method name="set_image"> + <return type="void" /> + <argument index="0" name="image" type="Image" /> + <description> + Replaces the texture's data with a new [Image]. This will re-allocate new memory for the texture. + If you want to update the image, but don't need to change its parameters (format, size), use [method update] instead for better performance. + </description> + </method> <method name="set_size_override"> <return type="void" /> - <argument index="0" name="size" type="Vector2" /> + <argument index="0" name="size" type="Vector2i" /> <description> Resizes the texture to the specified dimensions. </description> @@ -54,8 +62,8 @@ <argument index="0" name="image" type="Image" /> <description> Replaces the texture's data with a new [Image]. - [b]Note:[/b] The texture has to be initialized first with the [method create_from_image] method before it can be updated. The new image dimensions, format, and mipmaps configuration should match the existing texture's image configuration, otherwise it has to be re-created with the [method create_from_image] method. - Use this method over [method create_from_image] if you need to update the texture frequently, which is faster than allocating additional memory for a new texture each time. + [b]Note:[/b] The texture has to be created using [method create_from_image] or initialized first with the [method set_image] method before it can be updated. The new image dimensions, format, and mipmaps configuration should match the existing texture's image configuration. + Use this method over [method set_image] if you need to update the texture frequently, which is faster than allocating additional memory for a new texture each time. </description> </method> </methods> diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml index 00601cec75..201c0ddd38 100644 --- a/doc/classes/ImporterMesh.xml +++ b/doc/classes/ImporterMesh.xml @@ -30,7 +30,7 @@ <description> Creates a new surface, analogous to [method ArrayMesh.add_surface_from_arrays]. Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface. - The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used. + The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array (or be an exact multiple of the vertex array's length, when multiple elements of a sub-array correspond to a single vertex) or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used. </description> </method> <method name="clear"> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index e73021ead4..796a80873f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -354,9 +354,11 @@ <return type="void" /> <argument index="0" name="duration_ms" type="int" default="500" /> <description> - Vibrate Android and iOS devices. + Vibrate handheld devices. + [b]Note:[/b] This method is implemented on Android, iOS, and HTML5. [b]Note:[/b] For Android, it requires enabling the [code]VIBRATE[/code] permission in the export preset. [b]Note:[/b] For iOS, specifying the duration is supported in iOS 13 and later. + [b]Note:[/b] Some web browsers such as Safari and Firefox for Android do not support this method. </description> </method> <method name="warp_mouse"> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 15c97b0838..97ee946acd 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -445,7 +445,7 @@ <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Text [Color] used when the item is selected. </theme_item> - <theme_item name="guide_color" data_type="color" type="Color" default="Color(0, 0, 0, 0.1)"> + <theme_item name="guide_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 0.25)"> [Color] of the guideline. The guideline is a line drawn between each row of items. </theme_item> <theme_item name="h_separation" data_type="constant" type="int" default="4"> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 1eac58b9f2..1ebf770f7e 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -49,6 +49,8 @@ <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0"> Controls the text's horizontal alignment. Supports left, center, right, and fill, or justify. Set it to one of the [enum HorizontalAlignment] constants. </member> + <member name="label_settings" type="LabelSettings" setter="set_label_settings" getter="get_label_settings"> + </member> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index 2c3c27079a..5ba0a2d79a 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -79,7 +79,7 @@ </member> <member name="outline_render_priority" type="int" setter="set_outline_render_priority" getter="get_outline_render_priority" default="-1"> Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects. - [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). + [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). [b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority). </member> <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0"> @@ -90,7 +90,7 @@ </member> <member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0"> Sets the render priority for the text. Higher priority objects will be sorted in front of lower priority objects. - [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). + [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). [b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority). </member> <member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> @@ -126,7 +126,7 @@ If set, lights in the environment affect the label. </constant> <constant name="FLAG_DOUBLE_SIDED" value="1" enum="DrawFlags"> - If set, text can be seen from the back as well. If not, the texture is invisible when looking at it from behind. + If set, text can be seen from the back as well. If not, the text is invisible when looking at it from behind. </constant> <constant name="FLAG_DISABLE_DEPTH_TEST" value="2" enum="DrawFlags"> Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it. diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml new file mode 100644 index 0000000000..aa972f2cf3 --- /dev/null +++ b/doc/classes/LabelSettings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="LabelSettings" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <members> + <member name="font" type="Font" setter="set_font" getter="get_font"> + </member> + <member name="font_color" type="Color" setter="set_font_color" getter="get_font_color" default="Color(1, 1, 1, 1)"> + </member> + <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16"> + </member> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0"> + </member> + <member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)"> + </member> + <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0"> + </member> + <member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color(0, 0, 0, 0)"> + </member> + <member name="shadow_offset" type="Vector2" setter="set_shadow_offset" getter="get_shadow_offset" default="Vector2(1, 1)"> + </member> + <member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" default="1"> + </member> + </members> +</class> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 0ebd83c882..46c3e57547 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -37,13 +37,12 @@ [b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D]. </member> <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0"> - Distance over which the light fades. The light's energy is progressively reduced over this distance and is completely invisible at the end. + Distance over which the light and its shadow fades. The light's energy and shadow's opacity is progressively reduced over this distance and is completely invisible at the end. [b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D]. </member> <member name="distance_fade_shadow" type="float" setter="set_distance_fade_shadow" getter="get_distance_fade_shadow" default="50.0"> The distance from the camera at which the light's shadow cuts off (in 3D units). Set this to a value lower than [member distance_fade_begin] + [member distance_fade_length] to further improve performance, as shadow rendering is often more expensive than light rendering itself. [b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D], and only when [member shadow_enabled] is [code]true[/code]. - [b]Note:[/b] Due to a rendering engine limitation, shadows will be disabled instantly instead of fading smoothly according to [member distance_fade_length]. This may result in visible pop-in depending on the scene topography. </member> <member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only" default="false"> If [code]true[/code], the light only appears in the editor and will not be visible at runtime. @@ -95,6 +94,9 @@ <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="1.0"> Offsets the lookup into the shadow map by the object's normal. This can be used to reduce self-shadowing artifacts without using [member shadow_bias]. In practice, this value should be tweaked along with [member shadow_bias] to reduce artifacts as much as possible. </member> + <member name="shadow_opacity" type="float" setter="set_param" getter="get_param" default="1.0"> + The opacity to use when rendering the light's shadow map. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost. + </member> <member name="shadow_reverse_cull_face" type="bool" setter="set_shadow_reverse_cull_face" getter="get_shadow_reverse_cull_face" default="false"> If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [constant GeometryInstance3D.SHADOW_CASTING_SETTING_DOUBLE_SIDED]. </member> @@ -150,15 +152,19 @@ <constant name="PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="Param"> Constant for accessing [member DirectionalLight3D.directional_shadow_pancake_size]. </constant> - <constant name="PARAM_SHADOW_BLUR" value="16" enum="Param"> + <constant name="PARAM_SHADOW_OPACITY" value="16" enum="Param"> + Constant for accessing [member shadow_opacity]. + </constant> + <constant name="PARAM_SHADOW_BLUR" value="17" enum="Param"> Constant for accessing [member shadow_blur]. </constant> - <constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="Param"> + <constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="Param"> + Constant for accessing [member shadow_fog_fade]. </constant> - <constant name="PARAM_TRANSMITTANCE_BIAS" value="18" enum="Param"> + <constant name="PARAM_TRANSMITTANCE_BIAS" value="19" enum="Param"> Constant for accessing [member shadow_transmittance_bias]. </constant> - <constant name="PARAM_MAX" value="19" enum="Param"> + <constant name="PARAM_MAX" value="20" enum="Param"> Represents the size of the [enum Param] enum. </constant> <constant name="BAKE_DISABLED" value="0" enum="BakeMode"> diff --git a/doc/classes/LightmapGIData.xml b/doc/classes/LightmapGIData.xml index 20113ac309..13f44150d7 100644 --- a/doc/classes/LightmapGIData.xml +++ b/doc/classes/LightmapGIData.xml @@ -22,7 +22,7 @@ <method name="clear_users"> <return type="void" /> <description> - Clear all objects that are considred baked within this [LightmapGIData]. + Clear all objects that are considered baked within this [LightmapGIData]. </description> </method> <method name="get_user_count" qualifiers="const"> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 84471bafc0..2ff13a676b 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -246,6 +246,9 @@ <member name="virtual_keyboard_enabled" type="bool" setter="set_virtual_keyboard_enabled" getter="is_virtual_keyboard_enabled" default="true"> If [code]true[/code], the native virtual keyboard is shown when focused on platforms that support it. </member> + <member name="virtual_keyboard_type" type="int" setter="set_virtual_keyboard_type" getter="get_virtual_keyboard_type" enum="LineEdit.VirtualKeyboardType" default="0"> + Specifies the type of virtual keyboard to show. + </member> </members> <signals> <signal name="text_change_rejected"> @@ -356,6 +359,31 @@ <constant name="MENU_MAX" value="28" enum="MenuItems"> Represents the size of the [enum MenuItems] enum. </constant> + <constant name="KEYBOARD_TYPE_DEFAULT" value="0" enum="VirtualKeyboardType"> + Default text virtual keyboard. + </constant> + <constant name="KEYBOARD_TYPE_MULTILINE" value="1" enum="VirtualKeyboardType"> + Multiline virtual keyboard. + </constant> + <constant name="KEYBOARD_TYPE_NUMBER" value="2" enum="VirtualKeyboardType"> + Virtual number keypad, useful for PIN entry. + </constant> + <constant name="KEYBOARD_TYPE_NUMBER_DECIMAL" value="3" enum="VirtualKeyboardType"> + Virtual number keypad, useful for entering fractional numbers. + </constant> + <constant name="KEYBOARD_TYPE_PHONE" value="4" enum="VirtualKeyboardType"> + Virtual phone number keypad. + </constant> + <constant name="KEYBOARD_TYPE_EMAIL_ADDRESS" value="5" enum="VirtualKeyboardType"> + Virtual keyboard with additional keys to assist with typing email addresses. + </constant> + <constant name="KEYBOARD_TYPE_PASSWORD" value="6" enum="VirtualKeyboardType"> + Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization. + [b]Note:[/b] This is not supported on HTML5. Instead, this behaves identically to [constant KEYBOARD_TYPE_DEFAULT]. + </constant> + <constant name="KEYBOARD_TYPE_URL" value="7" enum="VirtualKeyboardType"> + Virtual keyboard with additional keys to assist with typing URLs. + </constant> </constants> <theme_items> <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml index f368190a29..24f1f9918b 100644 --- a/doc/classes/MeshInstance3D.xml +++ b/doc/classes/MeshInstance3D.xml @@ -4,7 +4,7 @@ Node that instances meshes into a scenario. </brief_description> <description> - MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reuse of geometry which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead. + MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reusing geometry, which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead. </description> <tutorials> <link title="3D Material Testers Demo">https://godotengine.org/asset-library/asset/123</link> diff --git a/doc/classes/MovieWriter.xml b/doc/classes/MovieWriter.xml index bc702adde6..d47e52d7c0 100644 --- a/doc/classes/MovieWriter.xml +++ b/doc/classes/MovieWriter.xml @@ -68,7 +68,7 @@ <return type="void" /> <argument index="0" name="writer" type="MovieWriter" /> <description> - Adds a writer to be usable by the engine. The supported file extensions can be set by overridding [method _handles_file]. + Adds a writer to be usable by the engine. The supported file extensions can be set by overriding [method _handles_file]. [b]Note:[/b] [method add_writer] must be called early enough in the engine initialization to work, as movie writing is designed to start at the same time as the rest of the engine. </description> </method> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 631b2ea050..3431a3347b 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -54,7 +54,7 @@ <argument index="1" name="color" type="Color" /> <description> Sets the color of a specific instance by [i]multiplying[/i] the mesh's existing vertex colors. - For the color to take effect, ensure that [member use_colors] is [code]true[/code] on the [MultiMesh] and [member BaseMaterial3D.vertex_color_use_as_albedo] is [code]true[/code] on the material. + For the color to take effect, ensure that [member use_colors] is [code]true[/code] on the [MultiMesh] and [member BaseMaterial3D.vertex_color_use_as_albedo] is [code]true[/code] on the material. If the color doesn't look as expected, make sure the material's albedo color is set to pure white ([code]Color(1, 1, 1)[/code]). </description> </method> <method name="set_instance_custom_data"> @@ -91,7 +91,8 @@ <member name="custom_data_array" type="PackedColorArray" setter="_set_custom_data_array" getter="_get_custom_data_array"> </member> <member name="instance_count" type="int" setter="set_instance_count" getter="get_instance_count" default="0"> - Number of instances that will get drawn. This clears and (re)sizes the buffers. By default, all instances are drawn but you can limit this with [member visible_instance_count]. + Number of instances that will get drawn. This clears and (re)sizes the buffers. Setting data format or flags afterwards will have no effect. + By default, all instances are drawn but you can limit this with [member visible_instance_count]. </member> <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> Mesh to be drawn. diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index 059d147979..06658bf004 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -1,88 +1,108 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="MultiplayerAPI" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - High-level multiplayer API. + High-level multiplayer API interface. </brief_description> <description> - This class implements the high-level multiplayer API. See also [MultiplayerPeer]. - By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPCs) across the whole scene. + Base class for high-level multiplayer API implementations. See also [MultiplayerPeer]. + By default, [SceneTree] has a reference to an implementation of this class and uses it to provide multiplayer capabilities (i.e. RPCs) across the whole scene. It is possible to override the MultiplayerAPI instance used by specific tree branches by calling the [method SceneTree.set_multiplayer] method, effectively allowing to run both client and server in the same scene. - [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice. - [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. + It is also possible to extend or replace the default implementation via scripting or native extensions. See [MultiplayerAPIExtension] for details about extensions, [SceneMultiplayer] for the details about the default implementation. </description> <tutorials> </tutorials> <methods> - <method name="clear"> - <return type="void" /> + <method name="create_default_interface" qualifiers="static"> + <return type="MultiplayerAPI" /> + <description> + Returns a new instance of the default MultiplayerAPI. + </description> + </method> + <method name="get_default_interface" qualifiers="static"> + <return type="StringName" /> <description> - Clears the current MultiplayerAPI network state (you shouldn't call this unless you know what you are doing). + Returns the default MultiplayerAPI implementation class name. This is usually [code]"SceneMultiplayer"[/code] when [SceneMultiplayer] is available. See [method set_default_interface]. </description> </method> - <method name="get_peers" qualifiers="const"> + <method name="get_peers"> <return type="PackedInt32Array" /> <description> Returns the peer IDs of all connected peers of this MultiplayerAPI's [member multiplayer_peer]. </description> </method> - <method name="get_remote_sender_id" qualifiers="const"> + <method name="get_remote_sender_id"> <return type="int" /> <description> Returns the sender's peer ID for the RPC currently being executed. [b]Note:[/b] If not inside an RPC this method will return 0. </description> </method> - <method name="get_unique_id" qualifiers="const"> + <method name="get_unique_id"> <return type="int" /> <description> Returns the unique peer ID of this MultiplayerAPI's [member multiplayer_peer]. </description> </method> - <method name="has_multiplayer_peer" qualifiers="const"> + <method name="has_multiplayer_peer"> <return type="bool" /> <description> Returns [code]true[/code] if there is a [member multiplayer_peer] set. </description> </method> - <method name="is_server" qualifiers="const"> + <method name="is_server"> <return type="bool" /> <description> Returns [code]true[/code] if this MultiplayerAPI's [member multiplayer_peer] is valid and in server mode (listening for connections). </description> </method> + <method name="object_configuration_add"> + <return type="int" enum="Error" /> + <argument index="0" name="object" type="Object" /> + <argument index="1" name="configuration" type="Variant" /> + <description> + Notifies the MultiplayerAPI of a new [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and a valid [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it. + [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension]. + </description> + </method> + <method name="object_configuration_remove"> + <return type="int" enum="Error" /> + <argument index="0" name="object" type="Object" /> + <argument index="1" name="configuration" type="Variant" /> + <description> + Notifies the MultiplayerAPI to remove a [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and an empty [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it. + [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension]. + </description> + </method> <method name="poll"> - <return type="void" /> + <return type="int" enum="Error" /> <description> Method used for polling the MultiplayerAPI. You only need to worry about this if you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI(s) for you. [b]Note:[/b] This method results in RPCs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]). </description> </method> - <method name="send_bytes"> + <method name="rpc"> <return type="int" enum="Error" /> - <argument index="0" name="bytes" type="PackedByteArray" /> - <argument index="1" name="id" type="int" default="0" /> - <argument index="2" name="mode" type="int" enum="TransferMode" default="2" /> - <argument index="3" name="channel" type="int" default="0" /> + <argument index="0" name="peer" type="int" /> + <argument index="1" name="object" type="Object" /> + <argument index="2" name="method" type="StringName" /> + <argument index="3" name="arguments" type="Array" default="[]" /> + <description> + Sends an RPC to the target [code]peer[/code]. The given [code]method[/code] will be called on the remote [code]object[/code] with the provided [code]arguments[/code]. The RPC may also be called locally depending on the implementation and RPC configuration. See [method Node.rpc] and [method Node.rpc_config]. + [b]Note:[/b] Prefer using [method Node.rpc], [method Node.rpc_id], or [code]my_method.rpc(peer, arg1, arg2, ...)[/code] (in GDScript), since they are faster. This method is mostly useful in conjunction with [MultiplayerAPIExtension] when augmenting or replacing the multiplayer capabilities. + </description> + </method> + <method name="set_default_interface" qualifiers="static"> + <return type="void" /> + <argument index="0" name="interface_name" type="StringName" /> <description> - Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers. + Sets the default MultiplayerAPI implementation class. This method can be used by modules and extensions to configure which implementation will be used by [SceneTree] when the engine starts. </description> </method> </methods> <members> - <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false"> - If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs. - [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats such as remote code execution. - </member> <member name="multiplayer_peer" type="MultiplayerPeer" setter="set_multiplayer_peer" getter="get_multiplayer_peer"> The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_server]) and will set root node's network mode to authority, or it will become a regular client peer. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals. </member> - <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false"> - If [code]true[/code], the MultiplayerAPI's [member multiplayer_peer] refuses new incoming connections. - </member> - <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("")"> - The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed. - This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene. - </member> </members> <signals> <signal name="connected_to_server"> @@ -107,17 +127,21 @@ Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server. </description> </signal> - <signal name="peer_packet"> - <argument index="0" name="id" type="int" /> - <argument index="1" name="packet" type="PackedByteArray" /> - <description> - Emitted when this MultiplayerAPI's [member multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet. - </description> - </signal> <signal name="server_disconnected"> <description> Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from server. Only emitted on clients. </description> </signal> </signals> + <constants> + <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode"> + Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods. + </constant> + <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode"> + Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not. + </constant> + <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode"> + Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority]. + </constant> + </constants> </class> diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml new file mode 100644 index 0000000000..c369977d57 --- /dev/null +++ b/doc/classes/MultiplayerAPIExtension.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="MultiplayerAPIExtension" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Base class used for extending the [MultiplayerAPI]. + </brief_description> + <description> + This class can be used to augment or replace the default [MultiplayerAPI] implementation via script or extensions. + The following example augment the default implemenation ([SceneMultiplayer]) by logging every RPC being made, and every object being configured for replication. + [codeblocks] + [gdscript] + extends MultiplayerAPIExtension + class_name LogMultiplayer + + # We want to augment the default SceneMultiplayer. + var base_multiplayer = SceneMultiplayer.new() + + func _init(): + # Just passthourgh base signals (copied to var to avoid cyclic reference) + var cts = connected_to_server + var cf = connection_failed + var pc = peer_connected + var pd = peer_disconnected + base_multiplayer.connected_to_server.connect(func(): cts.emit()) + base_multiplayer.connection_failed.connect(func(): cf.emit()) + base_multiplayer.peer_connected.connect(func(id): pc.emit(id)) + base_multiplayer.peer_disconnected.connect(func(id): pd.emit(id)) + + # Log RPC being made and forward it to the default multiplayer. + func _rpc(peer: int, object: Object, method: StringName, args: Array) -> int: # Error + print("Got RPC for %d: %s::%s(%s)" % [peer, object, method, args]) + return base_multiplayer.rpc(peer, object, method, args) + + # Log configuration add. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom. + func _object_configuration_add(object, config: Variant) -> int: # Error + if config is MultiplayerSynchronizer: + print("Adding synchronization configuration for %s. Synchronizer: %s" % [object, config]) + elif config is MultiplayerSpawner: + print("Adding node %s to the spawn list. Spawner: %s" % [object, config]) + return base_multiplayer.object_configuration_add(object, config) + + # Log configuration remove. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom. + func _object_configuration_remove(object, config: Variant) -> int: # Error + if config is MultiplayerSynchronizer: + print("Removing synchronization configuration for %s. Synchronizer: %s" % [object, config]) + elif config is MultiplayerSpawner: + print("Removing node %s from the spawn list. Spawner: %s" % [object, config]) + return base_multiplayer.object_configuration_remove(object, config) + + # These can be optional, but in our case we want to augment SceneMultiplayer, so forward everything. + func _set_multiplayer_peer(p_peer: MultiplayerPeer): + base_multiplayer.multiplayer_peer = p_peer + + func _get_multiplayer_peer() -> MultiplayerPeer: + return base_multiplayer.multiplayer_peer + + func _get_unique_id() -> int: + return base_multiplayer.get_unique_id() + + func _get_peer_ids() -> PackedInt32Array: + return base_multiplayer.get_peers() + [/gdscript] + [/codeblocks] + Then in your main scene or in an autoload call [method SceneTree.set_multiplayer] to start using your custom [MultiplayerAPI]: + [codeblocks] + [gdscript] + # autoload.gd + func _enter_tree(): + # Sets our custom multiplayer as the main one in SceneTree. + get_tree().set_multiplayer(LogMultiplayer.new()) + [/gdscript] + [/codeblocks] + Native extensions can alternatively use the [method MultiplayerAPI.set_default_interface] method during initialization to configure themselves as the default implementation. + </description> + <tutorials> + </tutorials> + <methods> + <method name="_get_multiplayer_peer" qualifiers="virtual"> + <return type="MultiplayerPeer" /> + <description> + Called when the [member MultiplayerAPI.multiplayer_peer] is retrieved. + </description> + </method> + <method name="_get_peer_ids" qualifiers="virtual const"> + <return type="PackedInt32Array" /> + <description> + Callback for [method MultiplayerAPI.get_peers]. + </description> + </method> + <method name="_get_remote_sender_id" qualifiers="virtual const"> + <return type="int" /> + <description> + Callback for [method MultiplayerAPI.get_remote_sender_id]. + </description> + </method> + <method name="_get_unique_id" qualifiers="virtual const"> + <return type="int" /> + <description> + Callback for [method MultiplayerAPI.get_unique_id]. + </description> + </method> + <method name="_object_configuration_add" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="object" type="Object" /> + <argument index="1" name="configuration" type="Variant" /> + <description> + Callback for [method MultiplayerAPI.object_configuration_add]. + </description> + </method> + <method name="_object_configuration_remove" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="object" type="Object" /> + <argument index="1" name="configuration" type="Variant" /> + <description> + Callback for [method MultiplayerAPI.object_configuration_remove]. + </description> + </method> + <method name="_poll" qualifiers="virtual"> + <return type="int" /> + <description> + Callback for [method MultiplayerAPI.poll]. + </description> + </method> + <method name="_rpc" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="peer" type="int" /> + <argument index="1" name="object" type="Object" /> + <argument index="2" name="method" type="StringName" /> + <argument index="3" name="args" type="Array" /> + <description> + Callback for [method MultiplayerAPI.rpc]. + </description> + </method> + <method name="_set_multiplayer_peer" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="multiplayer_peer" type="MultiplayerPeer" /> + <description> + Called when the [member MultiplayerAPI.multiplayer_peer] is set. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/MultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml index 4a3559b0f7..6dde40f018 100644 --- a/doc/classes/MultiplayerPeer.xml +++ b/doc/classes/MultiplayerPeer.xml @@ -60,7 +60,7 @@ The channel to use to send packets. Many network APIs such as ENet and WebRTC allow the creation of multiple independent channels which behaves, in a way, like separate connections. This means that reliable data will only block delivery of other packets on that channel, and ordering will only be in respect to the channel the packet is being sent on. Using different channels to send [b]different and independent[/b] state updates is a common way to optimize network usage and decrease latency in fast-paced games. [b]Note:[/b] The default channel ([code]0[/code]) actually works as 3 separate channels (one for each [enum TransferMode]) so that [constant TRANSFER_MODE_RELIABLE] and [constant TRANSFER_MODE_UNRELIABLE_ORDERED] does not interact with each other by default. Refer to the specific network API documentation (e.g. ENet or WebRTC) to learn how to set up channels correctly. </member> - <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="TransferMode" default="2"> + <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="MultiplayerPeer.TransferMode" default="2"> The manner in which to send packets to the [code]target_peer[/code]. See [enum TransferMode]. </member> </members> @@ -109,5 +109,14 @@ <constant name="TARGET_PEER_SERVER" value="1"> Packets are sent to the server alone. </constant> + <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode"> + Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters. + </constant> + <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode"> + Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data. + </constant> + <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode"> + Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly. + </constant> </constants> </class> diff --git a/doc/classes/MultiplayerPeerExtension.xml b/doc/classes/MultiplayerPeerExtension.xml index bd11c76039..f837171e2f 100644 --- a/doc/classes/MultiplayerPeerExtension.xml +++ b/doc/classes/MultiplayerPeerExtension.xml @@ -41,6 +41,12 @@ Called when the ID of the [MultiplayerPeer] who sent the most recent packet is requested (see [method MultiplayerPeer.get_packet_peer]). </description> </method> + <method name="_get_packet_script" qualifiers="virtual"> + <return type="PackedByteArray" /> + <description> + Called when a packet needs to be received by the [MultiplayerAPI], if [method _get_packet] isn't implemented. Use this when extending this class via GDScript. + </description> + </method> <method name="_get_transfer_channel" qualifiers="virtual const"> <return type="int" /> <description> @@ -85,6 +91,13 @@ Called when a packet needs to be sent by the [MultiplayerAPI], with [code]p_buffer_size[/code] being the size of the binary [code]p_buffer[/code] in bytes. </description> </method> + <method name="_put_packet_script" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="p_buffer" type="PackedByteArray" /> + <description> + Called when a packet needs to be sent by the [MultiplayerAPI], if [method _put_packet] isn't implemented. Use this when extending this class via GDScript. + </description> + </method> <method name="_set_refuse_new_connections" qualifiers="virtual"> <return type="void" /> <argument index="0" name="p_enable" type="bool" /> diff --git a/doc/classes/MultiplayerSpawner.xml b/doc/classes/MultiplayerSpawner.xml deleted file mode 100644 index 4ca92728ff..0000000000 --- a/doc/classes/MultiplayerSpawner.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - <method name="_spawn_custom" qualifiers="virtual"> - <return type="Object" /> - <argument index="0" name="data" type="Variant" /> - <description> - </description> - </method> - <method name="add_spawnable_scene"> - <return type="void" /> - <argument index="0" name="path" type="String" /> - <description> - </description> - </method> - <method name="clear_spawnable_scenes"> - <return type="void" /> - <description> - </description> - </method> - <method name="get_spawnable_scene" qualifiers="const"> - <return type="String" /> - <argument index="0" name="path" type="int" /> - <description> - </description> - </method> - <method name="get_spawnable_scene_count" qualifiers="const"> - <return type="int" /> - <description> - </description> - </method> - <method name="spawn"> - <return type="Node" /> - <argument index="0" name="data" type="Variant" default="null" /> - <description> - </description> - </method> - </methods> - <members> - <member name="auto_spawn" type="bool" setter="set_auto_spawning" getter="is_auto_spawning" default="false"> - </member> - <member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0"> - </member> - <member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath("")"> - </member> - </members> - <signals> - <signal name="despawned"> - <argument index="0" name="scene_id" type="int" /> - <argument index="1" name="node" type="Node" /> - <description> - </description> - </signal> - <signal name="spawned"> - <argument index="0" name="scene_id" type="int" /> - <argument index="1" name="node" type="Node" /> - <description> - </description> - </signal> - </signals> -</class> diff --git a/doc/classes/MultiplayerSynchronizer.xml b/doc/classes/MultiplayerSynchronizer.xml deleted file mode 100644 index ac067791e6..0000000000 --- a/doc/classes/MultiplayerSynchronizer.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <members> - <member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config"> - </member> - <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0"> - </member> - <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("..")"> - </member> - </members> -</class> diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index 966f964b12..33d2535ca2 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -28,6 +28,7 @@ <argument index="0" name="mesh" type="Mesh" /> <description> Initializes the navigation mesh by setting the vertices and indices according to a [Mesh]. + [b]Note:[/b] The given [code]mesh[/code] must be of type [constant Mesh.PRIMITIVE_TRIANGLES] and have an index array. </description> </method> <method name="get_collision_mask_value" qualifiers="const"> diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml index c48ca18e9e..75b6544827 100644 --- a/doc/classes/NavigationRegion2D.xml +++ b/doc/classes/NavigationRegion2D.xml @@ -8,7 +8,7 @@ Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer2D.map_set_edge_connection_margin]. [b]Note:[/b] Overlapping two regions' polygons is not enough for connecting two regions. They must share a similar edge. The pathfinding cost of entering this region from another region can be controlled with the [member enter_cost] value. - [b]Note[/b]: This value is not added to the path cost when the start position is already inside this region. + [b]Note:[/b] This value is not added to the path cost when the start position is already inside this region. The pathfinding cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier. </description> <tutorials> diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml index 9f4feee072..f5824a24fd 100644 --- a/doc/classes/NavigationRegion3D.xml +++ b/doc/classes/NavigationRegion3D.xml @@ -8,7 +8,7 @@ Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer3D.map_set_edge_connection_margin]. [b]Note:[/b] Overlapping two regions' navmeshes is not enough for connecting two regions. They must share a similar edge. The cost of entering this region from another region can be controlled with the [member enter_cost] value. - [b]Note[/b]: This value is not added to the path cost when the start position is already inside this region. + [b]Note:[/b] This value is not added to the path cost when the start position is already inside this region. The cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier. </description> <tutorials> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 5185b353bc..8600c2643a 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -415,5 +415,10 @@ Emitted when a navigation map is updated, when a region moves or is modified. </description> </signal> + <signal name="navigation_debug_changed"> + <description> + Emitted when navigation debug settings are changed. Only available in debug builds. + </description> + </signal> </signals> </class> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index b7591ed4f4..8cc8498609 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -622,7 +622,7 @@ </description> </method> <method name="rpc" qualifiers="vararg"> - <return type="void" /> + <return type="int" enum="Error" /> <argument index="0" name="method" type="StringName" /> <description> Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns [code]null[/code]. @@ -630,18 +630,24 @@ </description> </method> <method name="rpc_config"> - <return type="int" /> + <return type="void" /> <argument index="0" name="method" type="StringName" /> - <argument index="1" name="rpc_mode" type="int" enum="RPCMode" /> - <argument index="2" name="call_local" type="bool" default="false" /> - <argument index="3" name="transfer_mode" type="int" enum="TransferMode" default="2" /> - <argument index="4" name="channel" type="int" default="0" /> + <argument index="1" name="config" type="Variant" /> <description> - Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum RPCMode] and [enum TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs). + Changes the RPC mode for the given [code]method[/code] with the given [code]config[/code] which should be [code]null[/code] (to disable) or a [Dictionary] in the form: + [codeblock] + { + rpc_mode = MultiplayerAPI.RPCMode, + transfer_mode = MultiplayerPeer.TranferMode, + call_local = false, + channel = 0, + } + [/codeblock] + See [enum MultiplayerAPI.RPCMode] and [enum MultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs). </description> </method> <method name="rpc_id" qualifiers="vararg"> - <return type="void" /> + <return type="int" enum="Error" /> <argument index="0" name="peer_id" type="int" /> <argument index="1" name="method" type="StringName" /> <description> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index aaf08dec2f..75cd52787a 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -198,6 +198,17 @@ } [/csharp] [/codeblocks] + [b]Note:[/b] Passing custom user arguments directly is not recommended, as the engine may discard or modify them. Instead, the best way is to use the standard UNIX double dash ([code]--[/code]) and then pass custom arguments, which the engine itself will ignore. These can be read via [method get_cmdline_user_args]. + </description> + </method> + <method name="get_cmdline_user_args"> + <return type="PackedStringArray" /> + <description> + Similar to [method get_cmdline_args], but this returns the user arguments (any argument passed after the double dash [code]--[/code] argument). These are left untouched by Godot for the user. + For example, in the command line below, [code]--fullscreen[/code] will not be returned in [method get_cmdline_user_args] and [code]--level 1[/code] will only be returned in [method get_cmdline_user_args]: + [codeblock] + godot --fullscreen -- --level 1 + [/codeblock] </description> </method> <method name="get_config_dir" qualifiers="const"> @@ -363,6 +374,12 @@ [b]Note:[/b] This method is only implemented on Windows, macOS, Linux and iOS. On Android, HTML5 and UWP, [method get_processor_name] returns an empty string. </description> </method> + <method name="get_restart_on_exit_arguments" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns the list of command line arguments that will be used when the project automatically restarts using [method set_restart_on_exit]. See also [method is_restart_on_exit_set]. + </description> + </method> <method name="get_static_memory_peak_usage" qualifiers="const"> <return type="int" /> <description> @@ -385,6 +402,23 @@ [b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android. </description> </method> + <method name="get_system_font_path" qualifiers="const"> + <return type="String" /> + <argument index="0" name="font_name" type="String" /> + <argument index="1" name="bold" type="bool" default="false" /> + <argument index="2" name="italic" type="bool" default="false" /> + <description> + Returns path to the system font file with [code]font_name[/code] and style. Return empty string if no matching fonts found. + [b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows. + </description> + </method> + <method name="get_system_fonts" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns list of font family names available. + [b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows. + </description> + </method> <method name="get_thread_caller_id" qualifiers="const"> <return type="int" /> <description> @@ -453,6 +487,12 @@ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> + <method name="is_restart_on_exit_set" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the project will automatically restart when it exits for any reason, [code]false[/code] otherwise. See also [method set_restart_on_exit] and [method get_restart_on_exit_arguments]. + </description> + </method> <method name="is_stdout_verbose" qualifiers="const"> <return type="bool" /> <description> @@ -544,6 +584,17 @@ [b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows. </description> </method> + <method name="set_restart_on_exit"> + <return type="void" /> + <argument index="0" name="restart" type="bool" /> + <argument index="1" name="arguments" type="PackedStringArray" default="PackedStringArray()" /> + <description> + If [code]restart[/code] is [code]true[/code], restarts the project automatically when it is exited with [method SceneTree.quit] or [constant Node.NOTIFICATION_WM_CLOSE_REQUEST]. Command line [code]arguments[/code] can be supplied. To restart the project with the same command line arguments as originally used to run the project, pass [method get_cmdline_args] as the value for [code]arguments[/code]. + [method set_restart_on_exit] can be used to apply setting changes that require a restart. See also [method is_restart_on_exit_set] and [method get_restart_on_exit_arguments]. + [b]Note:[/b] This method is only effective on desktop platforms, and only when the project isn't started from the editor. It will have no effect on mobile and Web platforms, or when the project is started from the editor. + [b]Note:[/b] If the project process crashes or is [i]killed[/i] by the user (by sending [code]SIGKILL[/code] instead of the usual [code]SIGTERM[/code]), the project won't restart automatically. + </description> + </method> <method name="set_thread_name"> <return type="int" enum="Error" /> <argument index="0" name="name" type="String" /> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 11ae7cc2b0..061b32bfdf 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -152,11 +152,9 @@ <return type="int" enum="Error" /> <argument index="0" name="signal" type="StringName" /> <argument index="1" name="callable" type="Callable" /> - <argument index="2" name="binds" type="Array" default="[]" /> - <argument index="3" name="flags" type="int" default="0" /> + <argument index="2" name="flags" type="int" default="0" /> <description> - Connects a [code]signal[/code] to a [code]callable[/code]. Pass optional [code]binds[/code] to the call as an [Array] of parameters. These parameters will be passed to the [Callable]'s method after any parameter used in the call to [method emit_signal]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants. - [b]Note:[/b] This method is the legacy implementation for connecting signals. The recommended modern approach is to use [method Signal.connect] and to use [method Callable.bind] to add and validate parameter binds. Both syntaxes are shown below. + Connects a [code]signal[/code] to a [code]callable[/code]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants. A signal can only be connected once to a [Callable]. It will print an error if already connected, unless the signal was connected with [constant CONNECT_REFERENCE_COUNTED]. To avoid this, first, use [method is_connected] to check for existing connections. If the callable's target is destroyed in the game's lifecycle, the connection will be lost. [b]Examples with recommended syntax:[/b] diff --git a/doc/classes/OccluderInstance3D.xml b/doc/classes/OccluderInstance3D.xml index abd99dd3aa..08d12341cd 100644 --- a/doc/classes/OccluderInstance3D.xml +++ b/doc/classes/OccluderInstance3D.xml @@ -31,7 +31,7 @@ </methods> <members> <member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295"> - The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects are taken into account for the occluder baking. + The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects with [i]opaque[/i] materials are taken into account for the occluder baking. To improve performance and avoid artifacts, it is recommended to exclude dynamic objects, small objects and fixtures from the baking process by moving them to a separate visual layer and excluding this layer in [member bake_mask]. </member> <member name="bake_simplification_distance" type="float" setter="set_bake_simplification_distance" getter="get_bake_simplification_distance" default="0.1"> diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml index a7b1f0ea33..737662fe69 100644 --- a/doc/classes/OptionButton.xml +++ b/doc/classes/OptionButton.xml @@ -194,6 +194,10 @@ <members> <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" overrides="BaseButton" enum="BaseButton.ActionMode" default="0" /> <member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" overrides="Button" enum="HorizontalAlignment" default="0" /> + <member name="fit_to_longest_item" type="bool" setter="set_fit_to_longest_item" getter="is_fit_to_longest_item" default="true"> + If [code]true[/code], minimum size will be determined by the longest item's text, instead of the currently selected one's. + [b]Note:[/b] For performance reasons, the minimum size doesn't update immediately when adding, removing or modifying items. + </member> <member name="item_count" type="int" setter="set_item_count" getter="get_item_count" default="0"> The number of items to select from. </member> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 354fbd462c..7badd826d9 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -271,6 +271,42 @@ <member name="tangential_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> Minimum equivalent of [member tangential_accel_max]. </member> + <member name="turbulence_enabled" type="bool" setter="set_turbulence_enabled" getter="get_turbulence_enabled" default="false"> + Enables and disables Turbulence for the particle system. + </member> + <member name="turbulence_influence_max" type="float" setter="set_param_max" getter="get_param_max" default="0.1"> + Minimum turbulence influence on each particle. + The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life]. + </member> + <member name="turbulence_influence_min" type="float" setter="set_param_min" getter="get_param_min" default="0.1"> + Maximum turbulence influence on each particle. + The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life]. + </member> + <member name="turbulence_influence_over_life" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> + Each particle's amount of turbulence will be influenced along this [CurveTexture] over its life time. + </member> + <member name="turbulence_initial_displacement_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0"> + Maximum displacement of each particles spawn position by the turbulence. + The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max]. + </member> + <member name="turbulence_initial_displacement_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> + Minimum displacement of each particles spawn position by the turbulence. + The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max]. + </member> + <member name="turbulence_noise_scale" type="float" setter="set_turbulence_noise_scale" getter="get_turbulence_noise_scale" default="9.0"> + This value controls the overall scale/frequency of the turbulence noise pattern. + A small scale will result in smaller features with more detail while a high scale will result in smoother noise with larger features. + </member> + <member name="turbulence_noise_speed" type="Vector3" setter="set_turbulence_noise_speed" getter="get_turbulence_noise_speed" default="Vector3(0.5, 0.5, 0.5)"> + The movement speed of the turbulence pattern. This changes how quickly the noise changes over time. + A value of [code]Vector3(0.0, 0.0, 0.0)[/code] will freeze the turbulence pattern in place. + </member> + <member name="turbulence_noise_speed_random" type="float" setter="set_turbulence_noise_speed_random" getter="get_turbulence_noise_speed_random" default="0.0"> + Use to influence the noise speed in a random pattern. This helps to break up visible movement patterns. + </member> + <member name="turbulence_noise_strength" type="float" setter="set_turbulence_noise_strength" getter="get_turbulence_noise_strength" default="1.0"> + The turbulence noise strength. Increasing this will result in a stronger, more contrasting, noise pattern. + </member> </members> <constants> <constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter"> @@ -309,7 +345,7 @@ <constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter"> Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set animation offset properties. </constant> - <constant name="PARAM_MAX" value="12" enum="Parameter"> + <constant name="PARAM_MAX" value="15" enum="Parameter"> Represents the size of the [enum Parameter] enum. </constant> <constant name="PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="ParticleFlags"> @@ -348,6 +384,15 @@ <constant name="EMISSION_SHAPE_MAX" value="7" enum="EmissionShape"> Represents the size of the [enum EmissionShape] enum. </constant> + <constant name="PARAM_TURB_VEL_INFLUENCE" value="13" enum="Parameter"> + Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum und maximum influence on each particles velocity. + </constant> + <constant name="PARAM_TURB_INIT_DISPLACEMENT" value="14" enum="Parameter"> + Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum and maximum displacement of the particles spawn position. + </constant> + <constant name="PARAM_TURB_INFLUENCE_OVER_LIFE" value="12" enum="Parameter"> + Use with [method set_param_texture] to set the turbulence influence over the particles life time. + </constant> <constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode"> </constant> <constant name="SUB_EMITTER_CONSTANT" value="1" enum="SubEmitterMode"> @@ -357,6 +402,7 @@ <constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode"> </constant> <constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode"> + Represents the size of the [enum SubEmitterMode] enum. </constant> </constants> </class> diff --git a/doc/classes/PhysicsRayQueryParameters2D.xml b/doc/classes/PhysicsRayQueryParameters2D.xml index 36933ef9a2..1cfc6caadf 100644 --- a/doc/classes/PhysicsRayQueryParameters2D.xml +++ b/doc/classes/PhysicsRayQueryParameters2D.xml @@ -8,6 +8,22 @@ </description> <tutorials> </tutorials> + <methods> + <method name="create" qualifiers="static"> + <return type="PhysicsRayQueryParameters2D" /> + <argument index="0" name="from" type="Vector2" /> + <argument index="1" name="to" type="Vector2" /> + <argument index="2" name="collision_mask" type="int" default="4294967295" /> + <argument index="3" name="exclude" type="Array" default="[]" /> + <description> + Returns a new, pre-configured [PhysicsRayQueryParameters2D] object. Use it to quickly create query parameters using the most common options. + [codeblock] + var query = PhysicsRayQueryParameters2D.create(global_position, global_position + Vector2(0, 100)) + var collision = get_world_2d().direct_space_state.intersect_ray(query) + [/codeblock] + </description> + </method> + </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], the query will take [Area2D]s into account. diff --git a/doc/classes/PhysicsRayQueryParameters3D.xml b/doc/classes/PhysicsRayQueryParameters3D.xml index 4244ec785f..e9216a8300 100644 --- a/doc/classes/PhysicsRayQueryParameters3D.xml +++ b/doc/classes/PhysicsRayQueryParameters3D.xml @@ -8,6 +8,22 @@ </description> <tutorials> </tutorials> + <methods> + <method name="create" qualifiers="static"> + <return type="PhysicsRayQueryParameters3D" /> + <argument index="0" name="from" type="Vector3" /> + <argument index="1" name="to" type="Vector3" /> + <argument index="2" name="collision_mask" type="int" default="4294967295" /> + <argument index="3" name="exclude" type="Array" default="[]" /> + <description> + Returns a new, pre-configured [PhysicsRayQueryParameters3D] object. Use it to quickly create query parameters using the most common options. + [codeblock] + var query = PhysicsRayQueryParameters3D.create(position, position + Vector3(0, -10, 0)) + var collision = get_world_3d().direct_space_state.intersect_ray(query) + [/codeblock] + </description> + </method> + </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], the query will take [Area3D]s into account. diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index a42ceba777..df9d25902b 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -77,15 +77,15 @@ <return type="float" /> <argument index="0" name="point" type="Vector3" /> <description> - Returns the shortest distance from the plane to the position [code]point[/code]. + Returns the shortest distance from the plane to the position [code]point[/code]. If the point is above the plane, the distance will be positive. If below, the distance will be negative. </description> </method> <method name="has_point" qualifiers="const"> <return type="bool" /> <argument index="0" name="point" type="Vector3" /> - <argument index="1" name="epsilon" type="float" default="1e-05" /> + <argument index="1" name="tolerance" type="float" default="1e-05" /> <description> - Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]epsilon[/code] threshold. + Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]tolerance[/code] threshold. </description> </method> <method name="intersect_3" qualifiers="const"> @@ -109,7 +109,7 @@ <argument index="0" name="from" type="Vector3" /> <argument index="1" name="to" type="Vector3" /> <description> - Returns the intersection point of a segment from position [code]begin[/code] to position [code]end[/code] with this plane. If no intersection is found, [code]null[/code] is returned. + Returns the intersection point of a segment from position [code]from[/code] to position [code]to[/code] with this plane. If no intersection is found, [code]null[/code] is returned. </description> </method> <method name="is_equal_approx" qualifiers="const"> @@ -121,7 +121,7 @@ </method> <method name="is_point_over" qualifiers="const"> <return type="bool" /> - <argument index="0" name="plane" type="Vector3" /> + <argument index="0" name="point" type="Vector3" /> <description> Returns [code]true[/code] if [code]point[/code] is located above the plane. </description> @@ -179,6 +179,13 @@ [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> + <operator name="operator *"> + <return type="Plane" /> + <argument index="0" name="right" type="Transform3D" /> + <description> + Inversely transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix. + </description> + </operator> <operator name="operator =="> <return type="bool" /> <argument index="0" name="right" type="Plane" /> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 2a47d4af25..9df8d2df80 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -494,9 +494,39 @@ <member name="debug/shapes/navigation/disabled_geometry_color" type="Color" setter="" getter="" default="Color(1, 0.7, 0.1, 0.4)"> Color of the disabled navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu. </member> + <member name="debug/shapes/navigation/edge_connection_color" type="Color" setter="" getter="" default="Color(1, 0, 1, 1)"> + Color to display edge connections between navigation regions, visible when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/enable_edge_connections" type="bool" setter="" getter="" default="true"> + If enabled, displays edge connections between navigation regions when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/enable_edge_connections_xray" type="bool" setter="" getter="" default="true"> + If enabled, displays edge connections between navigation regions through geometry when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/enable_edge_lines" type="bool" setter="" getter="" default="true"> + If enabled, displays navigation mesh polygon edges when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/enable_edge_lines_xray" type="bool" setter="" getter="" default="true"> + If enabled, displays navigation mesh polygon edges through geometry when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/enable_geometry_face_random_color" type="bool" setter="" getter="" default="true"> + If enabled, colorizes each navigation mesh polygon face with a random color when "Visible Navigation" is enabled in the Debug menu. + </member> <member name="debug/shapes/navigation/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)"> Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu. </member> + <member name="debug/shapes/navigation/geometry_edge_color" type="Color" setter="" getter="" default="Color(0.5, 1, 1, 1)"> + Color to display enabled navigation mesh polygon edges, visible when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/geometry_edge_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 1)"> + Color to display disabled navigation mesh polygon edges, visible when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/geometry_face_color" type="Color" setter="" getter="" default="Color(0.5, 1, 1, 0.4)"> + Color to display enabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu. + </member> + <member name="debug/shapes/navigation/geometry_face_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 0.4)"> + Color to display disabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu. + </member> <member name="debug/shapes/paths/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)"> Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu. </member> @@ -519,6 +549,9 @@ <member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true"> If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms. </member> + <member name="display/window/energy_saving/keep_screen_on.editor" type="bool" setter="" getter="" default="false"> + Editor-only override for [member display/window/energy_saving/keep_screen_on]. Does not affect exported projects in debug or release mode. + </member> <member name="display/window/handheld/orientation" type="int" setter="" getter="" default="0"> The default screen orientation to use on mobile devices. See [enum DisplayServer.ScreenOrientation] for possible values. [b]Note:[/b] When set to a portrait orientation, this project setting does not flip the project resolution's width and height automatically. Instead, you have to set [member display/window/size/viewport_width] and [member display/window/size/viewport_height] accordingly. @@ -558,7 +591,7 @@ [b]Note:[/b] By default, or when set to 0, the initial window width is the viewport [member display/window/size/viewport_width]. This setting is ignored on iOS, Android, and HTML5. </member> <member name="display/window/vsync/vsync_mode" type="int" setter="" getter="" default="1"> - Sets the VSync mode for the main game window. + Sets the V-Sync mode for the main game window. See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application. Depending on the platform and used renderer, the engine will fall back to [code]Enabled[/code], if the desired mode is not supported. </member> @@ -1632,13 +1665,13 @@ Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also bilinear scaling 3d [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive. </member> <member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0"> - Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. + Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled]. </member> <member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false"> </member> <member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false"> - Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. + Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). [b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts. </member> <member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25"> @@ -1856,9 +1889,6 @@ <member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false"> Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support. </member> - <member name="rendering/scaling_3d/fsr_mipmap_bias" type="float" setter="" getter="" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code] - </member> <member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2"> Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference. </member> @@ -1898,53 +1928,61 @@ <member name="rendering/shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048"> Lower-end override for [member rendering/shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support. </member> - <member name="rendering/shadows/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2"> + <member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2"> Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy. [b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance]. [b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply [i]constant[/i] shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows. </member> - <member name="rendering/shadows/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0"> - Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support. + <member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0"> + Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support. </member> - <member name="rendering/shadows/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true"> + <member name="rendering/shadows/positional_shadow/atlas_16_bits" type="bool" setter="" getter="" default="true"> </member> - <member name="rendering/shadows/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="2"> + <member name="rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv" type="int" setter="" getter="" default="2"> Subdivision quadrant size for shadow mapping. See shadow mapping documentation. </member> - <member name="rendering/shadows/shadow_atlas/quadrant_1_subdiv" type="int" setter="" getter="" default="2"> + <member name="rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv" type="int" setter="" getter="" default="2"> Subdivision quadrant size for shadow mapping. See shadow mapping documentation. </member> - <member name="rendering/shadows/shadow_atlas/quadrant_2_subdiv" type="int" setter="" getter="" default="3"> + <member name="rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv" type="int" setter="" getter="" default="3"> Subdivision quadrant size for shadow mapping. See shadow mapping documentation. </member> - <member name="rendering/shadows/shadow_atlas/quadrant_3_subdiv" type="int" setter="" getter="" default="4"> + <member name="rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv" type="int" setter="" getter="" default="4"> Subdivision quadrant size for shadow mapping. See shadow mapping documentation. </member> - <member name="rendering/shadows/shadow_atlas/size" type="int" setter="" getter="" default="4096"> + <member name="rendering/shadows/positional_shadow/atlas_size" type="int" setter="" getter="" default="4096"> Size for shadow atlas (used for OmniLights and SpotLights). See documentation. </member> - <member name="rendering/shadows/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048"> - Lower-end override for [member rendering/shadows/shadow_atlas/size] on mobile devices, due to performance concerns or driver support. + <member name="rendering/shadows/positional_shadow/atlas_size.mobile" type="int" setter="" getter="" default="2048"> + Lower-end override for [member rendering/shadows/positional_shadow/atlas_size] on mobile devices, due to performance concerns or driver support. </member> - <member name="rendering/shadows/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2"> + <member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2"> Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy. [b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance]. [b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows. </member> - <member name="rendering/shadows/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0"> - Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support. + <member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0"> + Lower-end override for [member rendering/shadows/positional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support. </member> <member name="rendering/textures/decals/filter" type="int" setter="" getter="" default="3"> + The filtering quality to use for [Decal] nodes. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level]. </member> <member name="rendering/textures/default_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2"> Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled. + The anisotropic filtering level also affects decals and light projectors if they are configured to use anisotropic filtering. See [member rendering/textures/decals/filter] and [member rendering/textures/light_projectors/filter]. [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> + <member name="rendering/textures/default_filters/texture_mipmap_bias" type="float" setter="" getter="" default="0.0"> + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. + [b]Note:[/b] This property is only read when the project starts. To change the mipmap LOD bias at run-time, set [member Viewport.texture_mipmap_bias] instead. + </member> <member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false"> If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used. [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> <member name="rendering/textures/light_projectors/filter" type="int" setter="" getter="" default="3"> + The filtering quality to use for [OmniLight3D] and [SpotLight3D] projectors. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level]. </member> <member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false"> If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP. @@ -1968,6 +2006,12 @@ If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles. [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]). </member> + <member name="rendering/vrs/mode" type="int" setter="" getter="" default="0"> + Set the default Variable Rate Shading (VRS) mode for the main viewport. See [member Viewport.vrs_mode] to change this at runtime, and [enum Viewport.VRSMode] for possible values. + </member> + <member name="rendering/vrs/texture" type="String" setter="" getter="" default=""""> + If [member rendering/vrs/mode] is set to texture, this is the path to default texture loaded as the VRS image. + </member> <member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64"> </member> <member name="rendering/vulkan/rendering/back_end" type="int" setter="" getter="" default="0"> @@ -1980,6 +2024,12 @@ </member> <member name="rendering/vulkan/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64"> </member> + <member name="threading/worker_pool/low_priority_thread_ratio" type="float" setter="" getter="" default="0.3"> + </member> + <member name="threading/worker_pool/max_threads" type="int" setter="" getter="" default="-1"> + </member> + <member name="threading/worker_pool/use_system_threads_for_low_priority_tasks" type="bool" setter="" getter="" default="true"> + </member> <member name="xr/openxr/default_action_map" type="String" setter="" getter="" default=""res://openxr_action_map.tres""> Action map configuration to load by default. </member> diff --git a/doc/classes/Projection.xml b/doc/classes/Projection.xml new file mode 100644 index 0000000000..2bbfd04e9e --- /dev/null +++ b/doc/classes/Projection.xml @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="Projection" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <constructors> + <constructor name="Projection"> + <return type="Projection" /> + <description> + </description> + </constructor> + <constructor name="Projection"> + <return type="Projection" /> + <argument index="0" name="from" type="Projection" /> + <description> + </description> + </constructor> + <constructor name="Projection"> + <return type="Projection" /> + <argument index="0" name="from" type="Transform3D" /> + <description> + </description> + </constructor> + </constructors> + <methods> + <method name="create_depth_correction" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="flip_y" type="bool" /> + <description> + </description> + </method> + <method name="create_fit_aabb" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="aabb" type="AABB" /> + <description> + </description> + </method> + <method name="create_for_hmd" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="eye" type="int" /> + <argument index="1" name="aspect" type="float" /> + <argument index="2" name="intraocular_dist" type="float" /> + <argument index="3" name="display_width" type="float" /> + <argument index="4" name="display_to_lens" type="float" /> + <argument index="5" name="oversample" type="float" /> + <argument index="6" name="z_near" type="float" /> + <argument index="7" name="z_far" type="float" /> + <description> + </description> + </method> + <method name="create_frustum" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="left" type="float" /> + <argument index="1" name="right" type="float" /> + <argument index="2" name="bottom" type="float" /> + <argument index="3" name="top" type="float" /> + <argument index="4" name="z_near" type="float" /> + <argument index="5" name="z_far" type="float" /> + <description> + </description> + </method> + <method name="create_frustum_aspect" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="size" type="float" /> + <argument index="1" name="aspect" type="float" /> + <argument index="2" name="offset" type="Vector2" /> + <argument index="3" name="z_near" type="float" /> + <argument index="4" name="z_far" type="float" /> + <argument index="5" name="flip_fov" type="bool" default="false" /> + <description> + </description> + </method> + <method name="create_light_atlas_rect" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="rect" type="Rect2" /> + <description> + </description> + </method> + <method name="create_orthogonal" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="left" type="float" /> + <argument index="1" name="right" type="float" /> + <argument index="2" name="bottom" type="float" /> + <argument index="3" name="top" type="float" /> + <argument index="4" name="z_near" type="float" /> + <argument index="5" name="z_far" type="float" /> + <description> + </description> + </method> + <method name="create_orthogonal_aspect" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="size" type="float" /> + <argument index="1" name="aspect" type="float" /> + <argument index="2" name="z_near" type="float" /> + <argument index="3" name="z_far" type="float" /> + <argument index="4" name="flip_fov" type="bool" default="false" /> + <description> + </description> + </method> + <method name="create_perspective" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="fovy" type="float" /> + <argument index="1" name="aspect" type="float" /> + <argument index="2" name="z_near" type="float" /> + <argument index="3" name="z_far" type="float" /> + <argument index="4" name="flip_fov" type="bool" default="false" /> + <description> + </description> + </method> + <method name="create_perspective_hmd" qualifiers="static"> + <return type="Projection" /> + <argument index="0" name="fovy" type="float" /> + <argument index="1" name="aspect" type="float" /> + <argument index="2" name="z_near" type="float" /> + <argument index="3" name="z_far" type="float" /> + <argument index="4" name="flip_fov" type="bool" /> + <argument index="5" name="eye" type="int" /> + <argument index="6" name="intraocular_dist" type="float" /> + <argument index="7" name=" convergence_dist" type="float" /> + <description> + </description> + </method> + <method name="determinant" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="flipped_y" qualifiers="const"> + <return type="Projection" /> + <description> + </description> + </method> + <method name="get_aspect" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="get_far_plane_half_extents" qualifiers="const"> + <return type="Vector2" /> + <description> + </description> + </method> + <method name="get_fov" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="get_fovy" qualifiers="static"> + <return type="float" /> + <argument index="0" name="fovx" type="float" /> + <argument index="1" name="aspect" type="float" /> + <description> + </description> + </method> + <method name="get_lod_multiplier" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="get_pixels_per_meter" qualifiers="const"> + <return type="int" /> + <argument index="0" name="for_pixel_width" type="int" /> + <description> + </description> + </method> + <method name="get_projection_plane" qualifiers="const"> + <return type="Plane" /> + <argument index="0" name="plane" type="int" /> + <description> + </description> + </method> + <method name="get_viewport_half_extents" qualifiers="const"> + <return type="Vector2" /> + <description> + </description> + </method> + <method name="get_z_far" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="get_z_near" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="inverse" qualifiers="const"> + <return type="Projection" /> + <description> + </description> + </method> + <method name="is_orthogonal" qualifiers="const"> + <return type="bool" /> + <description> + </description> + </method> + <method name="jitter_offseted" qualifiers="const"> + <return type="Projection" /> + <argument index="0" name="offset" type="Vector2" /> + <description> + </description> + </method> + <method name="perspective_znear_adjusted" qualifiers="const"> + <return type="Projection" /> + <argument index="0" name="new_znear" type="float" /> + <description> + </description> + </method> + </methods> + <members> + <member name="w" type="Vector4" setter="" getter="" default="Vector4(0, 0, 0, 1)"> + </member> + <member name="x" type="Vector4" setter="" getter="" default="Vector4(1, 0, 0, 0)"> + </member> + <member name="y" type="Vector4" setter="" getter="" default="Vector4(0, 1, 0, 0)"> + </member> + <member name="z" type="Vector4" setter="" getter="" default="Vector4(0, 0, 1, 0)"> + </member> + </members> + <constants> + <constant name="PLANE_NEAR" value="0"> + </constant> + <constant name="PLANE_FAR" value="1"> + </constant> + <constant name="PLANE_LEFT" value="2"> + </constant> + <constant name="PLANE_TOP" value="3"> + </constant> + <constant name="PLANE_RIGHT" value="4"> + </constant> + <constant name="PLANE_BOTTOM" value="5"> + </constant> + <constant name="IDENTITY" value="Projection(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)"> + </constant> + <constant name="ZERO" value="Projection(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)"> + </constant> + </constants> + <operators> + <operator name="operator !="> + <return type="bool" /> + <argument index="0" name="right" type="Projection" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Projection" /> + <argument index="0" name="right" type="Projection" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + </description> + </operator> + <operator name="operator =="> + <return type="bool" /> + <argument index="0" name="right" type="Projection" /> + <description> + </description> + </operator> + <operator name="operator []"> + <return type="Vector4" /> + <argument index="0" name="index" type="int" /> + <description> + </description> + </operator> + </operators> +</class> diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index 48e6317b11..30e96607da 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -74,16 +74,6 @@ [b]Note:[/b] This method has an abnormally high amount of floating-point error, so methods such as [code]is_zero_approx[/code] will not work reliably. </description> </method> - <method name="cubic_slerp" qualifiers="const"> - <return type="Quaternion" /> - <argument index="0" name="b" type="Quaternion" /> - <argument index="1" name="pre_a" type="Quaternion" /> - <argument index="2" name="post_b" type="Quaternion" /> - <argument index="3" name="weight" type="float" /> - <description> - Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code]. - </description> - </method> <method name="dot" qualifiers="const"> <return type="float" /> <argument index="0" name="with" type="Quaternion" /> @@ -171,6 +161,16 @@ Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees. </description> </method> + <method name="spherical_cubic_interpolate" qualifiers="const"> + <return type="Quaternion" /> + <argument index="0" name="b" type="Quaternion" /> + <argument index="1" name="pre_a" type="Quaternion" /> + <argument index="2" name="post_b" type="Quaternion" /> + <argument index="3" name="weight" type="float" /> + <description> + Performs a spherical cubic interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code]. + </description> + </method> </methods> <members> <member name="w" type="float" setter="" getter="" default="1.0"> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 0d121a29d2..3962f309de 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -305,6 +305,12 @@ <description> </description> </method> + <method name="framebuffer_is_valid" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="framebuffer" type="RID" /> + <description> + </description> + </method> <method name="free_rid"> <return type="void" /> <argument index="0" name="rid" type="RID" /> @@ -395,7 +401,7 @@ <description> </description> </method> - <method name="limit_get"> + <method name="limit_get" qualifiers="const"> <return type="int" /> <argument index="0" name="limit" type="int" enum="RenderingDevice.Limit" /> <description> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index d92121a950..c06b2e1d98 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -890,7 +890,7 @@ <description> </description> </method> - <method name="directional_shadow_quality_set"> + <method name="directional_soft_shadow_filter_set_quality"> <return type="void" /> <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" /> <description> @@ -1293,45 +1293,45 @@ If [code]half_resolution[/code] is [code]true[/code], renders [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) buffers at halved resolution (e.g. 960×540 when the viewport size is 1920×1080). This improves performance significantly when VoxelGI or SDFGI is enabled, at the cost of artifacts that may be visible on polygon edges. The loss in quality becomes less noticeable as the viewport resolution increases. [LightmapGI] rendering is not affected by this setting. See also [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution]. </description> </method> - <method name="global_variable_add"> + <method name="global_shader_uniform_add"> <return type="void" /> <argument index="0" name="name" type="StringName" /> - <argument index="1" name="type" type="int" enum="RenderingServer.GlobalVariableType" /> + <argument index="1" name="type" type="int" enum="RenderingServer.GlobalShaderUniformType" /> <argument index="2" name="default_value" type="Variant" /> <description> </description> </method> - <method name="global_variable_get" qualifiers="const"> + <method name="global_shader_uniform_get" qualifiers="const"> <return type="Variant" /> <argument index="0" name="name" type="StringName" /> <description> </description> </method> - <method name="global_variable_get_list" qualifiers="const"> + <method name="global_shader_uniform_get_list" qualifiers="const"> <return type="PackedStringArray" /> <description> </description> </method> - <method name="global_variable_get_type" qualifiers="const"> - <return type="int" enum="RenderingServer.GlobalVariableType" /> + <method name="global_shader_uniform_get_type" qualifiers="const"> + <return type="int" enum="RenderingServer.GlobalShaderUniformType" /> <argument index="0" name="name" type="StringName" /> <description> </description> </method> - <method name="global_variable_remove"> + <method name="global_shader_uniform_remove"> <return type="void" /> <argument index="0" name="name" type="StringName" /> <description> </description> </method> - <method name="global_variable_set"> + <method name="global_shader_uniform_set"> <return type="void" /> <argument index="0" name="name" type="StringName" /> <argument index="1" name="value" type="Variant" /> <description> </description> </method> - <method name="global_variable_set_override"> + <method name="global_shader_uniform_set_override"> <return type="void" /> <argument index="0" name="name" type="StringName" /> <argument index="1" name="value" type="Variant" /> @@ -1391,21 +1391,21 @@ Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method. </description> </method> - <method name="instance_geometry_get_shader_parameter" qualifiers="const"> + <method name="instance_geometry_get_shader_uniform" qualifiers="const"> <return type="Variant" /> <argument index="0" name="instance" type="RID" /> <argument index="1" name="parameter" type="StringName" /> <description> </description> </method> - <method name="instance_geometry_get_shader_parameter_default_value" qualifiers="const"> + <method name="instance_geometry_get_shader_uniform_default_value" qualifiers="const"> <return type="Variant" /> <argument index="0" name="instance" type="RID" /> <argument index="1" name="parameter" type="StringName" /> <description> </description> </method> - <method name="instance_geometry_get_shader_parameter_list" qualifiers="const"> + <method name="instance_geometry_get_shader_uniform_list" qualifiers="const"> <return type="Array" /> <argument index="0" name="instance" type="RID" /> <description> @@ -1460,7 +1460,7 @@ Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override]. </description> </method> - <method name="instance_geometry_set_shader_parameter"> + <method name="instance_geometry_set_shader_uniform"> <return type="void" /> <argument index="0" name="instance" type="RID" /> <argument index="1" name="parameter" type="StringName" /> @@ -2519,6 +2519,12 @@ If [code]true[/code], particles use local coordinates. If [code]false[/code] they use global coordinates. Equivalent to [member GPUParticles3D.local_coords]. </description> </method> + <method name="positional_soft_shadow_filter_set_quality"> + <return type="void" /> + <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" /> + <description> + </description> + </method> <method name="reflection_probe_create"> <return type="RID" /> <description> @@ -2735,13 +2741,20 @@ <description> </description> </method> - <method name="shader_get_param_list" qualifiers="const"> + <method name="shader_get_shader_uniform_list" qualifiers="const"> <return type="Dictionary[]" /> <argument index="0" name="shader" type="RID" /> <description> Returns the parameters of a shader. </description> </method> + <method name="shader_set_code"> + <return type="void" /> + <argument index="0" name="shader" type="RID" /> + <argument index="1" name="code" type="String" /> + <description> + </description> + </method> <method name="shader_set_default_texture_param"> <return type="void" /> <argument index="0" name="shader" type="RID" /> @@ -2753,9 +2766,10 @@ [b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture. </description> </method> - <method name="shadows_quality_set"> + <method name="shader_set_path_hint"> <return type="void" /> - <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" /> + <argument index="0" name="shader" type="RID" /> + <argument index="1" name="path" type="String" /> <description> </description> </method> @@ -3161,14 +3175,6 @@ If [code]true[/code], rendering of a viewport's environment is disabled. </description> </method> - <method name="viewport_set_fsr_mipmap_bias"> - <return type="void" /> - <argument index="0" name="viewport" type="RID" /> - <argument index="1" name="mipmap_bias" type="float" /> - <description> - Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code] - </description> - </method> <method name="viewport_set_fsr_sharpness"> <return type="void" /> <argument index="0" name="viewport" type="RID" /> @@ -3220,6 +3226,25 @@ Sets the viewport's parent to another viewport. </description> </method> + <method name="viewport_set_positional_shadow_atlas_quadrant_subdivision"> + <return type="void" /> + <argument index="0" name="viewport" type="RID" /> + <argument index="1" name="quadrant" type="int" /> + <argument index="2" name="subdivision" type="int" /> + <description> + Sets the shadow atlas quadrant's subdivision. + </description> + </method> + <method name="viewport_set_positional_shadow_atlas_size"> + <return type="void" /> + <argument index="0" name="viewport" type="RID" /> + <argument index="1" name="size" type="int" /> + <argument index="2" name="use_16_bits" type="bool" default="false" /> + <description> + Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2. + [b]Note:[/b] If this is set to [code]0[/code], no shadows will be visible at all (including directional shadows). + </description> + </method> <method name="viewport_set_render_direct_to_screen"> <return type="void" /> <argument index="0" name="viewport" type="RID" /> @@ -3269,24 +3294,6 @@ <description> </description> </method> - <method name="viewport_set_shadow_atlas_quadrant_subdivision"> - <return type="void" /> - <argument index="0" name="viewport" type="RID" /> - <argument index="1" name="quadrant" type="int" /> - <argument index="2" name="subdivision" type="int" /> - <description> - Sets the shadow atlas quadrant's subdivision. - </description> - </method> - <method name="viewport_set_shadow_atlas_size"> - <return type="void" /> - <argument index="0" name="viewport" type="RID" /> - <argument index="1" name="size" type="int" /> - <argument index="2" name="use_16_bits" type="bool" default="false" /> - <description> - Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2. - </description> - </method> <method name="viewport_set_size"> <return type="void" /> <argument index="0" name="viewport" type="RID" /> @@ -3310,6 +3317,15 @@ <description> </description> </method> + <method name="viewport_set_texture_mipmap_bias"> + <return type="void" /> + <argument index="0" name="viewport" type="RID" /> + <argument index="1" name="mipmap_bias" type="float" /> + <description> + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. + </description> + </method> <method name="viewport_set_transparent_background"> <return type="void" /> <argument index="0" name="viewport" type="RID" /> @@ -3356,6 +3372,22 @@ If [code]true[/code], the viewport uses augmented or virtual reality technologies. See [XRInterface]. </description> </method> + <method name="viewport_set_vrs_mode"> + <return type="void" /> + <argument index="0" name="viewport" type="RID" /> + <argument index="1" name="mode" type="int" enum="RenderingServer.ViewportVRSMode" /> + <description> + Sets the Variable Rate Shading (VRS) mode for the viewport. Note, if hardware does not support VRS this property is ignored. + </description> + </method> + <method name="viewport_set_vrs_texture"> + <return type="void" /> + <argument index="0" name="viewport" type="RID" /> + <argument index="1" name="texture" type="RID" /> + <description> + Texture to use when the VRS mode is set to [constant RenderingServer.VIEWPORT_VRS_TEXTURE]. + </description> + </method> <method name="visibility_notifier_create"> <return type="RID" /> <description> @@ -3715,14 +3747,22 @@ Use [Transform3D] to store MultiMesh transform. </constant> <constant name="LIGHT_PROJECTOR_FILTER_NEAREST" value="0" enum="LightProjectorFilter"> + Nearest-neighbor filter for light projectors (use for pixel art light projectors). No mipmaps are used for rendering, which means light projectors at a distance will look sharp but grainy. This has roughly the same performance cost as using mipmaps. </constant> - <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS" value="1" enum="LightProjectorFilter"> + <constant name="LIGHT_PROJECTOR_FILTER_LINEAR" value="1" enum="LightProjectorFilter"> + Linear filter for light projectors (use for non-pixel art light projectors). No mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as using mipmaps. </constant> - <constant name="LIGHT_PROJECTOR_FILTER_LINEAR" value="2" enum="LightProjectorFilter"> + <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS" value="2" enum="LightProjectorFilter"> + Nearest-neighbor filter for light projectors (use for pixel art light projectors). Isotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps. </constant> <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS" value="3" enum="LightProjectorFilter"> + Linear filter for light projectors (use for non-pixel art light projectors). Isotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps. + </constant> + <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC" value="4" enum="LightProjectorFilter"> + Nearest-neighbor filter for light projectors (use for pixel art light projectors). Anisotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level]. </constant> - <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="LightProjectorFilter"> + <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="5" enum="LightProjectorFilter"> + Linear filter for light projectors (use for non-pixel art light projectors). Anisotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level]. </constant> <constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType"> Is a directional (sun) light. @@ -3737,6 +3777,7 @@ The light's energy. </constant> <constant name="LIGHT_PARAM_INDIRECT_ENERGY" value="1" enum="LightParam"> + The light's indirect energy multiplier (final indirect energy is [constant LIGHT_PARAM_ENERGY] * [constant LIGHT_PARAM_INDIRECT_ENERGY]). </constant> <constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam"> The light's influence on specularity. @@ -3780,14 +3821,17 @@ <constant name="LIGHT_PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="LightParam"> Sets the size of the directional shadow pancake. The pancake offsets the start of the shadow's camera frustum to provide a higher effective depth resolution for the shadow. However, a high pancake size can cause artifacts in the shadows of large objects that are close to the edge of the frustum. Reducing the pancake size can help. Setting the size to [code]0[/code] turns off the pancaking effect. </constant> - <constant name="LIGHT_PARAM_SHADOW_BLUR" value="16" enum="LightParam"> + <constant name="LIGHT_PARAM_SHADOW_OPACITY" value="16" enum="LightParam"> + The light's shadow opacity. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost. + </constant> + <constant name="LIGHT_PARAM_SHADOW_BLUR" value="17" enum="LightParam"> Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible. </constant> - <constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="LightParam"> + <constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="LightParam"> </constant> - <constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="18" enum="LightParam"> + <constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="19" enum="LightParam"> </constant> - <constant name="LIGHT_PARAM_MAX" value="19" enum="LightParam"> + <constant name="LIGHT_PARAM_MAX" value="20" enum="LightParam"> Represents the size of the [enum LightParam] enum. </constant> <constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode"> @@ -3864,14 +3908,22 @@ <constant name="DECAL_TEXTURE_MAX" value="4" enum="DecalTexture"> </constant> <constant name="DECAL_FILTER_NEAREST" value="0" enum="DecalFilter"> + Nearest-neighbor filter for decals (use for pixel art decals). No mipmaps are used for rendering, which means decals at a distance will look sharp but grainy. This has roughly the same performance cost as using mipmaps. </constant> - <constant name="DECAL_FILTER_NEAREST_MIPMAPS" value="1" enum="DecalFilter"> + <constant name="DECAL_FILTER_LINEAR" value="1" enum="DecalFilter"> + Linear filter for decals (use for non-pixel art decals). No mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as using mipmaps. </constant> - <constant name="DECAL_FILTER_LINEAR" value="2" enum="DecalFilter"> + <constant name="DECAL_FILTER_NEAREST_MIPMAPS" value="2" enum="DecalFilter"> + Nearest-neighbor filter for decals (use for pixel art decals). Isotropic mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps. </constant> <constant name="DECAL_FILTER_LINEAR_MIPMAPS" value="3" enum="DecalFilter"> + Linear filter for decals (use for non-pixel art decals). Isotropic mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps. + </constant> + <constant name="DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC" value="4" enum="DecalFilter"> + Nearest-neighbor filter for decals (use for pixel art decals). Anisotropic mipmaps are used for rendering, which means decals at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level]. </constant> - <constant name="DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="DecalFilter"> + <constant name="DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="5" enum="DecalFilter"> + Linear filter for decals (use for non-pixel art decals). Anisotropic mipmaps are used for rendering, which means decals at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level]. </constant> <constant name="VOXEL_GI_QUALITY_LOW" value="0" enum="VoxelGIQuality"> </constant> @@ -4115,6 +4167,18 @@ </constant> <constant name="VIEWPORT_DEBUG_DRAW_MOTION_VECTORS" value="25" enum="ViewportDebugDraw"> </constant> + <constant name="VIEWPORT_VRS_DISABLED" value="0" enum="ViewportVRSMode"> + VRS is disabled. + </constant> + <constant name="VIEWPORT_VRS_TEXTURE" value="1" enum="ViewportVRSMode"> + VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view. + </constant> + <constant name="VIEWPORT_VRS_XR" value="2" enum="ViewportVRSMode"> + VRS texture is supplied by the primary [XRInterface]. + </constant> + <constant name="VIEWPORT_VRS_MAX" value="3" enum="ViewportVRSMode"> + Represents the size of the [enum ViewportVRSMode] enum. + </constant> <constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode"> </constant> <constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode"> @@ -4493,63 +4557,63 @@ <constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2" enum="CanvasOccluderPolygonCullMode"> Culling of the canvas occluder is counterclockwise. </constant> - <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalShaderUniformType"> </constant> - <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalVariableType"> + <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalShaderUniformType"> </constant> <constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo"> </constant> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index 36b64f5a86..fef94b5f3b 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -17,6 +17,12 @@ <description> </description> </method> + <method name="_get_classes_used" qualifiers="virtual const"> + <return type="PackedStringArray" /> + <argument index="0" name="path" type="String" /> + <description> + </description> + </method> <method name="_get_dependencies" qualifiers="virtual const"> <return type="PackedStringArray" /> <argument index="0" name="path" type="String" /> diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml index c156814a1d..f9c4ca0d49 100644 --- a/doc/classes/ResourceFormatSaver.xml +++ b/doc/classes/ResourceFormatSaver.xml @@ -26,8 +26,8 @@ </method> <method name="_save" qualifiers="virtual"> <return type="int" /> - <argument index="0" name="path" type="String" /> - <argument index="1" name="resource" type="Resource" /> + <argument index="0" name="path" type="Resource" /> + <argument index="1" name="resource" type="String" /> <argument index="2" name="flags" type="int" /> <description> Saves the given resource object to a file at the target [code]path[/code]. [code]flags[/code] is a bitmask composed with [enum ResourceSaver.SaverFlags] constants. diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml index d6e9a233b0..729058c9b3 100644 --- a/doc/classes/ResourceLoader.xml +++ b/doc/classes/ResourceLoader.xml @@ -6,6 +6,7 @@ <description> Singleton used to load resource files from the filesystem. It uses the many [ResourceFormatLoader] classes registered in the engine (either built-in or from a plugin) to load files into memory and convert them to a format that can be used by the engine. + [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. </description> <tutorials> <link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link> @@ -17,7 +18,7 @@ <argument index="1" name="at_front" type="bool" default="false" /> <description> Registers a new [ResourceFormatLoader]. The ResourceLoader will use the ResourceFormatLoader as described in [method load]. - This method is performed implictly for ResourceFormatLoaders written in GDScript (see [ResourceFormatLoader] for more information). + This method is performed implicitly for ResourceFormatLoaders written in GDScript (see [ResourceFormatLoader] for more information). </description> </method> <method name="exists"> @@ -94,8 +95,10 @@ <argument index="0" name="path" type="String" /> <argument index="1" name="type_hint" type="String" default="""" /> <argument index="2" name="use_sub_threads" type="bool" default="false" /> + <argument index="3" name="cache_mode" type="int" enum="ResourceLoader.CacheMode" default="1" /> <description> Loads the resource using threads. If [code]use_sub_threads[/code] is [code]true[/code], multiple threads will be used to load the resource, which makes loading faster, but may affect the main thread (and thus cause game slowdowns). + The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details. </description> </method> <method name="remove_resource_format_loader"> diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml index 213d8c585a..10387a4f14 100644 --- a/doc/classes/ResourceSaver.xml +++ b/doc/classes/ResourceSaver.xml @@ -16,7 +16,7 @@ <argument index="1" name="at_front" type="bool" default="false" /> <description> Registers a new [ResourceFormatSaver]. The ResourceSaver will use the ResourceFormatSaver as described in [method save]. - This method is performed implictly for ResourceFormatSavers written in GDScript (see [ResourceFormatSaver] for more information). + This method is performed implicitly for ResourceFormatSavers written in GDScript (see [ResourceFormatSaver] for more information). </description> </method> <method name="get_recognized_extensions"> @@ -35,11 +35,11 @@ </method> <method name="save"> <return type="int" enum="Error" /> - <argument index="0" name="path" type="String" /> - <argument index="1" name="resource" type="Resource" /> + <argument index="0" name="resource" type="Resource" /> + <argument index="1" name="path" type="String" default="""" /> <argument index="2" name="flags" type="int" enum="ResourceSaver.SaverFlags" default="0" /> <description> - Saves a resource to disk to the given path, using a [ResourceFormatSaver] that recognizes the resource object. + Saves a resource to disk to the given path, using a [ResourceFormatSaver] that recognizes the resource object. If [code]path[/code] is empty, [ResourceSaver] will try to use [member Resource.resource_path]. The [code]flags[/code] bitmask can be specified to customize the save behavior using [enum SaverFlags] flags. Returns [constant OK] on success. </description> diff --git a/doc/classes/ResourceUID.xml b/doc/classes/ResourceUID.xml index f91c39b512..782a8a2968 100644 --- a/doc/classes/ResourceUID.xml +++ b/doc/classes/ResourceUID.xml @@ -1,8 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ResourceUID" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Singleton for managing a cache of resource UIDs within a project. </brief_description> <description> + Resources can not only be referenced using their resource paths [code]res://[/code], but alternatively through a unique identifier specified via [code]uid://[/code]. + Using UIDs allows for the engine to keep references between resources intact, even if the files get renamed or moved. + This singleton is responsible for keeping track of all registered resource UIDs of a project, generating new UIDs and converting between the string and integer representation. </description> <tutorials> </tutorials> @@ -12,35 +16,45 @@ <argument index="0" name="id" type="int" /> <argument index="1" name="path" type="String" /> <description> + Adds a new UID value which is mapped to the given resource path. + Fails with an error if the UID already exists, so be sure to check [method has_id] beforehand, or use [method set_id] instead. </description> </method> <method name="create_id"> <return type="int" /> <description> + Generates a random resource UID which is guaranteed to be unique within the list of currently loaded UIDs. + In order for this UID to be registered, you must call [method add_id] or [method set_id]. </description> </method> <method name="get_id_path" qualifiers="const"> <return type="String" /> <argument index="0" name="id" type="int" /> <description> + Returns the path that the given UID value refers to. + Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand. </description> </method> <method name="has_id" qualifiers="const"> <return type="bool" /> <argument index="0" name="id" type="int" /> <description> + Returns whether the given UID value is known to the cache. </description> </method> <method name="id_to_text" qualifiers="const"> <return type="String" /> <argument index="0" name="id" type="int" /> <description> + Converts the given UID to a [code]uid://[/code] string value. </description> </method> <method name="remove_id"> <return type="void" /> <argument index="0" name="id" type="int" /> <description> + Removes a loaded UID value from the cache. + Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand. </description> </method> <method name="set_id"> @@ -48,17 +62,22 @@ <argument index="0" name="id" type="int" /> <argument index="1" name="path" type="String" /> <description> + Updates the resource path of an existing UID. + Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand, or use [method add_id] instead. </description> </method> <method name="text_to_id" qualifiers="const"> <return type="int" /> <argument index="0" name="text_id" type="String" /> <description> + Extracts the UID value from the given [code]uid://[/code] string. </description> </method> </methods> <constants> <constant name="INVALID_ID" value="-1"> + The value to use for an invalid UID, for example if the resource could not be loaded. + Its text representation is [code]uid://<invalid>[/code]. </constant> </constants> </class> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 3c9e9b1bfc..8228bcc442 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -272,6 +272,7 @@ <method name="push_font"> <return type="void" /> <argument index="0" name="font" type="Font" /> + <argument index="1" name="font_size" type="int" /> <description> Adds a [code][font][/code] tag to the tag stack. Overrides default fonts for its duration. </description> diff --git a/doc/classes/RootMotionView.xml b/doc/classes/RootMotionView.xml index 88b8f2cd03..3f3b00e2cb 100644 --- a/doc/classes/RootMotionView.xml +++ b/doc/classes/RootMotionView.xml @@ -5,25 +5,25 @@ </brief_description> <description> [i]Root motion[/i] refers to an animation technique where a mesh's skeleton is used to give impulse to a character. When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton. This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics. See also [AnimationTree]. - [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project, and will also be converted to a plain [Node] in the running project. This means a script attached to a [RootMotionView] node [i]must[/i] have [code]extends Node[/code] instead of [code]extends RootMotionView[/code]. Additionally, it must not be a [code]@tool[/code] script. + [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project. </description> <tutorials> <link title="Using AnimationTree - Root motion">$DOCS_URL/tutorials/animation/animation_tree.html#root-motion</link> </tutorials> <members> - <member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path"> + <member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path" default="NodePath("")"> Path to an [AnimationTree] node to use as a basis for root motion. </member> - <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size"> + <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="1.0"> The grid's cell size in 3D units. </member> - <member name="color" type="Color" setter="set_color" getter="get_color"> + <member name="color" type="Color" setter="set_color" getter="get_color" default="Color(0.5, 0.5, 1, 1)"> The grid's color. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0"> The grid's radius in 3D units. The grid's opacity will fade gradually as the distance from the origin increases until this [member radius] is reached. </member> - <member name="zero_y" type="bool" setter="set_zero_y" getter="get_zero_y"> + <member name="zero_y" type="bool" setter="set_zero_y" getter="get_zero_y" default="true"> If [code]true[/code], the grid's points will all be on the same Y coordinate ([i]local[/i] Y = 0). If [code]false[/code], the points' original Y coordinate is preserved. </member> </members> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index cf6ab977db..9982cc0d60 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -18,8 +18,7 @@ <argument index="0" name="group" type="StringName" /> <argument index="1" name="method" type="StringName" /> <description> - Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. - [b]Note:[/b] Due to design limitations, [method call_group] will fail silently if one of the arguments is [code]null[/code]. + Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped. [b]Note:[/b] [method call_group] will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members. To wait for one frame after [method call_group] was called, use [method call_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. </description> </method> @@ -29,12 +28,11 @@ <argument index="1" name="group" type="StringName" /> <argument index="2" name="method" type="StringName" /> <description> - Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. + Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped. [codeblock] # Call the method in a deferred manner and in reverse order. get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED | SceneTree.GROUP_CALL_REVERSE) [/codeblock] - [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code]. [b]Note:[/b] Group call flags are used to control the method calling behavior. By default, methods will be called immediately in a way similar to [method call_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, methods will be called with a one-frame delay in a way similar to [method Object.set_deferred]. </description> </method> diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml index 91fa6206d7..4e432ca9a8 100644 --- a/doc/classes/ScriptExtension.xml +++ b/doc/classes/ScriptExtension.xml @@ -65,8 +65,8 @@ <description> </description> </method> - <method name="_get_rpc_methods" qualifiers="virtual const"> - <return type="Dictionary[]" /> + <method name="_get_rpc_config" qualifiers="virtual const"> + <return type="Variant" /> <description> </description> </method> diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml index 10deaf1c41..1921c5b91d 100644 --- a/doc/classes/Shader.xml +++ b/doc/classes/Shader.xml @@ -26,7 +26,7 @@ Returns the shader mode for the shader, either [constant MODE_CANVAS_ITEM], [constant MODE_SPATIAL] or [constant MODE_PARTICLES]. </description> </method> - <method name="has_param" qualifiers="const"> + <method name="has_uniform" qualifiers="const"> <return type="bool" /> <argument index="0" name="name" type="StringName" /> <description> diff --git a/doc/classes/ShaderInclude.xml b/doc/classes/ShaderInclude.xml new file mode 100644 index 0000000000..40072a933b --- /dev/null +++ b/doc/classes/ShaderInclude.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ShaderInclude" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <members> + <member name="code" type="String" setter="set_code" getter="get_code" default=""""> + </member> + </members> +</class> diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml index 672b660c34..1208b93a62 100644 --- a/doc/classes/ShaderMaterial.xml +++ b/doc/classes/ShaderMaterial.xml @@ -10,7 +10,7 @@ <link title="Shaders documentation index">$DOCS_URL/tutorials/shaders/index.html</link> </tutorials> <methods> - <method name="get_shader_param" qualifiers="const"> + <method name="get_shader_uniform" qualifiers="const"> <return type="Variant" /> <argument index="0" name="param" type="StringName" /> <description> @@ -31,7 +31,7 @@ Returns the default value of the material property with given [code]name[/code]. </description> </method> - <method name="set_shader_param"> + <method name="set_shader_uniform"> <return type="void" /> <argument index="0" name="param" type="StringName" /> <argument index="1" name="value" type="Variant" /> diff --git a/doc/classes/ShapeCast2D.xml b/doc/classes/ShapeCast2D.xml index 5fcb60dd09..70da03dc6e 100644 --- a/doc/classes/ShapeCast2D.xml +++ b/doc/classes/ShapeCast2D.xml @@ -6,7 +6,7 @@ <description> Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons). Immediate collision overlaps can be done with the [member target_position] set to [code]Vector2(0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area2D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area2D] nodes, and when using the signals creates unnecessary complexity. - The node can detect multiple collision objects, but usually the first detected collision + The node can detect multiple collision objects, but it's usually used to detect the first collision. [b]Note:[/b] shape casting is more computationally expensive compared to ray casting. </description> <tutorials> @@ -42,27 +42,27 @@ <method name="get_closest_collision_safe_fraction" qualifiers="const"> <return type="float" /> <description> - The fraction of the motion (between 0 and 1) of how far the shape can move without triggering a collision. The motion is determined by [member target_position]. + The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision. </description> </method> <method name="get_closest_collision_unsafe_fraction" qualifiers="const"> <return type="float" /> <description> - The fraction of the motion (between 0 and 1) when the shape triggers a collision. The motion is determined by [member target_position]. + The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision. </description> </method> <method name="get_collider" qualifiers="const"> <return type="Object" /> <argument index="0" name="index" type="int" /> <description> - Returns the [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collider_shape" qualifiers="const"> <return type="int" /> <argument index="0" name="index" type="int" /> <description> - Returns the shape ID of one of the multiple collisions at [code]index[/code] that the shape intersects, or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). </description> </method> <method name="get_collision_count" qualifiers="const"> @@ -82,14 +82,14 @@ <return type="Vector2" /> <argument index="0" name="index" type="int" /> <description> - Returns the normal containing one of the multiple collisions at [code]index[/code] of the intersecting object. + Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object. </description> </method> <method name="get_collision_point" qualifiers="const"> <return type="Vector2" /> <argument index="0" name="index" type="int" /> <description> - Returns the collision point containing one of the multiple collisions at [code]index[/code] at which the shape intersects the object. + Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object. [b]Note:[/b] this point is in the [b]global[/b] coordinate system. </description> </method> @@ -133,7 +133,7 @@ The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. </member> <member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]"> - A complete collision information. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method. + Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method. </member> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> If [code]true[/code], collisions will be reported. @@ -148,7 +148,7 @@ The number of intersections can be limited with this parameter, to reduce the processing time. </member> <member name="shape" type="Shape2D" setter="set_shape" getter="get_shape"> - Any [Shape2D] derived shape used for collision queries. + The [Shape2D]-derived shape to be used for collision queries. </member> <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)"> The shape's destination point, relative to this node's [code]position[/code]. diff --git a/doc/classes/ShapeCast3D.xml b/doc/classes/ShapeCast3D.xml new file mode 100644 index 0000000000..085bc9acd1 --- /dev/null +++ b/doc/classes/ShapeCast3D.xml @@ -0,0 +1,168 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ShapeCast3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Node for physics collision sweep and immediate overlap queries. Similar to the [RayCast3D] node. + </brief_description> + <description> + Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons). + Immediate collision overlaps can be done with the [member target_position] set to [code]Vector3(0, 0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area3D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area3D] nodes, and when using the signals creates unnecessary complexity. + The node can detect multiple collision objects, but it's usually used to detect the first collision. + [b]Note:[/b] Shape casting is more computationally expensive compared to ray casting. + </description> + <tutorials> + </tutorials> + <methods> + <method name="add_exception"> + <return type="void" /> + <argument index="0" name="node" type="Object" /> + <description> + Adds a collision exception so the shape does not report collisions with the specified [CollisionObject3D] node. + </description> + </method> + <method name="add_exception_rid"> + <return type="void" /> + <argument index="0" name="rid" type="RID" /> + <description> + Adds a collision exception so the shape does not report collisions with the specified [RID]. + </description> + </method> + <method name="clear_exceptions"> + <return type="void" /> + <description> + Removes all collision exceptions for this [ShapeCast3D]. + </description> + </method> + <method name="force_shapecast_update"> + <return type="void" /> + <description> + Updates the collision information for the shape. Use this method to update the collision information immediately instead of waiting for the next [code]_physics_process[/code] call, for example if the shape or its parent has changed state. + [b]Note:[/b] [code]enabled == true[/code] is not required for this to work. + </description> + </method> + <method name="get_closest_collision_safe_fraction" qualifiers="const"> + <return type="float" /> + <description> + The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision. + </description> + </method> + <method name="get_closest_collision_unsafe_fraction" qualifiers="const"> + <return type="float" /> + <description> + The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision. + </description> + </method> + <method name="get_collider" qualifiers="const"> + <return type="Object" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + </description> + </method> + <method name="get_collider_shape" qualifiers="const"> + <return type="int" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + </description> + </method> + <method name="get_collision_count" qualifiers="const"> + <return type="int" /> + <description> + The number of collisions detected at the point of impact. Use this to iterate over multiple collisions as provided by [method get_collider], [method get_collider_shape], [method get_collision_point], and [method get_collision_normal] methods. + </description> + </method> + <method name="get_collision_mask_value" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="layer_number" type="int" /> + <description> + Returns whether or not the specified layer of the [member collision_mask] is enabled, given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + <method name="get_collision_normal" qualifiers="const"> + <return type="Vector3" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object. + </description> + </method> + <method name="get_collision_point" qualifiers="const"> + <return type="Vector3" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object. + [b]Note:[/b] this point is in the [b]global[/b] coordinate system. + </description> + </method> + <method name="is_colliding" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether any object is intersecting with the shape's vector (considering the vector length). + </description> + </method> + <method name="remove_exception"> + <return type="void" /> + <argument index="0" name="node" type="Object" /> + <description> + Removes a collision exception so the shape does report collisions with the specified [CollisionObject3D] node. + </description> + </method> + <method name="remove_exception_rid"> + <return type="void" /> + <argument index="0" name="rid" type="RID" /> + <description> + Removes a collision exception so the shape does report collisions with the specified [RID]. + </description> + </method> + <method name="resource_changed"> + <return type="void" /> + <argument index="0" name="resource" type="Resource" /> + <description> + This method is used internally to update the debug gizmo in the editor. Any code placed in this function will be called whenever the [member shape] resource is modified. + </description> + </method> + <method name="set_collision_mask_value"> + <return type="void" /> + <argument index="0" name="layer_number" type="int" /> + <argument index="1" name="value" type="bool" /> + <description> + Based on [code]value[/code], enables or disables the specified layer in the [member collision_mask], given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + </methods> + <members> + <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> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], collision with [PhysicsBody3D]s will be reported. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> + The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + </member> + <member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]"> + Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState3D.get_rest_info] method. + </member> + <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color(0, 0, 0, 1)"> + The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [ShapeCast3D] is colliding with something. + If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used. + </member> + <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> + If [code]true[/code], collisions will be reported. + </member> + <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="margin" type="float" setter="set_margin" getter="get_margin" default="0.0"> + The collision margin for the shape. A larger margin helps detecting collisions more consistently, at the cost of precision. + </member> + <member name="max_results" type="int" setter="set_max_results" getter="get_max_results" default="32"> + The number of intersections can be limited with this parameter, to reduce the processing time. + </member> + <member name="shape" type="Shape3D" setter="set_shape" getter="get_shape"> + The [Shape3D]-derived shape to be used for collision queries. + </member> + <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)"> + The shape's destination point, relative to this node's [code]position[/code]. + </member> + </members> +</class> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index f271220989..6295724aa2 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -392,6 +392,10 @@ <members> <member name="animate_physical_bones" type="bool" setter="set_animate_physical_bones" getter="get_animate_physical_bones" default="true"> </member> + <member name="motion_scale" type="float" setter="set_motion_scale" getter="get_motion_scale" default="1.0"> + Multiplies the position 3D track animation. + [b]Note:[/b] Unless this value is [code]1.0[/code], the key value in animation will not match the actual position value. + </member> <member name="show_rest_only" type="bool" setter="set_show_rest_only" getter="is_show_rest_only" default="false"> </member> </members> diff --git a/doc/classes/SkeletonProfile.xml b/doc/classes/SkeletonProfile.xml index 55a2ea6759..5c2d0eefb4 100644 --- a/doc/classes/SkeletonProfile.xml +++ b/doc/classes/SkeletonProfile.xml @@ -9,6 +9,13 @@ <tutorials> </tutorials> <methods> + <method name="find_bone" qualifiers="const"> + <return type="int" /> + <argument index="0" name="bone_name" type="StringName" /> + <description> + Returns the bone index that matches [code]bone_name[/code] as its name. + </description> + </method> <method name="get_bone_name" qualifiers="const"> <return type="StringName" /> <argument index="0" name="bone_idx" type="int" /> @@ -17,6 +24,20 @@ In the retargeting process, the returned bone name is the bone name of the target skeleton. </description> </method> + <method name="get_bone_parent" qualifiers="const"> + <return type="StringName" /> + <argument index="0" name="bone_idx" type="int" /> + <description> + Returns the name of the bone which is the parent to the bone at [code]bone_idx[/code]. The result is empty if the bone has no parent. + </description> + </method> + <method name="get_bone_tail" qualifiers="const"> + <return type="StringName" /> + <argument index="0" name="bone_idx" type="int" /> + <description> + Returns the name of the bone which is the tail of the bone at [code]bone_idx[/code]. + </description> + </method> <method name="get_group" qualifiers="const"> <return type="StringName" /> <argument index="0" name="bone_idx" type="int" /> @@ -39,6 +60,20 @@ This is the offset with origin at the top left corner of the square. </description> </method> + <method name="get_reference_pose" qualifiers="const"> + <return type="Transform3D" /> + <argument index="0" name="bone_idx" type="int" /> + <description> + Returns the reference pose transform for bone [code]bone_idx[/code]. + </description> + </method> + <method name="get_tail_direction" qualifiers="const"> + <return type="int" enum="SkeletonProfile.TailDirection" /> + <argument index="0" name="bone_idx" type="int" /> + <description> + Returns the tail direction of the bone at [code]bone_idx[/code]. + </description> + </method> <method name="get_texture" qualifiers="const"> <return type="Texture2D" /> <argument index="0" name="group_idx" type="int" /> @@ -55,6 +90,22 @@ In the retargeting process, the setting bone name is the bone name of the target skeleton. </description> </method> + <method name="set_bone_parent"> + <return type="void" /> + <argument index="0" name="bone_idx" type="int" /> + <argument index="1" name="bone_parent" type="StringName" /> + <description> + Sets the bone with name [code]bone_parent[/code] as the parent of the bone at [code]bone_idx[/code]. If an empty string is passed, then the bone has no parent. + </description> + </method> + <method name="set_bone_tail"> + <return type="void" /> + <argument index="0" name="bone_idx" type="int" /> + <argument index="1" name="bone_tail" type="StringName" /> + <description> + Sets the bone with name [code]bone_tail[/code] as the tail of the bone at [code]bone_idx[/code]. + </description> + </method> <method name="set_group"> <return type="void" /> <argument index="0" name="bone_idx" type="int" /> @@ -80,6 +131,23 @@ This is the offset with origin at the top left corner of the square. </description> </method> + <method name="set_reference_pose"> + <return type="void" /> + <argument index="0" name="bone_idx" type="int" /> + <argument index="1" name="bone_name" type="Transform3D" /> + <description> + Sets the reference pose transform for bone [code]bone_idx[/code]. + </description> + </method> + <method name="set_tail_direction"> + <return type="void" /> + <argument index="0" name="bone_idx" type="int" /> + <argument index="1" name="tail_direction" type="int" enum="SkeletonProfile.TailDirection" /> + <description> + Sets the tail direction of the bone at [code]bone_idx[/code]. + [b]Note:[/b] This only specifies the method of calculation. The actual coordinates required should be stored in an external skeleton, so the calculation itself needs to be done externally. + </description> + </method> <method name="set_texture"> <return type="void" /> <argument index="0" name="group_idx" type="int" /> @@ -94,13 +162,32 @@ </member> <member name="group_size" type="int" setter="set_group_size" getter="get_group_size" default="0"> </member> + <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" default="&"""> + A name of bone that will be used as the root bone in [AnimationTree]. + [b]Note:[/b] In most cases, it is the bone of the parent of the hips that exists at the world origin in the humanoid model. + </member> + <member name="scale_base_bone" type="StringName" setter="set_scale_base_bone" getter="get_scale_base_bone" default="&"""> + A name of bone which height will be used as the coefficient for normalization. + [b]Note:[/b] In most cases, it is hips in the humanoid model. + </member> </members> <signals> <signal name="profile_updated"> <description> This signal is emitted when change the value in profile. This is used to update key name in the [BoneMap] and to redraw the [BoneMap] editor. - [b]Note[/b]: This signal is not connected directly to editor to simplify the reference, instead it is passed on to editor through the [BoneMap]. + [b]Note:[/b] This signal is not connected directly to editor to simplify the reference, instead it is passed on to editor through the [BoneMap]. </description> </signal> </signals> + <constants> + <constant name="TAIL_DIRECTION_AVERAGE_CHILDREN" value="0" enum="TailDirection"> + Direction to the average coordinates of bone children. + </constant> + <constant name="TAIL_DIRECTION_SPECIFIC_CHILD" value="1" enum="TailDirection"> + Direction to the coordinates of specified bone child. + </constant> + <constant name="TAIL_DIRECTION_END" value="2" enum="TailDirection"> + Direction is not calculated. + </constant> + </constants> </class> diff --git a/doc/classes/SkeletonProfileHumanoid.xml b/doc/classes/SkeletonProfileHumanoid.xml index 065184244e..11f0521718 100644 --- a/doc/classes/SkeletonProfileHumanoid.xml +++ b/doc/classes/SkeletonProfileHumanoid.xml @@ -10,5 +10,7 @@ <members> <member name="bone_size" type="int" setter="set_bone_size" getter="get_bone_size" overrides="SkeletonProfile" default="56" /> <member name="group_size" type="int" setter="set_group_size" getter="get_group_size" overrides="SkeletonProfile" default="4" /> + <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" overrides="SkeletonProfile" default="&"Root"" /> + <member name="scale_base_bone" type="StringName" setter="set_scale_base_bone" getter="get_scale_base_bone" overrides="SkeletonProfile" default="&"Hips"" /> </members> </class> diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index e84f9c38ff..8df039794a 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -47,6 +47,9 @@ <members> <member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0"> </member> + <member name="custom_arrow_step" type="float" setter="set_custom_arrow_step" getter="get_custom_arrow_step" default="0.0"> + If not [code]0[/code], [code]value[/code] will always be rounded to a multiple of [code]custom_arrow_step[/code] when interacting with the arrow buttons of the [SpinBox]. + </member> <member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true"> If [code]true[/code], the [SpinBox] will be editable. Otherwise, it will be read only. </member> diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index 41b02b6dc9..bc381578d9 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -77,7 +77,7 @@ </member> <member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0"> Sets the render priority for the sprite. Higher priority objects will be sorted in front of lower priority objects. - [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). + [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value). [b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority). </member> <member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml index b0d1e1efcf..0d423630d4 100644 --- a/doc/classes/SpriteFrames.xml +++ b/doc/classes/SpriteFrames.xml @@ -130,9 +130,4 @@ </description> </method> </methods> - <members> - <member name="frames" type="Array" setter="_set_frames" getter="_get_frames"> - Compatibility property, always equals to an empty array. - </member> - </members> </class> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 9f197dae02..35ad5f03ab 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -640,6 +640,7 @@ <description> Splits the string by a [code]delimiter[/code] string and returns an array of the substrings, starting from right. The splits in the returned array are sorted in the same order as the original string, from left to right. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [code]maxsplit[/code] is specified, it defines the number of splits to do from the right up to [code]maxsplit[/code]. The default value of 0 means that all items are split, thus giving the same result as [method split]. Example: [codeblocks] @@ -714,6 +715,7 @@ <argument index="2" name="maxsplit" type="int" default="0" /> <description> Splits the string by a [code]delimiter[/code] string and returns an array of the substrings. The [code]delimiter[/code] can be of any length. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [code]maxsplit[/code] is specified, it defines the number of splits to do from the left up to [code]maxsplit[/code]. The default value of [code]0[/code] means that all items are split. If you need only one element from the array at a specific index, [method get_slice] is a more performant option. Example: @@ -742,6 +744,7 @@ <description> Splits the string in floats by using a delimiter string and returns an array of the substrings. For example, [code]"1,2.5,3"[/code] will return [code][1,2.5,3][/code] if split by [code]","[/code]. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. </description> </method> <method name="strip_edges" qualifiers="const"> diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml new file mode 100644 index 0000000000..b1b78f1705 --- /dev/null +++ b/doc/classes/SystemFont.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="SystemFont" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Font loaded from a system font. + [b]Note:[/b] This class is implemented on iOS, Linux, macOS and Windows, on other platforms it will fallback to default theme font. + </brief_description> + <description> + [SystemFont] loads a font from a system font with the first matching name from [member font_names]. + It will attempt to match font style, but it's not guaranteed. + The returned font might be part of a font collection or be a variable font with OpenType "weight" and/or "italic" features set. + You can create [FontVariation] of the system font for fine control over its features. + </description> + <tutorials> + </tutorials> + <members> + <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> + If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. + </member> + <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]"> + Array of fallback [Font]s. + </member> + <member name="font_names" type="PackedStringArray" setter="set_font_names" getter="get_font_names" default="PackedStringArray()"> + Array of font family names to search, first matching font found is used. + </member> + <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" enum="TextServer.FontStyle" default="0"> + Font style flags, see [enum TextServer.FontStyle]. + </member> + <member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false"> + If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting. + </member> + <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="get_generate_mipmaps" default="false"> + If set to [code]true[/code], generate mipmaps for the font textures. + </member> + <member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="TextServer.Hinting" default="1"> + Font hinting mode. + </member> + <member name="oversampling" type="float" setter="set_oversampling" getter="get_oversampling" default="0.0"> + Font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. + </member> + <member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1"> + Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size. + </member> + </members> +</class> diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml index c3574980b1..601650db2e 100644 --- a/doc/classes/TextLine.xml +++ b/doc/classes/TextLine.xml @@ -148,8 +148,8 @@ <member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0"> Text writing direction. </member> - <member name="flags" type="int" setter="set_flags" getter="get_flags" default="3"> - Line Alignment rules. For more info see [TextServer]. + <member name="flags" type="int" setter="set_flags" getter="get_flags" enum="TextServer.JustificationFlag" default="3"> + Line alignment rules. For more info see [TextServer]. </member> <member name="orientation" type="int" setter="set_orientation" getter="get_orientation" enum="TextServer.Orientation" default="0"> Text orientation. diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index 6d615bd404..c733d8fcee 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -263,14 +263,17 @@ <member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="HorizontalAlignment" default="0"> Paragraph horizontal alignment. </member> + <member name="break_flags" type="int" setter="set_break_flags" getter="get_break_flags" enum="TextServer.LineBreakFlag" default="3"> + Line breaking rules. For more info see [TextServer]. + </member> <member name="custom_punctuation" type="String" setter="set_custom_punctuation" getter="get_custom_punctuation" default=""""> Custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. </member> <member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0"> Text writing direction. </member> - <member name="flags" type="int" setter="set_flags" getter="get_flags" default="99"> - Line breaking and alignment rules. For more info see [TextServer]. + <member name="justification_flags" type="int" setter="set_justification_flags" getter="get_justification_flags" enum="TextServer.JustificationFlag" default="3"> + Line alignment rules. For more info see [TextServer]. </member> <member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1"> Limits the lines of text shown. diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 4c8cf3982e..b54536f897 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -356,7 +356,7 @@ </description> </method> <method name="font_get_style" qualifiers="const"> - <return type="int" /> + <return type="int" enum="TextServer.FontStyle" /> <argument index="0" name="font_rid" type="RID" /> <description> Returns font style flags, see [enum FontStyle]. @@ -786,7 +786,7 @@ <method name="font_set_style"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> - <argument index="1" name="style" type="int" /> + <argument index="1" name="style" type="int" enum="TextServer.FontStyle" /> <description> Sets the font style flags, see [enum FontStyle]. </description> @@ -937,6 +937,16 @@ Returns [code]true[/code] if the server supports a feature. </description> </method> + <method name="is_confusable" qualifiers="const"> + <return type="int" /> + <argument index="0" name="string" type="String" /> + <argument index="1" name="dict" type="PackedStringArray" /> + <description> + Returns index of the first string in [code]dict[/dict] which is visually confusable with the [code]string[/string], or [code]-1[/code] if none is found. + [b]Note:[/b] This method doesn't detect invisible characters, for spoof detection use it in combination with [method spoof_check]. + [b]Note:[/b] Always returns [code]-1[/code] if the server does not support the [constant FEATURE_UNICODE_SECURITY] feature. + </description> + </method> <method name="is_locale_right_to_left" qualifiers="const"> <return type="bool" /> <argument index="0" name="locale" type="String" /> @@ -944,6 +954,21 @@ Returns [code]true[/code] if locale is right-to-left. </description> </method> + <method name="is_valid_identifier" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="string" type="String" /> + <description> + Returns [code]true[/code] is [code]string[/code] is a valid identifier. + If the text server supports the [constant FEATURE_UNICODE_IDENTIFIERS] feature, a valid identifier must: + - Conform to normalization form C. + - Begin with a Unicode character of class XID_Start or [code]"_"[/code]. + - May contain Unicode characters of class XID_Continue in the other positions. + - Use UAX #31 recommended scripts only (mixed scripts are allowed). + If the [constant FEATURE_UNICODE_IDENTIFIERS] feature is not supported, a valid identifier must: + - Begin with a Unicode character of class XID_Start or [code]"_"[/code]. + - May contain Unicode characters of class XID_Continue in the other positions. + </description> + </method> <method name="load_support_data"> <return type="bool" /> <argument index="0" name="filename" type="String" /> @@ -1077,7 +1102,7 @@ <return type="float" /> <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" /> - <argument index="2" name="jst_flags" type="int" default="3" /> + <argument index="2" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" /> <description> Adjusts text with to fit to specified width, returns new text width. </description> @@ -1184,7 +1209,7 @@ <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" /> <argument index="2" name="start" type="int" default="0" /> - <argument index="3" name="break_flags" type="int" default="96" /> + <argument index="3" name="break_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> <description> Breaks text to the lines and returns character ranges for each line. </description> @@ -1195,7 +1220,7 @@ <argument index="1" name="width" type="PackedFloat32Array" /> <argument index="2" name="start" type="int" default="0" /> <argument index="3" name="once" type="bool" default="true" /> - <argument index="4" name="break_flags" type="int" default="96" /> + <argument index="4" name="break_flags" type="int" enum="TextServer.LineBreakFlag" default="3" /> <description> Breaks text to the lines and columns. Returns character ranges for each segment. </description> @@ -1306,7 +1331,7 @@ <method name="shaped_text_get_word_breaks" qualifiers="const"> <return type="PackedInt32Array" /> <argument index="0" name="shaped" type="RID" /> - <argument index="1" name="grapheme_flags" type="int" default="264" /> + <argument index="1" name="grapheme_flags" type="int" enum="TextServer.GraphemeFlag" default="264" /> <description> Breaks text into words and returns array of character ranges. Use [code]grapheme_flags[/code] to set what characters are used for breaking (see [enum GraphemeFlag]). </description> @@ -1346,7 +1371,7 @@ <return type="void" /> <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" default="0" /> - <argument index="2" name="overrun_trim_flags" type="int" default="0" /> + <argument index="2" name="overrun_trim_flags" type="int" enum="TextServer.TextOverrunFlag" default="0" /> <description> Trims text if it exceeds the given width. </description> @@ -1461,6 +1486,14 @@ Aligns shaped text to the given tab-stops. </description> </method> + <method name="spoof_check" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="string" type="String" /> + <description> + Returns [code]true[/code] if [code]string[/code] is likely to be an attempt at confusing the reader. + [b]Note:[/b] Always returns [code]false[/code] if the server does not support the [constant FEATURE_UNICODE_SECURITY] feature. + </description> + </method> <method name="string_get_word_breaks" qualifiers="const"> <return type="PackedInt32Array" /> <argument index="0" name="string" type="String" /> @@ -1522,22 +1555,22 @@ Left to right text is written vertically from top to bottom. Right to left text is written vertically from bottom to top. </constant> - <constant name="JUSTIFICATION_NONE" value="0" enum="JustificationFlag"> + <constant name="JUSTIFICATION_NONE" value="0" enum="JustificationFlag" is_bitfield="true"> Do not justify text. </constant> - <constant name="JUSTIFICATION_KASHIDA" value="1" enum="JustificationFlag"> + <constant name="JUSTIFICATION_KASHIDA" value="1" enum="JustificationFlag" is_bitfield="true"> Justify text by adding and removing kashidas. </constant> - <constant name="JUSTIFICATION_WORD_BOUND" value="2" enum="JustificationFlag"> + <constant name="JUSTIFICATION_WORD_BOUND" value="2" enum="JustificationFlag" is_bitfield="true"> Justify text by changing width of the spaces between the words. </constant> - <constant name="JUSTIFICATION_TRIM_EDGE_SPACES" value="4" enum="JustificationFlag"> + <constant name="JUSTIFICATION_TRIM_EDGE_SPACES" value="4" enum="JustificationFlag" is_bitfield="true"> Remove trailing and leading spaces from the justified text. </constant> - <constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag"> + <constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag" is_bitfield="true"> Only apply justification to the part of the text after the last tab. </constant> - <constant name="JUSTIFICATION_CONSTRAIN_ELLIPSIS" value="16" enum="JustificationFlag"> + <constant name="JUSTIFICATION_CONSTRAIN_ELLIPSIS" value="16" enum="JustificationFlag" is_bitfield="true"> Apply justification to the trimmed line with ellipsis. </constant> <constant name="AUTOWRAP_OFF" value="0" enum="AutowrapMode"> @@ -1552,20 +1585,19 @@ <constant name="AUTOWRAP_WORD_SMART" value="3" enum="AutowrapMode"> Behaves similarly to [constant AUTOWRAP_WORD], but force-breaks a word if that single word does not fit in one line. </constant> - <constant name="BREAK_NONE" value="0" enum="LineBreakFlag"> + <constant name="BREAK_NONE" value="0" enum="LineBreakFlag" is_bitfield="true"> Do not break the line. </constant> - <constant name="BREAK_MANDATORY" value="32" enum="LineBreakFlag"> + <constant name="BREAK_MANDATORY" value="1" enum="LineBreakFlag" is_bitfield="true"> Break the line at the line mandatory break characters (e.g. [code]"\n"[/code]). </constant> - <constant name="BREAK_WORD_BOUND" value="64" enum="LineBreakFlag"> + <constant name="BREAK_WORD_BOUND" value="2" enum="LineBreakFlag" is_bitfield="true"> Break the line between the words. </constant> - <constant name="BREAK_GRAPHEME_BOUND" value="128" enum="LineBreakFlag"> + <constant name="BREAK_GRAPHEME_BOUND" value="4" enum="LineBreakFlag" is_bitfield="true"> Break the line between any unconnected graphemes. </constant> - <constant name="BREAK_WORD_BOUND_ADAPTIVE" value="320" enum="LineBreakFlag"> - Break the line between the words, or any unconnected graphemes if line is too short to fit the whole word. + <constant name="BREAK_ADAPTIVE" value="8" enum="LineBreakFlag" is_bitfield="true"> </constant> <constant name="VC_CHARS_BEFORE_SHAPING" value="0" enum="VisibleCharactersBehavior"> Trims text before the shaping. e.g, increasing [member Label.visible_characters] or [member RichTextLabel.visible_characters] value is visually identical to typing the text. @@ -1597,56 +1629,59 @@ <constant name="OVERRUN_TRIM_WORD_ELLIPSIS" value="4" enum="OverrunBehavior"> Trims the text per word and adds an ellipsis to indicate that parts are hidden. </constant> - <constant name="OVERRUN_NO_TRIM" value="0" enum="TextOverrunFlag"> + <constant name="OVERRUN_NO_TRIM" value="0" enum="TextOverrunFlag" is_bitfield="true"> No trimming is performed. </constant> - <constant name="OVERRUN_TRIM" value="1" enum="TextOverrunFlag"> + <constant name="OVERRUN_TRIM" value="1" enum="TextOverrunFlag" is_bitfield="true"> Trims the text when it exceeds the given width. </constant> - <constant name="OVERRUN_TRIM_WORD_ONLY" value="2" enum="TextOverrunFlag"> + <constant name="OVERRUN_TRIM_WORD_ONLY" value="2" enum="TextOverrunFlag" is_bitfield="true"> Trims the text per word instead of per grapheme. </constant> - <constant name="OVERRUN_ADD_ELLIPSIS" value="4" enum="TextOverrunFlag"> + <constant name="OVERRUN_ADD_ELLIPSIS" value="4" enum="TextOverrunFlag" is_bitfield="true"> Determines whether an ellipsis should be added at the end of the text. </constant> - <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag"> + <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag" is_bitfield="true"> Determines whether the ellipsis at the end of the text is enforced and may not be hidden. </constant> - <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag"> + <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true"> </constant> - <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true"> Grapheme is supported by the font, and can be drawn. </constant> - <constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag" is_bitfield="true"> Grapheme is part of right-to-left or bottom-to-top run. </constant> - <constant name="GRAPHEME_IS_VIRTUAL" value="4" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_VIRTUAL" value="4" enum="GraphemeFlag" is_bitfield="true"> Grapheme is not part of source text, it was added by justification process. </constant> - <constant name="GRAPHEME_IS_SPACE" value="8" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_SPACE" value="8" enum="GraphemeFlag" is_bitfield="true"> Grapheme is whitespace. </constant> - <constant name="GRAPHEME_IS_BREAK_HARD" value="16" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_BREAK_HARD" value="16" enum="GraphemeFlag" is_bitfield="true"> Grapheme is mandatory break point (e.g. [code]"\n"[/code]). </constant> - <constant name="GRAPHEME_IS_BREAK_SOFT" value="32" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_BREAK_SOFT" value="32" enum="GraphemeFlag" is_bitfield="true"> Grapheme is optional break point (e.g. space). </constant> - <constant name="GRAPHEME_IS_TAB" value="64" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_TAB" value="64" enum="GraphemeFlag" is_bitfield="true"> Grapheme is the tabulation character. </constant> - <constant name="GRAPHEME_IS_ELONGATION" value="128" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_ELONGATION" value="128" enum="GraphemeFlag" is_bitfield="true"> Grapheme is kashida. </constant> - <constant name="GRAPHEME_IS_PUNCTUATION" value="256" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_PUNCTUATION" value="256" enum="GraphemeFlag" is_bitfield="true"> Grapheme is punctuation character. </constant> - <constant name="GRAPHEME_IS_UNDERSCORE" value="512" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_UNDERSCORE" value="512" enum="GraphemeFlag" is_bitfield="true"> Grapheme is underscore character. </constant> - <constant name="GRAPHEME_IS_CONNECTED" value="1024" enum="GraphemeFlag"> + <constant name="GRAPHEME_IS_CONNECTED" value="1024" enum="GraphemeFlag" is_bitfield="true"> Grapheme is connected to the previous grapheme. Breaking line before this grapheme is not safe. </constant> + <constant name="GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL" value="2048" enum="GraphemeFlag" is_bitfield="true"> + It is safe to insert a U+0640 before this grapheme for elongation. + </constant> <constant name="HINTING_NONE" value="0" enum="Hinting"> Disables font hinting (smoother but less crisp). </constant> @@ -1714,7 +1749,13 @@ TextServer supports locale dependent and context sensitive case conversion. </constant> <constant name="FEATURE_USE_SUPPORT_DATA" value="4096" enum="Feature"> - TextServer require external data file for some features. + TextServer require external data file for some features, see [method load_support_data]. + </constant> + <constant name="FEATURE_UNICODE_IDENTIFIERS" value="8192" enum="Feature"> + TextServer supports UAX #31 identifier validation, see [method is_valid_identifier]. + </constant> + <constant name="FEATURE_UNICODE_SECURITY" value="16384" enum="Feature"> + TextServer supports [url=https://unicode.org/reports/tr36/]Unicode Technical Report #36[/url] and [url=https://unicode.org/reports/tr39/]Unicode Technical Standard #39[/url] based spoof detection features. </constant> <constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag"> Contour point is on the curve. @@ -1737,13 +1778,15 @@ <constant name="SPACING_BOTTOM" value="3" enum="SpacingType"> Spacing at the bottom of the line. </constant> - <constant name="FONT_BOLD" value="1" enum="FontStyle"> + <constant name="SPACING_MAX" value="4" enum="SpacingType"> + </constant> + <constant name="FONT_BOLD" value="1" enum="FontStyle" is_bitfield="true"> Font is bold. </constant> - <constant name="FONT_ITALIC" value="2" enum="FontStyle"> + <constant name="FONT_ITALIC" value="2" enum="FontStyle" is_bitfield="true"> Font is italic or oblique. </constant> - <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle"> + <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle" is_bitfield="true"> Font have fixed-width characters. </constant> <constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser"> diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 2f7b31b663..c686a06e5e 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -346,7 +346,7 @@ </description> </method> <method name="font_get_style" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="TextServer.FontStyle" /> <argument index="0" name="font_rid" type="RID" /> <description> Returns font style flags, see [enum TextServer.FontStyle]. @@ -782,7 +782,7 @@ <method name="font_set_style" qualifiers="virtual"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> - <argument index="1" name="style" type="int" /> + <argument index="1" name="style" type="int" enum="TextServer.FontStyle" /> <description> Sets the font style flags, see [enum TextServer.FontStyle]. </description> @@ -934,6 +934,14 @@ Returns [code]true[/code] if the server supports a feature. </description> </method> + <method name="is_confusable" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="string" type="String" /> + <argument index="1" name="dict" type="PackedStringArray" /> + <description> + Returns index of the first string in [code]dict[/dict] which is visually confusable with the [code]string[/string], or [code]-1[/code] if none is found. + </description> + </method> <method name="is_locale_right_to_left" qualifiers="virtual const"> <return type="bool" /> <argument index="0" name="locale" type="String" /> @@ -941,6 +949,13 @@ Returns [code]true[/code] if locale is right-to-left. </description> </method> + <method name="is_valid_identifier" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="string" type="String" /> + <description> + Returns [code]true[/code] is [code]string[/code] is a valid identifier. + </description> + </method> <method name="load_support_data" qualifiers="virtual"> <return type="bool" /> <argument index="0" name="filename" type="String" /> @@ -1074,7 +1089,7 @@ <return type="float" /> <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" /> - <argument index="2" name="jst_flags" type="int" /> + <argument index="2" name="jst_flags" type="int" enum="TextServer.JustificationFlag" /> <description> Adjusts text with to fit to specified width, returns new text width. </description> @@ -1183,7 +1198,7 @@ <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" /> <argument index="2" name="start" type="int" /> - <argument index="3" name="break_flags" type="int" /> + <argument index="3" name="break_flags" type="int" enum="TextServer.LineBreakFlag" /> <description> Breaks text to the lines and returns character ranges for each line. [b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used. @@ -1195,7 +1210,7 @@ <argument index="1" name="width" type="PackedFloat32Array" /> <argument index="2" name="start" type="int" /> <argument index="3" name="once" type="bool" /> - <argument index="4" name="break_flags" type="int" /> + <argument index="4" name="break_flags" type="int" enum="TextServer.LineBreakFlag" /> <description> Breaks text to the lines and columns. Returns character ranges for each segment. [b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used. @@ -1308,7 +1323,7 @@ <method name="shaped_text_get_word_breaks" qualifiers="virtual const"> <return type="PackedInt32Array" /> <argument index="0" name="shaped" type="RID" /> - <argument index="1" name="grapheme_flags" type="int" /> + <argument index="1" name="grapheme_flags" type="int" enum="TextServer.GraphemeFlag" /> <description> Breaks text into words and returns array of character ranges. [b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used. @@ -1352,7 +1367,7 @@ <return type="void" /> <argument index="0" name="shaped" type="RID" /> <argument index="1" name="width" type="float" /> - <argument index="2" name="trim_flags" type="int" /> + <argument index="2" name="trim_flags" type="int" enum="TextServer.TextOverrunFlag" /> <description> Trims text if it exceeds the given width. </description> @@ -1481,6 +1496,13 @@ [b]Note:[/b] This method is used by default line/word breaking methods, and its implementation might be omitted if custom line breaking in implemented. </description> </method> + <method name="spoof_check" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="string" type="String" /> + <description> + Returns [code]true[/code] if [code]string[/code] is likely to be an attempt at confusing the reader. + </description> + </method> <method name="string_get_word_breaks" qualifiers="virtual const"> <return type="PackedInt32Array" /> <argument index="0" name="string" type="String" /> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 10ccad973f..180e868ef8 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -117,6 +117,27 @@ If the TileSet has no proxy for the given identifiers, returns an empty Array. </description> </method> + <method name="get_custom_data_layer_by_name" qualifiers="const"> + <return type="int" /> + <argument index="0" name="layer_name" type="String" /> + <description> + Returns the index of the custom data layer identified by the given name. + </description> + </method> + <method name="get_custom_data_layer_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="layer_index" type="int" /> + <description> + Returns the name of the custom data layer identified by the given index. + </description> + </method> + <method name="get_custom_data_layer_type" qualifiers="const"> + <return type="int" enum="Variant.Type" /> + <argument index="0" name="layer_index" type="int" /> + <description> + Returns the type of the custom data layer identified by the given index. + </description> + </method> <method name="get_custom_data_layers_count" qualifiers="const"> <return type="int" /> <description> @@ -464,6 +485,22 @@ Proxied tiles can be automatically replaced in TileMap nodes using the editor. </description> </method> + <method name="set_custom_data_layer_name"> + <return type="void" /> + <argument index="0" name="layer_index" type="int" /> + <argument index="1" name="layer_name" type="String" /> + <description> + Sets the name of the custom data layer identified by the given index. Names are identifiers of the layer therefore if the name is already taken it will fail and raise an error. + </description> + </method> + <method name="set_custom_data_layer_type"> + <return type="void" /> + <argument index="0" name="layer_index" type="int" /> + <argument index="1" name="layer_type" type="int" enum="Variant.Type" /> + <description> + Sets the type of the custom data layer identified by the given index. + </description> + </method> <method name="set_navigation_layer_layers"> <return type="void" /> <argument index="0" name="layer_index" type="int" /> @@ -591,7 +628,7 @@ Tile coordinates layout where both axis stay consistent with their respective local horizontal and vertical axis. </constant> <constant name="TILE_LAYOUT_STACKED_OFFSET" value="1" enum="TileLayout"> - Same as [code]TILE_LAYOUT_STAKED[/code], but the first half-offset is negative instead of positive. + Same as [constant TILE_LAYOUT_STACKED], but the first half-offset is negative instead of positive. </constant> <constant name="TILE_LAYOUT_STAIRS_RIGHT" value="2" enum="TileLayout"> Tile coordinates layout where the horizontal axis stay horizontal, and the vertical one goes down-right. diff --git a/doc/classes/TorusMesh.xml b/doc/classes/TorusMesh.xml new file mode 100644 index 0000000000..6b83152793 --- /dev/null +++ b/doc/classes/TorusMesh.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TorusMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Class representing a torus [PrimitiveMesh]. + </brief_description> + <description> + Class representing a torus [PrimitiveMesh]. + </description> + <tutorials> + </tutorials> + <members> + <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="0.5"> + The inner radius of the torus. + </member> + <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="1.0"> + The outer radius of the torus. + </member> + <member name="ring_segments" type="int" setter="set_ring_segments" getter="get_ring_segments" default="32"> + The number of edges each ring of the torus is constructed of. + </member> + <member name="rings" type="int" setter="set_rings" getter="get_rings" default="64"> + The number of slices the torus is constructed of. + </member> + </members> +</class> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index e1f7ff21d0..9979a73527 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -141,14 +141,40 @@ <return type="Transform2D" /> <argument index="0" name="angle" type="float" /> <description> - Returns a copy of the transform rotated by the given [code]angle[/code] (in radians), using matrix multiplication. + Returns a copy of the transform rotated by the given [code]angle[/code] (in radians). + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding rotation transform [code]R[/code] from the left, i.e., [code]R * X[/code]. + This can be seen as transforming with respect to the global/parent frame. + </description> + </method> + <method name="rotated_local" qualifiers="const"> + <return type="Transform2D" /> + <argument index="0" name="angle" type="float" /> + <description> + Returns a copy of the transform rotated by the given [code]angle[/code] (in radians). + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding rotation transform [code]R[/code] from the right, i.e., [code]X * R[/code]. + This can be seen as transforming with respect to the local frame. </description> </method> <method name="scaled" qualifiers="const"> <return type="Transform2D" /> <argument index="0" name="scale" type="Vector2" /> <description> - Returns a copy of the transform scaled by the given [code]scale[/code] factor, using matrix multiplication. + Returns a copy of the transform scaled by the given [code]scale[/code] factor. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding scaling transform [code]S[/code] from the left, i.e., [code]S * X[/code]. + This can be seen as transforming with respect to the global/parent frame. + </description> + </method> + <method name="scaled_local" qualifiers="const"> + <return type="Transform2D" /> + <argument index="0" name="scale" type="Vector2" /> + <description> + Returns a copy of the transform scaled by the given [code]scale[/code] factor. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding scaling transform [code]S[/code] from the right, i.e., [code]X * S[/code]. + This can be seen as transforming with respect to the local frame. </description> </method> <method name="set_rotation"> @@ -177,8 +203,20 @@ <return type="Transform2D" /> <argument index="0" name="offset" type="Vector2" /> <description> - Returns a copy of the transform translated by the given [code]offset[/code], relative to the transform's basis vectors. - Unlike [method rotated] and [method scaled], this does not use matrix multiplication. + Returns a copy of the transform translated by the given [code]offset[/code]. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding translation transform [code]T[/code] from the left, i.e., [code]T * X[/code]. + This can be seen as transforming with respect to the global/parent frame. + </description> + </method> + <method name="translated_local" qualifiers="const"> + <return type="Transform2D" /> + <argument index="0" name="offset" type="Vector2" /> + <description> + Returns a copy of the transform translated by the given [code]offset[/code]. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding translation transform [code]T[/code] from the right, i.e., [code]X * T[/code]. + This can be seen as transforming with respect to the local frame. </description> </method> </methods> diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index afd11b6c77..cefc74867c 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -39,6 +39,12 @@ </constructor> <constructor name="Transform3D"> <return type="Transform3D" /> + <argument index="0" name="from" type="Projection" /> + <description> + </description> + </constructor> + <constructor name="Transform3D"> + <return type="Transform3D" /> <argument index="0" name="x_axis" type="Vector3" /> <argument index="1" name="y_axis" type="Vector3" /> <argument index="2" name="z_axis" type="Vector3" /> @@ -96,17 +102,46 @@ <argument index="0" name="axis" type="Vector3" /> <argument index="1" name="angle" type="float" /> <description> - Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians), using matrix multiplication. The [code]axis[/code] must be a normalized vector. + Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians). + The [code]axis[/code] must be a normalized vector. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding rotation transform [code]R[/code] from the left, i.e., [code]R * X[/code]. + This can be seen as transforming with respect to the global/parent frame. + </description> + </method> + <method name="rotated_local" qualifiers="const"> + <return type="Transform3D" /> + <argument index="0" name="axis" type="Vector3" /> + <argument index="1" name="angle" type="float" /> + <description> + Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians). + The [code]axis[/code] must be a normalized vector. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding rotation transform [code]R[/code] from the right, i.e., [code]X * R[/code]. + This can be seen as transforming with respect to the local frame. </description> </method> <method name="scaled" qualifiers="const"> <return type="Transform3D" /> <argument index="0" name="scale" type="Vector3" /> <description> - Returns a copy of the transform with its basis and origin scaled by the given [code]scale[/code] factor, using matrix multiplication. + Returns a copy of the transform scaled by the given [code]scale[/code] factor. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding scaling transform [code]S[/code] from the left, i.e., [code]S * X[/code]. + This can be seen as transforming with respect to the global/parent frame. </description> </method> - <method name="sphere_interpolate_with" qualifiers="const"> + <method name="scaled_local" qualifiers="const"> + <return type="Transform3D" /> + <argument index="0" name="scale" type="Vector3" /> + <description> + Returns a copy of the transform scaled by the given [code]scale[/code] factor. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding scaling transform [code]S[/code] from the right, i.e., [code]X * S[/code]. + This can be seen as transforming with respect to the local frame. + </description> + </method> + <method name="spherical_interpolate_with" qualifiers="const"> <return type="Transform3D" /> <argument index="0" name="xform" type="Transform3D" /> <argument index="1" name="weight" type="float" /> @@ -118,8 +153,20 @@ <return type="Transform3D" /> <argument index="0" name="offset" type="Vector3" /> <description> - Returns a copy of the transform translated by the given [code]offset[/code], relative to the transform's basis vectors. - Unlike [method rotated] and [method scaled], this does not use matrix multiplication. + Returns a copy of the transform translated by the given [code]offset[/code]. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding translation transform [code]T[/code] from the left, i.e., [code]T * X[/code]. + This can be seen as transforming with respect to the global/parent frame. + </description> + </method> + <method name="translated_local" qualifiers="const"> + <return type="Transform3D" /> + <argument index="0" name="offset" type="Vector3" /> + <description> + Returns a copy of the transform translated by the given [code]offset[/code]. + This method is an optimized version of multiplying the given transform [code]X[/code] + with a corresponding translation transform [code]T[/code] from the right, i.e., [code]X * T[/code]. + This can be seen as transforming with respect to the local frame. </description> </method> </methods> @@ -169,6 +216,13 @@ </description> </operator> <operator name="operator *"> + <return type="Plane" /> + <argument index="0" name="right" type="Plane" /> + <description> + Transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix. + </description> + </operator> + <operator name="operator *"> <return type="Transform3D" /> <argument index="0" name="right" type="Transform3D" /> <description> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index b06be0cf99..f326948e9c 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -461,7 +461,7 @@ <theme_item name="custom_button_font_highlight" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's hovered. </theme_item> - <theme_item name="drop_position_color" data_type="color" type="Color" default="Color(1, 0.3, 0.2, 1)"> + <theme_item name="drop_position_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> [Color] used to draw possible drop locations. See [enum DropModeFlags] constants for further description of drop locations. </theme_item> <theme_item name="font_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> diff --git a/doc/classes/Vector4.xml b/doc/classes/Vector4.xml new file mode 100644 index 0000000000..ee9d97019e --- /dev/null +++ b/doc/classes/Vector4.xml @@ -0,0 +1,377 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="Vector4" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Vector used for 4D math using floating point coordinates. + </brief_description> + <description> + 4-element structure that can be used to represent any quadruplet of numeric values. + It uses floating-point coordinates. See [Vector4i] for its integer counterpart. + [b]Note:[/b] In a boolean context, a Vector4 will evaluate to [code]false[/code] if it's equal to [code]Vector4(0, 0, 0, 0)[/code]. Otherwise, a Vector4 will always evaluate to [code]true[/code]. + </description> + <tutorials> + </tutorials> + <constructors> + <constructor name="Vector4"> + <return type="Vector4" /> + <description> + Constructs a default-initialized [Vector4] with all components set to [code]0[/code]. + </description> + </constructor> + <constructor name="Vector4"> + <return type="Vector4" /> + <argument index="0" name="from" type="Vector4" /> + <description> + Constructs a [Vector4] as a copy of the given [Vector4]. + </description> + </constructor> + <constructor name="Vector4"> + <return type="Vector4" /> + <argument index="0" name="from" type="Vector4i" /> + <description> + Constructs a new [Vector4] from [Vector4i]. + </description> + </constructor> + <constructor name="Vector4"> + <return type="Vector4" /> + <argument index="0" name="x" type="float" /> + <argument index="1" name="y" type="float" /> + <argument index="2" name="z" type="float" /> + <argument index="3" name="w" type="float" /> + <description> + Returns a [Vector4] with the given components. + </description> + </constructor> + </constructors> + <methods> + <method name="abs" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns a new vector with all components in absolute values (i.e. positive). + </description> + </method> + <method name="ceil" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns a new vector with all components rounded up (towards positive infinity). + </description> + </method> + <method name="clamp" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="min" type="Vector4" /> + <argument index="1" name="max" type="Vector4" /> + <description> + Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. + </description> + </method> + <method name="cubic_interpolate" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="b" type="Vector4" /> + <argument index="1" name="pre_a" type="Vector4" /> + <argument index="2" name="post_b" type="Vector4" /> + <argument index="3" name="weight" type="float" /> + <description> + Performs a cubic interpolation between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + </description> + </method> + <method name="direction_to" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="to" type="Vector4" /> + <description> + Returns the normalized vector pointing from this vector to [code]to[/code]. This is equivalent to using [code](b - a).normalized()[/code]. + </description> + </method> + <method name="distance_to" qualifiers="const"> + <return type="float" /> + <argument index="0" name="to" type="Vector4" /> + <description> + Returns the distance between this vector and [code]to[/code]. + </description> + </method> + <method name="dot" qualifiers="const"> + <return type="float" /> + <argument index="0" name="with" type="Vector4" /> + <description> + Returns the dot product of this vector and [code]with[/code]. + </description> + </method> + <method name="floor" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns a new vector with all components rounded down (towards negative infinity). + </description> + </method> + <method name="inverse" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns the inverse of the vector. This is the same as [code]Vector4(1.0 / v.x, 1.0 / v.y, 1.0 / v.z, 1.0 / v.w)[/code]. + </description> + </method> + <method name="is_equal_approx" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="with" type="Vector4" /> + <description> + Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. + </description> + </method> + <method name="is_normalized" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the vector is normalized, i.e. its length is equal to 1. + </description> + </method> + <method name="length" qualifiers="const"> + <return type="float" /> + <description> + Returns the length (magnitude) of this vector. + </description> + </method> + <method name="length_squared" qualifiers="const"> + <return type="float" /> + <description> + Returns the squared length (squared magnitude) of this vector. This method runs faster than [method length]. + </description> + </method> + <method name="lerp" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="to" type="Vector4" /> + <argument index="1" name="weight" type="float" /> + <description> + Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of [code]0.0[/code] to [code]1.0[/code], representing the amount of interpolation. + </description> + </method> + <method name="max_axis_index" qualifiers="const"> + <return type="int" /> + <description> + Returns the axis of the vector's highest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X]. + </description> + </method> + <method name="min_axis_index" qualifiers="const"> + <return type="int" /> + <description> + Returns the axis of the vector's lowest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_W]. + </description> + </method> + <method name="normalized" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code]. + </description> + </method> + <method name="posmod" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="mod" type="float" /> + <description> + Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]mod[/code]. + </description> + </method> + <method name="posmodv" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="modv" type="Vector4" /> + <description> + Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]modv[/code]'s components. + </description> + </method> + <method name="round" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns a new vector with all components rounded to the nearest integer, with halfway cases rounded away from zero. + </description> + </method> + <method name="sign" qualifiers="const"> + <return type="Vector4" /> + <description> + Returns a new vector with each component set to one or negative one, depending on the signs of the components, or zero if the component is zero, by calling [method @GlobalScope.sign] on each component. + </description> + </method> + <method name="snapped" qualifiers="const"> + <return type="Vector4" /> + <argument index="0" name="step" type="Vector4" /> + <description> + Returns this vector with each component snapped to the nearest multiple of [code]step[/code]. This can also be used to round to an arbitrary number of decimals. + </description> + </method> + </methods> + <members> + <member name="w" type="float" setter="" getter="" default="0.0"> + The vector's W component. Also accessible by using the index position [code][3][/code]. + </member> + <member name="x" type="float" setter="" getter="" default="0.0"> + The vector's X component. Also accessible by using the index position [code][0][/code]. + </member> + <member name="y" type="float" setter="" getter="" default="0.0"> + The vector's Y component. Also accessible by using the index position [code][1][/code]. + </member> + <member name="z" type="float" setter="" getter="" default="0.0"> + The vector's Z component. Also accessible by using the index position [code][2][/code]. + </member> + </members> + <constants> + <constant name="AXIS_X" value="0"> + Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. + </constant> + <constant name="AXIS_Y" value="1"> + Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. + </constant> + <constant name="AXIS_Z" value="2"> + Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. + </constant> + <constant name="AXIS_W" value="3"> + Enumerated value for the W axis. Returned by [method max_axis_index] and [method min_axis_index]. + </constant> + <constant name="ZERO" value="Vector4(0, 0, 0, 0)"> + Zero vector, a vector with all components set to [code]0[/code]. + </constant> + <constant name="ONE" value="Vector4(1, 1, 1, 1)"> + One vector, a vector with all components set to [code]1[/code]. + </constant> + <constant name="INF" value="Vector4(inf, inf, inf, inf)"> + Infinity vector, a vector with all components set to [constant @GDScript.INF]. + </constant> + </constants> + <operators> + <operator name="operator !="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Returns [code]true[/code] if the vectors are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Projection" /> + <description> + Inversely transforms (multiplies) the [Vector4] by the given [Projection] matrix. + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Multiplies each component of the [Vector4] by the components of the given [Vector4]. + [codeblock] + print(Vector4(10, 20, 30, 40) * Vector4(3, 4, 5, 6)) # Prints "(30, 80, 150, 240)" + [/codeblock] + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="float" /> + <description> + Multiplies each component of the [Vector4] by the given [float]. + [codeblock] + print(Vector4(10, 20, 30, 40) * 2) # Prints "(20, 40, 60, 80)" + [/codeblock] + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="int" /> + <description> + Multiplies each component of the [Vector4] by the given [int]. + </description> + </operator> + <operator name="operator +"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Adds each component of the [Vector4] by the components of the given [Vector4]. + [codeblock] + print(Vector4(10, 20, 30, 40) + Vector4(3, 4, 5, 6)) # Prints "(13, 24, 35, 46)" + [/codeblock] + </description> + </operator> + <operator name="operator -"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Subtracts each component of the [Vector4] by the components of the given [Vector4]. + [codeblock] + print(Vector4(10, 20, 30, 40) - Vector4(3, 4, 5, 6)) # Prints "(7, 16, 25, 34)" + [/codeblock] + </description> + </operator> + <operator name="operator /"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Divides each component of the [Vector4] by the components of the given [Vector4]. + [codeblock] + print(Vector4(10, 20, 30, 40) / Vector4(2, 5, 3, 4)) # Prints "(5, 4, 10, 10)" + [/codeblock] + </description> + </operator> + <operator name="operator /"> + <return type="Vector4" /> + <argument index="0" name="right" type="float" /> + <description> + Divides each component of the [Vector4] by the given [float]. + [codeblock] + print(Vector4(10, 20, 30, 40) / 2 # Prints "(5, 10, 15, 20)" + [/codeblock] + </description> + </operator> + <operator name="operator /"> + <return type="Vector4" /> + <argument index="0" name="right" type="int" /> + <description> + Divides each component of the [Vector4] by the given [int]. + </description> + </operator> + <operator name="operator <"> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Compares two [Vector4] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. + </description> + </operator> + <operator name="operator <="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Compares two [Vector4] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. + </description> + </operator> + <operator name="operator =="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Returns [code]true[/code] if the vectors are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. + </description> + </operator> + <operator name="operator >"> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Compares two [Vector4] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. + </description> + </operator> + <operator name="operator >="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4" /> + <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], and [code]v[2][/code] is equivalent to [code]v.z[/code]. + </description> + </operator> + <operator name="operator []"> + <return type="float" /> + <argument index="0" name="index" type="int" /> + <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], [code]v[2][/code] is equivalent to [code]v.z[/code], and [code]v[3][/code] is equivalent to [code]v.w[/code]. + </description> + </operator> + <operator name="operator unary+"> + <return type="Vector4" /> + <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. + </description> + </operator> + <operator name="operator unary-"> + <return type="Vector4" /> + <description> + Returns the negative value of the [Vector4]. This is the same as writing [code]Vector4(-v.x, -v.y, -v.z, -v.w)[/code]. This operation flips the direction of the vector while keeping the same magnitude. With floats, the number zero can be either positive or negative. + </description> + </operator> + </operators> +</class> diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml new file mode 100644 index 0000000000..6acce12e9f --- /dev/null +++ b/doc/classes/Vector4i.xml @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="Vector4i" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <constructors> + <constructor name="Vector4i"> + <return type="Vector4i" /> + <description> + </description> + </constructor> + <constructor name="Vector4i"> + <return type="Vector4i" /> + <argument index="0" name="from" type="Vector4i" /> + <description> + </description> + </constructor> + <constructor name="Vector4i"> + <return type="Vector4i" /> + <argument index="0" name="from" type="Vector4" /> + <description> + </description> + </constructor> + <constructor name="Vector4i"> + <return type="Vector4i" /> + <argument index="0" name="x" type="int" /> + <argument index="1" name="y" type="int" /> + <argument index="2" name="z" type="int" /> + <argument index="3" name="w" type="int" /> + <description> + </description> + </constructor> + </constructors> + <methods> + <method name="abs" qualifiers="const"> + <return type="Vector4i" /> + <description> + </description> + </method> + <method name="clamp" qualifiers="const"> + <return type="Vector4i" /> + <argument index="0" name="min" type="Vector4i" /> + <argument index="1" name="max" type="Vector4i" /> + <description> + </description> + </method> + <method name="length" qualifiers="const"> + <return type="float" /> + <description> + </description> + </method> + <method name="length_squared" qualifiers="const"> + <return type="int" /> + <description> + </description> + </method> + <method name="max_axis_index" qualifiers="const"> + <return type="int" /> + <description> + </description> + </method> + <method name="min_axis_index" qualifiers="const"> + <return type="int" /> + <description> + </description> + </method> + <method name="sign" qualifiers="const"> + <return type="Vector4i" /> + <description> + </description> + </method> + </methods> + <members> + <member name="w" type="int" setter="" getter="" default="0"> + </member> + <member name="x" type="int" setter="" getter="" default="0"> + </member> + <member name="y" type="int" setter="" getter="" default="0"> + </member> + <member name="z" type="int" setter="" getter="" default="0"> + </member> + </members> + <constants> + <constant name="AXIS_X" value="0"> + </constant> + <constant name="AXIS_Y" value="1"> + </constant> + <constant name="AXIS_Z" value="2"> + </constant> + <constant name="AXIS_W" value="3"> + </constant> + <constant name="ZERO" value="Vector4i(0, 0, 0, 0)"> + </constant> + <constant name="ONE" value="Vector4i(1, 1, 1, 1)"> + </constant> + </constants> + <operators> + <operator name="operator !="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator %"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator %"> + <return type="Vector4i" /> + <argument index="0" name="right" type="int" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="float" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4i" /> + <argument index="0" name="right" type="int" /> + <description> + </description> + </operator> + <operator name="operator +"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator -"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator /"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator /"> + <return type="Vector4" /> + <argument index="0" name="right" type="float" /> + <description> + </description> + </operator> + <operator name="operator /"> + <return type="Vector4i" /> + <argument index="0" name="right" type="int" /> + <description> + </description> + </operator> + <operator name="operator <"> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator <="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator =="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator >"> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator >="> + <return type="bool" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator []"> + <return type="int" /> + <argument index="0" name="index" type="int" /> + <description> + </description> + </operator> + <operator name="operator unary+"> + <return type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator unary-"> + <return type="Vector4i" /> + <description> + </description> + </operator> + </operators> +</class> diff --git a/doc/classes/VehicleBody3D.xml b/doc/classes/VehicleBody3D.xml index 330a405d5f..08309a8ecc 100644 --- a/doc/classes/VehicleBody3D.xml +++ b/doc/classes/VehicleBody3D.xml @@ -16,7 +16,7 @@ Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the vehicle by applying an engine force. The vehicle is only speed up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the vehicle reversing. </member> diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml index 1c164d7c9a..ac126f824e 100644 --- a/doc/classes/VehicleWheel3D.xml +++ b/doc/classes/VehicleWheel3D.xml @@ -48,7 +48,7 @@ The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the wheel by applying an engine force. The wheel is only speed up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the wheel reversing. </member> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 4727bc389e..0808a8f1cf 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -57,6 +57,13 @@ Returns the mouse's position in this [Viewport] using the coordinate system of this [Viewport]. </description> </method> + <method name="get_positional_shadow_atlas_quadrant_subdiv" qualifiers="const"> + <return type="int" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" /> + <argument index="0" name="quadrant" type="int" /> + <description> + Returns the [enum PositionalShadowAtlasQuadrantSubdiv] of the specified quadrant. + </description> + </method> <method name="get_render_info"> <return type="int" /> <argument index="0" name="type" type="int" enum="Viewport.RenderInfoType" /> @@ -64,13 +71,6 @@ <description> </description> </method> - <method name="get_shadow_atlas_quadrant_subdiv" qualifiers="const"> - <return type="int" enum="Viewport.ShadowAtlasQuadrantSubdiv" /> - <argument index="0" name="quadrant" type="int" /> - <description> - Returns the [enum ShadowAtlasQuadrantSubdiv] of the specified quadrant. - </description> - </method> <method name="get_texture" qualifiers="const"> <return type="ViewportTexture" /> <description> @@ -158,10 +158,10 @@ Stops the input from propagating further down the [SceneTree]. </description> </method> - <method name="set_shadow_atlas_quadrant_subdiv"> + <method name="set_positional_shadow_atlas_quadrant_subdiv"> <return type="void" /> <argument index="0" name="quadrant" type="int" /> - <argument index="1" name="subdiv" type="int" enum="Viewport.ShadowAtlasQuadrantSubdiv" /> + <argument index="1" name="subdiv" type="int" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" /> <description> Sets the number of subdivisions to use in the specified quadrant. A higher number of subdivisions allows you to have more shadows in the scene at once, but reduces the quality of the shadows. A good practice is to have quadrants with a varying number of subdivisions and to have as few subdivisions as possible. </description> @@ -196,10 +196,6 @@ <member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled" default="false"> Disable 3D rendering (but keep 2D rendering). </member> - <member name="fsr_mipmap_bias" type="float" setter="set_fsr_mipmap_bias" getter="get_fsr_mipmap_bias" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap when using FSR. Mipmap bias does nothing when FSR is not being used. Negative values make textures sharper, while positive values make textures blurrier. This value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. This updates the rendering server's mipmap bias when called - To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_mipmap_bias] project setting. - </member> <member name="fsr_sharpness" type="float" setter="set_fsr_sharpness" getter="get_fsr_sharpness" default="0.2"> Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference. To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_sharpness] project setting. @@ -232,6 +228,24 @@ <member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking" default="false"> If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process. </member> + <member name="positional_shadow_atlas_16_bits" type="bool" setter="set_positional_shadow_atlas_16_bits" getter="get_positional_shadow_atlas_16_bits" default="true"> + </member> + <member name="positional_shadow_atlas_quad_0" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="2"> + The subdivision amount of the first quadrant on the shadow atlas. + </member> + <member name="positional_shadow_atlas_quad_1" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="2"> + The subdivision amount of the second quadrant on the shadow atlas. + </member> + <member name="positional_shadow_atlas_quad_2" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="3"> + The subdivision amount of the third quadrant on the shadow atlas. + </member> + <member name="positional_shadow_atlas_quad_3" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="4"> + The subdivision amount of the fourth quadrant on the shadow atlas. + </member> + <member name="positional_shadow_atlas_size" type="int" setter="set_positional_shadow_atlas_size" getter="get_positional_shadow_atlas_size" default="2048"> + The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2. + [b]Note:[/b] If this is set to [code]0[/code], no shadows will be visible at all (including directional shadows). + </member> <member name="scaling_3d_mode" type="int" setter="set_scaling_3d_mode" getter="get_scaling_3d_mode" enum="Viewport.Scaling3DMode" default="0"> Sets scaling 3d mode. Bilinear scaling renders at different resolution to either undersample or supersample the viewport. FidelityFX Super Resolution 1.0, abbreviated to FSR, is an upscaling technology that produces high quality images at fast framerates by using a spatially aware upscaling algorithm. FSR is slightly more expensive than bilinear, but it produces significantly higher image quality. FSR should be used where possible. To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/mode] project setting. @@ -248,28 +262,15 @@ </member> <member name="sdf_scale" type="int" setter="set_sdf_scale" getter="get_sdf_scale" enum="Viewport.SDFScale" default="1"> </member> - <member name="shadow_atlas_16_bits" type="bool" setter="set_shadow_atlas_16_bits" getter="get_shadow_atlas_16_bits" default="true"> - </member> - <member name="shadow_atlas_quad_0" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2"> - The subdivision amount of the first quadrant on the shadow atlas. - </member> - <member name="shadow_atlas_quad_1" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2"> - The subdivision amount of the second quadrant on the shadow atlas. - </member> - <member name="shadow_atlas_quad_2" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="3"> - The subdivision amount of the third quadrant on the shadow atlas. - </member> - <member name="shadow_atlas_quad_3" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="4"> - The subdivision amount of the fourth quadrant on the shadow atlas. - </member> - <member name="shadow_atlas_size" type="int" setter="set_shadow_atlas_size" getter="get_shadow_atlas_size" default="2048"> - The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2. - [b]Note:[/b] If this is set to 0, shadows won't be visible. - </member> <member name="snap_2d_transforms_to_pixel" type="bool" setter="set_snap_2d_transforms_to_pixel" getter="is_snap_2d_transforms_to_pixel_enabled" default="false"> </member> <member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false"> </member> + <member name="texture_mipmap_bias" type="float" setter="set_texture_mipmap_bias" getter="get_texture_mipmap_bias" default="0.0"> + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. + To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting. + </member> <member name="transparent_bg" type="bool" setter="set_transparent_background" getter="has_transparent_background" default="false"> If [code]true[/code], the viewport should render its background as transparent. </member> @@ -286,6 +287,12 @@ <member name="use_xr" type="bool" setter="set_use_xr" getter="is_using_xr" default="false"> If [code]true[/code], the viewport will use the primary XR interface to render XR output. When applicable this can result in a stereoscopic image and the resulting render being output to a headset. </member> + <member name="vrs_mode" type="int" setter="set_vrs_mode" getter="get_vrs_mode" enum="Viewport.VRSMode" default="0"> + The Variable Rate Shading (VRS) mode that is used for this viewport. Note, if hardware does not support VRS this property is ignored. + </member> + <member name="vrs_texture" type="Texture2D" setter="set_vrs_texture" getter="get_vrs_texture"> + Texture to use when [member vrs_mode] is set to [constant Viewport.VRS_TEXTURE]. + </member> <member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d"> The custom [World2D] which can be used as 2D environment source. </member> @@ -307,29 +314,29 @@ </signal> </signals> <constants> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="ShadowAtlasQuadrantSubdiv"> + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="PositionalShadowAtlasQuadrantSubdiv"> This quadrant will not be used. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1" value="1" enum="ShadowAtlasQuadrantSubdiv"> + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1" value="1" enum="PositionalShadowAtlasQuadrantSubdiv"> This quadrant will only be used by one shadow map. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_4" value="2" enum="ShadowAtlasQuadrantSubdiv"> + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_4" value="2" enum="PositionalShadowAtlasQuadrantSubdiv"> This quadrant will be split in 4 and used by up to 4 shadow maps. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_16" value="3" enum="ShadowAtlasQuadrantSubdiv"> + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_16" value="3" enum="PositionalShadowAtlasQuadrantSubdiv"> This quadrant will be split 16 ways and used by up to 16 shadow maps. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_64" value="4" enum="ShadowAtlasQuadrantSubdiv"> + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_64" value="4" enum="PositionalShadowAtlasQuadrantSubdiv"> This quadrant will be split 64 ways and used by up to 64 shadow maps. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_256" value="5" enum="ShadowAtlasQuadrantSubdiv"> - This quadrant will be split 256 ways and used by up to 256 shadow maps. Unless the [member shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution. + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_256" value="5" enum="PositionalShadowAtlasQuadrantSubdiv"> + This quadrant will be split 256 ways and used by up to 256 shadow maps. Unless the [member positional_shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1024" value="6" enum="ShadowAtlasQuadrantSubdiv"> - This quadrant will be split 1024 ways and used by up to 1024 shadow maps. Unless the [member shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution. + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1024" value="6" enum="PositionalShadowAtlasQuadrantSubdiv"> + This quadrant will be split 1024 ways and used by up to 1024 shadow maps. Unless the [member positional_shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution. </constant> - <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_MAX" value="7" enum="ShadowAtlasQuadrantSubdiv"> - Represents the size of the [enum ShadowAtlasQuadrantSubdiv] enum. + <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_MAX" value="7" enum="PositionalShadowAtlasQuadrantSubdiv"> + Represents the size of the [enum PositionalShadowAtlasQuadrantSubdiv] enum. </constant> <constant name="SCALING_3D_MODE_BILINEAR" value="0" enum="Scaling3DMode"> Use bilinear scaling for the viewport's 3D buffer. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling. @@ -492,5 +499,17 @@ </constant> <constant name="SDF_SCALE_MAX" value="3" enum="SDFScale"> </constant> + <constant name="VRS_DISABLED" value="0" enum="VRSMode"> + VRS is disabled. + </constant> + <constant name="VRS_TEXTURE" value="1" enum="VRSMode"> + VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view. + </constant> + <constant name="VRS_XR" value="2" enum="VRSMode"> + VRS texture is supplied by the primary [XRInterface]. + </constant> + <constant name="VRS_MAX" value="3" enum="VRSMode"> + Represents the size of the [enum VRSMode] enum. + </constant> </constants> </class> diff --git a/doc/classes/VisualShaderNodeTextureUniform.xml b/doc/classes/VisualShaderNodeTextureUniform.xml index bff6f2015d..9014f79f54 100644 --- a/doc/classes/VisualShaderNodeTextureUniform.xml +++ b/doc/classes/VisualShaderNodeTextureUniform.xml @@ -39,12 +39,15 @@ Represents the size of the [enum TextureType] enum. </constant> <constant name="COLOR_DEFAULT_WHITE" value="0" enum="ColorDefault"> - Defaults to white color. + Defaults to fully opaque white color. </constant> <constant name="COLOR_DEFAULT_BLACK" value="1" enum="ColorDefault"> - Defaults to black color. + Defaults to fully opaque black color. </constant> - <constant name="COLOR_DEFAULT_MAX" value="2" enum="ColorDefault"> + <constant name="COLOR_DEFAULT_TRANSPARENT" value="2" enum="ColorDefault"> + Defaults to fully transparent black color. + </constant> + <constant name="COLOR_DEFAULT_MAX" value="3" enum="ColorDefault"> Represents the size of the [enum ColorDefault] enum. </constant> <constant name="FILTER_DEFAULT" value="0" enum="TextureFilter"> diff --git a/doc/classes/VisualShaderNodeVectorRefract.xml b/doc/classes/VisualShaderNodeVectorRefract.xml index d12188ea55..003b505671 100644 --- a/doc/classes/VisualShaderNodeVectorRefract.xml +++ b/doc/classes/VisualShaderNodeVectorRefract.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorRefract" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="VisualShaderNodeVectorRefract" inherits="VisualShaderNodeVectorBase" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Returns the [Vector3] that points in the direction of refraction. For use within the visual shader graph. + Returns the vector that points in the direction of refraction. For use within the visual shader graph. </brief_description> <description> Translated to [code]refract(I, N, eta)[/code] in the shader language, where [code]I[/code] is the incident vector, [code]N[/code] is the normal vector and [code]eta[/code] is the ratio of the indices of the refraction. diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml index b8d424b5fe..9198da4bc6 100644 --- a/doc/classes/VoxelGIData.xml +++ b/doc/classes/VoxelGIData.xml @@ -72,10 +72,10 @@ <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0"> The normal bias to use for indirect lighting and reflections. Higher values reduce self-reflections visible in non-rough materials, at the cost of more visible light leaking and flatter-looking indirect lighting. See also [member bias]. To prioritize hiding self-reflections over lighting quality, set [member bias] to [code]0.0[/code] and [member normal_bias] to a value between [code]1.0[/code] and [code]2.0[/code]. </member> - <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7"> - If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness. + <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.5"> + The multiplier to use when light bounces off a surface. Higher values result in brighter indirect lighting. If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness. </member> - <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="false"> + <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="true"> If [code]true[/code], performs two bounces of indirect lighting instead of one. This makes indirect lighting look more natural and brighter at a small performance cost. The second bounce is also visible in reflections. If the scene appears too bright after enabling [member use_two_bounces], adjust [member propagation] and [member energy]. </member> </members> diff --git a/doc/classes/WeakRef.xml b/doc/classes/WeakRef.xml index f80381acda..ea520178c7 100644 --- a/doc/classes/WeakRef.xml +++ b/doc/classes/WeakRef.xml @@ -12,7 +12,7 @@ <method name="get_ref" qualifiers="const"> <return type="Variant" /> <description> - Returns the [Object] this weakref is referring to. + Returns the [Object] this weakref is referring to. Returns [code]null[/code] if that object no longer exists. </description> </method> </methods> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index f4eaaac2e1..84f3b6a4b1 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -344,9 +344,11 @@ </member> <member name="max_size" type="Vector2i" setter="set_max_size" getter="get_max_size" default="Vector2i(0, 0)"> If non-zero, the [Window] can't be resized to be bigger than this size. + [b]Note:[/b] This property will be ignored if the value is lower than [member min_size]. </member> <member name="min_size" type="Vector2i" setter="set_min_size" getter="get_min_size" default="Vector2i(0, 0)"> If non-zero, the [Window] can't be resized to be smaller than this size. + [b]Note:[/b] This property will be ignored in favor of [method get_contents_minimum_size] if [member wrap_controls] is enabled and if its size is bigger. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="Window.Mode" default="0"> Set's the window's current mode. @@ -388,7 +390,7 @@ If [code]true[/code], the window is visible. </member> <member name="wrap_controls" type="bool" setter="set_wrap_controls" getter="is_wrapping_controls" default="false"> - If [code]true[/code], the window's size will automatically update when a child node is added or removed. + If [code]true[/code], the window's size will automatically update when a child node is added or removed, ignoring [member min_size] if the new size is bigger. If [code]false[/code], you need to call [method child_controls_changed] manually. </member> </members> diff --git a/doc/classes/WorkerThreadPool.xml b/doc/classes/WorkerThreadPool.xml new file mode 100644 index 0000000000..4f614bdadb --- /dev/null +++ b/doc/classes/WorkerThreadPool.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WorkerThreadPool" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="add_group_task"> + <return type="int" /> + <argument index="0" name="action" type="Callable" /> + <argument index="1" name="elements" type="int" /> + <argument index="2" name="tasks_needed" type="int" default="-1" /> + <argument index="3" name="high_priority" type="bool" default="false" /> + <argument index="4" name="description" type="String" default="""" /> + <description> + </description> + </method> + <method name="add_task"> + <return type="int" /> + <argument index="0" name="action" type="Callable" /> + <argument index="1" name="high_priority" type="bool" default="false" /> + <argument index="2" name="description" type="String" default="""" /> + <description> + </description> + </method> + <method name="get_group_processed_element_count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="group_id" type="int" /> + <description> + </description> + </method> + <method name="is_group_task_completed" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="group_id" type="int" /> + <description> + </description> + </method> + <method name="is_task_completed" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="task_id" type="int" /> + <description> + </description> + </method> + <method name="wait_for_group_task_completion"> + <return type="void" /> + <argument index="0" name="group_id" type="int" /> + <description> + </description> + </method> + <method name="wait_for_task_completion"> + <return type="void" /> + <argument index="0" name="task_id" type="int" /> + <description> + </description> + </method> + </methods> +</class> diff --git a/doc/classes/XRCamera3D.xml b/doc/classes/XRCamera3D.xml index e0fc016a7d..4d6baa327b 100644 --- a/doc/classes/XRCamera3D.xml +++ b/doc/classes/XRCamera3D.xml @@ -8,6 +8,6 @@ The position and orientation of this node is automatically updated by the XR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that, in contrast to the XR Controller, the render thread has access to the most up-to-date tracking data of the HMD and the location of the XRCamera3D can lag a few milliseconds behind what is used for rendering as a result. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> </class> diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml index deea888b8f..ff4aec46e1 100644 --- a/doc/classes/XRController3D.xml +++ b/doc/classes/XRController3D.xml @@ -10,7 +10,7 @@ As many XR runtimes now use a configurable action map all inputs are named. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> <methods> <method name="get_axis" qualifiers="const"> diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml index 0f4159cbbf..26b7699af2 100644 --- a/doc/classes/XRInterface.xml +++ b/doc/classes/XRInterface.xml @@ -8,7 +8,7 @@ Interfaces should be written in such a way that simply enabling them will give us a working setup. You can query the available interfaces through [XRServer]. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> <methods> <method name="get_camera_feed_id"> diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml index 71f6a44724..1642ae61f7 100644 --- a/doc/classes/XRInterfaceExtension.xml +++ b/doc/classes/XRInterfaceExtension.xml @@ -106,6 +106,11 @@ Returns the number of views this interface requires, 1 for mono, 2 for stereoscopic. </description> </method> + <method name="_get_vrs_texture" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> <method name="_initialize" qualifiers="virtual"> <return type="bool" /> <description> diff --git a/doc/classes/XROrigin3D.xml b/doc/classes/XROrigin3D.xml index b7811f4d53..7acee097e7 100644 --- a/doc/classes/XROrigin3D.xml +++ b/doc/classes/XROrigin3D.xml @@ -10,7 +10,7 @@ For example, if your character is driving a car, the XROrigin3D node should be a child node of this car. Or, if you're implementing a teleport system to move your character, you should change the position of this node. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> <members> <member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale" default="1.0"> diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index d15558c9e8..c146b27fcb 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -9,7 +9,7 @@ The [XRController3D] and [XRAnchor3D] both consume objects of this type and should be used in your project. The positional trackers are just under-the-hood objects that make this all work. These are mostly exposed so that GDExtension-based interfaces can interact with them. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> <methods> <method name="get_input" qualifiers="const"> diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml index a322a3c5c9..d3cb958cbc 100644 --- a/doc/classes/XRServer.xml +++ b/doc/classes/XRServer.xml @@ -7,7 +7,7 @@ The AR/VR server is the heart of our Advanced and Virtual Reality solution and handles all the processing. </description> <tutorials> - <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> + <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link> </tutorials> <methods> <method name="add_interface"> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index f36b1fddeb..a7c6533ef5 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -111,6 +111,18 @@ </description> </operator> <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator *"> <return type="float" /> <argument index="0" name="right" type="float" /> <description> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 2eceba40fa..6b492ca923 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -158,6 +158,18 @@ </description> </operator> <operator name="operator *"> + <return type="Vector4" /> + <argument index="0" name="right" type="Vector4" /> + <description> + </description> + </operator> + <operator name="operator *"> + <return type="Vector4i" /> + <argument index="0" name="right" type="Vector4i" /> + <description> + </description> + </operator> + <operator name="operator *"> <return type="float" /> <argument index="0" name="right" type="float" /> <description> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 312dffc7ee..196a26ef77 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -9,9 +9,12 @@ import re import sys import xml.etree.ElementTree as ET from collections import OrderedDict +from typing import List, Dict, TextIO, Tuple, Optional, Any, Union -# Uncomment to do type checks. I have it commented out so it works below Python 3.5 -# from typing import List, Dict, TextIO, Tuple, Iterable, Optional, DefaultDict, Any, Union +# Import hardcoded version information from version.py +root_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../") +sys.path.append(root_directory) # Include the root directory +import version # $DOCS_URL/path/to/page.html(#fragment-tag) GODOT_DOCS_PATTERN = re.compile(r"^\$DOCS_URL/(.*)\.html(#.*)?$") @@ -56,126 +59,18 @@ BASE_STRINGS = [ "This method doesn't need an instance to be called, so it can be called directly using the class name.", "This method describes a valid operator to use with this type as left-hand operand.", ] -strings_l10n = {} +strings_l10n: Dict[str, str] = {} -STYLES = {} - - -def print_error(error, state): # type: (str, State) -> None - print("{}{}ERROR:{} {}{}".format(STYLES["red"], STYLES["bold"], STYLES["regular"], error, STYLES["reset"])) - state.num_errors += 1 - - -class TypeName: - def __init__(self, type_name, enum=None): # type: (str, Optional[str]) -> None - self.type_name = type_name - self.enum = enum - - def to_rst(self, state): # type: ("State") -> str - if self.enum is not None: - return make_enum(self.enum, state) - elif self.type_name == "void": - return "void" - else: - return make_type(self.type_name, state) - - @classmethod - def from_element(cls, element): # type: (ET.Element) -> "TypeName" - return cls(element.attrib["type"], element.get("enum")) - - -class PropertyDef: - def __init__( - self, name, type_name, setter, getter, text, default_value, overrides - ): # type: (str, TypeName, Optional[str], Optional[str], Optional[str], Optional[str], Optional[str]) -> None - self.name = name - self.type_name = type_name - self.setter = setter - self.getter = getter - self.text = text - self.default_value = default_value - self.overrides = overrides - - -class ParameterDef: - def __init__(self, name, type_name, default_value): # type: (str, TypeName, Optional[str]) -> None - self.name = name - self.type_name = type_name - self.default_value = default_value - - -class SignalDef: - def __init__(self, name, parameters, description): # type: (str, List[ParameterDef], Optional[str]) -> None - self.name = name - self.parameters = parameters - self.description = description - - -class MethodDef: - def __init__( - self, name, return_type, parameters, description, qualifiers - ): # type: (str, TypeName, List[ParameterDef], Optional[str], Optional[str]) -> None - self.name = name - self.return_type = return_type - self.parameters = parameters - self.description = description - self.qualifiers = qualifiers - - -class ConstantDef: - def __init__(self, name, value, text, bitfield): # type: (str, str, Optional[str], Optional[bool]) -> None - self.name = name - self.value = value - self.text = text - self.is_bitfield = bitfield - - -class EnumDef: - def __init__(self, name, bitfield): # type: (str, Optional[bool]) -> None - self.name = name - self.values = OrderedDict() # type: OrderedDict[str, ConstantDef] - self.is_bitfield = bitfield - - -class ThemeItemDef: - def __init__( - self, name, type_name, data_name, text, default_value - ): # type: (str, TypeName, str, Optional[str], Optional[str]) -> None - self.name = name - self.type_name = type_name - self.data_name = data_name - self.text = text - self.default_value = default_value - - -class ClassDef: - def __init__(self, name): # type: (str) -> None - self.name = name - self.constants = OrderedDict() # type: OrderedDict[str, ConstantDef] - self.enums = OrderedDict() # type: OrderedDict[str, EnumDef] - self.properties = OrderedDict() # type: OrderedDict[str, PropertyDef] - self.constructors = OrderedDict() # type: OrderedDict[str, List[MethodDef]] - self.methods = OrderedDict() # type: OrderedDict[str, List[MethodDef]] - self.operators = OrderedDict() # type: OrderedDict[str, List[MethodDef]] - self.signals = OrderedDict() # type: OrderedDict[str, SignalDef] - self.annotations = OrderedDict() # type: OrderedDict[str, List[MethodDef]] - self.theme_items = OrderedDict() # type: OrderedDict[str, ThemeItemDef] - self.inherits = None # type: Optional[str] - self.brief_description = None # type: Optional[str] - self.description = None # type: Optional[str] - self.tutorials = [] # type: List[Tuple[str, str]] - - # Used to match the class with XML source for output filtering purposes. - self.filepath = "" # type: str +STYLES: Dict[str, str] = {} class State: - def __init__(self): # type: () -> None + def __init__(self) -> None: self.num_errors = 0 - self.classes = OrderedDict() # type: OrderedDict[str, ClassDef] - self.current_class = "" # type: str + self.classes: OrderedDict[str, ClassDef] = OrderedDict() + self.current_class: str = "" - def parse_class(self, class_root, filepath): # type: (ET.Element, str) -> None + def parse_class(self, class_root: ET.Element, filepath: str) -> None: class_name = class_root.attrib["name"] class_def = ClassDef(class_name) @@ -228,7 +123,6 @@ class State: return_element = constructor.find("return") if return_element is not None: return_type = TypeName.from_element(return_element) - else: return_type = TypeName("void") @@ -309,7 +203,7 @@ class State: constant_name = constant.attrib["name"] value = constant.attrib["value"] enum = constant.get("enum") - is_bitfield = constant.get("is_bitfield") or False + is_bitfield = constant.get("is_bitfield") == "true" constant_def = ConstantDef(constant_name, value, constant.text, is_bitfield) if enum is None: if constant_name in class_def.constants: @@ -343,7 +237,7 @@ class State: if desc_element is not None: annotation_desc = desc_element.text - annotation_def = MethodDef(annotation_name, return_type, params, annotation_desc, qualifiers) + annotation_def = AnnotationDef(annotation_name, params, annotation_desc, qualifiers) if annotation_name not in class_def.annotations: class_def.annotations[annotation_name] = [] @@ -408,13 +302,147 @@ class State: if link.text is not None: class_def.tutorials.append((link.text.strip(), link.get("title", ""))) - def sort_classes(self): # type: () -> None + def sort_classes(self) -> None: self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0])) -def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef] +class TypeName: + def __init__(self, type_name: str, enum: Optional[str] = None) -> None: + self.type_name = type_name + self.enum = enum + + def to_rst(self, state: State) -> str: + if self.enum is not None: + return make_enum(self.enum, state) + elif self.type_name == "void": + return "void" + else: + return make_type(self.type_name, state) + + @classmethod + def from_element(cls, element: ET.Element) -> "TypeName": + return cls(element.attrib["type"], element.get("enum")) + + +class PropertyDef: + def __init__( + self, + name: str, + type_name: TypeName, + setter: Optional[str], + getter: Optional[str], + text: Optional[str], + default_value: Optional[str], + overrides: Optional[str], + ) -> None: + self.name = name + self.type_name = type_name + self.setter = setter + self.getter = getter + self.text = text + self.default_value = default_value + self.overrides = overrides + + +class ParameterDef: + def __init__(self, name: str, type_name: TypeName, default_value: Optional[str]) -> None: + self.name = name + self.type_name = type_name + self.default_value = default_value + + +class SignalDef: + def __init__(self, name: str, parameters: List[ParameterDef], description: Optional[str]) -> None: + self.name = name + self.parameters = parameters + self.description = description + + +class AnnotationDef: + def __init__( + self, + name: str, + parameters: List[ParameterDef], + description: Optional[str], + qualifiers: Optional[str], + ) -> None: + self.name = name + self.parameters = parameters + self.description = description + self.qualifiers = qualifiers + + +class MethodDef: + def __init__( + self, + name: str, + return_type: TypeName, + parameters: List[ParameterDef], + description: Optional[str], + qualifiers: Optional[str], + ) -> None: + self.name = name + self.return_type = return_type + self.parameters = parameters + self.description = description + self.qualifiers = qualifiers + + +class ConstantDef: + def __init__(self, name: str, value: str, text: Optional[str], bitfield: bool) -> None: + self.name = name + self.value = value + self.text = text + self.is_bitfield = bitfield + + +class EnumDef: + def __init__(self, name: str, bitfield: bool) -> None: + self.name = name + self.values: OrderedDict[str, ConstantDef] = OrderedDict() + self.is_bitfield = bitfield + + +class ThemeItemDef: + def __init__( + self, name: str, type_name: TypeName, data_name: str, text: Optional[str], default_value: Optional[str] + ) -> None: + self.name = name + self.type_name = type_name + self.data_name = data_name + self.text = text + self.default_value = default_value + + +class ClassDef: + def __init__(self, name: str) -> None: + self.name = name + self.constants: OrderedDict[str, ConstantDef] = OrderedDict() + self.enums: OrderedDict[str, EnumDef] = OrderedDict() + self.properties: OrderedDict[str, PropertyDef] = OrderedDict() + self.constructors: OrderedDict[str, List[MethodDef]] = OrderedDict() + self.methods: OrderedDict[str, List[MethodDef]] = OrderedDict() + self.operators: OrderedDict[str, List[MethodDef]] = OrderedDict() + self.signals: OrderedDict[str, SignalDef] = OrderedDict() + self.annotations: OrderedDict[str, List[AnnotationDef]] = OrderedDict() + self.theme_items: OrderedDict[str, ThemeItemDef] = OrderedDict() + self.inherits: Optional[str] = None + self.brief_description: Optional[str] = None + self.description: Optional[str] = None + self.tutorials: List[Tuple[str, str]] = [] + + # Used to match the class with XML source for output filtering purposes. + self.filepath: str = "" + + +def print_error(error: str, state: State) -> None: + print("{}{}ERROR:{} {}{}".format(STYLES["red"], STYLES["bold"], STYLES["regular"], error, STYLES["reset"])) + state.num_errors += 1 + + +def parse_arguments(root: ET.Element) -> List[ParameterDef]: param_elements = root.findall("argument") - params = [None] * len(param_elements) # type: Any + params: Any = [None] * len(param_elements) for param_element in param_elements: param_name = param_element.attrib["name"] index = int(param_element.attrib["index"]) @@ -423,16 +451,16 @@ def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef] params[index] = ParameterDef(param_name, type_name, default) - cast = params # type: List[ParameterDef] + cast: List[ParameterDef] = params return cast -def main(): # type: () -> None +def main() -> None: # Enable ANSI escape code support on Windows 10 and later (for colored console output). # <https://bugs.python.org/issue29059> if platform.system().lower() == "windows": - from ctypes import windll, c_int, byref + from ctypes import windll, c_int, byref # type: ignore stdout_handle = windll.kernel32.GetStdHandle(c_int(-11)) mode = c_int(0) @@ -486,7 +514,7 @@ def main(): # type: () -> None print("Checking for errors in the XML class reference...") - file_list = [] # type: List[str] + file_list: List[str] = [] for path in args.path: # Cut off trailing slashes so os.path.basename doesn't choke. @@ -510,7 +538,7 @@ def main(): # type: () -> None file_list.append(path) - classes = {} # type: Dict[str, ET.Element] + classes: Dict[str, Tuple[ET.Element, str]] = {} state = State() for cur_file in file_list: @@ -571,7 +599,7 @@ def main(): # type: () -> None exit(1) -def translate(string): # type: (str) -> str +def translate(string: str) -> str: """Translate a string based on translations sourced from `doc/translations/*.po` for a language if defined via the --lang command line argument. Returns the original string if no translation exists. @@ -579,7 +607,7 @@ def translate(string): # type: (str) -> str return strings_l10n.get(string, string) -def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, State, bool, str) -> None +def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: str) -> None: class_name = class_def.name if dry_run: @@ -587,12 +615,26 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S else: f = open(os.path.join(output_dir, "class_" + class_name.lower() + ".rst"), "w", encoding="utf-8") - # Warn contributors not to edit this file directly + # Remove the "Edit on Github" button from the online docs page. f.write(":github_url: hide\n\n") - f.write(".. Generated automatically by doc/tools/make_rst.py in Godot's source tree.\n") - f.write(".. DO NOT EDIT THIS FILE, but the " + class_name + ".xml source instead.\n") - f.write(".. The source is found in doc/classes or modules/<name>/doc_classes.\n\n") + # Warn contributors not to edit this file directly. + # Also provide links to the source files for reference. + + git_branch = "master" + if hasattr(version, "docs") and version.docs != "latest": + git_branch = version.docs + + source_xml_path = os.path.relpath(class_def.filepath, root_directory).replace("\\", "/") + source_github_url = "https://github.com/godotengine/godot/tree/{}/{}".format(git_branch, source_xml_path) + generator_github_url = "https://github.com/godotengine/godot/tree/{}/doc/tools/make_rst.py".format(git_branch) + + f.write(".. DO NOT EDIT THIS FILE!!!\n") + f.write(".. Generated automatically from Godot engine sources.\n") + f.write(".. Generator: " + generator_github_url + ".\n") + f.write(".. XML source: " + source_github_url + ".\n\n") + + # Document reference id and header. f.write(".. _class_" + class_name + ":\n\n") f.write(make_heading(class_name, "=", False)) @@ -616,8 +658,8 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S break f.write("\n\n") - # Descendents - inherited = [] + # Descendants + inherited: List[str] = [] for c in state.classes.values(): if c.inherits and c.inherits.strip() == class_name: inherited.append(c.name) @@ -648,7 +690,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Properties overview if len(class_def.properties) > 0: f.write(make_heading("Properties", "-")) - ml = [] # type: List[Tuple[str, str, str]] + ml: List[Tuple[Optional[str], ...]] = [] for property_def in class_def.properties.values(): type_rst = property_def.type_name.to_rst(state) default = property_def.default_value @@ -664,7 +706,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Constructors, Methods, Operators overview if len(class_def.constructors) > 0: f.write(make_heading("Constructors", "-")) - ml = [] + ml: List[Tuple[Optional[str], ...]] = [] for method_list in class_def.constructors.values(): for m in method_list: ml.append(make_method_signature(class_def, m, "constructor", state)) @@ -672,7 +714,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S if len(class_def.methods) > 0: f.write(make_heading("Methods", "-")) - ml = [] + ml: List[Tuple[Optional[str], ...]] = [] for method_list in class_def.methods.values(): for m in method_list: ml.append(make_method_signature(class_def, m, "method", state)) @@ -680,7 +722,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S if len(class_def.operators) > 0: f.write(make_heading("Operators", "-")) - ml = [] + ml: List[Tuple[Optional[str], ...]] = [] for method_list in class_def.operators.values(): for m in method_list: ml.append(make_method_signature(class_def, m, "operator", state)) @@ -689,7 +731,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Theme properties if len(class_def.theme_items) > 0: f.write(make_heading("Theme Properties", "-")) - pl = [] + pl: List[Tuple[Optional[str], ...]] = [] for theme_item_def in class_def.theme_items.values(): ref = ":ref:`{0}<class_{2}_theme_{1}_{0}>`".format( theme_item_def.name, theme_item_def.data_name, class_name @@ -762,6 +804,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write("\n\n") + # Annotations if len(class_def.annotations) > 0: f.write(make_heading("Annotations", "-")) index = 0 @@ -774,8 +817,8 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S if i == 0: f.write(".. _class_{}_annotation_{}:\n\n".format(class_name, m.name.strip("@"))) - ret_type, signature = make_method_signature(class_def, m, "", state) - f.write("- {} {}\n\n".format(ret_type, signature)) + _, signature = make_method_signature(class_def, m, "", state) + f.write("- {}\n\n".format(signature)) if m.description is not None and m.description.strip() != "": f.write(rstize_text(m.description.strip(), state) + "\n\n") @@ -797,7 +840,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write(".. _class_{}_property_{}:\n\n".format(class_name, property_def.name)) f.write("- {} **{}**\n\n".format(property_def.type_name.to_rst(state), property_def.name)) - info = [] + info: List[Tuple[Optional[str], ...]] = [] # Not using translate() for now as it breaks table formatting. if property_def.default_value is not None: info.append(("*" + "Default" + "*", property_def.default_value)) @@ -907,7 +950,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write(make_footer()) -def escape_rst(text, until_pos=-1): # type: (str) -> str +def escape_rst(text: str, until_pos: int = -1) -> str: # Escape \ character, otherwise it ends up as an escape character in rst pos = 0 while True: @@ -941,7 +984,7 @@ def escape_rst(text, until_pos=-1): # type: (str) -> str return text -def format_codeblock(code_type, post_text, indent_level, state): # types: str, str, int, state +def format_codeblock(code_type: str, post_text: str, indent_level: int, state: State) -> Union[Tuple[str, int], None]: end_pos = post_text.find("[/" + code_type + "]") if end_pos == -1: print_error("{}.xml: [" + code_type + "] without a closing tag.".format(state.current_class), state) @@ -975,10 +1018,10 @@ def format_codeblock(code_type, post_text, indent_level, state): # types: str, else: code_text = code_text[:code_pos] + "\n " + code_text[code_pos + to_skip + 1 :] code_pos += 5 - to_skip - return ["\n[" + code_type + "]" + code_text + post_text, len("\n[" + code_type + "]" + code_text)] + return ("\n[" + code_type + "]" + code_text + post_text, len("\n[" + code_type + "]" + code_text)) -def rstize_text(text, state): # type: (str, State) -> str +def rstize_text(text: str, state: State) -> str: # Linebreak + tabs in the XML should become two line breaks unless in a "codeblock" pos = 0 while True: @@ -1018,7 +1061,6 @@ def rstize_text(text, state): # type: (str, State) -> str inside_code = False pos = 0 tag_depth = 0 - previous_pos = 0 while True: pos = text.find("[", pos) if pos == -1: @@ -1185,7 +1227,6 @@ def rstize_text(text, state): # type: (str, State) -> str text = pre_text + tag_text + post_text pos = len(pre_text) + len(tag_text) - previous_pos = pos continue elif cmd == "center": tag_depth += 1 @@ -1291,7 +1332,6 @@ def rstize_text(text, state): # type: (str, State) -> str text = pre_text + tag_text + post_text pos = len(pre_text) + len(tag_text) - previous_pos = pos if tag_depth > 0: print_error( @@ -1301,7 +1341,7 @@ def rstize_text(text, state): # type: (str, State) -> str return text -def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterable[Tuple[str, ...]]) -> None +def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_columns: bool = False) -> None: if len(data) == 0: return @@ -1332,7 +1372,7 @@ def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterabl f.write("\n") -def make_type(klass, state): # type: (str, State) -> str +def make_type(klass: str, state: State) -> str: if klass.find("*") != -1: # Pointer, ignore return klass link_type = klass @@ -1344,7 +1384,7 @@ def make_type(klass, state): # type: (str, State) -> str return klass -def make_enum(t, state): # type: (str, State) -> str +def make_enum(t: str, state: State) -> str: p = t.find(".") if p >= 0: c = t[0:p] @@ -1370,31 +1410,36 @@ def make_enum(t, state): # type: (str, State) -> str def make_method_signature( - class_def, method_def, ref_type, state -): # type: (ClassDef, Union[MethodDef, SignalDef], str, State) -> Tuple[str, str] - ret_type = " " + class_def: ClassDef, definition: Union[AnnotationDef, MethodDef, SignalDef], ref_type: str, state: State +) -> Tuple[str, str]: + ret_type = "" + + is_method_def = isinstance(definition, MethodDef) + if is_method_def: + ret_type = definition.return_type.to_rst(state) - if isinstance(method_def, MethodDef): - ret_type = method_def.return_type.to_rst(state) + qualifiers = None + if is_method_def or isinstance(definition, AnnotationDef): + qualifiers = definition.qualifiers out = "" - if ref_type != "": + if is_method_def and ref_type != "": if ref_type == "operator": out += ":ref:`{0}<class_{1}_{2}_{3}_{4}>` ".format( - method_def.name, + definition.name.replace("<", "\\<"), # So operator "<" gets correctly displayed. class_def.name, ref_type, - sanitize_operator_name(method_def.name, state), - method_def.return_type.type_name, + sanitize_operator_name(definition.name, state), + definition.return_type.type_name, ) else: - out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(method_def.name, class_def.name, ref_type) + out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(definition.name, class_def.name, ref_type) else: - out += "**{}** ".format(method_def.name) + out += "**{}** ".format(definition.name) out += "**(**" - for i, arg in enumerate(method_def.parameters): + for i, arg in enumerate(definition.parameters): if i > 0: out += ", " else: @@ -1405,24 +1450,24 @@ def make_method_signature( if arg.default_value is not None: out += "=" + arg.default_value - if isinstance(method_def, MethodDef) and method_def.qualifiers is not None and "vararg" in method_def.qualifiers: - if len(method_def.parameters) > 0: + if qualifiers is not None and "vararg" in qualifiers: + if len(definition.parameters) > 0: out += ", ..." else: out += " ..." out += " **)**" - if isinstance(method_def, MethodDef) and method_def.qualifiers is not None: + if qualifiers is not None: # Use substitutions for abbreviations. This is used to display tooltips on hover. # See `make_footer()` for descriptions. - for qualifier in method_def.qualifiers.split(): + for qualifier in qualifiers.split(): out += " |" + qualifier + "|" return ret_type, out -def make_heading(title, underline, l10n=True): # type: (str, str, bool) -> str +def make_heading(title: str, underline: str, l10n: bool = True) -> str: if l10n: new_title = translate(title) if new_title != title: @@ -1431,7 +1476,7 @@ def make_heading(title, underline, l10n=True): # type: (str, str, bool) -> str return title + "\n" + (underline * len(title)) + "\n\n" -def make_footer(): # type: () -> str +def make_footer() -> str: # Generate reusable abbreviation substitutions. # This way, we avoid bloating the generated rST with duplicate abbreviations. # fmt: off @@ -1446,7 +1491,7 @@ def make_footer(): # type: () -> str # fmt: on -def make_link(url, title): # type: (str, str) -> str +def make_link(url: str, title: str) -> str: match = GODOT_DOCS_PATTERN.search(url) if match: groups = match.groups() @@ -1463,15 +1508,15 @@ def make_link(url, title): # type: (str, str) -> str if title != "": return ":doc:`" + title + " <../" + groups[0] + ">`" return ":doc:`../" + groups[0] + "`" - else: - # External link, for example: - # `http://enet.bespin.org/usergroup0.html` - if title != "": - return "`" + title + " <" + url + ">`__" - return "`" + url + " <" + url + ">`__" + + # External link, for example: + # `http://enet.bespin.org/usergroup0.html` + if title != "": + return "`" + title + " <" + url + ">`__" + return "`" + url + " <" + url + ">`__" -def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str +def sanitize_operator_name(dirty_name: str, state: State) -> str: clear_name = dirty_name.replace("operator ", "") if clear_name == "!=": @@ -1529,7 +1574,7 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str return clear_name -def indent_bullets(text): # type: (str) -> str +def indent_bullets(text: str) -> str: # Take the text and check each line for a bullet point represented by "-". # Where found, indent the given line by a further "\t". # Used to properly indent bullet points contained in the description for enum values. diff --git a/doc/translations/ar.po b/doc/translations/ar.po index b21374a37f..43e62ecab2 100644 --- a/doc/translations/ar.po +++ b/doc/translations/ar.po @@ -19,12 +19,14 @@ # Hamza Kalash <mogo.gogo170@gmail.com>, 2022. # ywmaa <ywmaa.personal@gmail.com>, 2022. # TabbyDev <Mandomody25@gmail.com>, 2022. +# عبد الرØÙ…Ù† أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-05-31 22:35+0000\n" -"Last-Translator: TabbyDev <Mandomody25@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:56+0000\n" +"Last-Translator: عبد الرØÙ…Ù† أبو سعدة ||Abd Alrahman abo saada " +"<abdalrahmanabs2005@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/ar/>\n" "Language: ar\n" @@ -33,7 +35,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\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.13-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -1004,7 +1006,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7850,8 +7859,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10132,7 +10141,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10297,7 +10312,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11910,7 +11931,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20335,7 +20361,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23727,7 +23753,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25564,7 +25590,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28607,13 +28633,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30029,9 +30056,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30605,10 +30632,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30621,6 +30651,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32657,7 +32693,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32673,7 +32709,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32703,7 +32739,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36837,7 +36873,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37100,7 +37136,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37218,6 +37254,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -37772,7 +37854,7 @@ msgstr "" #: doc/classes/Node.xml msgid "Nodes and Scenes" -msgstr "" +msgstr "العقد Ùˆ المشاهد" #: doc/classes/Node.xml msgid "All Demos" @@ -39915,7 +39997,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39927,7 +40015,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45558,6 +45647,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54487,7 +54583,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54527,15 +54624,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56011,11 +56109,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57685,7 +57802,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60586,8 +60703,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64219,13 +64336,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64237,13 +64355,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66053,11 +66172,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66137,8 +66256,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71152,7 +71271,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71237,6 +71360,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/ca.po b/doc/translations/ca.po index 0e33b91074..2fce9a4d08 100644 --- a/doc/translations/ca.po +++ b/doc/translations/ca.po @@ -960,7 +960,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7797,8 +7804,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10078,7 +10085,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10243,7 +10256,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11854,7 +11873,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20265,7 +20289,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23654,7 +23678,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25485,7 +25509,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28526,13 +28550,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29946,9 +29971,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30522,10 +30547,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30538,6 +30566,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32571,7 +32605,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32587,7 +32621,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32617,7 +32651,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36717,7 +36751,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36978,7 +37012,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37092,6 +37126,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39789,7 +39869,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39801,7 +39887,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45405,6 +45492,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54329,7 +54423,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54369,15 +54464,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55853,11 +55949,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57527,7 +57642,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60418,8 +60533,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64042,13 +64157,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64060,13 +64176,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65874,11 +65991,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65958,8 +66075,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70952,7 +71069,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71037,6 +71158,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot index 8d833031fe..b8187d24d5 100644 --- a/doc/translations/classes.pot +++ b/doc/translations/classes.pot @@ -840,7 +840,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7677,8 +7684,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9958,7 +9965,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10123,7 +10136,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11734,7 +11753,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20145,7 +20169,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23531,7 +23555,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25362,7 +25386,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28403,13 +28427,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29823,9 +29848,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30399,10 +30424,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30415,6 +30443,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32448,7 +32482,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32464,7 +32498,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32494,7 +32528,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36594,7 +36628,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36855,7 +36889,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36969,6 +37003,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39666,7 +39746,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39678,7 +39764,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45282,6 +45369,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54206,7 +54300,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54246,15 +54341,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55730,11 +55826,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57404,7 +57519,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60295,8 +60410,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63919,13 +64034,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63937,13 +64053,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65751,11 +65868,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65835,8 +65952,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70829,7 +70946,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70914,6 +71035,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/cs.po b/doc/translations/cs.po index 85a9d50b28..878b7e9aae 100644 --- a/doc/translations/cs.po +++ b/doc/translations/cs.po @@ -1230,8 +1230,15 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "Jako [method print], ale tiskne pouze pokud je použita v debug módu." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8187,8 +8194,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10475,7 +10482,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10640,7 +10653,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12254,7 +12273,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20713,7 +20737,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24111,7 +24135,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25948,7 +25972,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28996,13 +29020,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30419,9 +30444,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30995,10 +31020,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31010,6 +31038,15 @@ msgid "Mouse and input coordinates" msgstr "" #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"Vracà [code]true[/code] pokud si jsou [code]a[/code] a [code]b[/code] " +"pÅ™iblÞnÄ› rovny." + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -33049,7 +33086,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33065,7 +33102,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33096,7 +33133,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37239,7 +37276,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37502,7 +37539,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37620,6 +37657,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40320,7 +40403,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40332,7 +40421,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45974,6 +46064,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54913,7 +55010,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54953,15 +55051,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56438,11 +56537,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58113,7 +58231,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61029,8 +61147,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64687,13 +64805,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64705,13 +64824,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66526,11 +66646,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66610,8 +66730,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71635,9 +71755,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "Vrátà [code] true [/code], pokud je vektor normalizován, jinak false." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -71721,6 +71844,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/de.po b/doc/translations/de.po index ae8d8f2165..0cf8d9ae17 100644 --- a/doc/translations/de.po +++ b/doc/translations/de.po @@ -35,7 +35,7 @@ # spoadr <spoadr@gmx.ch>, 2021. # Tim <tim14speckenwirth@gmail.com>, 2021. # user <online141@gmx.de>, 2021. -# Jummit <jummit@web.de>, 2021. +# Jummit <jummit@web.de>, 2021, 2022. # Bastian <bastian.ike@gmail.com>, 2021. # KuhnChris <kuhnchris@kuhnchris.eu>, 2021. # Rémi Verschelde <remi@godotengine.org>, 2021. @@ -52,7 +52,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-06-22 23:17+0000\n" +"PO-Revision-Date: 2022-07-23 03:56+0000\n" "Last-Translator: Hans Peter <figefi6308@runqx.com>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/de/>\n" @@ -61,7 +61,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -534,7 +534,6 @@ msgstr "" "[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Compares two values by checking their actual contents, recursing into any " "[Array] or [Dictionary] up to its deepest level.\n" @@ -566,9 +565,9 @@ msgstr "" "- Für [code]Array[/code]s, [code]==[/code] werden die Arrays elementweise " "mit [code]==[/code] verglichen. Der Elemente-Vergleich ist also wieder " "einfach, nicht tief.\n" -"Zusammengefasst, immer wenn ein [code]Dictionary[/code] potentiell " -"involviert ist, und du einen wahren Inhaltsvergleich brauchst, musst du " -"[code]deep_equal[/code] verwenden." +"Zusammengefasst, immer wenn möglicherweise ein [code]Dictionary[/code] " +"involviert ist und du einen echten Inhaltsvergleich brauchst, verwende " +"[code]deep_equal[/code]." #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -969,7 +968,6 @@ msgstr "" "[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Linearly interpolates between two values by the factor defined in " "[code]weight[/code]. To perform interpolation, [code]weight[/code] should be " @@ -989,17 +987,24 @@ msgid "" "To perform eased interpolation with [method lerp], combine it with [method " "ease] or [method smoothstep]." msgstr "" -"Interpoliert einen normalisierten Wert linear zwischen zwei Grenzwerten. " -"Dies entspricht der Umkehrfunktion von [method inverse_lerp].\n" -"Wenn die [code]from[/code] und [code]to[/code] Argumente vom Typ [int] oder " -"[float] sind, dann ist der Rückgabewert ein [float].\n" -"Sind beide Argumente vom gleichen Typ ([Vector2], [Vector3] oder [Color]), " -"dann ist der Rückgabewert auch von diesem Typ ([code]lerp[/code] ruft dann " -"die Methode [code]lerp[/code] dieses Vektortyps auf).\n" +"Interpoliert linear zwischen zwei Werten mit dem in [code]weight[/code] " +"definierten Faktor. Um eine Interpolation durchzuführen, sollte " +"[code]Gewicht[/code] zwischen [code]0.0[/code] und [code]1.0[/code] " +"(einschließlich) liegen. Werte außerhalb dieses Bereichs sind jedoch " +"zulässig und können verwendet werden, um [i]Extrapolation[/i] " +"durchzuführen.\n" +"Wenn die Argumente [code]von[/code] und [code]bis[/code] vom Typ [int] oder " +"[float] sind, ist der Rückgabewert ein [float].\n" +"Wenn beide vom gleichen Vektortyp sind ([Vector2], [Vector3] oder [Color]), " +"ist der Rückgabewert vom gleichen Typ ([code]lerp[/code] ruft dann die " +"Methode [code]linear_interpolate[/code] des Vektortyps auf).\n" "[codeblock]\n" -"lerp(0, 4, 0.75) # Returns 3.0\n" -"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Returns Vector2(2, 3.5)\n" -"[/codeblock]" +"lerp(0, 4, 0.75) # Gibt 3.0 zurück\n" +"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Liefert Vector2(2, 3.5)\n" +"[/codeblock]\n" +"Siehe auch [method inverse_lerp], die die Umkehrung dieser Operation " +"durchführt. Um eine Interpolation mit [method lerp] durchzuführen, " +"kombiniere sie mit [method ease] oder [method smoothstep]." #: modules/gdscript/doc_classes/@GDScript.xml #, fuzzy @@ -1398,9 +1403,22 @@ msgstr "" "Trace aus." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Funktioniert wie [method print], gibt jedoch nur im Debug Modues Text aus." +"Gibt einen Stacktrace zum Quelltextort aus, funktioniert nur wenn das " +"\"Ausführen mit Debugger\" aktiviert ist.\n" +"Die Ausgabe in der Konsole würde ungefähr so aussehen:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -1660,6 +1678,45 @@ msgid "" "3\n" "[/codeblock]" msgstr "" +"Gibt ein Array mit dem angegebenen Bereich zurück. Die [Methode range] kann " +"auf drei Arten aufgerufen werden:\n" +"[code]range(n: int)[/code]: Beginnt bei 0, erhöht sich in Schritten von 1 " +"und endet [i]vor[/i] [code]n[/code]. Das Argument [code]n[/code] ist " +"[b]exklusiv[/b].\n" +"[code]range(b: int, n: int)[/code]: Beginnt bei [code]b[/code], erhöht sich " +"in Schritten von 1 und endet [i]vor[/i] [code]n[/code]. Die Argumente " +"[code]b[/code] und [code]n[/code] sind [b]inklusive[/b] bzw. [b]exklusive[/" +"b].\n" +"[code]bereich(b: int, n: int, s: int)[/code]: Beginnt bei [code]b[/code], " +"erhöht/verringert sich um Schritte von [code]s[/code] und endet [i]vor[/i] " +"[code]n[/code]. Die Argumente [code]b[/code] und [code]n[/code] sind " +"[b]inklusive[/b] bzw. [b]exklusive[/b]. Das Argument [code]s[/code] [b]kann[/" +"b] negativ sein, aber nicht [code]0[/code]. Wenn [code]s[/code] [code]0[/" +"code] ist, wird eine Fehlermeldung ausgegeben.\n" +"Der [Methodenbereich] wandelt alle Argumente vor der Verarbeitung in [int] " +"um.\n" +"[b]Hinweis:[/b] Gibt ein leeres Array zurück, wenn kein Wert die " +"Werteinschränkung erfüllt (z. B. [code]range(2, 5, -1)[/code] oder " +"[code]range(5, 5, 1)[/code]).\n" +"Beispiele:\n" +"[codeblock]\n" +"print(bereich(4)) # Gibt [0, 1, 2, 3] aus\n" +"print(bereich(2, 5)) # Gibt [2, 3, 4] aus\n" +"print(range(0, 6, 2)) # Gibt [0, 2, 4] aus\n" +"print(range(4, 1, -1)) # Gibt [4, 3, 2] aus\n" +"[/codeblock]\n" +"Um rückwärts über ein [Array] zu iterieren, benutze:\n" +"[codeblock]\n" +"var array = [3, 6, 9]\n" +"for i in range(array.size(), 0, -1):\n" +" print(array[i - 1])\n" +"[/codeblock]\n" +"Ausgabe:\n" +"[codeblock]\n" +"9\n" +"6\n" +"3\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -2194,6 +2251,50 @@ msgid "" "[code]GDScriptFunctionState[/code]. Notice [code]yield(get_tree(), " "\"idle_frame\")[/code] from the above example." msgstr "" +"Stoppt die Ausführung der Funktion und gibt den aktuellen angehaltenen " +"Zustand an die aufrufende Funktion zurück.\n" +"Rufe vom Aufrufer [Methode GDScriptFunctionState.resume] von dem Zustand " +"auf, um die Ausführung wieder aufzunehmen. Dadurch wird der Zustand " +"ungültig. Innerhalb der wiederaufgenommenen Funktion gibt [code]yield()[/" +"code] das zurück, was an den Funktionsaufruf [code]resume()[/code] übergeben " +"wurde.\n" +"Wenn ein Objekt und ein Signal übergeben werden, wird die Ausführung " +"fortgesetzt, wenn das Objekt das angegebene Signal aussendet. In diesem Fall " +"gibt [code]yield()[/code] das an [code]emit_signal()[/code] übergebene " +"Argument zurück, wenn das Signal nur ein Argument benötigt, oder ein Array " +"mit allen an [code]emit_signal()[/code] übergebenen Argumenten, wenn das " +"Signal mehrere Argumente benötigt.\n" +"[code]yield[/code] kann auch verwendet werden um auf das Ende einer Funktion " +"zu warten:\n" +"[codeblock]\n" +"func _ready():\n" +" yield(countdown(), \"completed\") # Warten auf die Beendigung der " +"Funktion countdown()\n" +" print('Fertig')\n" +"\n" +"func countdown():\n" +" yield(get_tree(), \"idle_frame\") # gibt ein GDScriptFunctionState " +"Objekt an _ready() zurück\n" +" print(3)\n" +" yield(get_tree().create_timer(1.0), \"timeout\")\n" +" print(2)\n" +" yield(get_tree().create_timer(1.0), \"timeout\")\n" +" print(1)\n" +" yield(get_tree().create_timer(1.0), \"timeout\")\n" +"\n" +"# gibt aus:\n" +"# 3\n" +"# 2\n" +"# 1\n" +"# bereit\n" +"[/codeblock]\n" +"Beim Yielding einer Funktion wird das Signal [code]completed[/code] " +"automatisch ausgegeben, wenn die Funktion zurückkehrt. Es kann daher als " +"[code]signal[/code] Parameter der [code]yield[/code] Methode verwendet " +"werden, um fortzufahren.\n" +"Um eine Funktion zu beenden, sollte die resultierende Funktion auch einen " +"[code]GDScriptFunctionState[/code] zurückgeben. Beachte " +"[code]yield(get_tree(), \"idle_frame\")[/code] aus dem obigen Beispiel." #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -3946,6 +4047,8 @@ msgid "" "MIDI aftertouch message. This message is most often sent by pressing down on " "the key after it \"bottoms out\"." msgstr "" +"MIDI-Aftertouch-Meldung. Diese Meldung wird meistens durch Drücken der Taste " +"nachdem sie den Tiefpunkt erreicht hat gesendet." #: doc/classes/@GlobalScope.xml msgid "" @@ -3961,6 +4064,8 @@ msgid "" "MIDI program change message. This message sent when the program patch number " "changes." msgstr "" +"MIDI-Programmwechselmeldung. Diese Meldung wird gesendet, wenn sich die " +"Programm-Patch-Nummer ändert." #: doc/classes/@GlobalScope.xml msgid "" @@ -3968,12 +4073,18 @@ msgid "" "down on the key after it \"bottoms out\". This message is different from " "polyphonic after-touch as it indicates the highest pressure across all keys." msgstr "" +"MIDI-Kanal-Druckmeldung. Diese Meldung wird meistens durch Drücken der Taste " +"nachdem sie den Tiefpunkt erreicht hat gesendet.Diese Meldung unterscheidet " +"sich von der polyphonen Aftertouch-Meldung, da sie den höchsten Druck über " +"alle Tasten hinweg anzeigt." #: doc/classes/@GlobalScope.xml msgid "" "MIDI pitch bend message. This message is sent to indicate a change in the " "pitch bender (wheel or lever, typically)." msgstr "" +"MIDI-Pitch-Bend-Meldung. Diese Meldung wird gesendet, um eine Änderung des " +"Pitch-Benders (typischerweise Rad oder Hebel) anzuzeigen." #: doc/classes/@GlobalScope.xml msgid "" @@ -9731,8 +9842,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -12026,7 +12137,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -12192,7 +12309,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -13821,7 +13944,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -22431,7 +22559,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -25849,7 +25977,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -27691,7 +27819,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -30778,13 +30906,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -31775,7 +31904,7 @@ msgstr "" #: doc/classes/Input.xml msgid "A singleton that deals with inputs." -msgstr "" +msgstr "Ein Singleton, der sich mit Inputs befasst." #: doc/classes/Input.xml msgid "" @@ -31784,6 +31913,11 @@ msgid "" "set in the [b]Input Map[/b] tab in the [b]Project > Project Settings[/b], or " "with the [InputMap] class." msgstr "" +"Ein Singleton, das sich mit Inputs befasst. Dazu gehören Tastendrucke, " +"Maustasten und -bewegungen, Joypads und Eingabeaktionen. Aktionen und ihre " +"Ereignisse können auf der Registerkarte [b]Eingabe-Zuordnung[/b] unter " +"[b]Projekt > Projekteinstellungen[/b] oder mit der Klasse [InputMap] " +"festgelegt werden." #: doc/classes/Input.xml msgid "Inputs tutorial index" @@ -32015,6 +32149,20 @@ msgid "" "[url=$DOCS_URL/tutorials/inputs/input_examples.html#keyboard-events]Input " "examples[/url] in the documentation for more information." msgstr "" +"Gibt [code]true[/code] aus, wenn Sie das Aktionsereignis drücken. Beachten " +"Sie, dass, wenn einer Aktion mehrere Tasten zugewiesen sind und mehr als " +"eine von ihnen gedrückt wird, das Loslassen einer Taste die Aktion auslöst, " +"selbst wenn eine andere Taste, die dieser Aktion zugewiesen ist, noch " +"gedrückt ist.\n" +"Wenn [code]exact[/code] [code] false[/code] ist, werden zusätzliche " +"Eingabemodifikatoren für die Ereignisse [InputEventKey] und " +"[InputEventMouseButton] sowie die Richtung für die Ereignisse " +"[InputEventJoypadMotion] ignoriert.\n" +"[b]Hinweis:[/b] Aufgrund von Tastatur-Ghosting kann [method " +"is_action_pressed] [code]false[/code] zurückgeben, auch wenn eine der Tasten " +"der Aktion gedrückt ist. Siehe [url=$DOCS_URL/tutorials/inputs/" +"input_examples.html#keyboard-events]Eingabebeispiele[/url] in der " +"Dokumentation für weitere Informationen." #: doc/classes/Input.xml #, fuzzy @@ -32210,9 +32358,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -32786,10 +32934,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -32801,6 +32952,14 @@ msgid "Mouse and input coordinates" msgstr "" #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"Liefert [code]true[/code] wenn die Länge der Zeichenkette [code]0[/code] ist." + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -34887,7 +35046,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -34903,7 +35062,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -34939,7 +35098,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -39116,7 +39275,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -39383,7 +39542,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -39504,6 +39663,53 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +#, fuzzy +msgid "Set the max packet size that this peer can handle." +msgstr "Gibt das AnimationNode mit dem gegebenen Namen zurück." + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -42207,7 +42413,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -42219,7 +42431,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -47902,6 +48115,14 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +#, fuzzy +msgid "Sorts the elements of the array in ascending order." +msgstr "Entfernt das Element der Arrays dessen Position übergeben wurde." + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -56953,7 +57174,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56993,15 +57215,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -58489,11 +58712,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -60184,7 +60426,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -63144,8 +63386,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -66842,13 +67084,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -66860,13 +67103,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -68828,11 +69072,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -68912,8 +69156,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -74012,9 +74256,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "Wenn [code]true[/code], wird die Textur zentriert." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -74098,6 +74345,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/el.po b/doc/translations/el.po index d3cbf69925..87eee32604 100644 --- a/doc/translations/el.po +++ b/doc/translations/el.po @@ -855,7 +855,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7694,8 +7701,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9976,7 +9983,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10141,7 +10154,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11754,7 +11773,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20180,7 +20204,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23572,7 +23596,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25409,7 +25433,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28452,13 +28476,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29874,9 +29899,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30450,10 +30475,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30466,6 +30494,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32502,7 +32536,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32518,7 +32552,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32548,7 +32582,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36676,7 +36710,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36939,7 +36973,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37057,6 +37091,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39754,7 +39834,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39766,7 +39852,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45384,6 +45471,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54313,7 +54407,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54353,15 +54448,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55837,11 +55933,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57511,7 +57626,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60412,8 +60527,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64045,13 +64160,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64063,13 +64179,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65879,11 +65996,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65963,8 +66080,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70978,7 +71095,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71063,6 +71184,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/es.po b/doc/translations/es.po index e38eb521c0..f9d008c41a 100644 --- a/doc/translations/es.po +++ b/doc/translations/es.po @@ -1380,9 +1380,22 @@ msgstr "" "mientras muestra un trazo de cuando un error o advertencia se muestra." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Como [method print], pero imprime sólo cuando se usa en modo de depuración." +"Imprime una registro de la pila en la ubicación del código, sólo funciona " +"cuando se ejecuta con el depurador activado.\n" +"La salida en la consola se verÃa algo asÃ:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -10108,8 +10121,8 @@ msgstr "" #, fuzzy msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -13142,8 +13155,14 @@ msgstr "" "escena." #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." -msgstr "El bus en el que se está reproduciendo este audio." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer.xml msgid "" @@ -13329,9 +13348,14 @@ msgstr "" "escena." #: doc/classes/AudioStreamPlayer3D.xml -#, fuzzy -msgid "The bus on which this audio is playing." -msgstr "El bus en el que se está reproduciendo este audio." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -15364,10 +15388,13 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" -"Si [code]true[/code], el ancestro [Viewport] está actualmente usando esta " -"cámara." #: doc/classes/Camera.xml msgid "" @@ -26607,10 +26634,11 @@ msgstr "" "save_to_file]." #: doc/classes/EditorFeatureProfile.xml +#, fuzzy msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" "Guarda el perfil de caracterÃsticas del editor en un archivo en formato " "JSON. Luego puede ser importado usando el botón [b]Import[/b] del " @@ -31139,9 +31167,10 @@ msgid "The default exposure used for tonemapping." msgstr "La exposición predeterminada que se utiliza para el mapeo de tonos." #: doc/classes/Environment.xml +#, fuzzy msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" "El modo de mapeo de tonos a utilizar. El \"tonemapping\" es el proceso que " @@ -33568,9 +33597,10 @@ msgstr "" "puntos finales." #: doc/classes/Geometry.xml +#, fuzzy msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -37678,13 +37708,14 @@ msgstr "Número máximo de redirecciones permitidas." #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -39554,9 +39585,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" "Habilita o deshabilita la acumulación de eventos de entrada similares " "enviados por el sistema operativo. Cuando la acumulación de entrada está " @@ -40315,10 +40346,13 @@ msgstr "Tipo de evento de entrada para los eventos de movimiento del ratón." msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -40342,6 +40376,15 @@ msgid "Mouse and input coordinates" msgstr "Medio desplazamiento en la coordenada X." #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"Devuelve el número de disposiciones del teclado.\n" +"[b]Nota:[/b] Este método está implementado en Linux, macOS y Windows." + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -43028,7 +43071,7 @@ msgstr "La altura del cilindro." msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -43054,7 +43097,7 @@ msgstr "El tamaño del ancho de un pÃxel en el sprite para escalarlo en 3D." msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -43101,7 +43144,7 @@ msgstr "Si se ajusta, las luces del entorno afectan al sprite." #: doc/classes/Label3D.xml #, fuzzy msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" "Si se fija, la textura puede ser vista desde atrás también, si no, es " @@ -48229,7 +48272,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -48552,7 +48595,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -48678,6 +48721,54 @@ msgstr "" msgid "Control activation of this server." msgstr "Traducción local de este nodo." +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +#, fuzzy +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "Devuelve el estado actual de la conexión. Ver [enum ConnectionStatus]." + +#: doc/classes/NetworkedMultiplayerCustom.xml +#, fuzzy +msgid "Set the max packet size that this peer can handle." +msgstr "Establece la piel que se utilizará en esta instancia." + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -52600,8 +52691,14 @@ msgid "See [enum ShadowDetail]." msgstr "Ver [enum ShadowMode]." #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." -msgstr "Ver [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." +msgstr "" #: doc/classes/OmniLight.xml msgid "" @@ -52612,9 +52709,11 @@ msgstr "" "que [constant SHADOW_CUBE], pero de menor calidad." #: doc/classes/OmniLight.xml +#, fuzzy msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" "Las sombras se representan en un mapa de cubos. Más lento que [constant " "SHADOW_DUAL_PARABOLOID], pero de mayor calidad." @@ -60077,6 +60176,14 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "Cambia el byte en el Ãndice dado." +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +#, fuzzy +msgid "Sorts the elements of the array in ascending order." +msgstr "Elimina un elemento del array por indice." + #: doc/classes/PoolByteArray.xml #, fuzzy msgid "" @@ -71442,7 +71549,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -71482,15 +71590,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -73306,11 +73415,41 @@ msgstr "" #: doc/classes/Spatial.xml #, fuzzy +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" +"Parte de la rotación de la transformación local en radianes, especificada en " +"términos de ángulos YXZ-Euler en el formato (ángulo X, ángulo Y, ángulo Z).\n" +"[b]Nota:[/b] En el sentido matemático, la rotación es una matriz y no un " +"vector. Los tres ángulos de Euler, que son los tres parámetros " +"independientes de la parametrización del ángulo de Euler de la matriz de " +"rotación, se almacenan en una estructura de datos [Vector3] no porque la " +"rotación sea un vector, sino sólo porque el [Vector3] existe como una " +"estructura de datos conveniente para almacenar 3 números reales. Por lo " +"tanto, la aplicación de operaciones afines en el \"vector\" de rotación no " +"es significativa." + +#: doc/classes/Spatial.xml +#, fuzzy msgid "World space (global) [Transform] of this node." msgstr "World3D espacio (global) [Transform] de este nodo." #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -75444,7 +75583,7 @@ msgstr "El tamaño del ancho de un pÃxel en el sprite para escalarlo en 3D." msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -79147,8 +79286,8 @@ msgstr "Establece el texto para una lÃnea especÃfica." #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -83770,15 +83909,18 @@ msgstr "" "elementos pueden establecerse utilizando [method set_item_metadata]." #: doc/classes/TreeItem.xml +#, fuzzy msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" "Devuelve el siguiente TreeItem del árbol o un objeto nulo si no hay ninguno." #: doc/classes/TreeItem.xml +#, fuzzy msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -83794,15 +83936,18 @@ msgid "Returns the parent TreeItem or a null object if there is none." msgstr "Devuelve el TreeItem padre o un objeto nulo si no hay ninguno." #: doc/classes/TreeItem.xml +#, fuzzy msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" "Devuelve el TreeItem anterior del árbol o un objeto nulo si no hay ninguno." #: doc/classes/TreeItem.xml +#, fuzzy msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -86302,11 +86447,11 @@ msgstr "" #, fuzzy msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -86430,8 +86575,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml #, fuzzy msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -92976,9 +93121,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "Establece la matriz de transformación global del Viewport." #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "Si [code]true[/code], el canvas del viewport no se renderiza." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -93086,6 +93234,15 @@ msgstr "" "ViewportUpdateMode] para las opciones." #: doc/classes/VisualServer.xml +msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml #, fuzzy msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " diff --git a/doc/translations/fa.po b/doc/translations/fa.po index db8018d209..7416d80072 100644 --- a/doc/translations/fa.po +++ b/doc/translations/fa.po @@ -1269,8 +1269,15 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "شبیه متد چاپ، اما چاپ کردن تنها در ØØ§Ù„ت اشکال زدایی Ø§Ø³ØªÙØ§Ø¯Ù‡ میشود." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8118,8 +8125,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10399,7 +10406,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10564,7 +10577,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12175,7 +12194,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20586,7 +20610,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23975,7 +23999,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25806,7 +25830,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28847,13 +28871,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30267,9 +30292,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30843,10 +30868,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30859,6 +30887,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32892,7 +32926,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32908,7 +32942,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32938,7 +32972,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37044,7 +37078,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37305,7 +37339,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37419,6 +37453,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40116,7 +40196,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40128,7 +40214,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45744,6 +45831,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54672,7 +54766,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54712,15 +54807,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56196,11 +56292,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57870,7 +57985,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60761,8 +60876,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64385,13 +64500,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64403,13 +64519,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66217,11 +66334,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66301,8 +66418,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71295,7 +71412,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71380,6 +71501,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/fi.po b/doc/translations/fi.po index 9317c255a7..b1d940aa14 100644 --- a/doc/translations/fi.po +++ b/doc/translations/fi.po @@ -922,7 +922,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7767,8 +7774,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10049,7 +10056,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10214,7 +10227,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11828,7 +11847,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20256,7 +20280,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23648,7 +23672,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25485,7 +25509,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28535,13 +28559,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29957,9 +29982,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30533,10 +30558,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30549,6 +30577,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32585,7 +32619,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32601,7 +32635,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32631,7 +32665,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36761,7 +36795,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37024,7 +37058,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37142,6 +37176,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39839,7 +39919,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39851,7 +39937,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45469,6 +45556,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54398,7 +54492,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54438,15 +54533,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55923,11 +56019,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57598,7 +57713,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60500,8 +60615,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64135,13 +64250,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64153,13 +64269,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65972,11 +66089,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66056,8 +66173,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71073,7 +71190,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71158,6 +71279,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/fil.po b/doc/translations/fil.po index f7a8c0fd9b..42ab5537f4 100644 --- a/doc/translations/fil.po +++ b/doc/translations/fil.po @@ -856,7 +856,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7693,8 +7700,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9974,7 +9981,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10139,7 +10152,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11750,7 +11769,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20161,7 +20185,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23550,7 +23574,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25381,7 +25405,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28422,13 +28446,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29842,9 +29867,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30418,10 +30443,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30434,6 +30462,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32467,7 +32501,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32483,7 +32517,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32513,7 +32547,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36613,7 +36647,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36874,7 +36908,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36988,6 +37022,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39685,7 +39765,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39697,7 +39783,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45301,6 +45388,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54225,7 +54319,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54265,15 +54360,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55749,11 +55845,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57423,7 +57538,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60314,8 +60429,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63938,13 +64053,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63956,13 +64072,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65770,11 +65887,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65854,8 +65971,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70848,7 +70965,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70933,6 +71054,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/fr.po b/doc/translations/fr.po index 7b3d3c7435..44d40e1bd5 100644 --- a/doc/translations/fr.po +++ b/doc/translations/fr.po @@ -61,7 +61,7 @@ msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-06 04:47+0000\n" +"PO-Revision-Date: 2022-08-04 05:23+0000\n" "Last-Translator: Maxime Leroy <lisacintosh@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/fr/>\n" @@ -70,7 +70,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -548,7 +548,6 @@ msgstr "" "[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Compares two values by checking their actual contents, recursing into any " "[Array] or [Dictionary] up to its deepest level.\n" @@ -574,15 +573,15 @@ msgstr "" "- Pour [code]null[/code], [code]int[/code], [code]float[/code], " "[code]String[/code], [code]Object[/code] et [code]RID[/code], les résultats " "de [code]deep_equal[/code] et [code]==[/code] sont les mêmes.\n" -"- Pour [code]Dictionary[/code], [code]==[/code] considère que l'égalité est " -"respéctée si et seulement si les deux variables pointent vers le même " -"[code]Dictionary[/code], sans recursion ou connaissance du contenu des " +"- Pour les [code]Dictionary[/code], [code]==[/code] considère que l'égalité " +"est respectée si et seulement si les deux variables pointent vers le même " +"[code]Dictionary[/code], sans récursion ou comparaison du contenu des " "variables.\n" -"- For [code]Array[/code], [code]==[/code] considère que l'égalité est " -"respéctée si et seulement si chaque élement du premier [code]Tableau[/code] " +"- Pour les [code]Array[/code], [code]==[/code] considère que l'égalité est " +"respectée si et seulement si chaque élément du premier [code]Array[/code] " "est égal à l'élément au même index du second [code]Array[/code], évalué par " -"[code]==[/code] lui même. Cela implique que [code]==[/code] recurses dans un " -"[code]Array[/code], mais pas dans un [code]Dictionary[/code].\n" +"[code]==[/code] lui-même. Cela implique un récursion avec [code]==[/code] " +"pour les [code]Array[/code], mais pas les [code]Dictionary[/code].\n" "Rapidement, dès qu'un [code]Dictionary[/code] est potentiellement impliqué, " "si une vraie comparaison du contenu est souhaité, il faut utiliser " "[code]deep_equal[/code]." @@ -608,7 +607,6 @@ msgstr "" "nouveau en une instance. Utile pour la désérialisation." #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Returns an \"eased\" value of [code]x[/code] based on an easing function " "defined with [code]curve[/code]. This easing function is based on an " @@ -634,13 +632,15 @@ msgstr "" "nombre à virgule flottante, avec des valeurs spécifiques conduisant aux " "comportements suivants:\n" "[codeblock]\n" -"- Inférieur à -1.0 (exclusif): Ease in-out\n" -"- 1.0: Linéaire\n" -"- Entre -1.0 et 0.0 (exclusif): Ease out-in\n" -"- 0.0: Constante\n" -"- Entre 0.0 et 1.0 (exclusif): Ease in\n" -"- 1.0: Linéaire\n" -"- Supérieur à 1.0 (exclusif): Ease out\n" +"- Inférieur à -1.0 (exclus) : Plus lent au début et à la fin (\"ease in-out\"" +")\n" +"- 1.0 : Linéaire\n" +"- Entre -1.0 et 0.0 (exclus) : Plus rapide au début et à la fin (\"ease out-" +"in\")\n" +"- 0.0 : Constante\n" +"- Entre 0.0 et 1.0 (exclus) : Plus lent au début (\"ease in\")\n" +"- 1.0 : Linéaire\n" +"- Supérieur à 1.0 (exclus) : Plus lent à la fin (\"ease out\")\n" "[/codeblock]\n" "[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/" "ease_cheatsheet.png]ease() curve values cheatsheet[/url]\n" @@ -1423,9 +1423,22 @@ msgstr "" "ou un avertissement est affiché." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Comme [method print], mais ne s'affiche que lorsqu'utilisé en mode débogage." +"Comme [method prunt], mais inclus la frame de la pile actuelle quand le " +"débogueur est activé.\n" +"La sortie dans la console ressemblerait à ceci :\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -1811,7 +1824,6 @@ msgstr "" "[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Returns the result of smoothly interpolating the value of [code]s[/code] " "between [code]0[/code] and [code]1[/code], based on the where [code]s[/code] " @@ -1837,25 +1849,26 @@ msgid "" "-1.6521) return values[/url]" msgstr "" "Retourne le résultat de l'interpolation douce de la valeur [code]s[/code] " -"entre [code]0[/code] et [code]1[/code], basée sur la position de [code]s[/" -"code] entre [code]from[/code] et [code]to[/code].\n" -"La valeur de retour est [code]0[/code] si [code]s <= from[/code], et " +"entre [code]0[/code] et [code]1[/code], basée sur la position de " +"[code]s[/code] entre [code]from[/code] et [code]to[/code].\n" +"La valeur retournée est [code]0[/code] si [code]s <= from[/code], et " "[code]1[/code] si [code]s >= to[/code]. Si [code]s[/code] se trouve entre " "[code]from[/code] et [code]to[/code], la valeur retournée suit une courbe en " -"S qui représente les positions de [code]s[/code] entre[code]0[/code] and " +"S qui représente les positions de [code]s[/code] entre[code]0[/code] et " "[code]1[/code].\n" -"Cette courbe en S est l'interpolateur cubique d'Hermite, obtenu par " -"[code]f(y) = 3*y^2 - 2*y^3[/code] où [code]y = (x-from) / (to-from)[/code].\n" -"[codeblock]\n" -"smoothstep(0, 2, -5.0) # Renvoie 0.0\n" -"smoothstep(0, 2, 0.5) # Renvoie 0.15625\n" -"smoothstep(0, 2, 1.0) # Renvoie 0.5\n" -"smoothstep(0, 2, 2.0) # Renvoie 1.0\n" +"Cette courbe en S est l'interpolation cubique d'Hermite, obtenu par la " +"fonction mathématique [code]f(y) = 3*y^2 - 2*y^3[/code] où [code]y = (x-from)" +" / (to-from)[/code].\n" +"[codeblock]\n" +"smoothstep(0, 2, -5.0) # Retourne 0.0\n" +"smoothstep(0, 2, 0.5) # Retourne 0.15625\n" +"smoothstep(0, 2, 1.0) # Retourne 0.5\n" +"smoothstep(0, 2, 2.0) # Retourne 1.0\n" "[/codeblock]\n" -"Comparé à [method ease] avec une valeur de courbe de [code]-1.6521[/code], " -"[method smoothstep] retourne la courbe la plus douce possible sans change " -"brusque dans la dérivée. Si vous avez besoin d'effectuer des transitions " -"plus avancées, utilisez [Tween] ou [AnimationPlayer].\n" +"Comparé à l'utilisateur [method ease] avec une valeur de courbe de [code]-1." +"6521[/code], [method smoothstep] retourne la courbe la plus douce possible, " +"sans changement brusque de dérivée. Si vous avez besoin d'effectuer des " +"transitions plus avancées, utilisez [Tween] ou [AnimationPlayer].\n" "[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/" "smoothstep_ease_comparison.png]Comparaison entre les valeurs retournées par " "smoothstep() et ease(x, -1.6521)[/url]" @@ -4497,13 +4510,12 @@ msgstr "" "les couches de physique 2D optionnellement nommées." #: doc/classes/@GlobalScope.xml -#, fuzzy msgid "" "Hints that an integer property is a bitmask using the optionally named 2D " "navigation layers." msgstr "" -"Indique qu'une propriété nombre entier est un masque de bits utilisant les " -"couches de rendu 2D optionnellement nommées." +"Indique qu'une propriété de nombre entier est un masque de bits indiquant " +"des calques de navigation 2D, qui peuvent être nommées." #: doc/classes/@GlobalScope.xml msgid "" @@ -4522,13 +4534,12 @@ msgstr "" "couches de physique 3D optionnellement nommées." #: doc/classes/@GlobalScope.xml -#, fuzzy msgid "" "Hints that an integer property is a bitmask using the optionally named 3D " "navigation layers." msgstr "" -"Indique qu'une propriété nombre entier est un masque de bits utilisant les " -"couches de rendu 2D optionnellement nommées." +"Indique qu'une propriété de nombre entier est un masque de bits indiquant " +"des calques de navigation 3D, qui peuvent être nommées." #: doc/classes/@GlobalScope.xml msgid "" @@ -4647,9 +4658,10 @@ msgid "The property is a translatable string." msgstr "La propriété est une chaîne de caractères traduisible." #: doc/classes/@GlobalScope.xml -#, fuzzy msgid "Used to group properties together in the editor. See [EditorInspector]." -msgstr "Utilisé pour rassembler des propriétés ensemble dans l'éditeur." +msgstr "" +"Utilisé pour rassembler des propriétés ensemble dans l'éditeur. Voir " +"[EditorInspector]." #: doc/classes/@GlobalScope.xml msgid "Used to categorize properties together in the editor." @@ -5430,10 +5442,11 @@ msgid "Maximum value for the mode enum." msgstr "Valeur maximale pour le mode énumeration." #: doc/classes/AnimatedSprite.xml -#, fuzzy msgid "" "Sprite node that contains multiple textures as frames to play for animation." -msgstr "NÅ“ud de sprite qui peut utiliser plusieurs textures pour l'animation." +msgstr "" +"Le nÅ“ud de sprite qui peut utiliser plusieurs textures pour jouer une " +"animation." #: doc/classes/AnimatedSprite.xml msgid "" @@ -7359,7 +7372,7 @@ msgstr "Le type de transition." #: doc/classes/AnimationNodeStateMachineTransition.xml msgid "The time to cross-fade between this state and the next." -msgstr "" +msgstr "La durée du fondu entre cet état et le suivant." #: doc/classes/AnimationNodeStateMachineTransition.xml msgid "Emitted when [member advance_condition] is changed." @@ -7502,9 +7515,8 @@ msgstr "" "processus." #: doc/classes/AnimationPlayer.xml -#, fuzzy msgid "Animation tutorial index" -msgstr "NÅ“ud d'animation." +msgstr "" #: doc/classes/AnimationPlayer.xml msgid "" @@ -8086,9 +8098,8 @@ msgstr "" "connectés à l'emplacement spécifié.." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the blend amount of a Blend2 node given its name." -msgstr "Retourne le nombre de clés d'une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8116,9 +8127,8 @@ msgstr "" "code]. Les enfants modifiés du node's continuent d'être animés." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the blend amount of a Blend3 node given its name." -msgstr "Retourne le nombre de clés d'une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8139,9 +8149,8 @@ msgstr "" "de B+ est à 0. À 1, la sortie est l'entrée B+." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the blend amount of a Blend4 node given its name." -msgstr "Retourne le nombre de clés d'une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8173,9 +8182,8 @@ msgid "Returns a [PoolStringArray] containing the name of all nodes." msgstr "Retourne un [PoolStringArray] contenant le nom de tous les nÅ“uds." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the mix amount of a Mix node given its name." -msgstr "Retourne le nombre de clés d'une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8221,23 +8229,20 @@ msgstr "" "position." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the autostart delay of a OneShot node given its name." -msgstr "Retourne la valeur d'une clé donnée dans une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "Returns the autostart random delay of a OneShot node given its name." msgstr "" #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the fade in time of a OneShot node given its name." -msgstr "Retourne le nom du nÅ“ud d'animation donné." +msgstr "" #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "Returns the fade out time of a OneShot node given its name." -msgstr "Retourne la valeur d'une clé donnée dans une piste donnée." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "Returns whether a OneShot node will auto restart given its name." @@ -8351,26 +8356,25 @@ msgstr "" "transition nommé [code]id[/code]." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "" "Returns the index of the currently evaluated input for the transition node " "with name [code]id[/code]." msgstr "" -"Retourne la distance la plus courte de l'avion à la position [code]point [/" -"code]." #: doc/classes/AnimationTreePlayer.xml msgid "" "Returns the number of inputs for the transition node with name [code]id[/" "code]. You can add inputs by right-clicking on the transition node." msgstr "" +"Retourne le nombre d'entrées pour le nÅ“ud de transition nommé [code]id[/" +"code]. Vous pouvez ajouter des entrées en faisant un clic droit sur le nÅ“ud " +"de transition." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "" "Returns the cross fade time for the transition node with name [code]id[/" "code]." -msgstr "Retourne le nom du nÅ“ud à [code]idx[/code]." +msgstr "" #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8378,21 +8382,23 @@ msgid "" "transition node with name [code]id[/code] is set to automatically advance to " "the next input upon completion." msgstr "" +"Retourne [code]true[/code] si l'entrée [code]input_idx[/code] du nÅ“ud de " +"transition nommé [code]id[/code] est définie pour avancer automatiquement " +"vers la prochaine entrée dès que la transition se termine." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "" "The transition node with name [code]id[/code] sets its current input at " "[code]input_idx[/code]." msgstr "" -"Change la position de l'index de la piste [code]idx[/code] à celui définie " -"par [code]to_idx[/code]." #: doc/classes/AnimationTreePlayer.xml msgid "" "The transition node with name [code]id[/code] advances to its next input " "automatically when the input at [code]input_idx[/code] completes." msgstr "" +"Le nÅ“ud de transition nommé [code]id[/code] avance à sa prochaine entrée " +"automatiquement lorsque l'entrée [code]input_idx[/code] se termine." #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8403,13 +8409,10 @@ msgstr "" "nommé [code]id[/code]." #: doc/classes/AnimationTreePlayer.xml -#, fuzzy msgid "" "The transition node with name [code]id[/code] sets its cross fade time to " "[code]time_sec[/code]." msgstr "" -"Change la position de l'index de la piste [code]idx[/code] à celui définie " -"par [code]to_idx[/code]." #: doc/classes/AnimationTreePlayer.xml msgid "" @@ -8490,6 +8493,10 @@ msgid "" "exiting. Can also alter or override local physics parameters (gravity, " "damping) and route audio to custom audio buses." msgstr "" +"La zone 3D qui détecte nÅ“uds [CollisionObject] qui se chevauchent, entrent " +"ou sortent. Peut également modifier ou surcharger les paramètres de physique " +"locale (gravité, amortissement) et passer l'audio à des bus audio " +"personnalisés." #: doc/classes/Area.xml doc/classes/QuadMesh.xml doc/classes/Viewport.xml #: doc/classes/ViewportTexture.xml @@ -8570,6 +8577,10 @@ msgid "" "See [member ProjectSettings.physics/3d/default_angular_damp] for more " "details about damping." msgstr "" +"La vitesse à laquelle les objets s'arrêtent de tourner dans cette zone. " +"Représente la vitesse angulaire perdue par seconde.\n" +"Voir [member ProjectSettings.physics/3d/default_angular_damp] pour plus de " +"détails sur l'amortissement." #: doc/classes/Area.xml doc/classes/Area2D.xml msgid "The name of the area's audio bus." @@ -8681,6 +8692,9 @@ msgid "" "be set to [code]true[/code].\n" "[code]area[/code] the other Area." msgstr "" +"Émis quand une autre Area entre dans cette zone. Nécessite [member " +"monitoring] d'être défini à [code]true[/code].\n" +"[code]area[/code] l'autre Area." #: doc/classes/Area.xml msgid "" @@ -8688,6 +8702,9 @@ msgid "" "be set to [code]true[/code].\n" "[code]area[/code] the other Area." msgstr "" +"Émis quand une autre Area quitte cette Area. Nécessite [member monitoring] " +"d'être défini à [code]true[/code].\n" +"[code]area[/code] l'autre Area." #: doc/classes/Area.xml msgid "" @@ -8855,6 +8872,14 @@ msgid "" "list is modified once during the physics step, not immediately after objects " "are moved. Consider using signals instead." msgstr "" +"Retourne la liste des intersections entre les [PhysiqueBody2D]. Le calque " +"[member CollisionObject2D.collision_layer] du corps entrant en intersection " +"doit être dans le masque [member CollisionObject2D.collision_mask] de ce " +"corps pour être détecté.\n" +"Pour des raisons de performance (les collisions sont toutes traitées en même " +"temps) cette liste est modifiée une fois pendant l'étape physique, pas " +"immédiatement après le déplacement des objets. Considérez plutôt " +"l'utilisation des signaux." #: doc/classes/Area2D.xml msgid "" @@ -8863,6 +8888,11 @@ msgid "" "For performance, the list of overlaps is updated once per frame and before " "the physics step. Consider using signals instead." msgstr "" +"Si [code]true[/code], la zone donnée recouvre la Area2D.\n" +"[b]Note :[/b] Le résultat de ce test n'est pas immédiat après le déplacement " +"des objets. Pour des raisons de performance, la liste des collisions est " +"mise à jour une fois par trame et avant l'étape physique. Considérez plutôt " +"l'utilisation des signaux." #: doc/classes/Area2D.xml msgid "" @@ -8913,6 +8943,10 @@ msgid "" "See [member ProjectSettings.physics/2d/default_linear_damp] for more details " "about damping." msgstr "" +"La vitesse à laquelle les objets arrêtent de se déplacer dans cette zone. " +"Représente la vitesse linéaire perdue par seconde.\n" +"Voir [member ProjectSettings.physics/2d/default_linear_damp] pour plus de " +"détails sur l'amortissement." #: doc/classes/Area2D.xml msgid "" @@ -8920,6 +8954,9 @@ msgid "" "to be set to [code]true[/code].\n" "[code]area[/code] the other Area2D." msgstr "" +"Émis quand une autre Area2D entre dans cette Area2D. Nécessite [member " +"monitoring] d'être défini à [code]true[/code].\n" +"[code]area[/code] l'autre Area2D." #: doc/classes/Area2D.xml msgid "" @@ -8927,6 +8964,9 @@ msgid "" "to be set to [code]true[/code].\n" "[code]area[/code] the other Area2D." msgstr "" +"Émis quand une autre Area2D quitte cette Area2D. Nécessite [member " +"monitoring] d'être défini à [code]true[/code].\n" +"[code]area[/code] l'autre Area2D." #: doc/classes/Area2D.xml msgid "" @@ -9532,7 +9572,7 @@ msgid "" "element, the slower [method pop_at] will be." msgstr "" "Retire et retourne l'élément du tableau à la [code]position[/code]. Si " -"négatif, [code]position[/code] part de la la fin du tableau vers le début. " +"négatif, [code]position[/code] part de la fin du tableau vers le début. " "Laisse le tableau intact et retourne [code]null[/code] si le tableau est " "vide ou s'il la position est en dehors des limites du tableau. Un message " "d'erreur est affiché lorsque la position est en dehors des limites du " @@ -9858,7 +9898,7 @@ msgstr "" #: doc/classes/ArrayMesh.xml msgid "Will regenerate normal maps for the [ArrayMesh]." -msgstr "" +msgstr "Régénérera les cartes normales pour le [ArrayMesh]." #: doc/classes/ArrayMesh.xml msgid "" @@ -9873,12 +9913,16 @@ msgid "" "Returns the length in indices of the index array in the requested surface " "(see [method add_surface_from_arrays])." msgstr "" +"Retourne la longueur des indices du tableau d'indices pour la surface " +"spécifiée (voir [method add_surface_from_arrays])." #: doc/classes/ArrayMesh.xml msgid "" "Returns the length in vertices of the vertex array in the requested surface " "(see [method add_surface_from_arrays])." msgstr "" +"Retourne la longueur des sommets du tableau des sommets dans la surface " +"spécifiée (voir [method add_surface_from_arrays])." #: doc/classes/ArrayMesh.xml msgid "" @@ -9926,7 +9970,7 @@ msgstr "" #: doc/classes/ArrayMesh.xml msgid "Sets the blend shape mode to one of [enum Mesh.BlendShapeMode]." -msgstr "" +msgstr "Définit le mode de forme de mélange avec [enum Mesh.BlendShapeMode]." #: doc/classes/ArrayMesh.xml doc/classes/PrimitiveMesh.xml msgid "" @@ -9939,10 +9983,8 @@ msgstr "" "lors de l'utilisation d'un shader qui décale les sommets." #: doc/classes/ArrayMesh.xml -#, fuzzy msgid "Value used internally when no indices are present." -msgstr "" -"La valeur par défaut utilisée pour index_array_len quand il n'y pas d'indice." +msgstr "La valeur par défaut utilisée en interne quand il n'y pas d'indice." #: doc/classes/ArrayMesh.xml msgid "Amount of weights/bone indices per vertex (always 4)." @@ -10165,7 +10207,6 @@ msgstr "" "constamment mise à jour [code]mesh_updated[/code]." #: doc/classes/ARVRCamera.xml -#, fuzzy msgid "" "A camera node with a few overrules for AR/VR applied, such as location " "tracking." @@ -10324,14 +10365,14 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" "L'intensité de vibration du contrôleur. L'intervalle va de [code]0.0[/code] " -"à [code]1.0[/code] avec une précision de [code]0.01[/code]. Si changé, met à " -"jour [membrez ARVRPositionalTracker.rumble] en conséquence.\n" +"à [code]1.0[/code]. Si changé, [member ARVRPositionalTracker.rumble] sera " +"mis à jour en conséquence.\n" "C'est une propriété utile à animer si vous souhaitez que le contrôleur vibre " "pendant une durée limitée." @@ -10501,6 +10542,7 @@ msgstr "Cette interface est compatible avec le rendu stéréoscopique." #: doc/classes/ARVRInterface.xml msgid "This interface supports AR (video background and real world tracking)." msgstr "" +"Cette interface supporte la AR (arrière-plan vidéo et suivi du monde réel)." #: doc/classes/ARVRInterface.xml msgid "" @@ -10577,9 +10619,8 @@ msgstr "" "lumières sont éteintes, etc.)." #: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml -#, fuzzy msgid "GDNative wrapper for an ARVR interface." -msgstr "Classe de base pour une implémentation d’interface AR / VR." +msgstr "L'encapsulation GDNative pour les interfaces ARVR." #: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml msgid "" @@ -10865,7 +10906,7 @@ msgid "" msgstr "" "Retourne l'horodatage absolu (en μs) de la dernière mise à jour des yeux AR/" "VR du [ARVRServer] envoyée au [VisualServer]. La valeur est récupérée via un " -"appel interne à [method OS.get_ticks_usec]" +"appel interne à [method OS.get_ticks_usec]." #: doc/classes/ARVRServer.xml msgid "" @@ -10885,7 +10926,7 @@ msgid "" msgstr "" "Retourne l'horodatage absolu (en μs) du dernier appel de mise à jour du " "[ARVRServer]. La valeur vient est récupérée via un appel interne à [method " -"OS.get_ticks_usec]" +"OS.get_ticks_usec]." #: doc/classes/ARVRServer.xml msgid "" @@ -11011,7 +11052,6 @@ msgstr "" "position du joueur." #: doc/classes/AspectRatioContainer.xml -#, fuzzy msgid "Container that preserves its child controls' aspect ratio." msgstr "Un conteneur qui préserve le ratio d'aspect des contrôles enfants." @@ -11034,19 +11074,16 @@ msgstr "" #: doc/classes/PanelContainer.xml doc/classes/ScrollContainer.xml #: doc/classes/SplitContainer.xml doc/classes/TabContainer.xml #: doc/classes/VBoxContainer.xml doc/classes/VSplitContainer.xml -#, fuzzy msgid "GUI containers" -msgstr "Conteneur à onglets." +msgstr "Conteneurs d'interface" #: doc/classes/AspectRatioContainer.xml -#, fuzzy msgid "Specifies the horizontal relative position of child controls." -msgstr "La séparation horizontale des nÅ“uds enfants." +msgstr "Définit la position horizontale relative des nÅ“uds enfants." #: doc/classes/AspectRatioContainer.xml -#, fuzzy msgid "Specifies the vertical relative position of child controls." -msgstr "La séparation verticale des nÅ“uds enfants." +msgstr "Définit la position verticale relative des nÅ“uds enfants." #: doc/classes/AspectRatioContainer.xml msgid "" @@ -11097,19 +11134,17 @@ msgstr "" "de limiter la visibilité à seulement la taille du conteneur." #: doc/classes/AspectRatioContainer.xml -#, fuzzy msgid "" "Aligns child controls with the beginning (left or top) of the container." -msgstr "Aligne les enfants avec le début du conteneur." +msgstr "Aligne les enfants au début (à gauche ou en haut) du conteneur." #: doc/classes/AspectRatioContainer.xml msgid "Aligns child controls with the center of the container." msgstr "Aligne les contrôles enfants au centre du conteneur." #: doc/classes/AspectRatioContainer.xml -#, fuzzy msgid "Aligns child controls with the end (right or bottom) of the container." -msgstr "Aligne les enfants avec le centre du conteneur." +msgstr "Aligne les enfants à la fin (à droite ou en-bas) du conteneur." #: doc/classes/AStar.xml msgid "" @@ -11406,6 +11441,8 @@ msgid "" "Returns the capacity of the structure backing the points, useful in " "conjunction with [code]reserve_space[/code]." msgstr "" +"Retourne la capacité de la structure qui garde les points en cache, utile " +"avec [code]reserve_space[/code]." #: doc/classes/AStar.xml msgid "" @@ -11468,6 +11505,8 @@ msgid "" "Returns the weight scale of the point associated with the given [code]id[/" "code]." msgstr "" +"Retourne l'échelle de poids du point associé pour le [code]id[/code] " +"spécifié." #: doc/classes/AStar.xml doc/classes/AStar2D.xml msgid "Returns an array of all points." @@ -11484,6 +11523,8 @@ msgid "" "Returns whether a point is disabled or not for pathfinding. By default, all " "points are enabled." msgstr "" +"Retourne si un point est désactivé ou non pour le calcul du chemin. Par " +"défaut, tous les points sont activés." #: doc/classes/AStar.xml doc/classes/AStar2D.xml msgid "" @@ -11499,6 +11540,9 @@ msgid "" "you're adding a known large number of points at once, for a grid for " "instance. New capacity must be greater or equals to old capacity." msgstr "" +"Réserve l'espace interne pour [code]num_nodes[/code] points, utile si vous " +"voulez ajouter un grand nombre de points à la fois, pour une grille par " +"exemple. La nouvelle capacité doit être supérieure ou égale à l'ancienne." #: doc/classes/AStar.xml doc/classes/AStar2D.xml msgid "" @@ -11585,14 +11629,13 @@ msgstr "" "position et sont facteur de poids seront mis à jour avec la valeur donnée." #: doc/classes/AStar2D.xml -#, fuzzy msgid "" "Returns whether there is a connection/segment between the given points. If " "[code]bidirectional[/code] is [code]false[/code], returns whether movement " "from [code]id[/code] to [code]to_id[/code] is possible through this segment." msgstr "" "Retourne si les deux points donnés sont directement reliés par un segment. " -"Si [code]bidirectionnel[/code] est [code]false[/code], retourne si le " +"Si [code]bidirectional[/code] est [code]false[/code], retourne si le " "mouvement d'identifiant [code]id[/code] vers l'autre identifiant " "[code]to_id[/code] est possible par ce segment." @@ -11780,11 +11823,10 @@ msgstr "" "sont ignorés pour les AtlasTexture." #: doc/classes/AtlasTexture.xml -#, fuzzy msgid "The texture that contains the atlas. Can be any [Texture] subtype." msgstr "" -"La texture qui contient l'atlas. Peut être de n'importe quel sous-type " -"[Texture2D]." +"La texture qui contient l'atlas. Peut être de n'importe quel sous-type de " +"[Texture]." #: doc/classes/AtlasTexture.xml msgid "" @@ -11859,6 +11901,9 @@ msgid "" "Limits the frequencies in a range around the [member AudioEffectFilter." "cutoff_hz] and allows frequencies outside of this range to pass." msgstr "" +"Limite l'intensité des fréquences dans la gamme autour de [member " +"AudioEffectFilter.cutoff_hz], et permet aux fréquences en dehors de cette " +"gamme de passer." #: doc/classes/AudioEffectBandPassFilter.xml msgid "Adds a band pass filter to the audio bus." @@ -11869,6 +11914,9 @@ msgid "" "Attenuates the frequencies inside of a range around the [member " "AudioEffectFilter.cutoff_hz] and cuts frequencies outside of this band." msgstr "" +"Atténue les fréquences à l'intérieur de la gamme autour de [member " +"AudioEffectFilter.cutoff_hz] et coupe les fréquences en dehors de cette " +"gamme." #: doc/classes/AudioEffectCapture.xml msgid "Captures audio from an audio bus in real-time." @@ -11913,9 +11961,8 @@ msgstr "" "pas assez de données disponibles." #: doc/classes/AudioEffectCapture.xml -#, fuzzy msgid "Returns the total size of the internal ring buffer in frames." -msgstr "Renvoie le reste de deux vecteurs." +msgstr "" #: doc/classes/AudioEffectCapture.xml msgid "" @@ -11926,15 +11973,13 @@ msgstr "" "mémoire est pleine." #: doc/classes/AudioEffectCapture.xml -#, fuzzy msgid "" "Returns the number of frames available to read using [method get_buffer]." -msgstr "Retourne le nombre de formes assignées à une zone." +msgstr "" #: doc/classes/AudioEffectCapture.xml -#, fuzzy msgid "Returns the number of audio frames inserted from the audio bus." -msgstr "Renvoie le nombre de points sur l'axe de mélange." +msgstr "" #: doc/classes/AudioEffectCapture.xml msgid "" @@ -12058,6 +12103,9 @@ msgid "" "Compressor's delay time to stop reducing the signal after the signal level " "falls below the threshold, in milliseconds. Value can range from 20 to 2000." msgstr "" +"Le retard du compresseur avant d'arrêter de réduire le signal après que le " +"niveau de signal sous le seuil, en millisecondes. La valeur peut aller de 20 " +"à 2000." #: doc/classes/AudioEffectCompressor.xml msgid "Reduce the sound level using another audio bus for threshold detection." @@ -12090,6 +12138,10 @@ msgid "" "echo. Delay effects range from a subtle echo effect to a pronounced blending " "of previous sounds with new sounds." msgstr "" +"Joue le signal d'entrée après une période de temps. Le signal retardé peut " +"être joué plusieurs fois pour créer un écho qui s'amortit dans le temps. Les " +"effets de retard vont d'un subtil écho à un mélange prononcé de sons " +"précédents avec les nouveaux sons." #: doc/classes/AudioEffectDelay.xml msgid "" @@ -12128,6 +12180,8 @@ msgid "" "Pan position for [code]tap1[/code]. Value can range from -1 (fully left) to " "1 (fully right)." msgstr "" +"La position gauche-droite pour [code]tap1[/code]. La valeur peut aller de -1 " +"(complètement à gauche) à 1 (complètement à droite)." #: doc/classes/AudioEffectDelay.xml msgid "If [code]true[/code], [code]tap2[/code] will be enabled." @@ -12146,6 +12200,8 @@ msgid "" "Pan position for [code]tap2[/code]. Value can range from -1 (fully left) to " "1 (fully right)." msgstr "" +"La position gauche-droite pour [code]tap2[/code]. La valeur peut aller de -1 " +"(complètement à gauche) à 1 (complètement à droite)." #: doc/classes/AudioEffectDistortion.xml msgid "" @@ -12488,15 +12544,22 @@ msgid "" "Attenuates frequencies in a narrow band around the [member AudioEffectFilter." "cutoff_hz] and cuts frequencies outside of this range." msgstr "" +"Atténue les fréquences dans une bande étroite autour du [member " +"AudioEffectFilter.cutoff_hz] et coupe les fréquences en dehors de cette " +"gamme." #: doc/classes/AudioEffectPanner.xml msgid "Adds a panner audio effect to an Audio bus. Pans sound left or right." msgstr "" +"Ajoute un effet audio de balance à un bus audio. Balance les sons à gauche " +"ou à droite." #: doc/classes/AudioEffectPanner.xml msgid "" "Determines how much of an audio signal is sent to the left and right buses." msgstr "" +"Détermine quelle quantité d'un signal audio est envoyé aux bus de gauche et " +"de droite." #: doc/classes/AudioEffectPanner.xml msgid "Pan position. Value can range from -1 (fully left) to 1 (fully right)." @@ -12510,6 +12573,9 @@ msgid "" "Combines the original signal with a copy that is slightly out of phase with " "the original." msgstr "" +"Ajoute un effet audio de phaseur à un bus audio.\n" +"Combine le signal original avec une copie de l'original légèrement hors " +"phase." #: doc/classes/AudioEffectPhaser.xml msgid "" @@ -12914,7 +12980,6 @@ msgid "Returns the names of all audio devices detected on the system." msgstr "Retourne les noms de tous les appareils audio détectés sur le système." #: doc/classes/AudioServer.xml -#, fuzzy msgid "Returns the sample rate at the output of the [AudioServer]." msgstr "Retourne le débit de sortie du [AudioServer]." @@ -13199,14 +13264,11 @@ msgstr "" "pour lire l'audio généré en temps réel." #: doc/classes/AudioStreamGeneratorPlayback.xml -#, fuzzy msgid "" "Returns [code]true[/code] if a buffer of the size [code]amount[/code] can be " "pushed to the audio sample data buffer without overflowing it, [code]false[/" "code] otherwise." msgstr "" -"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] " -"existe, [code]false[/code] autrement." #: doc/classes/AudioStreamGeneratorPlayback.xml msgid "Clears the audio sample data buffer." @@ -13248,9 +13310,8 @@ msgstr "" "[i]moins[/i] efficace avec GDScript." #: modules/minimp3/doc_classes/AudioStreamMP3.xml -#, fuzzy msgid "MP3 audio stream driver." -msgstr "Pilote de flux audio OGG Vorbis." +msgstr "Le pilote de flux audio MP3." #: modules/minimp3/doc_classes/AudioStreamMP3.xml #: modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -13334,8 +13395,14 @@ msgstr "" "scènes." #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." -msgstr "Bus sur lequel cet audio joue." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer.xml msgid "" @@ -13548,8 +13615,14 @@ msgstr "" "ajouté à la scène." #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." -msgstr "Le bus sur lequel cet audio est joué." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -13585,7 +13658,7 @@ msgstr "" #: doc/classes/AudioStreamPlayer3D.xml msgid "Sets the absolute maximum of the soundlevel, in decibels." -msgstr "" +msgstr "Définit le maximum absolu du niveau sonore, en décibels." #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -13617,13 +13690,15 @@ msgstr "" #: doc/classes/AudioStreamPlayer3D.xml msgid "The base sound level unaffected by dampening, in decibels." -msgstr "" +msgstr "Le niveau sonore de base non affecté par l'amortissement, en décibels." #: doc/classes/AudioStreamPlayer3D.xml msgid "" "The factor for the attenuation effect. Higher values make the sound audible " "over a larger distance." msgstr "" +"Le facteur pour l'effet d'atténuation. Des valeurs plus élevées rendent le " +"son audible sur une distance plus grande." #: doc/classes/AudioStreamPlayer3D.xml msgid "Linear dampening of loudness according to distance." @@ -13654,6 +13729,10 @@ msgid "" "but keeps the sound playing at the correct position if the camera leaves and " "enters the [AudioStreamPlayer3D]'s [member max_distance] radius." msgstr "" +"Mélanger ce son, même lorsqu'il est hors de portée. Cela augmente " +"l'utilisation de CPU, mais garde le son à la bonne position de lecture si la " +"caméra quitte puis entre à nouveau dans le rayon [member max_distance] du " +"[AudioStreamPlayer3D]." #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -13661,6 +13740,9 @@ msgid "" "will cause the sound to restart if the camera leaves and enters the " "[AudioStreamPlayer3D]'s [member max_distance] radius." msgstr "" +"Pause ce son quand il hors de portée. Cela diminue l'utilisation du CPU, " +"mais cela fera redémarrer le son si la caméra quitte puis entre dans le " +"rayon [member max_distance] du [AudioStreamPlayer3D]." #: doc/classes/AudioStreamPlayer3D.xml msgid "Disables doppler tracking." @@ -14029,9 +14111,8 @@ msgstr "" "[constant ENVIRONMENT_MODE_CUSTOM_SKY]." #: doc/classes/BakedLightmap.xml -#, fuzzy msgid "The rotation of the baked custom sky." -msgstr "La racine de la scène éditée." +msgstr "" #: doc/classes/BakedLightmap.xml msgid "" @@ -14057,6 +14138,8 @@ msgid "" "Deprecated, in previous versions it determined the location where lightmaps " "were be saved." msgstr "" +"Obsolète, dans les versions précédentes ça déterminait l'emplacement où les " +"textures de lumière étaient enregistrées." #: doc/classes/BakedLightmap.xml msgid "The calculated light data." @@ -14094,6 +14177,15 @@ msgid "" "lightmap banding even when using the GLES2 backend or if [member " "ProjectSettings.rendering/quality/depth/hdr] is [code]false[/code]." msgstr "" +"Si [code]true[/code], enregistre les textures de lumière dans un format de " +"plage dynamique élevée (type EXR). Si [code]false[/code], enregistre les " +"textures de lumière dans une image PNG de plage dynamique faible. Ceci peut " +"être défini à [code]false[/code] pour réduire l'usage du disque, mais les " +"valeurs lumineuses supérieures à 1.0 seront limitées et vous pouvez voir un " +"effet de bandes qui apparaissent à cause de cette précision réduite.\n" +"[b]Note :[/b] Définir [member use_hdr] à [code]true[/code] réduira l'effet " +"de bandes même sous GLES2 ou quand [member ProjectSettings.rendering/quality/" +"depth/hdr] est [code]false[/code]." #: doc/classes/BakedLightmap.xml msgid "The lowest bake quality mode. Fastest to calculate." @@ -14120,15 +14212,17 @@ msgid "" "Returns if no viable save path is found. This can happen where an [member " "image_path] is not specified or when the save location is invalid." msgstr "" +"Retourne si aucun chemin d'enregistrement invalid n'est trouvé. Cela peut se " +"produire lorsqu'un [member image_path] n'est pas spécifié ou lorsque " +"l'emplacement de sauvegarde est invalide." #: doc/classes/BakedLightmap.xml doc/classes/SpatialMaterial.xml msgid "Currently unused." msgstr "Actuellement inutilisé." #: doc/classes/BakedLightmap.xml -#, fuzzy msgid "Returns when the baker cannot save per-mesh textures to file." -msgstr "Renvoie l'arc tangente des paramètres." +msgstr "" #: doc/classes/BakedLightmap.xml msgid "The size of the generated lightmaps is too large." @@ -14229,7 +14323,6 @@ msgstr "" "défini par l'enumération [enum DrawMode]." #: doc/classes/BaseButton.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the mouse has entered the button and has not " "left it yet." @@ -14342,6 +14435,8 @@ msgid "" "If [code]true[/code], the button is in toggle mode. Makes the button flip " "state between pressed and unpressed each time its area is clicked." msgstr "" +"Si [code]true[/code], le bouton est en mode basculement. Fait basculer le " +"bouton entre les états pressé et non-pressé chaque fois qu'il est cliqué." #: doc/classes/BaseButton.xml msgid "Emitted when the button starts being held down." @@ -14359,6 +14454,11 @@ msgid "" "If you need to know the button's pressed state (and [member toggle_mode] is " "active), use [signal toggled] instead." msgstr "" +"Émis quand le bouton est basculé ou pressé. Émis lors de [signal " +"button_down] si [member action_mode] est [constant ACTION_MODE_BUTTON_PRESS] " +"et lors de [signal button_up] sinon.\n" +"Si vous avez besoin de connaître l'état du bouton (et que [member " +"toggle_mode] est actif), utilisez plutôt [signal toggled]." #: doc/classes/BaseButton.xml msgid "" @@ -14366,6 +14466,9 @@ msgid "" "(only if [member toggle_mode] is active). The new state is contained in the " "[code]button_pressed[/code] argument." msgstr "" +"Émis lorsque le bouton a été juste basculé entre les états pressé et normal " +"(seulement si [member toggle_mode] est actif). Le nouvel état est passé dans " +"l'argument [code]button_pressed[/code]." #: doc/classes/BaseButton.xml msgid "" @@ -14606,6 +14709,10 @@ msgid "" "[b]Note:[/b] This results in a multiplication by the inverse of the matrix " "only if it represents a rotation-reflection." msgstr "" +"Retourne un vecteur transformé (multiplié) par la matrice de base " +"transposée.\n" +"[b]Note :[/b] Cela entraîne une multiplication par l'inverse de la matrice " +"seulement si elle représente une rotation-réflexion." #: doc/classes/Basis.xml doc/classes/Transform2D.xml msgid "" @@ -14772,6 +14879,10 @@ msgid "" "Supports distance fields. For using vector font files like TTF directly, see " "[DynamicFont]." msgstr "" +"Rend le texte en utilisant les atlas des texture contenues dans le fichier " +"[code]*.fnt[/code]. Supporte les champs de distance. Pour utiliser " +"directement des fichiers de police vectorielles, comme le TTF, voir " +"[DynamicFont]." #: doc/classes/BitmapFont.xml msgid "" @@ -14781,6 +14892,11 @@ msgid "" "alignment for the character and [code]advance[/code] is the (optional) " "advance." msgstr "" +"Ajoute un caractère à la police, où [code]character[/code] est la valeur " +"Unicode, [code]texture[/code] est l'index de la texture, [code]rect[/code] " +"est la région de la texture (en pixels !), [code]align[/code] est " +"l'alignement (optionnel) du caractère et [code]advance[/code] est " +"l'avancement (optionnel)." #: doc/classes/BitmapFont.xml msgid "" @@ -14851,6 +14967,17 @@ msgid "" "menu option, from the code, you need to iterate over the bones to set their " "individual rest poses." msgstr "" +"Utilise une hiérarchie [code]Bone2D[/code] liée à un [Skeleton2D] pour " +"contrôler et animer d'autres nÅ“uds [Node2D].\n" +"Vous pouvez utiliser les nÅ“uds [code]Bone2D[/code] et [code]Skeleton2D[/" +"code] pour animer les maillages 2D créées avec l'éditeur d'UV de Polygon " +"2D.\n" +"Chaque os a une transformation de repos [member rest] que vous pouvez " +"réinitialiser avec [method apply_rest]. Ces poses de repos sont par rapport " +"au parent de l'os.\n" +"Si dans l'éditeur vous pouvez définir la pose de repos d'un squelette entier " +"en utilisant une option de menu, à partir du code, vous devez itérer sur les " +"os pour définir leurs poses de repos individuelles." #: doc/classes/Bone2D.xml msgid "Stores the node's current transforms in [member rest]." @@ -15329,14 +15456,12 @@ msgid "Returns the current pressed button." msgstr "Renvoie le bouton actuellement enfoncé." #: doc/classes/ButtonGroup.xml -#, fuzzy msgid "Emitted when one of the buttons of the group is pressed." -msgstr "Émis lorsqu’un bouton de ce contrôleur est appuyé." +msgstr "Émis lorsqu’un des boutons de ce groupe est appuyé." #: doc/classes/CallbackTweener.xml -#, fuzzy msgid "Calls the specified method after optional delay." -msgstr "Verrouille l'axe linéaire et de rotation spécifié." +msgstr "Appelle la méthode spécifiée après un délai optionnel." #: doc/classes/CallbackTweener.xml msgid "" @@ -15439,6 +15564,9 @@ msgid "" "[b]Note:[/b] A position which returns [code]false[/code] may still be " "outside the camera's field of view." msgstr "" +"Retourne [code]true[/code] si la position donnée est derrière la caméra.\n" +"[b]Note :[/b] Une position qui retourne [code]false[/code] peut quand même " +"être en dehors du champ de vision de la caméra." #: doc/classes/Camera.xml msgid "" @@ -15446,6 +15574,10 @@ msgid "" "description). If the camera node is outside the scene tree, it will attempt " "to become current once it's added." msgstr "" +"Fait que cette caméra devient l'actuelle pour le [Viewport] (voir la " +"description de la classe). Si le nÅ“ud de la caméra est en dehors de " +"l'arborescence de la scène, il tentera de devenir l'actuel dès qu'il sera " +"ajouté." #: doc/classes/Camera.xml msgid "" @@ -15460,6 +15592,9 @@ msgid "" "the [Viewport] rectangle on a plane that is the given [code]z_depth[/code] " "distance into the scene away from the camera." msgstr "" +"Retourne le point 3D dans l'espace global qui correspond à la coordonnées 2D " +"donnée dans le rectangle du [Viewport] sur un plan qui est à la distance " +"[code]z_depth[/code] donnée dans la scène par rapport à la caméra." #: doc/classes/Camera.xml msgid "" @@ -15468,6 +15603,10 @@ msgid "" "useful for casting rays in the form of (origin, normal) for object " "intersection or picking." msgstr "" +"Retourne la normale dans l'espace global, qui est le résultat de la " +"projection d'un point sur le rectangle [Viewport] par la projection inverse " +"de la caméra. Ceci est utile pour lancer des rayons sous la forme (origine, " +"normale) pour l'intersection ou la sélection d'objets." #: doc/classes/Camera.xml msgid "" @@ -15476,6 +15615,10 @@ msgid "" "useful for casting rays in the form of (origin, normal) for object " "intersection or picking." msgstr "" +"Retourne la position 3D dans l'espace global, qui est le résultat de " +"projeter un point sur le rectangle [Viewport] par la projection inverse de " +"la caméra. Ceci est utile pour lancer des rayons sous la forme (origine, " +"normale) pour l'intersection ou la sélection d'objets." #: doc/classes/Camera.xml msgid "" @@ -15546,9 +15689,13 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" -"Si [code]true[/code], l’ancêtre [Viewport] utilise actuellement cette caméra." #: doc/classes/Camera.xml msgid "" @@ -15620,6 +15767,8 @@ msgid "" "The axis to lock during [member fov]/[member size] adjustments. Can be " "either [constant KEEP_WIDTH] or [constant KEEP_HEIGHT]." msgstr "" +"L'axe à verrouiller pendant les réglages [member fov] ou [member size]. Peut " +"être soit [constant KEEP_WIDTH] ou [constant KEEP_HEIGHT]." #: doc/classes/Camera.xml msgid "" @@ -15633,6 +15782,9 @@ msgid "" "objects' Z distance from the camera's local space scales their perceived " "size." msgstr "" +"Le mode de projection de la caméra. Dans le mode [constant " +"PROJECTION_PERSPECTIVE], la distance des objets dans l'espace local de la " +"caméra détermine la taille apparante de ces objets." #: doc/classes/Camera.xml msgid "" @@ -15640,6 +15792,10 @@ msgid "" "orthogonal and frustum modes. Since [member keep_aspect] locks on axis, " "[code]size[/code] sets the other axis' size length." msgstr "" +"La taille de la caméra mesurée comme la moitié de la largeur ou de la " +"hauteur. N'est applicable qu'en modes orthogonal et frustum. Comme [member " +"keep_aspect] verrouille l'axe, [code]size[/code] fixe la longueur de la " +"taille sur l'autre axe." #: doc/classes/Camera.xml msgid "The vertical (Y) offset of the camera viewport." @@ -15658,6 +15814,9 @@ msgid "" "Orthogonal projection, also known as orthographic projection. Objects remain " "the same size on the screen no matter how far away they are." msgstr "" +"La projection orthogonale, également connue sous le nom de projection " +"orthographique. Les objets gardent la même taille à l'écran, indépendamment " +"de leur distance." #: doc/classes/Camera.xml msgid "" @@ -15678,6 +15837,10 @@ msgid "" "usually the best option for projects running in landscape mode, as wider " "aspect ratios will automatically benefit from a wider horizontal FOV." msgstr "" +"Préserve le rapport d'aspect vertical ; également connu sous le nom " +"d'échelle Hor+. C'est généralement la meilleure option pour les projets en " +"mode paysage, car les ratios d'aspect plus larges bénéficieront " +"automatiquement d'un champ de vision horizontal plus large." #: doc/classes/Camera.xml msgid "" @@ -15778,6 +15941,11 @@ msgid "" "or [member Node2D.global_position], as it is affected by the [code]drag[/" "code] properties." msgstr "" +"Retourne la [code]position[/code] de la caméra (le point suivi que la caméra " +"essaye de suivre), par rapport à l'origine.\n" +"[b]Note :[/b] La valeur retournée n'est pas la même que [member Node2D." +"position] ou [member Node2D.global_position], car elle est aussi affectée " +"par les propriétés [code]drag[/code]." #: doc/classes/Camera2D.xml msgid "" @@ -15786,12 +15954,18 @@ msgid "" "[b]Note:[/b] The real [code]position[/code] of the camera may be different, " "see [method get_camera_position]." msgstr "" +"Retourne l'emplacement du centre de l'écran de la [Camera2D], par rapport à " +"l'origine.\n" +"[b]Note :[/b] La véritable [code]position[/code] de la caméra peut être " +"différente, voir [method get_camera_position]." #: doc/classes/Camera2D.xml msgid "" "Returns the specified margin. See also [member drag_margin_bottom], [member " "drag_margin_top], [member drag_margin_left], and [member drag_margin_right]." msgstr "" +"Retourne la marge spécifiée. Voir aussi [member drag_margin_bottom], [member " +"drag_margin_top], [member drag_margin_left], et [member drag_margin_right]." #: doc/classes/Camera2D.xml msgid "" @@ -15862,24 +16036,36 @@ msgid "" "drag margins. If [code]false[/code], the camera moves horizontally " "regardless of margins." msgstr "" +"Si [code]true[/code], la caméra ne bouge que lorsqu'elle atteint les marges " +"horizontales de glissage. Si [code]false[/code], la caméra se déplace " +"horizontalement indépendamment des marges." #: doc/classes/Camera2D.xml msgid "" "Left margin needed to drag the camera. A value of [code]1[/code] makes the " "camera move only when reaching the edge of the screen." msgstr "" +"La marge gauche nécessaire pour glisser la caméra. Une valeur de " +"[code]1[/code] ne déplace la caméra que lorsqu'elle atteint le bord de " +"l'écran." #: doc/classes/Camera2D.xml msgid "" "Right margin needed to drag the camera. A value of [code]1[/code] makes the " "camera move only when reaching the edge of the screen." msgstr "" +"La marge droite nécessaire pour glisser la caméra. Une valeur de " +"[code]1[/code] ne déplace la caméra que lorsqu'elle atteint le bord de " +"l'écran." #: doc/classes/Camera2D.xml msgid "" "Top margin needed to drag the camera. A value of [code]1[/code] makes the " "camera move only when reaching the edge of the screen." msgstr "" +"La marge supérieure nécessaire pour glisser la caméra. Une valeur de " +"[code]1[/code] ne déplacer la caméra que lorsqu'elle atteint le bord de " +"l'écran." #: doc/classes/Camera2D.xml msgid "" @@ -15887,16 +16073,23 @@ msgid "" "margins. If [code]false[/code], the camera moves vertically regardless of " "margins." msgstr "" +"Si [code]true[/code], la caméra ne bouge que lorsqu'elle atteint les marges " +"verticales de glissage. Si [code]false[/code], la caméra se déplace " +"verticalement indépendamment des marges." #: doc/classes/Camera2D.xml msgid "" "If [code]true[/code], draws the camera's drag margin rectangle in the editor." msgstr "" +"Si [code]true[/code], dessine le rectangle de la marge de glissage de la " +"caméra activée dans l'éditeur." #: doc/classes/Camera2D.xml msgid "" "If [code]true[/code], draws the camera's limits rectangle in the editor." msgstr "" +"Si [code]true[/code], dessine le rectangle des limites de la caméra activée " +"dans l'éditeur." #: doc/classes/Camera2D.xml msgid "" @@ -15966,12 +16159,19 @@ msgid "" "not updated in any way if drag margins are enabled and can be used to set " "initial offset." msgstr "" +"Le décalage horizontal de la caméra, par rapport aux marges de glissage.\n" +"[b]Note :[/b] Le décalage H est utilisé uniquement pour forcer le décalage " +"par rapport aux marges. Elle n'est pas mise à jour même si les marges de " +"glissage sont activées et peuvent être utilisées pour régler le décalage " +"initial." #: doc/classes/Camera2D.xml msgid "" "The vertical offset of the camera, relative to the drag margins.\n" "[b]Note:[/b] Used the same as [member offset_h]." msgstr "" +"Le décalage vertical de la caméra, par rapport aux marges de glissage.\n" +"[b]Note :[/b] Utilisé de la même manière que [member offset_h]." #: doc/classes/Camera2D.xml msgid "The camera's process callback. See [enum Camera2DProcessMode]." @@ -15979,9 +16179,8 @@ msgstr "" "La méthode de mise à jour de la camera. Voir [enum Camera2DProcessMode]." #: doc/classes/Camera2D.xml -#, fuzzy msgid "If [code]true[/code], the camera view rotates with the target." -msgstr "Si [code]true[/code], le bouton \"add preset\" est activé." +msgstr "" #: doc/classes/Camera2D.xml msgid "" @@ -16069,9 +16268,8 @@ msgid "Returns the unique ID for this feed." msgstr "Retourne l'identifiant unique de ce flux." #: doc/classes/CameraFeed.xml -#, fuzzy msgid "Returns the camera's name." -msgstr "Renvoie le nom de l'élément." +msgstr "Retourne le nom de la caméra." #: doc/classes/CameraFeed.xml msgid "Returns the position of camera on the device." @@ -16141,20 +16339,18 @@ msgstr "" "iOS. Sur les autres plates-formes, aucun [CameraFeed] ne sera disponible." #: doc/classes/CameraServer.xml -#, fuzzy msgid "Adds the camera [code]feed[/code] to the camera server." -msgstr "Ajoute un [Shape2D] au propriétaire de la forme." +msgstr "" #: doc/classes/CameraServer.xml msgid "Returns an array of [CameraFeed]s." msgstr "Retourne un tableau de [CameraFeed]s." #: doc/classes/CameraServer.xml -#, fuzzy msgid "" "Returns the [CameraFeed] corresponding to the camera with the given " "[code]index[/code]." -msgstr "Retourne la position du point à l'index [code]point[/code]." +msgstr "" #: doc/classes/CameraServer.xml msgid "Returns the number of [CameraFeed]s registered." @@ -16165,14 +16361,12 @@ msgid "Removes the specified camera [code]feed[/code]." msgstr "Supprime le flux de caméra [code]feed[/code] spécifié." #: doc/classes/CameraServer.xml -#, fuzzy msgid "Emitted when a [CameraFeed] is added (e.g. a webcam is plugged in)." -msgstr "Émis lorsqu'une interface est supprimée." +msgstr "" #: doc/classes/CameraServer.xml -#, fuzzy msgid "Emitted when a [CameraFeed] is removed (e.g. a webcam is unplugged)." -msgstr "Émis lorsqu'une interface est supprimée." +msgstr "" #: doc/classes/CameraServer.xml msgid "The RGBA camera image." @@ -16202,6 +16396,10 @@ msgid "" "[b]Note:[/b] Many cameras supply YCbCr images which need to be converted in " "a shader." msgstr "" +"Cette texture donne accès à la texture de la caméra fournie par " +"[CameraFeed].\n" +"[b]Note :[/b] Beaucoup de caméras fournissent des images au format YCbCr qui " +"doivent être converties dans un shader." #: doc/classes/CameraTexture.xml msgid "The ID of the [CameraFeed] for which we want to display the image." @@ -16212,13 +16410,15 @@ msgstr "" msgid "" "Convenience property that gives access to the active property of the " "[CameraFeed]." -msgstr "" +msgstr "Propriété utile qui donne accès à la propriété active du [CameraFeed]." #: doc/classes/CameraTexture.xml msgid "" "Which image within the [CameraFeed] we want access to, important if the " "camera image is split in a Y and CbCr component." msgstr "" +"L'image du [CameraFeed] pour laquelle nous voulons accéder, important si " +"l'image de la caméra est divisée en composants Y et CbCr." #: doc/classes/CanvasItem.xml msgid "Base class of anything 2D." @@ -16880,6 +17080,8 @@ msgid "" "The color applied to textures on this [CanvasItem]. This is not inherited by " "children [CanvasItem]s." msgstr "" +"La couleur appliquée aux textures sur ce [CanvasItem]. Cela n'est pas hérité " +"pour les [CanvasItem] enfants." #: doc/classes/CanvasItem.xml msgid "If [code]true[/code], the object draws behind its parent." @@ -16934,7 +17136,7 @@ msgid "" msgstr "" "Émis quand la position ou la taille du [Rect2] a changé, ou lorsqu'une " "action a changé ces valeurs là (par exemple en changeant [member Sprite." -"texture])" +"texture])." #: doc/classes/CanvasItem.xml msgid "Emitted when the visibility (hidden/visible) changes." @@ -16945,6 +17147,8 @@ msgid "" "Mix blending mode. Colors are assumed to be independent of the alpha " "(opacity) value." msgstr "" +"Le mode de mélange. Les couleurs sont supposées être indépendantes de " +"l'opacité." #: doc/classes/CanvasItem.xml doc/classes/CanvasItemMaterial.xml msgid "Additive blending mode." @@ -16963,6 +17167,8 @@ msgid "" "Mix blending mode. Colors are assumed to be premultiplied by the alpha " "(opacity) value." msgstr "" +"Le mode de mélange. Les couleurs sont supposées être prémultipliées par leur " +"opacité." #: doc/classes/CanvasItem.xml msgid "" @@ -16976,12 +17182,16 @@ msgid "" "The [CanvasItem]'s global transform has changed. This notification is only " "received if enabled by [method set_notify_transform]." msgstr "" +"La transformation globale du [CanvasItem] a changé. Cette notification n'est " +"reçue que si elle est activée par [method set_notify_transform]." #: doc/classes/CanvasItem.xml msgid "" "The [CanvasItem]'s local transform has changed. This notification is only " "received if enabled by [method set_notify_local_transform]." msgstr "" +"La transformation locale [CanvasItem] a changé. Cette notification n'est " +"reçue que si elle est activée par [method set_notify_local_transform]." #: doc/classes/CanvasItem.xml msgid "The [CanvasItem] is requested to draw." @@ -17192,9 +17402,8 @@ msgstr "" "[CanvasLayer] n'est pas propagée aux calques enfants." #: doc/classes/CanvasLayer.xml -#, fuzzy msgid "Emitted when visibility of the layer is changed. See [member visible]." -msgstr "Émis lorsque le VisibilityNotifier3D quitte la vue d'un [Camera3D]." +msgstr "" #: doc/classes/CanvasModulate.xml msgid "Tint the entire canvas." @@ -17289,13 +17498,12 @@ msgstr "" "contrôler le rendu de caractères individuels dans un [RichTextEffect]." #: doc/classes/CharFXTransform.xml -#, fuzzy msgid "" "The index of the current character (starting from 0) for the " "[RichTextLabel]'s BBCode text. Setting this property won't affect drawing." msgstr "" -"L'index du caractère actuel (commence à 0). Régler cette propriété n'affecte " -"pas l'affichage." +"L'index du caractère actuel (commence à 0) pour le texte BBCode du " +"[RichTextLabel]. Régler cette propriété n'affecte pas l'affichage." #: doc/classes/CharFXTransform.xml msgid "" @@ -17374,13 +17582,12 @@ msgstr "" "pixels)." #: doc/classes/CharFXTransform.xml -#, fuzzy msgid "" "The index of the current character (starting from 0) for this " "[RichTextEffect] custom block. Setting this property won't affect drawing." msgstr "" -"L'index du caractère actuel (commence à 0). Régler cette propriété n'affecte " -"pas l'affichage." +"L'index du caractère actuel (commence à 0) pour le bloc personnalisé du " +"[RichTextEffect]. Régler cette propriété n'affecte pas l'affichage." #: doc/classes/CharFXTransform.xml msgid "" @@ -17498,10 +17705,9 @@ msgid "The check icon to display when the [CheckBox] is unchecked." msgstr "L'icône de la coche à afficher quand la [CheckBox] est décochée." #: doc/classes/CheckBox.xml -#, fuzzy msgid "" "The check icon to display when the [CheckBox] is unchecked and disabled." -msgstr "Icône à afficher lorsque le [CheckButton] est coché et désactivé." +msgstr "L'icône à afficher lorsque le [CheckBox] est décoché et désactivé." #: doc/classes/CheckBox.xml msgid "" @@ -17718,22 +17924,26 @@ msgstr "" "code] de la [code]class[/code] ou de ses parents." #: doc/classes/ClassDB.xml -#, fuzzy msgid "" "Returns an array with all the enums of [code]class[/code] or its ancestry." -msgstr "Retourne si la [code]class[/code] spécifiée est disponible ou non." +msgstr "" #: doc/classes/ClassDB.xml msgid "" "Returns the value of the integer constant [code]name[/code] of [code]class[/" "code] or its ancestry. Always returns 0 when the constant could not be found." msgstr "" +"Retourne la valeur de la constante entière nommée [code]name[/code] dans " +"[code]class[/code] ou un de ses parents. Retourne toujours 0 si la constante " +"n'a pas été trouvée." #: doc/classes/ClassDB.xml msgid "" "Returns which enum the integer constant [code]name[/code] of [code]class[/" "code] or its ancestry belongs to." msgstr "" +"Retourne à quelle énumération la constante entière nommée [code]name[/code] " +"dans [code]class[/code] ou un de ses parents." #: doc/classes/ClassDB.xml msgid "" @@ -17825,6 +18035,9 @@ msgid "" "Returns whether [code]class[/code] (or its ancestry if [code]no_inheritance[/" "code] is [code]false[/code]) has a method called [code]method[/code] or not." msgstr "" +"Retourne si [code]class[/code] (ou un de ses parents si " +"[code]no_inheritance[/code] est [code]false[/code]) a une méthode nommée " +"[code]method[/code] ou non." #: doc/classes/ClassDB.xml msgid "" @@ -17850,6 +18063,8 @@ msgid "" "Returns the names of all the classes that directly or indirectly inherit " "from [code]class[/code]." msgstr "" +"Retourne le nom de toutes les classes qui héritent directement ou " +"indirectement de [code]class[/code]." #: doc/classes/ClassDB.xml msgid "Returns the parent class of [code]class[/code]." @@ -17880,6 +18095,9 @@ msgid "" "This node extends [Camera] to add collisions with [Area] and/or " "[PhysicsBody] nodes. The camera cannot move through colliding objects." msgstr "" +"Ce nÅ“ud étend [Camera] pour ajouter des collisions avec des nÅ“uds [Area] et/" +"ou [PhysicsBody]. La caméra ne peut pas passer à travers les objets avec " +"lesquels elle rentre en collision." #: doc/classes/ClippedCamera.xml msgid "" @@ -17980,7 +18198,7 @@ msgid "" msgstr "" "CollisionObject est la classe de base pour les objets physiques. Il peut " "contenir n'importe quel nombre de formes [Shape] de collision. Chaque forme " -"doit être assignée à un [i]propriétaire de forme[ /i]. Le CollisionObject " +"doit être assignée à un [i]propriétaire de forme[/i]. Le CollisionObject " "peut avoir n'importe quel nombre de propriétaires de forme. Les " "propriétaires de forme ne sont pas des nÅ“uds et ne apparaissent pas dans " "l'éditeur, mais sont accessibles par le code en utilisant les méthodes " @@ -18089,20 +18307,18 @@ msgid "Returns the parent object of the given shape owner." msgstr "Retourne l'objet parent du propriétaire de la forme spécifié." #: doc/classes/CollisionObject.xml -#, fuzzy msgid "Returns the [Shape] with the given id from the given shape owner." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "" #: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml msgid "Returns the number of shapes the given shape owner contains." msgstr "Retourne le nombre de formes que le propriétaire de forme contient." #: doc/classes/CollisionObject.xml -#, fuzzy msgid "" "Returns the child index of the [Shape] with the given id from the given " "shape owner." -msgstr "Retourne la liste de tous les nÅ“uds du shader avec le type spécifié." +msgstr "" #: doc/classes/CollisionObject.xml msgid "Returns the shape owner's [Transform]." @@ -18172,6 +18388,10 @@ msgid "" "the mouse pointer entering/leaving, and if the mouse is inside it, report " "input events. Requires at least one [member collision_layer] bit to be set." msgstr "" +"Si [code]true[/code], cet objet peut être sélectionné. Ces objets peuvent " +"détecter l'entrée/la sortie du pointeur de la souris sur eux, et si la " +"souris pointe sur l'objet, signaler par des événements d'entrée. Nécessite " +"au moins un bit de [member collision_layer] d'être réglé." #: doc/classes/CollisionObject.xml msgid "" @@ -18227,6 +18447,10 @@ msgid "" "[Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up " "these events." msgstr "" +"Accepte les [InputEvent] non traités. Nécessite [member input_pickable] " +"d'être à [code]true[/code]. [code]shape_idx[/code] est l'index de la " +"[Shape2D] enfant. Connectez-vous au signal [code]input_event[/code] pour " +"récupérer facilement ces événements." #: doc/classes/CollisionObject2D.xml msgid "" @@ -18242,6 +18466,9 @@ msgid "" "this [CollisionObject2D] will not be reported to collided with " "[CollisionObject2D]s." msgstr "" +"Retourne [code]true[/code] si les collisions pour le propriétaire de forme " +"venant de ce [CollisionObject2D] ne seront pas signalées aux " +"[CollisionObject2D] entrants en collision." #: doc/classes/CollisionObject2D.xml msgid "Adds a [Shape2D] to the shape owner." @@ -18250,12 +18477,16 @@ msgstr "Ajoute un [Shape2D] au propriétaire de la forme." #: doc/classes/CollisionObject2D.xml msgid "Returns the [Shape2D] with the given id from the given shape owner." msgstr "" +"Retourne la [Shape2D] avec l'identifiant donné du propriétaire donné de la " +"forme." #: doc/classes/CollisionObject2D.xml msgid "" "Returns the child index of the [Shape2D] with the given id from the given " "shape owner." msgstr "" +"Retourne l'indice de enfant du [Shape2D] avec l'identifiant donné du " +"propriétaire donné de forme." #: doc/classes/CollisionObject2D.xml msgid "Returns the shape owner's [Transform2D]." @@ -18267,12 +18498,17 @@ msgid "" "originating from this [CollisionObject2D] will not be reported to collided " "with [CollisionObject2D]s." msgstr "" +"Si [code]enable[/code] est [code]true[/code], les collisions pour le " +"propriétaire de forme original de ce [CollisionObject2D] ne seront pas " +"rapportées aux [CollisionObject2D] entrant en collision." #: doc/classes/CollisionObject2D.xml msgid "" "Sets the [code]one_way_collision_margin[/code] of the shape owner identified " "by given [code]owner_id[/code] to [code]margin[/code] pixels." msgstr "" +"Définit la marge [code]one_way_collision_margin[/code] du propriétaire de la " +"forme identifié par [code]owner_id[/code] à [code]margin[/code] pixels." #: doc/classes/CollisionObject2D.xml msgid "Sets the [Transform2D] of the given shape owner." @@ -18359,12 +18595,20 @@ msgid "" "editor. It will not appear in the scene tree at run-time. Creates a [Shape] " "for gameplay. Properties modified during gameplay will have no effect." msgstr "" +"Permet d'éditer des sommets de collision sur un plan sélectionné. Peut " +"également définir une profondeur perpendiculaire à ce plan. Cette classe " +"n'est disponible que dans l'éditeur. Elle n'apparaîtra pas dans " +"l'arborescence de la scène quand le jeu est lancé. Crée une [Shape] pour les " +"mécaniques de jeu. Les propriétés modifiées une fois le jeu lancé n'auront " +"aucun effet." #: doc/classes/CollisionPolygon.xml msgid "" "Length that the resulting collision extends in either direction " "perpendicular to its polygon." msgstr "" +"La longueur que la collision résultante s'étend dans la direction " +"perpendiculaire à son polygone." #: doc/classes/CollisionPolygon.xml msgid "If [code]true[/code], no collision will be produced." @@ -18375,6 +18619,8 @@ msgid "" "The collision margin for the generated [Shape]. See [member Shape.margin] " "for more details." msgstr "" +"La marge de collision pour la [Shape] générée. Voir [member Shape.margin] " +"pour plus d'informations." #: doc/classes/CollisionPolygon.xml msgid "" @@ -18385,6 +18631,12 @@ msgid "" "temporary variable and make changes before reassigning the [code]polygon[/" "code] member." msgstr "" +"Un tableau de sommets qui définissent le polygone.\n" +"[b]Note :[/b] La valeur retournée est une copie de l'original. Les méthodes " +"qui modifie la taille ou les propriétés de la valeur de retour n'affecteront " +"pas le polygone d'origine. Pour modifier les propriétés du polygone, " +"assignez-le à une variable temporaire et faites des changements avant de le " +"réassigner au membre [code]polygon[/code]." #: doc/classes/CollisionPolygon2D.xml msgid "Defines a 2D collision polygon." @@ -18395,10 +18647,14 @@ msgid "" "Provides a 2D collision polygon to a [CollisionObject2D] parent. Polygons " "can be drawn in the editor or specified by a list of vertices." msgstr "" +"Fournit un polygone de collision 2D à un parent [CollisionObject2D]. Les " +"polygones peuvent être dessinés manuellement dans l'éditeur ou spécifiés par " +"une liste de sommets." #: doc/classes/CollisionPolygon2D.xml msgid "Collision build mode. Use one of the [enum BuildMode] constants." msgstr "" +"Le mode d'assemblage. Utilisez l'une des constantes de [enum BuildMode]." #: doc/classes/CollisionPolygon2D.xml msgid "If [code]true[/code], no collisions will be detected." @@ -18411,6 +18667,11 @@ msgid "" "[b]Note:[/b] This property has no effect if this [CollisionPolygon2D] is a " "child of an [Area2D] node." msgstr "" +"Si [code]true[/code], seuls les bords qui font face, par rapport à la " +"rotation du [CollisionPolygon2D], entreront en collision avec d'autres " +"objets.\n" +"[b]Note :[/b] Cette propriété n'a aucun effet si cette [CollisionPolygon2D] " +"est un enfant d'un nÅ“ud [Area2D]." #: doc/classes/CollisionPolygon2D.xml msgid "" @@ -18418,6 +18679,9 @@ msgid "" "the shape thicker, and work better for colliders that enter the polygon at a " "high velocity." msgstr "" +"La marge (en pixels) utilisée pour une collision à sens unique. Des valeurs " +"plus élevées rendront la forme plus épaisse, et fonctionneront mieux pour " +"les objets entrant en collision quand ils vont à une vitesse élevée." #: doc/classes/CollisionPolygon2D.xml msgid "" @@ -18519,11 +18783,12 @@ msgid "2D Kinematic Character Demo" msgstr "Démo de caractère cinétique 2D" #: doc/classes/CollisionShape2D.xml -#, fuzzy msgid "" "A disabled collision shape has no effect in the world. This property should " "be changed with [method Object.set_deferred]." -msgstr "Une forme de collision désactivée n’a aucun effet dans le monde." +msgstr "" +"Une forme de collision désactivée n’a aucun effet dans le monde. Cette " +"propriété devrait être modifiée avec [method Object.set_deferred]." #: doc/classes/CollisionShape2D.xml msgid "" @@ -19622,11 +19887,18 @@ msgid "" "in the color picker and the user will be able to select them.\n" "[b]Note:[/b] The presets list is only for [i]this[/i] color picker." msgstr "" +"Ajoute la couleur donnée à une liste de pré-réglages de couleur. Les pré-" +"réglages sont affichés dans le sélectionneur de couleurs que l'utilisateur " +"pourra sélectionner.\n" +"[b]Note :[/b] La liste des pré-réglages est seulement pour [i]ce[/i] " +"sélectionneur de couleur." #: doc/classes/ColorPicker.xml msgid "" "Removes the given color from the list of color presets of this color picker." msgstr "" +"Retire la couleur donnée de la liste des pré-réglages de couleur de ce " +"sélectionneur de couleur." #: doc/classes/ColorPicker.xml msgid "Returns the list of colors in the presets of the color picker." @@ -19643,11 +19915,14 @@ msgid "" "mouse button, otherwise it will apply immediately even in mouse motion event " "(which can cause performance issues)." msgstr "" +"Si [code]true[/code], la couleur ne s'appliquera que quand l'utilisateur " +"relâche le bouton de la souris, sinon elle s'appliquera immédiatement en " +"suivant le déplacement de la souris (ce qui peut causer des problèmes de " +"performance)." #: doc/classes/ColorPicker.xml -#, fuzzy msgid "If [code]true[/code], shows an alpha channel slider (opacity)." -msgstr "Si [code]true[/code], le GraphNode est sélectionné." +msgstr "" #: doc/classes/ColorPicker.xml msgid "" @@ -19655,6 +19930,9 @@ msgid "" "sliders.\n" "[b]Note:[/b] Cannot be enabled if raw mode is on." msgstr "" +"Si [code]true[/code], permet de modifier la couleur avec des curseurs teinte/" +"saturation/valeur.\n" +"[b]Note :[/b] Ne peut être activé si le mode brut est activé." #: doc/classes/ColorPicker.xml msgid "If [code]true[/code], the \"add preset\" button is enabled." @@ -19722,10 +20000,12 @@ msgid "" "The indicator used to signalize that the color value is outside the 0-1 " "range." msgstr "" +"L'indicateur utilisé pour signaler que la valeur de couleur est en dehors de " +"l'intervalle 0-1." #: doc/classes/ColorPicker.xml msgid "The icon for the screen color picker button." -msgstr "" +msgstr "L'icône pour le bouton de sélecteur de couleurs." #: doc/classes/ColorPickerButton.xml msgid "Button that pops out a [ColorPicker]." @@ -20161,18 +20441,25 @@ msgid "" "Deletes the specified section along with all the key-value pairs inside. " "Raises an error if the section does not exist." msgstr "" +"Supprime la section spécifiée ainsi que toutes ses paires valeur-clé avec. " +"Affiche une erreur si la section n'existe pas." #: doc/classes/ConfigFile.xml msgid "" "Deletes the specified key in a section. Raises an error if either the " "section or the key do not exist." msgstr "" +"Supprime la clé spécifiée dans une section. Affiche une erreur si la section " +"ou la clé n'existe pas." #: doc/classes/ConfigFile.xml msgid "" "Returns an array of all defined key identifiers in the specified section. " "Raises an error and returns an empty array if the section does not exist." msgstr "" +"Retourne un tableau de tous les identifiants des clés définis dans la " +"section spécifiée. Affiche une erreur et retourne un tableau vide si la " +"section n'existe pas." #: doc/classes/ConfigFile.xml msgid "Returns an array of all defined section identifiers." @@ -20185,6 +20472,10 @@ msgid "" "[code]default[/code] value. If [code]default[/code] is not specified or set " "to [code]null[/code], an error is also raised." msgstr "" +"Retourne l'actuelle valeur pour la section et la clé spécifiées. Si la " +"section ou la clé n'existent pas, la méthode retourne la valeur du paramètre " +"[code]default[/code]. Si [code]default[/code] n'est pas spécifié ou défini à " +"[code]null[/code], une erreur est affichée." #: doc/classes/ConfigFile.xml msgid "Returns [code]true[/code] if the specified section exists." @@ -20202,6 +20493,10 @@ msgid "" "on.\n" "Returns one of the [enum Error] code constants ([code]OK[/code] on success)." msgstr "" +"Charge le fichier de configuration spécifié en paramètre. Le contenu du " +"fichier est interprété et chargé dans l'objet [ConfigFile] sur lequel la " +"méthode a été appelée.\n" +"Retourne un des codes [enum Error] ([code]OK[/code] en cas de succès)." #: doc/classes/ConfigFile.xml msgid "" @@ -20210,6 +20505,11 @@ msgid "" "the [ConfigFile] object which the method was called on.\n" "Returns one of the [enum Error] code constants ([code]OK[/code] on success)." msgstr "" +"Charge le fichier de configuration crypté spécifié en paramètre, en " +"utilisant la clé [code]key[/code] fournie pour le décrypter. Le contenu du " +"fichier est interprété et chargé dans l'objet [ConfigFile] sur lequel la " +"méthode a été appelée.\n" +"Retourne un des codes [enum Error] ([code]OK[/code] en cas de succès)." #: doc/classes/ConfigFile.xml msgid "" @@ -20279,6 +20579,10 @@ msgid "" "code] value deletes the specified key if it exists, and deletes the section " "if it ends up empty once the key has been removed." msgstr "" +"Attribue une valeur à la clé spécifiée de la section spécifiée. Si la " +"section ou la clé n'existe pas, elles sont créées. Passer une valeur " +"[code]null[/code] supprime la clé spécifiée si elle existe, et supprime la " +"section si elle est vide une fois que la clé a été supprimée." #: doc/classes/ConfirmationDialog.xml msgid "Dialog for confirmation of actions." @@ -20309,6 +20613,10 @@ msgid "" "may cause a crash. If you wish to hide it or any of its children, use their " "[member CanvasItem.visible] property." msgstr "" +"Retourne le bouton annuler.\n" +"[b]Avertissement :[/b] Il s'agit d'un nÅ“ud interne requis, le retirer et le " +"libérer peut causer un plantage. Si vous voulez le cacher lui ou un de ses " +"enfants, utilisez la propriété [member CanvasItem.visible]." #: doc/classes/Container.xml msgid "Base node for containers." @@ -20320,18 +20628,26 @@ msgid "" "automatically arranges them in a certain way.\n" "A Control can inherit this to create custom container classes." msgstr "" +"Le nÅ“ud de base pour les conteneurs. Un [Container] contient d'autres " +"contrôles et les arrange automatiquement d'une certaine manière.\n" +"Un Control peut en hériter pour créer des classes de conteneur qui arrange " +"les contrôles enfants de manière personnalisée." #: doc/classes/Container.xml msgid "" "Fit a child control in a given rect. This is mainly a helper for creating " "custom container classes." msgstr "" +"Ajuste un contrôle enfant dans un rectangle donné. Il s'agit principalement " +"d'une aide pour créer des classes de conteneurs personnalisées." #: doc/classes/Container.xml msgid "" "Queue resort of the contained children. This is called automatically anyway, " "but can be called upon request." msgstr "" +"Ajoute un commande de tri pour les contrôles enfants. Ceci est appelé " +"automatiquement de tous les cas, mais peut être appelé sur demande." #: doc/classes/Container.xml msgid "Emitted when sorting the children is needed." @@ -20341,12 +20657,17 @@ msgstr "Émis quand le tri des enfants est nécessaire." msgid "" "Notification for when sorting the children, it must be obeyed immediately." msgstr "" +"La notification pour le tri des enfants, à laquelle faut l'obéir " +"immédiatement." #: doc/classes/Control.xml msgid "" "All user interface nodes inherit from Control. A control's anchors and " "margins adapt its position and size relative to its parent." msgstr "" +"Tous les nÅ“uds d'interface utilisateur héritent de Control. Les ancres et " +"les marges des contrôles adaptent leur position et leur taille par rapport à " +"son parent." #: doc/classes/Control.xml msgid "" @@ -20433,7 +20754,7 @@ msgstr "Galerie des nÅ“uds de contrôle" #: doc/classes/Control.xml msgid "All GUI Demos" -msgstr "" +msgstr "Toutes les démos d'interface" #: doc/classes/Control.xml msgid "" @@ -20443,6 +20764,13 @@ msgid "" "Similar to [member rect_clip_content], but doesn't affect visibility.\n" "If not overridden, defaults to [code]false[/code]." msgstr "" +"Méthode virtuelle à surcharger par l'utilisateur. Retourne si [méthode " +"gui_input] ne doit pas être appelé pour les contrôles enfants en dehors du " +"rectangle englobant du contrôle. L'entrée sera limitée au Rect de ce " +"[Control]. Similaire à [member rect_clip_content], mais n'affecte pas la " +"visibilité.\n" +"Si la méthode n'est pas surchargée, la valeur par défaut retournée est " +"[code]false[/code]." #: doc/classes/Control.xml msgid "" @@ -20619,15 +20947,12 @@ msgstr "" "[/codeblock]" #: doc/classes/Control.xml -#, fuzzy msgid "" "Creates a local override for a theme constant with the specified [code]name[/" "code]. Local overrides always take precedence when fetching theme items for " "the control.\n" "See also [method get_constant], [method remove_constant_override]." msgstr "" -"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] " -"existe, [code]false[/code] autrement." #: doc/classes/Control.xml msgid "" @@ -20804,6 +21129,12 @@ msgid "" "The methods [method can_drop_data] and [method drop_data] must be " "implemented on controls that want to receive drop data." msgstr "" +"Force le glissage et contourne [method get_drag_data] et [method " +"set_drag_preview] en passant [code]data[/code] et [code]preview[/code]. Le " +"glissage va commencer même si la souris n'est ni sur, ni appuyé sur ce " +"contrôle.\n" +"Les méthodes [method can_drop_data] et [method drop_data] doivent être " +"implémentées pour les contrôles qui veulent recevoir ces données de glissage." #: doc/classes/Control.xml msgid "" @@ -20896,6 +21227,8 @@ msgid "" "Returns the mouse cursor shape the control displays on mouse hover. See " "[enum CursorShape]." msgstr "" +"Retourne le curseur de la souris que le contrôle affiche quand la souris le " +"survole. Voir [enum CursorShape]." #: doc/classes/Control.xml msgid "" @@ -21001,9 +21334,8 @@ msgstr "" "Retourne la taille minimale de ce contrôle. Voir [member rect_min_size]." #: doc/classes/Control.xml -#, fuzzy msgid "Returns the width/height occupied in the parent control." -msgstr "Renvoie la largeur / hauteur occupée dans le contrôle du parent." +msgstr "Retourne la largeur / hauteur occupée dans le contrôle du parent." #: doc/classes/Control.xml msgid "Returns the parent control node." @@ -21039,6 +21371,10 @@ msgid "" "[Theme] has a valid [member Theme.default_font] value.\n" "See [method get_color] for details." msgstr "" +"Retourne la police par défaut de la première correspondance [Theme] trouvée " +"dans l'arborescence si ce [Theme] a une valeur valide pour [member Theme." +"default_font].\n" +"Voir [method get_color] pour plus de détails." #: doc/classes/Control.xml msgid "" @@ -21104,7 +21440,7 @@ msgid "" "See [method get_color] for details." msgstr "" "Retourne [code]true[/code] s'il y a un [Theme] correspondant dans " -"l'arborescence qui a une propriété de constante nommée [/code]name[/code] et " +"l'arborescence qui a une propriété de constante nommée [code]name[/code] et " "du type de thème [code]theme_type[/code].\n" "Voir [method get_color] pour plus de détails." @@ -21203,6 +21539,10 @@ msgid "" "[code]theme_type[/code].\n" "See [method get_color] for details." msgstr "" +"Retourne [code]true[/code] s'il y a une correspondance [Theme] dans " +"l'arborescence qui a un élément de la boîte de style avec le code spécifié " +"[code]name[/code] et [code]theme_type[/code].\n" +"Voir [method get_color] pour plus de détails." #: doc/classes/Control.xml msgid "" @@ -21231,44 +21571,44 @@ msgid "" "changed. Setting [member rect_min_size] directly calls this method " "automatically." msgstr "" +"Invalide le cache de taille de ce nÅ“ud et des nÅ“uds parents jusqu'à la " +"racine. Prévu pour être utilisé avec [method get_minimum_size] quand la " +"valeur de retour est changée. Définir [member rect_min_size] appelle cette " +"méthode automatiquement." #: doc/classes/Control.xml msgid "" "Give up the focus. No other control will be able to receive keyboard input." msgstr "" +"Relâche le focus. Aucun autre contrôle ne pourra recevoir les entrées du " +"clavier." #: doc/classes/Control.xml -#, fuzzy msgid "" "Removes a theme override for a [Color] with the given [code]name[/code]." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/Control.xml -#, fuzzy msgid "" "Removes a theme override for a constant with the given [code]name[/code]." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/Control.xml -#, fuzzy msgid "Removes a theme override for a [Font] with the given [code]name[/code]." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/Control.xml -#, fuzzy msgid "Removes a theme override for an icon with the given [code]name[/code]." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/Control.xml -#, fuzzy msgid "Removes a theme override for a shader with the given [code]name[/code]." -msgstr "Retourne la position du point à l'index [code]point[/code]." +msgstr "" #: doc/classes/Control.xml -#, fuzzy msgid "" "Removes a theme override for a [StyleBox] with the given [code]name[/code]." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/Control.xml msgid "" @@ -21304,12 +21644,18 @@ msgid "" "code] argument and automatic update of margin, it allows to set the margin " "offset yourself (see [method set_margin])." msgstr "" +"Fonctionne comme [method set_anchor], mais au lieu de l'argument " +"[code]keep_margin[/code] et de la mise à jour automatique de la marge, ça " +"permet de définir la marge de décalage par vous-même (voir [method " +"set_margin])." #: doc/classes/Control.xml msgid "" "Sets both anchor preset and margin preset. See [method set_anchors_preset] " "and [method set_margins_preset]." msgstr "" +"Définit à la fois le préréglage de l'ancre et de la marge. Voir [method " +"set_anchors_preset] et [method set_margins_preset]." #: doc/classes/Control.xml msgid "" @@ -21523,6 +21869,15 @@ msgid "" "If [code]exclusive[/code] is [code]true[/code], other controls will not " "receive input and clicking outside this control will not close it." msgstr "" +"Affiche un contrôle en tant que modal. Le contrôle doit être une sous-" +"fenêtre. Les contrôles de modal capturent les signaux d'entrée jusqu'à ce " +"que la zone située à l'extérieur soit accessible. Lorsqu'un contrôle modal " +"perd le focus, ou que la touche échap est pressée, il disparait " +"automatiquement. Les contrôles de modal sont largement utilisés pour les " +"dialogues surgissants (popup) et les menus.\n" +"Si [code]exclusif[/code] est [code]true[/code], les autres contrôles ne " +"recevront pas les entrées, et cliquer à l'extérieur de ce contrôle ne le " +"fermera pas." #: doc/classes/Control.xml msgid "" @@ -21584,6 +21939,9 @@ msgid "" "The focus access mode for the control (None, Click or All). Only one Control " "can be focused at the same time, and it will receive keyboard signals." msgstr "" +"Le mode de focus du contrôle (aucun, clic ou tous). Un seul contrôle peut " +"avoir le focus à un moment donné, et il recevra des signaux des touches du " +"clavier appuyées." #: doc/classes/Control.xml msgid "" @@ -22188,6 +22546,9 @@ msgid "" "beam pointer has a shape similar to \"I\". It tells the user they can " "highlight or insert text." msgstr "" +"Affiche le curseur de la souris en forme de I lorsque l'utilisateur survole " +"le nÅ“ud. Le pointeur en I a une forme semblable à un \"I\". Il signale à " +"l'utilisateur qu'il peut insérer ou surligner du texte." #: doc/classes/Control.xml msgid "" @@ -22200,20 +22561,20 @@ msgstr "" "Affiche le curseur en croix du système quand l'utilisateur survole ce nÅ“ud." #: doc/classes/Control.xml -#, fuzzy msgid "" "Show the system's wait mouse cursor when the user hovers the node. Often an " "hourglass." msgstr "" -"Affiche le curseur en croix du système quand l'utilisateur survole ce nÅ“ud." +"Affiche le curseur d'attente du système quand l'utilisateur survole ce nÅ“ud. " +"Souvent un sablier." #: doc/classes/Control.xml -#, fuzzy msgid "" "Show the system's busy mouse cursor when the user hovers the node. Often an " "arrow with a small hourglass." msgstr "" -"Affiche le curseur en croix du système quand l'utilisateur survole ce nÅ“ud." +"Affiche le curseur d'occupation du système quand l'utilisateur survole ce " +"nÅ“ud. Souvent une flèche avec un petit sablier." #: doc/classes/Control.xml msgid "" @@ -22629,10 +22990,10 @@ msgid "" "variables, like [member anchor_left]. To change all 4 anchors at once, use " "[method set_anchors_preset]." msgstr "" -"Magnétise l'un des 4 côtés d'ancrage à l'origine de l'ancrage [code]Rect[/" -"code], en haut à gauche. Utilisez-le avec l'une des variables membres " -"[code]anchor_[* /code], comme [member anchor_left]. Pour modifier les 4 " -"ancres à la fois, utilisez [method set_anchors_preset]." +"Magnétise l'un des 4 côtés d'ancrage à l'origine de l'ancrage " +"[code]Rect[/code], en haut à gauche. Utilisez-le avec l'une des variables " +"membres [code]anchor_*[/code], comme [member anchor_left]. Pour modifier les " +"4 ancres à la fois, utilisez [method set_anchors_preset]." #: doc/classes/Control.xml msgid "" @@ -22643,18 +23004,19 @@ msgid "" msgstr "" "Magnétise l'un des 4 côtés d'ancrage à l'extrémité de l'extrémité " "[code]Rect[/code], en bas à droite. Utilisez-le avec l'une des variables " -"membres [code]anchor_[* /code], comme [member anchor_left]. Pour modifier " -"les 4 ancres à la fois, utilisez [method set_anchors_preset]." +"membres [code]anchor_*[/code], comme [member anchor_left]. Pour modifier les " +"4 ancres à la fois, utilisez [method set_anchors_preset]." #: doc/classes/ConvexPolygonShape.xml msgid "Convex polygon shape for 3D physics." msgstr "Forme de polygone convexe pour la physique 3D." #: doc/classes/ConvexPolygonShape.xml -#, fuzzy msgid "" "Convex polygon shape resource, which can be added to a [PhysicsBody] or area." -msgstr "Ressource de forme de polygone concave 2D pour la physique." +msgstr "" +"Un ressource de forme de polygone convexe, qui peut être ajoutée à un " +"[PhysicsBody] ou une aire." #: doc/classes/ConvexPolygonShape.xml msgid "The list of 3D points forming the convex polygon shape." @@ -22675,6 +23037,15 @@ msgid "" "uses a more complex method of collision detection, and a convex one forces " "itself to be convex in order to speed up collision detection." msgstr "" +"Forme polygone convexe pour la physique 2D. Un polygone convexe, quelle que " +"soit sa forme, est décomposé en interne par d'autant de polygones convexes " +"que nécessaire pour assurer que toutes les collisions sont toujours " +"effectués sur les polygones convexes (ce qui sont plus rapide à vérifier).\n" +"La principale différence entre un [ConvexPolygonShape2D] et un " +"[ConcavePolygonShape2D] est qu'un polygone concave suppose toujours qu'il " +"est concave et utilise une méthode plus complexe pour la détection des " +"collisions, alors qu'un polygone convexe suppose toujours qu'il est convexe " +"pour accélérer la détection des collisions." #: doc/classes/ConvexPolygonShape2D.xml msgid "" @@ -22682,6 +23053,10 @@ msgid "" "points] property using the convex hull algorithm. Removing all unneeded " "points. See [method Geometry.convex_hull_2d] for details." msgstr "" +"Basé sur l'ensemble des points fournis, cela crée et définit la propriété " +"[member points] en utilisant l'algorithme de découpage convexe. Ça enlève " +"aussi tous les points inutiles. Voir [method Geometry.convex_hull_2d] pour " +"plus de détails." #: doc/classes/ConvexPolygonShape2D.xml msgid "" @@ -22690,6 +23065,10 @@ msgid "" "[method set_point_cloud] to generate a convex hull shape from concave shape " "points." msgstr "" +"La liste des sommets du polygone. Peut être dans le sens horaire ou dans le " +"sens anti-horaire. Ne définissez cette propriété qu'avec des points d'une " +"forme convexe, et utilisez [method set_point_cloud] pour générer une forme " +"convexe à partir de points d'une forme concave." #: doc/classes/CPUParticles.xml msgid "CPU-based 3D particle emitter." @@ -22704,12 +23083,22 @@ msgid "" "[b]Note:[/b] Unlike [Particles], the visibility rect is generated on-the-fly " "and doesn't need to be configured by the user." msgstr "" +"Un nÅ“ud pour les particules 3D fonctionnant sur le CPU utilisé pour créer " +"une grande variété d'effets de particules.\n" +"Voir aussi [Particles], qui fournit la même fonctionnalité mais avec " +"l'accélération matérielle (via GPU), mais ne peut pas fonctionner sur des " +"appareils plus anciens.\n" +"[b]Note :[/b] Contrairement aux [Particles], le rect de visibilité est " +"généré à lors de émission et n'a pas besoin d'être configuré par " +"l'utilisateur." #: doc/classes/CPUParticles.xml msgid "" "Sets this node's properties to match a given [Particles] node with an " "assigned [ParticlesMaterial]." msgstr "" +"Génère les propriétés de ce nÅ“ud pour correspondre à un nÅ“ud [Particules] " +"avec en plus un nÅ“ud assigné [ParticlesMaterial]." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "Returns the base value of the parameter specified by [enum Parameter]." @@ -22767,6 +23156,11 @@ msgid "" "therefore removing all particles that were already emitted before changing " "[member amount]." msgstr "" +"Le nombre de particules émises dans un cycle d'émission (correspondant à la " +"durée [member lifetime]).\n" +"[b]Note :[/b] Changer [member amount] réinitialisera l'émission des " +"particules, supprimant ainsi toutes les particules déjà émises avant de " +"changer [member amount]." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "Initial rotation applied to each particle, in degrees." @@ -22838,6 +23232,9 @@ msgid "" "[SpatialMaterial] make sure to set [member SpatialMaterial." "vertex_color_use_as_albedo] to [code]true[/code]." msgstr "" +"La couleur initiale de chaque particule. Pour utiliser cette couleur dans un " +"[SpatialMaterial], assurez-vous de définir [membrer SpatialMaterial." +"vertex_color_use_as_albedo] à [code]true[/code]." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -22845,6 +23242,8 @@ msgid "" "Each particle's initial color will vary along this [GradientTexture] " "(multiplied with [member color])." msgstr "" +"La couleur initiale de chaque particule qui varie suivant la " +"[GradientTexture] (multipliée avec [member color])." #: doc/classes/CPUParticles.xml doc/classes/ParticlesMaterial.xml msgid "" @@ -22978,6 +23377,10 @@ msgid "" "the value to 2 will make the particles render at 2 frames per second. Note " "this does not slow down the particle system itself." msgstr "" +"Le nombre de trames du système de particules est fixé à une valeur. Par " +"exemple, changer la valeur à 2 rendra les particules à 2 trames par seconde. " +"Notez que cela ne ralentit pas le système de particules lui-même juste " +"l'affichage final." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -23001,6 +23404,8 @@ msgid "" "Amount of [member spread] in Y/Z plane. A value of [code]1[/code] restricts " "particles to X/Z plane." msgstr "" +"La quantité d'éparpillement [member spread] dans le plan Y/Z. Une valeur de " +"[code]1[/code] limite les particules au plan X/Z." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/Particles.xml doc/classes/Particles2D.xml @@ -23008,6 +23413,8 @@ msgid "" "If [code]true[/code], results in fractional delta calculation which has a " "smoother particles display effect." msgstr "" +"Si [code]true[/code], utilise un calcul d'étape fractionnelle qui permet " +"affichage plus lisse des particules." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -23034,6 +23441,8 @@ msgid "" "Initial velocity magnitude for each particle. Direction comes from [member " "spread] and the node's orientation." msgstr "" +"La magnitude de la vitesse initiale de chaque particule. L'orientation " +"dépend de [member spread] et de l'orientation du nÅ“ud." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -23055,6 +23464,8 @@ msgstr "Facteur d'aléatoire de la durée de vie d'une particule." msgid "" "Linear acceleration applied to each particle in the direction of motion." msgstr "" +"L'accélération linéaire appliquée à chaque particule dans la direction du " +"mouvement." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "Each particle's linear acceleration will vary along this [Curve]." @@ -23073,6 +23484,9 @@ msgid "" "If [code]true[/code], particles use the parent node's coordinate space. If " "[code]false[/code], they use global coordinates." msgstr "" +"Si [code]true[/code], les particules utilisent l'espace de coordonnées du " +"parent du nÅ“ud. Si [code]false[/code], ils utilisent des coordonnées " +"globales." #: doc/classes/CPUParticles.xml msgid "" @@ -23088,6 +23502,9 @@ msgid "" "If [code]true[/code], only one emission cycle occurs. If set [code]true[/" "code] during a cycle, emission will stop at the cycle's end." msgstr "" +"Si [code]true[/code], un seul cycle d'émission se produit. Si définit à " +"[code]true[/code] pendant un cycle, l'émission s'arrêtera à la fin de ce " +"cycle." #: doc/classes/CPUParticles.xml msgid "" @@ -23097,6 +23514,11 @@ msgid "" "This property is only available when [member flag_disable_z] is [code]true[/" "code]." msgstr "" +"La vitesse orbitale appliquée à chaque particule. Fait tourner les " +"particules autour d'origine sur le plan XY local. Spécifié en nombre de " +"rotations complètes autour de l'origine par seconde.\n" +"Cette propriété est uniquement disponible lorsque [member flag_disable_z] " +"est [code]true[/code]." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "Each particle's orbital velocity will vary along this [Curve]." @@ -23113,6 +23535,8 @@ msgstr "Facteur d'aléatoire de la vélocité orbitale." #: doc/classes/Particles2D.xml msgid "Particle system starts as if it had already run for this many seconds." msgstr "" +"Le système de particules démarre comme s'il avait déjà commencé depuis " +"plusieurs secondes." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -23159,6 +23583,8 @@ msgid "" "Particle system's running speed scaling ratio. A value of [code]0[/code] can " "be used to pause the particles." msgstr "" +"Le facteur de vitesse du système de particules. Une valeur de [code]0[/code] " +"peut être utilisée pour arrêter les particules." #: doc/classes/CPUParticles.xml msgid "" @@ -23176,6 +23602,9 @@ msgid "" "perpendicular to the particle's velocity giving the particles a swirling " "motion." msgstr "" +"L'accélération tangentielle appliquée à chaque particule. Elle est " +"perpendiculaire à la vitesse de la particule, ce qui donne aux particules un " +"mouvement de glissement." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "Each particle's tangential acceleration will vary along this [Curve]." @@ -23209,30 +23638,40 @@ msgid "" "Use with [method set_param], [method set_param_randomness], and [method " "set_param_curve] to set initial velocity properties." msgstr "" +"À utiliser avec [method set_param], [method set_param_randomness], et " +"[method set_param_curve] pour définir les propriétés de vitesse initiale." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" "Use with [method set_param], [method set_param_randomness], and [method " "set_param_curve] to set angular velocity properties." msgstr "" +"À utiliser avec [method set_param], [method set_param_randomness], et " +"[method set_param_curve] pour définir les propriétés de vitesse angulaire." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" "Use with [method set_param], [method set_param_randomness], and [method " "set_param_curve] to set orbital velocity properties." msgstr "" +"À utiliser avec [method set_param], [method set_param_randomness], et " +"[method set_param_curve] pour définir les propriétés de vitesse orbitale." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" "Use with [method set_param], [method set_param_randomness], and [method " "set_param_curve] to set linear acceleration properties." msgstr "" +"À utiliser avec [method set_param], [method set_param_randomness], et " +"[method set_param_curve] pour définir les propriétés d'accélération linéaire." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" "Use with [method set_param], [method set_param_randomness], and [method " "set_param_curve] to set radial acceleration properties." msgstr "" +"À utiliser avec [method set_param], [method set_param_randomness], et " +"[method set_param_curve] pour définir les propriétés d'accélération radiale." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" @@ -23336,6 +23775,9 @@ msgid "" "emission_points]. Particle color will be modulated by [member " "emission_colors]." msgstr "" +"Les particules seront émises à une position choisie au hasard parmi les " +"points [member emission_points]. La couleur des particules sera modulée par " +"[member emission_colors]." #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml msgid "" @@ -23344,6 +23786,10 @@ msgid "" "[member emission_normals]. Particle color will be modulated by [member " "emission_colors]." msgstr "" +"Les particules seront émises à une position choisie au hasard parmi [member " +"emission_points]. La vitesse et la rotation des particules seront " +"déterminées en fonction de [member emission_normals]. La couleur des " +"particules sera modulée par [member emission_colors]." #: doc/classes/CPUParticles.xml doc/classes/ParticlesMaterial.xml msgid "Particles will be emitted in a ring or cylinder." @@ -23367,30 +23813,45 @@ msgid "" "[b]Note:[/b] Unlike [Particles2D], the visibility rect is generated on-the-" "fly and doesn't need to be configured by the user." msgstr "" +"NÅ“ud de particules 2D calculées par le CPU pour créer une variété de " +"systèmes et d'effets de particules.\n" +"Voir aussi [Particles2D], qui fournit la même fonctionnalité mais en " +"utilisant l'accélération matérielle, mais ne peut pas fonctionner sur des " +"appareils plus anciens.\n" +"[b]Note :[/b] Contrairement [Particles2D], le rectangle de visibilité est " +"généré à l'émission et n'a donc pas besoin d'être définit par l'utilisateur." #: doc/classes/CPUParticles2D.xml msgid "" "Sets this node's properties to match a given [Particles2D] node with an " "assigned [ParticlesMaterial]." msgstr "" +"Définit les propriétés de ce nÅ“ud pour correspondre à au nÅ“ud [Particles2D] " +"spécifié, en incluant un nÅ“ud [ParticlesMaterial]." #: doc/classes/CPUParticles2D.xml msgid "" "Each particle's initial color. If [member texture] is defined, it will be " "multiplied by this color." msgstr "" +"La couleur initiale de chaque particule. Si [member texture] est défini, les " +"particules sont multipliées par cette couleur." #: doc/classes/CPUParticles2D.xml msgid "" "Each particle's color will vary along this [Gradient] (multiplied with " "[member color])." msgstr "" +"Chaque couleur de particle varie selon ce [Gradient] (multiplié avec [member " +"color])." #: doc/classes/CPUParticles2D.xml msgid "" "The rectangle's extents if [member emission_shape] is set to [constant " "EMISSION_SHAPE_RECTANGLE]." msgstr "" +"Le rectangle d'émission si [member emission_shape] est [constant " +"EMISSION_SHAPE_RECTANGLE]." #: doc/classes/CPUParticles2D.xml msgid "" @@ -23407,6 +23868,10 @@ msgid "" "the value to 2 will make the particles render at 2 frames per second. Note " "this does not slow down the simulation of the particle system itself." msgstr "" +"Le nombre de trames du système de particules est fixé à une valeur. Par " +"exemple, changer la valeur à 2 rendra les particules à 2 trames par seconde. " +"Notez que cela ne ralentit pas le système de particules lui-même juste " +"l'affichage final." #: doc/classes/CPUParticles2D.xml doc/classes/Particles2D.xml msgid "" @@ -23416,12 +23881,21 @@ msgid "" "Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for " "a comparison of normal map coordinates expected by popular engines." msgstr "" +"La texture de normale à utiliser pour la propriété [member texture].\n" +"[b]Note :[/b] Godot s'attend à ce que la texture de normale utilise les " +"coordonnées +X, -Y, et +Z. Voir [url=http://wiki.polycount.com/wiki/" +"Normal_Map_Technical_Details#Common_Swizzle_Coordinates]cette page[/url] " +"pour une comparaison des coordonnées des textures de normales attendues par " +"les principaux moteurs de jeu." #: doc/classes/CPUParticles2D.xml msgid "" "Orbital velocity applied to each particle. Makes the particles circle around " "origin. Specified in number of full rotations around origin per second." msgstr "" +"La vitesse orbitale appliquée à chaque particule. Fait tourner les " +"particules autour de l'origine. Spécifié en nombre de rotations complètes " +"autour de l'origine par seconde." #: doc/classes/CPUParticles2D.xml doc/classes/ParticlesMaterial.xml msgid "" @@ -23590,7 +24064,7 @@ msgid "" "certificates and passed to [method StreamPeerSSL.accept_stream]." msgstr "" "Génère une [CryptoKey] RSA qui peut être utilisé pour créer des certificats " -"autosignés et transmis à [method StreamPeerSSL.accept_stream]" +"autosignés et transmis à [method StreamPeerSSL.accept_stream]." #: doc/classes/Crypto.xml msgid "" @@ -23639,6 +24113,12 @@ msgid "" "Currently, only [constant HashingContext.HASH_SHA256] and [constant " "HashingContext.HASH_SHA1] are supported." msgstr "" +"Génère un résumé [url=https://en.wikipedia.org/wiki/HMAC]HMAC[/url] de " +"[code]msg[/code] à partir de la clé [code]key[/code]. Le paramètre " +"[code]hash_type[/code] est l'algorithme de hachage utilisé pour les hachages " +"intérieurs et extérieurs.\n" +"Actuellement, seuls les algorithmes [constant HashingContext.HASH_SHA256] et " +"[constant HashingContext.HASH_SHA1] sont supportés." #: doc/classes/Crypto.xml msgid "" @@ -23668,6 +24148,12 @@ msgid "" "Crypto.generate_self_signed_certificate] and as private key in [method " "StreamPeerSSL.accept_stream] along with the appropriate certificate." msgstr "" +"La classe CryptoKey représente une clé cryptographique. Les clés peuvent " +"être chargées et sauvegardées comme toute autre [Resource].\n" +"Elles peuvent être utilisées pour générer un certicat [X509Certificate] " +"autosigné avec [method Crypto.generate_self_signed_certificate] et comme clé " +"privée dans [method StreamPeerSSL.accept_stream] avec le certificat " +"approprié." #: doc/classes/CryptoKey.xml msgid "" @@ -23684,12 +24170,19 @@ msgid "" "[b]Note:[/b] [code]path[/code] should be a \"*.pub\" file if " "[code]public_only[/code] is [code]true[/code], a \"*.key\" file otherwise." msgstr "" +"Charge la clé à [code]path[/code]. Si [code]public_only[/code] est " +"[code]true[/code], seule la clé publique sera chargée.\n" +"[b]Note :[/b] [code]path[/code] doit être un fichier \"*.pub\" si " +"[code]public_only[/code] est [code]true[/code], et un fichier \"*.key\" " +"sinon." #: doc/classes/CryptoKey.xml msgid "" "Loads a key from the given [code]string[/code]. If [code]public_only[/code] " "is [code]true[/code], only the public key will be loaded." msgstr "" +"Charge une clé depuis la [code]string[/code] donnée. Si [code]public_only[/" +"code] est [code]true[/code], seule la clé publique sera chargée." #: doc/classes/CryptoKey.xml msgid "" @@ -23698,12 +24191,21 @@ msgid "" "[b]Note:[/b] [code]path[/code] should be a \"*.pub\" file if " "[code]public_only[/code] is [code]true[/code], a \"*.key\" file otherwise." msgstr "" +"Enregistre une clé au chemin [code]path[/code] spécifié. Si " +"[code]public_only[/code] est [code]true[/code], seule la clé publique sera " +"enregistrée.\n" +"[b]Note :[/b] [code]path[/code] doit être un fichier avec l'extension \"." +"pub\" si [code]public_only[/code] est [code]true[/code], et avec l'extension " +"\".key\" sinon." #: doc/classes/CryptoKey.xml msgid "" "Returns a string containing the key in PEM format. If [code]public_only[/" "code] is [code]true[/code], only the public key will be included." msgstr "" +"Retourne une chaîne de caractères contenant la clé en format PEM. Si " +"[code]public_only[/code] est [code]true[/code], seule la clé publique sera " +"incluse." #: modules/csg/doc_classes/CSGBox.xml msgid "A CSG Box shape." @@ -23781,7 +24283,6 @@ msgid "" msgstr "" #: modules/csg/doc_classes/CSGCylinder.xml -#, fuzzy msgid "" "If [code]true[/code] a cone is created, the [member radius] will only apply " "to one side." @@ -23984,9 +24485,8 @@ msgstr "" "aucun maillage ne sera généré." #: modules/csg/doc_classes/CSGPolygon.xml -#, fuzzy msgid "If [code]true[/code], applies smooth shading to the extrusions." -msgstr "Si [code]true[/code], l’audio est stéréo." +msgstr "" #: modules/csg/doc_classes/CSGPolygon.xml msgid "" @@ -24002,7 +24502,7 @@ msgstr "" #: modules/csg/doc_classes/CSGPolygon.xml msgid "The [member polygon] shape is extruded along the negative Z axis." -msgstr "" +msgstr "La forme [member polygone] est extrudée le long de l'axe Z négatif." #: modules/csg/doc_classes/CSGPolygon.xml msgid "" @@ -24016,6 +24516,8 @@ msgid "" "The [member polygon] shape is extruded along the [Path] specified in [member " "path_node]." msgstr "" +"La forme [member polygone] est extrudée le long du [Path] spécifié par " +"[member path_node]." #: modules/csg/doc_classes/CSGPolygon.xml msgid "" @@ -24110,6 +24612,9 @@ msgid "" "node and the second is the root [Mesh] of this node. Only works when this " "node is the root shape." msgstr "" +"Retourne un [Array] avec deux éléments, le premier est la [Transform] de ce " +"nÅ“ud et le second est le [Mesh] racine de ce nÅ“ud. Ne fonctionne que lorsque " +"ce nÅ“ud est la forme racine." #: modules/csg/doc_classes/CSGShape.xml msgid "" @@ -24180,6 +24685,9 @@ msgid "" "CSG child node as the operation is between this node and the previous child " "of this nodes parent." msgstr "" +"L'opération effectuée sur cette forme. Ceci est ignoré pour le premier nÅ“ud " +"enfant CSG puisque l'opération est entre ce nÅ“ud et l'enfant précédent de ce " +"nÅ“ud parent." #: modules/csg/doc_classes/CSGShape.xml msgid "" @@ -24194,6 +24702,9 @@ msgid "" "always act like a static body. Note that the collision shape is still active " "even if the CSG shape itself is hidden." msgstr "" +"Ajoute une forme de collision au moteur de physique pour cette forme CSG. " +"Cela agira toujours comme un corps statique. Notez que la forme de collision " +"est toujours active même si cette forme CSG est cachée." #: modules/csg/doc_classes/CSGShape.xml msgid "" @@ -24207,7 +24718,6 @@ msgid "Only intersecting geometry remains, the rest is removed." msgstr "Il ne reste que la géométrie d'intersection, le reste est supprimé." #: modules/csg/doc_classes/CSGShape.xml -#, fuzzy msgid "" "The second shape is subtracted from the first, leaving a dent with its shape." msgstr "" @@ -24291,15 +24801,17 @@ msgid "" "effect making the torus seem rounded. If [code]false[/code] the torus will " "have a flat shaded look." msgstr "" +"Si [code]true[/code] les normales du tore sont définies pour donner un effet " +"lisse donnant l'impression que le tore est arrondis. Si [code]false[/code] " +"le tore aura un aspect de rendu plat." #: modules/mono/doc_classes/CSharpScript.xml -#, fuzzy msgid "" "A script implemented in the C# programming language (Mono-enabled builds " "only)." msgstr "" -"Un script implémenté dans le langage de programmation C# (uniquement des " -"compilations Mono-activé)." +"Un script implémenté en langage C# (uniquement pour les versions où Mono est " +"activé)." #: modules/mono/doc_classes/CSharpScript.xml msgid "" @@ -24307,6 +24819,9 @@ msgid "" "class and is only available in Mono-enabled Godot builds.\n" "See also [GodotSharp]." msgstr "" +"Cette classe représente un script C#. C'est l'équivalent C# de la classe " +"[GDScript] et n'est disponible que dans les versions de Godot avec Mono.\n" +"Voir aussi [GodotSharp]." #: modules/mono/doc_classes/CSharpScript.xml #: modules/gdnative/doc_classes/PluginScript.xml @@ -24325,9 +24840,8 @@ msgid "" msgstr "" #: doc/classes/CubeMap.xml -#, fuzzy msgid "Returns the [CubeMap]'s height." -msgstr "Retourne la hauteur de texture." +msgstr "Retourne la hauteur du [CubeMap]." #: doc/classes/CubeMap.xml msgid "" @@ -24338,9 +24852,8 @@ msgstr "" "constantes [enum Side]." #: doc/classes/CubeMap.xml -#, fuzzy msgid "Returns the [CubeMap]'s width." -msgstr "Renvoie la largeur de texture." +msgstr "Renvoie la largeur du [CubeMap]." #: doc/classes/CubeMap.xml msgid "" @@ -24367,9 +24880,8 @@ msgstr "" "défini à [constant STORAGE_COMPRESS_LOSSY]." #: doc/classes/CubeMap.xml -#, fuzzy msgid "The [CubeMap]'s storage mode. See [enum Storage] constants." -msgstr "Convertit le format de l’image. Voir les constantes [enum Format]." +msgstr "" #: doc/classes/CubeMap.xml msgid "Store the [CubeMap] without any compression." @@ -24785,12 +25297,24 @@ msgid "" "get_point_count][/code]), the point will be appended at the end of the point " "list." msgstr "" +"Ajoute un point à une courbe à la [code]position[/code] par rapport à la " +"position de la [Curve2D], avec des points de contrôle d'entrée " +"[code]in[/code] et de sortie [code]out[/code].\n" +"Si [code]at_position[/code] est spécifié, le point est inséré juste avant ce " +"numéro de point [code]at_position[/code], en déplaçant ce point (et tous les " +"autres points qui suivent) après le point inséré. Si [code]at_position[/code]" +" n'est pas donné, ou est une valeur invalide ([code]at_position < 0[/code] " +"ou [code]at_position >= [method get_point_count][/code]), le point sera " +"ajouté en dernier." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" "Returns the total length of the curve, based on the cached points. Given " "enough density (see [member bake_interval]), it should be approximate enough." msgstr "" +"Retourne la longueur totale de la courbe, à partir de la distance entre les " +"points mis en cache. Si la densité est suffisante (voir [member " +"bake_interval]), cette longeur devrait être une approximation suffisante." #: doc/classes/Curve2D.xml msgid "Returns the cache of points as a [PoolVector2Array]." @@ -24802,6 +25326,9 @@ msgid "" "be used in [method interpolate_baked].\n" "[code]to_point[/code] must be in this curve's local space." msgstr "" +"Retourne le décalage le plus proche de [code]to_point[/code]. Ce décalage " +"est destiné à être utilisé dans [méthode interpolate_baked].\n" +"[code]to_point[/code] doit être dans l'espace local de la courbe." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" @@ -24809,6 +25336,9 @@ msgid "" "code].\n" "[code]to_point[/code] must be in this curve's local space." msgstr "" +"Retourne le point en cache le plus proche (dans l'espace local de la courbe) " +"de [code]to_point[/code].\n" +"[code]to_point[/code] doit être dans l'espace local de la courbe." #: doc/classes/Curve2D.xml msgid "" @@ -24817,6 +25347,10 @@ msgid "" "the index is out of bounds, the function sends an error to the console, and " "returns [code](0, 0)[/code]." msgstr "" +"Retourne la position du point de contrôle menant vers le sommet [code]idx[/" +"code]. La position retournée est relative au sommet [code]idx[/code]. Si " +"l'index est hors limites, la fonction affiche une erreur, et retourne [code]" +"(0, 0)[/code]." #: doc/classes/Curve2D.xml msgid "" @@ -24825,6 +25359,10 @@ msgid "" "code]. If the index is out of bounds, the function sends an error to the " "console, and returns [code](0, 0)[/code]." msgstr "" +"Retourne la position du point de contrôle en partant du sommet [code]idx[/" +"code]. La position retournée est relative au sommet [code]idx[/code]. Si " +"l'index est hors limites, la fonction affiche une erreur, et retourne [code]" +"(0, 0)[/code]." #: doc/classes/Curve2D.xml msgid "" @@ -24832,6 +25370,8 @@ msgid "" "bounds, the function sends an error to the console, and returns [code](0, 0)" "[/code]." msgstr "" +"Retourne la position du sommet [code]idx[/code]. Si l'index est hors " +"limites, la fonction affiche une erreur, et retourne [code](0, 0)[/code]." #: doc/classes/Curve2D.xml msgid "" @@ -24844,6 +25384,14 @@ msgid "" "vertex, and [code]t[/code] is ignored. If the curve has no points, the " "function sends an error to the console, and returns [code](0, 0)[/code]." msgstr "" +"Retourne la position entre le sommet [code]idx[/code] et le sommet [code]idx " +"+ 1[/code], où [code]t[/code] contrôle si le point est le premier sommet " +"([code]t = 0,0[/code]), le dernier sommet ([code]t = 1.0[/code]), ou entre " +"les deux. Les valeurs de [code]t[/code] en dehors de l'intervalle ([code]0.0 " +">= t <=1[/code]) donnent des résultats inattendus, mais prévisibles.\n" +"Si [code]idx[/code] est hors limites il est tronqué au premier ou au dernier " +"sommet, et [code]t[/code] est ignoré. Si la courbe n'a pas de points, la " +"fonction affiche une erreur, et retourne [code](0, 0)[/code]." #: doc/classes/Curve2D.xml msgid "" @@ -24856,6 +25404,14 @@ msgid "" "Cubic interpolation tends to follow the curves better, but linear is faster " "(and often, precise enough)." msgstr "" +"Retourne un point dans la courbe à la position [code]offset[/code], où " +"[code]offset[/code] est mesuré en pixels le long de la courbe.\n" +"Pour cela, il trouve les deux points dans le cache où le [code]offset[/code] " +"se situe entre, puis interpole les valeurs. Cette interpolation est cubique " +"si [code]cubic[/code] est [code]true[/code], ou linéaire si est [code]false[/" +"code].\n" +"L'interpolation cubique tend à mieux suivre les courbes, mais " +"l'interpolation linéaire est plus rapide (et souvent bien assez précise)." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" @@ -24863,12 +25419,17 @@ msgid "" "interpolate] using the integer part of [code]fofs[/code] as [code]idx[/" "code], and its fractional part as [code]t[/code]." msgstr "" +"Retourne la position au sommet [code]fofs[/code]. Ça appelle [method " +"interpolate] en utilisant la partie entière de [code]fofs[/code] pour " +"[code]idx[/code], et sa partie décimale pour [code]t[/code]." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" "Deletes the point [code]idx[/code] from the curve. Sends an error to the " "console if [code]idx[/code] is out of bounds." msgstr "" +"Supprime le point [code]idx[/code] de la courbe. Affiche une erreur si " +"[code]idx[/code] est hors limites." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" @@ -24876,6 +25437,9 @@ msgid "" "code]. If the index is out of bounds, the function sends an error to the " "console. The position is relative to the vertex." msgstr "" +"Régle la position du point de contrôle menant au sommet [code]idx[/code]. Si " +"l'index est hors limites, la fonction affiche une erreur. La position est " +"relative au sommet." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" @@ -24883,12 +25447,17 @@ msgid "" "code]. If the index is out of bounds, the function sends an error to the " "console. The position is relative to the vertex." msgstr "" +"Régle la position du point de contrôle partant du sommet [code]idx[/code]. " +"Si l'index est hors limites, la fonction affiche une erreur. La position est " +"relative au sommet." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" "Sets the position for the vertex [code]idx[/code]. If the index is out of " "bounds, the function sends an error to the console." msgstr "" +"Définit la position pour le vertex [code]idx[/code]. Si l'index est hors " +"limites, la fonction affiche une erreur." #: doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "" @@ -24944,6 +25513,11 @@ msgid "" "It keeps a cache of precalculated points along the curve, to speed up " "further calculations." msgstr "" +"Cette classe décrit une courbe de Bézier dans l'espace 3D. Elle est " +"principalement utilisée pour donner une forme à un [Path], mais peut être " +"échantillonné manuellement à d'autres fins.\n" +"Elle conserve un cache de points précalculés le long de la courbe, pour " +"accélérer de nouveaux calculs." #: doc/classes/Curve3D.xml msgid "" @@ -24956,6 +25530,15 @@ msgid "" "get_point_count][/code]), the point will be appended at the end of the point " "list." msgstr "" +"Ajoute un point à la courbe à [code]position[/code] par rapport à la " +"position [Curve3D], avec des points de contrôle [code]in[/code] et " +"[code]out[/code].\n" +"Si [code]at_position[/code] est spécifiée, le point est inséré avant le " +"numéro de point [code]at_position[/code], deplaçant ce point (et tous les " +"suivants) après le point inséré. Si [code]at_position[/code] n'est pas " +"spécifiée, ou est une valeur invalide ([code]at_position <0[/code] ou " +"[code]at_position >= [method get_point_count][/code]), le point sera ajouté " +"à la fin de la liste des points." #: doc/classes/Curve3D.xml msgid "Returns the cache of points as a [PoolVector3Array]." @@ -24970,6 +25553,8 @@ msgid "" "Returns the cache of up vectors as a [PoolVector3Array].\n" "If [member up_vector_enabled] is [code]false[/code], the cache will be empty." msgstr "" +"Retourne le cache des vecteurs du haut dans un [PoolVector3Array].\n" +"Si [member up_vector_enabled] est [code]false[/code], le cache sera vide." #: doc/classes/Curve3D.xml msgid "" @@ -24978,6 +25563,10 @@ msgid "" "interpolate_baked_up_vector].\n" "[code]to_point[/code] must be in this curve's local space." msgstr "" +"Retourne le décalage le plus proche de [code]to_point[/code]. Ce décalage " +"est destiné à être utilisé dans [method interpolate_baked] ou [method " +"interpolate_baked_up_vector].\n" +"[code]to_point[/code] doit être dans l'espace local de cette courbe." #: doc/classes/Curve3D.xml msgid "" @@ -24986,6 +25575,10 @@ msgid "" "the index is out of bounds, the function sends an error to the console, and " "returns [code](0, 0, 0)[/code]." msgstr "" +"Retourne la position du point de contrôle menant au sommet [code]idx[/code]. " +"La position retournée est relative au sommet [code]idx[/code]. Si l'index " +"est hors limites, la fonction affiche une erreur, et retourne [code](0, 0, 0)" +"[/code]." #: doc/classes/Curve3D.xml msgid "" @@ -24994,6 +25587,10 @@ msgid "" "code]. If the index is out of bounds, the function sends an error to the " "console, and returns [code](0, 0, 0)[/code]." msgstr "" +"Retourne la position du point de contrôle partant du sommet [code]idx[/" +"code]. La position retournée est relative au sommet [code]idx[/code]. Si " +"l'index est hors limites, la fonction affiche une erreur, et retourne [code]" +"(0, 0, 0)[/code]." #: doc/classes/Curve3D.xml msgid "" @@ -25001,6 +25598,8 @@ msgid "" "bounds, the function sends an error to the console, and returns [code](0, 0, " "0)[/code]." msgstr "" +"Retourne la position du sommet [code]idx[/code]. Si l'index est hors " +"limites, la fonction affiche une erreur, et retourne [code](0, 0, 0)[/code]." #: doc/classes/Curve3D.xml msgid "" @@ -25023,6 +25622,15 @@ msgid "" "vertex, and [code]t[/code] is ignored. If the curve has no points, the " "function sends an error to the console, and returns [code](0, 0, 0)[/code]." msgstr "" +"Retourne la position entre le sommet [code]idx[/code] et le sommet [code]idx " +"+ 1[/code], où [code]t[/code] contrôle si le point est le premier sommet " +"([code]t = 0,0[/code]), le dernier sommet ([code]t = 1.0[/code]), ou entre " +"ces deux valeurs. Les valeurs de [code]t[/code] en dehors de l'intervalle " +"([code]0.0 >= t <=1[/code]) donnent des résultats inattendus, mais " +"prévisibles.\n" +"Si [code]idx[/code] est hors limites il est tronqué au premier ou au dernier " +"sommet, et [code]t[/code] est ignoré. Si la courbe n'a pas de points, la " +"fonction affiche une erreur, et retourne [code](0, 0, 0)[/code]." #: doc/classes/Curve3D.xml msgid "" @@ -25035,6 +25643,14 @@ msgid "" "Cubic interpolation tends to follow the curves better, but linear is faster " "(and often, precise enough)." msgstr "" +"Retourne un point dans la courbe à la position [code]offset[/code], où " +"[code]offset[/code] est mesuré en unités 3D le long de la courbe.\n" +"Pour cela, il trouve les deux points dans le cache où le [code]offset[/code] " +"se situe entre, puis interpole les valeurs. Cette interpolation est cubique " +"si [code]cubic[/code] est [code]true[/code], ou linéaire si est [code]false[/" +"code].\n" +"L'interpolation cubique tend à mieux suivre les courbes, mais " +"l'interpolation linéaire est plus rapide (et souvent bien assez précise)." #: doc/classes/Curve3D.xml msgid "" @@ -25047,6 +25663,14 @@ msgid "" "If the curve has no up vectors, the function sends an error to the console, " "and returns [code](0, 1, 0)[/code]." msgstr "" +"Retourne un vecteur haut dans la courbe à la position [code]offset[/code], " +"où [code]offset[/code] est mesuré en unités 3D le long de la courbe.\n" +"Pour cela, il trouve les deux vecteurs dans le cache où le [code]offset[/" +"code] se situe entre, puis interpole les valeurs. Si [code]apply_tilt[/code] " +"est [code]true[/code], une inclinaison interpolée est aussi appliquée au " +"vecteur interpolé.\n" +"Si la courbe n'a pas de vecteurs, la fonction affiche une erreur, et " +"retourne [code](0, 1, 0)[/code]." #: doc/classes/Curve3D.xml msgid "" @@ -25056,6 +25680,11 @@ msgid "" "the path would have. In the case of a curve controlling a [PathFollow], this " "tilt is an offset over the natural tilt the [PathFollow] calculates." msgstr "" +"Définit l'angle d'inclinaison en radians pour le point [code]idx[/code]. Si " +"l'index est hors limites, la fonction affiche une erreur.\n" +"L'inclinaison contrôle la rotation qu'un objet parcourant la courbe aurait. " +"Dans le cas d'une courbe contrôlant un [PathFollow], cette inclinaison est " +"un décalage sur l'inclinaison naturelle que calcule le [PathFollow]." #: doc/classes/Curve3D.xml msgid "" @@ -25065,6 +25694,11 @@ msgid "" "smaller the distance, the more points in the cache and the more memory it " "will consume, so use with care." msgstr "" +"La distance en unités entre deux points de cache adjacents. Le changement " +"force le cache à être recalculé la prochaine fois que la fonction [method " +"get_baked_points] ou [method get_baked_length] sera appelée. Plus la " +"distance est petite, plus il y aura de points dans le cache, et plus ça " +"utilisera de mémoire, à utiliser donc avec soin." #: doc/classes/Curve3D.xml msgid "" @@ -25072,6 +25706,10 @@ msgid "" "This is used when [member PathFollow.rotation_mode] is set to [constant " "PathFollow.ROTATION_ORIENTED]. Changing it forces the cache to be recomputed." msgstr "" +"Si [code]true[/code], la courbe pré-calcule des vecteurs utilisés pour " +"l'orientation. Ceci est utilisé lorsque [member PathFollow.rotation_mode] " +"est défini à [constant PathFollow.ROTATION_ORIENTED]. Le changer force le " +"cache à être recalculé." #: doc/classes/CurveTexture.xml msgid "A texture that shows a curve." @@ -25082,11 +25720,12 @@ msgid "" "Renders a given [Curve] provided to it. Simplifies the task of drawing " "curves and/or saving them as image files." msgstr "" +"Fait le rendu d'une [Curve] donnée. Simplifie la tâche de dessiner les " +"courbes et/ou de les enregistrer dans des fichiers d'image." #: doc/classes/CurveTexture.xml -#, fuzzy msgid "The [Curve] that is rendered onto the texture." -msgstr "La [code]curve[/code] rendue sur la texture." +msgstr "La [Curve] qui est rendue dans la texture." #: doc/classes/CurveTexture.xml msgid "" @@ -25094,6 +25733,10 @@ msgid "" "represent high-frequency data better (such as sudden direction changes), at " "the cost of increased generation time and memory usage." msgstr "" +"La largeur de la texture (en pixels). Des valeurs plus élevées permettent de " +"mieux représenter les données à haute fréquence (comme les changements " +"soudains de direction) au coût de l'utilisation accrue du temps de " +"génération et de la mémoire." #: doc/classes/CylinderMesh.xml msgid "Class representing a cylindrical [PrimitiveMesh]." @@ -25105,12 +25748,17 @@ msgid "" "create cones by setting either the [member top_radius] or [member " "bottom_radius] properties to [code]0.0[/code]." msgstr "" +"La classe représentant un [PrimitiveMesh] cylindrique. Cette classe peut " +"être utilisée pour créer des cônes en définissant la propriété [member " +"top_radius] ou [member bottom_radius] à [code]0.0[/code]." #: doc/classes/CylinderMesh.xml msgid "" "Bottom radius of the cylinder. If set to [code]0.0[/code], the bottom faces " "will not be generated, resulting in a conic shape." msgstr "" +"Le rayon inférieur du cylindre. Si [code]0.0[/code], les faces inférieures " +"ne seront pas générées, ce qui donne une forme conique." #: doc/classes/CylinderMesh.xml msgid "Full height of the cylinder." @@ -25121,6 +25769,9 @@ msgid "" "Number of radial segments on the cylinder. Higher values result in a more " "detailed cylinder/cone at the cost of performance." msgstr "" +"Le nombre de segments radiaux sur le cylindre. Des valeurs plus élevées " +"génèrent des cylindres/cônes plus détaillés mais peuvent réduire les " +"performances." #: doc/classes/CylinderMesh.xml msgid "" @@ -25138,6 +25789,8 @@ msgid "" "Top radius of the cylinder. If set to [code]0.0[/code], the top faces will " "not be generated, resulting in a conic shape." msgstr "" +"Le rayon supérieur du cylindre. Si [code]0.0[/code], les faces supérieures " +"ne seront pas générées, ce qui donne une forme conique." #: doc/classes/CylinderShape.xml msgid "Cylinder shape for collisions." @@ -25152,9 +25805,8 @@ msgid "The cylinder's radius." msgstr "Le rayon du cylindre." #: doc/classes/DampedSpringJoint2D.xml -#, fuzzy msgid "Damped spring constraint for 2D physics." -msgstr "Contrainte de ressort amortie pour la physique 2D." +msgstr "Une contrainte de ressort avec amortissement pour la physique 2D." #: doc/classes/DampedSpringJoint2D.xml msgid "" @@ -25438,6 +26090,12 @@ msgid "" "[b]Note:[/b] Don't erase elements while iterating over the dictionary. You " "can iterate over the [method keys] array instead." msgstr "" +"Efface une paire de clé/valeur du dictionnaire spécifiée par sa clé. " +"Retourne [code]true[/code] si la clé donnée était présente dans le " +"dictionnaire, [code]false[/code] sinon.\n" +"[b]Note :[/b] Ne supprimez pas les éléments pendant l'énumération du " +"dictionnaire. Vous pouvez à la place énumérer le dictionnaire avec [method " +"keys] qui retourne un tableau immuable." #: doc/classes/Dictionary.xml msgid "" @@ -25445,6 +26103,9 @@ msgid "" "key does not exist, the method returns the value of the optional default " "argument, or [code]null[/code] if it is omitted." msgstr "" +"Retourne la valeur actuelle de la clé spécifiée dans le [Dictionnaire]. Si " +"la clé n'existe pas, la méthode retourne la valeur de l'argument optionnel " +"\"default\", ou [code]null[/code] si elle n'est pas spécifiée." #: doc/classes/Dictionary.xml msgid "" @@ -25525,6 +26186,9 @@ msgid "" "duplicate keys will not be copied over, unless [code]overwrite[/code] is " "[code]true[/code]." msgstr "" +"Ajoute tous les éléments de [code]dictionary[/code] à ce [Dictionnaire]. Par " +"défaut, les clés en double ne seront pas remplaçées, sauf si " +"[code]overwrite[/code] est [code]true[/code]." #: doc/classes/Dictionary.xml msgid "Returns the number of keys in the dictionary." @@ -25547,6 +26211,12 @@ msgid "" "or moonlight. The worldspace location of the DirectionalLight transform " "(origin) is ignored. Only the basis is used to determine light direction." msgstr "" +"Une lumière directionnelle est un type de nÅ“ud [Light] qui fait un rendu " +"d'un nombre infini de rayons parallèles couvrant toute la scène. Il est " +"utilisé pour les lumières à forte intensité qui sont situées loin de la " +"scène pour modéliser la lumière du soleil ou du clair de lune. L'emplacement " +"global de la DirectionalLight (son origine) est ignoré. Seule sa rotation " +"est utilisée pour déterminer la direction de la lumière." #: doc/classes/DirectionalLight.xml msgid "" @@ -25563,6 +26233,10 @@ msgid "" "moderate performance cost. This is ignored when [member " "directional_shadow_mode] is [constant SHADOW_ORTHOGONAL]." msgstr "" +"Si [code]true[/code], le détail des ombres est sacrifié pour obtenir des " +"transitions plus lisses entre les fractions. Activer cette option a " +"également un coût modéré sur les performances. Ceci est ignoré lorsque " +"[member directional_shadow_mode] est [constant SHADOW_ORTHOGONAL]." #: doc/classes/DirectionalLight.xml msgid "" @@ -25579,6 +26253,10 @@ msgid "" "shadow detail and performance (since more objects need to be included in the " "directional shadow rendering)." msgstr "" +"La distance maximale pour les fractions des ombres. Augmenter cette valeur " +"rendra visibles les ombres directionnelles de plus loin, mais affichera " +"moins de détails des ombres et de moins bonnes performances (puisque plus " +"d'objets doivent être inclus dans le rendu d'ombre directionnel)." #: doc/classes/DirectionalLight.xml msgid "The light's shadow rendering algorithm. See [enum ShadowMode]." @@ -25590,6 +26268,8 @@ msgid "" "Can be used to fix special cases of self shadowing when objects are " "perpendicular to the light." msgstr "" +"Peut être utilisé pour corriger des cas spéciaux pour les ombres des objets " +"qui sont perpendiculaires à la source de lumière." #: doc/classes/DirectionalLight.xml msgid "" @@ -25598,6 +26278,10 @@ msgid "" "directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant " "SHADOW_PARALLEL_4_SPLITS]." msgstr "" +"La distance de la caméra à la division 1 de l'ombre. Relative à [member " +"directional_shadow_max_distance]. Seulement utilisé lorsque [member " +"directional_shadow_mode] est [constant SHADOW_PARALLEL_2_SPLITS] ou " +"[constant SHADOW_PARALLEL_4_SPLITS]." #: doc/classes/DirectionalLight.xml msgid "" @@ -25606,6 +26290,10 @@ msgid "" "directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant " "SHADOW_PARALLEL_4_SPLITS]." msgstr "" +"La distance de la division 1 à la divion 2 de l'ombre. Relative à [member " +"directional_shadow_max_distance]. Seulement utilisé lorsque [member " +"directional_shadow_mode] est [constant SHADOW_PARALLEL_2_SPLITS] ou " +"[constant SHADOW_PARALLEL_4_SPLITS]." #: doc/classes/DirectionalLight.xml msgid "" @@ -25613,6 +26301,9 @@ msgid "" "directional_shadow_max_distance]. Only used when [member " "directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]." msgstr "" +"La distance de la division 2 à la divion 3 de l'ombre. Relative à [member " +"directional_shadow_max_distance]. Seulement utilisé lorsque [member " +"directional_shadow_mode] est [constant SHADOW_PARALLEL_4_SPLITS]." #: doc/classes/DirectionalLight.xml msgid "" @@ -25642,6 +26333,8 @@ msgid "" "Keeps the shadow stable when the camera moves, at the cost of lower " "effective shadow resolution." msgstr "" +"Garde l'ombre stable lorsque la caméra se déplace, mais la résolution de " +"l'ombre se trouve réduite." #: doc/classes/DirectionalLight.xml msgid "" @@ -25649,6 +26342,10 @@ msgid "" "shadow edges. This mode typically works best in games where the camera will " "often move at high speeds, such as most racing games." msgstr "" +"Essaye d'atteindre une résolution maximale pour l'ombre. Peut faire " +"apparaitre un effet de scie sur les bords de l'ombre. Ce mode fonctionne " +"généralement mieux dans les jeux où la caméra se déplace souvent à des " +"vitesses élevées, comme la plupart des jeux de course." #: doc/classes/Directory.xml msgid "Type used to handle the filesystem." @@ -25720,9 +26417,9 @@ msgid "" msgstr "" "Change le dossier actuellement ouvert par celui donné en argument. " "L'argument peut être relatif au répertoire actuel (par exemple " -"[code]nouveau_dossier[/code] ou [code]./dossier[ /code,)] ou être un chemin " +"[code]nouveau_dossier[/code] ou [code]./dossier[/code]), ou être un chemin " "absolu (par exemple [code]/tmp/dossier[/code] ou [code]res://parent/" -"dossier[ /code)].\n" +"dossier[/code]).\n" "Retourne une des constantes de code [enum Error] (et [code]OK[/code] en cas " "de succès)." @@ -26177,6 +26874,10 @@ msgid "" "If a given character is included in more than one font, it appears only once " "in the returned string." msgstr "" +"Retourne une chaîne contenant tous les caractères disponibles dans la police " +"principale et celles de repli.\n" +"Si un caractère donné est inclus dans plus d'une police, il apparaît " +"seulement une fois dans la chaîne retournée." #: doc/classes/DynamicFont.xml msgid "Returns the fallback font at index [code]idx[/code]." @@ -26206,6 +26907,8 @@ msgid "" "Sets the spacing for [code]type[/code] (see [enum SpacingType]) to " "[code]value[/code] in pixels (not relative to the font size)." msgstr "" +"Définit l'espacement pour [code]type[/code] (voir [enum SpacingType]) à " +"[code]value[/code] en pixels (et en fonction de la taille de la police)." #: doc/classes/DynamicFont.xml msgid "Extra spacing at the bottom in pixels." @@ -26217,6 +26920,8 @@ msgid "" "This can be a negative number to make the distance between characters " "smaller." msgstr "" +"L'espacement additionnel entre chaque caratère, en pixels.\n" +"Ceci peut être un nombre négatif pour rapprocher les caractères." #: doc/classes/DynamicFont.xml msgid "" @@ -26224,6 +26929,9 @@ msgid "" "extra_spacing_char]) in pixels.\n" "This can be a negative number to make the distance between words smaller." msgstr "" +"L'espacement additionnel entre les caractères d'espace (en plus de [member " +"extra_spacing_char]), en pixels.\n" +"Cela peut être un nombre négatif pour rapprocher les mots." #: doc/classes/DynamicFont.xml msgid "Extra spacing at the top in pixels." @@ -26241,10 +26949,17 @@ msgid "" "black here, it won't be possible to change its color using a Label's font " "outline modulate theme item." msgstr "" +"La couleur du contour de la police.\n" +"[b]Note :[/b] Il est recommandé de laisser ceci à la valeur par défaut afin " +"que vous puissiez l'ajuster dans les contrôles individuels. Par exemple, si " +"le contour est déclaré ici en noir, il ne sera pas possible de modifier sa " +"couleur même en utilisant un thème pour le Label." #: doc/classes/DynamicFont.xml msgid "The font outline's thickness in pixels (not relative to the font size)." msgstr "" +"L'épaisseur du contour de la police, en pixels (et non en fonction à la " +"taille de la police)." #: doc/classes/DynamicFont.xml msgid "The font size in pixels." @@ -26265,6 +26980,9 @@ msgid "" "appearance when downscaling it if font oversampling is disabled or " "ineffective." msgstr "" +"Si [code]true[/code], les mipmaps sont utilisées. Cela améliore l'apparence " +"de la police lorsqu'elle est désactivée si le sur-échantillonnage de la " +"police est désactivé ou non utilisé." #: doc/classes/DynamicFont.xml msgid "Spacing at the top." @@ -26292,6 +27010,8 @@ msgid "" "Used with [DynamicFont] to describe the location of a vector font file for " "dynamic rendering at runtime." msgstr "" +"Utilisé avec [DynamicFont] pour décrire l'emplacement d'un fichier de police " +"vectoriel pour un rendu dynamique au lancement du projet." #: doc/classes/DynamicFontData.xml msgid "" @@ -26322,9 +27042,8 @@ msgid "Disables font hinting (smoother but less crisp)." msgstr "" #: doc/classes/DynamicFontData.xml -#, fuzzy msgid "Use the light font hinting mode." -msgstr "Utilisez le mode d’allusion de police de lumière." +msgstr "Utilise le mode d'indice de police légère." #: doc/classes/DynamicFontData.xml msgid "Use the default font hinting mode (crisper but less smooth)." @@ -26433,6 +27152,12 @@ msgid "" "This method should not be used for System libraries as they are already " "present on the device." msgstr "" +"Ajoute une bibliothèque dynamique (*.dylib, *.framework) au \"Linking " +"Phase\" dans le projet Xcode d'iOS et l'intègre en binaire final.\n" +"[b]Note :[/b] Pour les bibliothèques statiques (*.a), ça fonctionne de la " +"même manière que [méthode add_ios_framework].\n" +"Cette méthode ne devrait pas être utilisée pour les bibliothèques système " +"car elles sont déjà présentes sur l'appareil." #: doc/classes/EditorExportPlugin.xml msgid "" @@ -26451,6 +27176,8 @@ msgstr "" #: doc/classes/EditorExportPlugin.xml msgid "Adds a static lib from the given [code]path[/code] to the iOS project." msgstr "" +"Ajoute la bibliothèque statique à l'emplacement [code]path[/code] spécifié " +"au projet iOS." #: doc/classes/EditorExportPlugin.xml msgid "" @@ -26458,6 +27185,9 @@ msgid "" "directory of macOS app bundle.\n" "[b]Note:[/b] This is useful only for macOS exports." msgstr "" +"Ajoute le fichier ou le dossier correspondant à l'emplacement [code]path[/" +"code] au dossier [code]PlugIns[/code] de l'applications macOS.\n" +"[b]Note :[/b] Cela n'est utile que pour les exports pour macOS." #: doc/classes/EditorExportPlugin.xml msgid "" @@ -26577,11 +27307,12 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" "Enregistre le profil de fonctionnalité de l'éditeur dans un fichier au " -"format JSON. Il peut ensuite être importé en utilisant le bouton [b]Import[/" -"b] ou la méthode [method load_from_file]." +"format JSON. Il peut ensuite être importé en utilisant le bouton " +"[b]Importer[/b] du gestionnaire de profils ou via la méthode [method " +"load_from_file]." #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -26613,6 +27344,11 @@ msgid "" "When a property is disabled, it won't appear in the inspector when selecting " "a node that extends the class specified by [code]class_name[/code]." msgstr "" +"Si [code]disable[/code] est [code]true[/code], désactive l'édition de la " +"[code]property[/code] dans la classe nommée [code]class_name[/code]. " +"Lorsqu'une propriété est désactivée, elle n'apparaît plus dans l'inspecteur " +"lors du choix d'un nÅ“ud qui étend la classe spécifiée par [code]class_name[/" +"code]." #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -26726,12 +27462,17 @@ msgid "" "Notify the [EditorFileDialog] that its view of the data is no longer " "accurate. Updates the view contents on next view update." msgstr "" +"Notifie le [EditorFileDialog] que sa vue que son contenu n'est plus à jour. " +"Mettre à jour le contenu de la vue sur la prochaine mise à jour de la vue." #: doc/classes/EditorFileDialog.xml msgid "" "The location from which the user may select a file, including [code]res://[/" "code], [code]user://[/code], and the local file system." msgstr "" +"L'emplacement à partir duquel l'utilisateur peut sélectionner un fichier, y " +"compris [code]res://[/code], [code]user://[/code], et le système de fichiers " +"local." #: doc/classes/EditorFileDialog.xml msgid "The currently occupied directory." @@ -26758,11 +27499,13 @@ msgid "" "The view format in which the [EditorFileDialog] displays resources to the " "user." msgstr "" +"Le format de vue dans lequel le [EditorFileDialog] affiche les ressources à " +"l'utilisateur." #: doc/classes/EditorFileDialog.xml msgid "" "The purpose of the [EditorFileDialog], which defines the allowed behaviors." -msgstr "" +msgstr "Le but du [EditorFileDialog], qui définit les comportements autorisés." #: doc/classes/EditorFileDialog.xml msgid "" @@ -26789,6 +27532,8 @@ msgid "" "The [EditorFileDialog] can select only one file. Accepting the window will " "open the file." msgstr "" +"Le [EditorFileDialog] ne peut sélectionner qu'un seul fichier. Accepter " +"cette fenêtre ouvrira le fichier sélectionné." #: doc/classes/EditorFileDialog.xml msgid "" @@ -26803,6 +27548,8 @@ msgid "" "The [EditorFileDialog] can select only one directory. Accepting the window " "will open the directory." msgstr "" +"Le [EditorFileDialog] ne peut sélectionner qu'un seul dossier. Accepter la " +"fenêtre ouvrira le dossier sélectionné." #: doc/classes/EditorFileDialog.xml msgid "" @@ -26860,6 +27607,11 @@ msgid "" "[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access " "the singleton using [method EditorInterface.get_resource_filesystem]." msgstr "" +"Cet objet contient des informations sur toutes les ressources du système de " +"fichiers, leurs types, etc.\n" +"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. " +"Accédez plutôt à l'instance unique avec [method EditorInterface." +"get_resource_filesystem]." #: doc/classes/EditorFileSystem.xml msgid "" @@ -26867,6 +27619,10 @@ msgid "" "string such as [code]\"Resource\"[/code] or [code]\"GDScript\"[/code], " "[i]not[/i] a file extension such as [code]\".gd\"[/code]." msgstr "" +"Retourne le type de ressource du fichier, spécifié par le chemin complet. " +"Ceci retourne une chaîne comme [code]\"Resource\"[/code] or " +"[code]\"GDScript\"[/code], mais [i]pas[/i] l'extension du fichier comme " +"[code]\".gd\"[/code]." #: doc/classes/EditorFileSystem.xml msgid "Gets the root directory object." @@ -26881,9 +27637,10 @@ msgstr "" #: doc/classes/EditorFileSystem.xml msgid "Returns the scan progress for 0 to 1 if the FS is being scanned." msgstr "" +"Retourne la progression de l'analyse de 0 à 1 si le système de fichiers est " +"en train d'être scanné." #: doc/classes/EditorFileSystem.xml -#, fuzzy msgid "Returns [code]true[/code] if the filesystem is being scanned." msgstr "Retourne [code]true[/code] si le système de fichier a été scanné." @@ -26900,10 +27657,14 @@ msgid "" "Update a file information. Call this if an external program (not Godot) " "modified the file." msgstr "" +"Met à jour les informations du fichier. Appelez cette méthode si un " +"programme externe (hors Godot) a modifié le fichier." #: doc/classes/EditorFileSystem.xml msgid "Scans the script files and updates the list of custom class names." msgstr "" +"Scanne les fichiers de script et met à jour la liste des noms de classe " +"personnalisés." #: doc/classes/EditorFileSystem.xml msgid "Emitted if the filesystem changed." @@ -26974,6 +27735,9 @@ msgid "" "[code]idx[/code]. If the file doesn't define a script class using the " "[code]class_name[/code] syntax, this will return an empty string." msgstr "" +"Retourne la classe de base de la classe de script définie dans le fichier à " +"index [code]idx[/code]. Si le fichier ne définit pas une classe de script en " +"utilisant la syntaxe [code]class_name[/code], une chaîne vide est retournée." #: doc/classes/EditorFileSystemDirectory.xml msgid "" @@ -26981,6 +27745,9 @@ msgid "" "code]. If the file doesn't define a script class using the [code]class_name[/" "code] syntax, this will return an empty string." msgstr "" +"Retourne le nom de la classe script définie dans le fichier à index " +"[code]idx[/code]. Si le fichier ne définit pas une classe de script en " +"utilisant la syntaxe [code]class_name[/code], une chaîne vide est retournée." #: doc/classes/EditorFileSystemDirectory.xml msgid "" @@ -26988,6 +27755,9 @@ msgid "" "returns a string such as [code]\"Resource\"[/code] or [code]\"GDScript\"[/" "code], [i]not[/i] a file extension such as [code]\".gd\"[/code]." msgstr "" +"Retourne le type de ressource du fichier à l'index [code]idx[/code]. Ceci " +"retourne une chaîne comme [code]\"Resource\"[/code] or [code]\"GDScript\"[/" +"code], mais [i]pas[/i] l'extension du fichier comme [code]\".gd\"[/code]." #: doc/classes/EditorFileSystemDirectory.xml msgid "Returns the name of this directory." @@ -27018,6 +27788,9 @@ msgid "" "Registers a custom resource importer in the editor. Use the class to parse " "any file and import it as a new resource type." msgstr "" +"Enregistre un importateur de ressources personnalisée dans l'éditeur. " +"Utilisez cette classe pour interpréter n'importe quel fichier pour " +"l'importer comme nouveau type de ressource." #: doc/classes/EditorImportPlugin.xml msgid "" @@ -27078,8 +27851,8 @@ msgid "" msgstr "" "Les [EditorImportPlugin] fournissent un moyen d'étendre la fonctionnalité " "d'importation des ressources dans l'éditeur. Utilisez-les pour importer des " -"ressources depuis des formats de de fichier personnalisés ou pour proposer " -"une alternative aux importateurs existants de l'éditeur.\n" +"ressources depuis des formats de fichier personnalisés ou pour proposer une " +"alternative aux importateurs existants de l'éditeur.\n" "Les EditorImportPlugins fonctionnent pas associés certaines extensions de " "fichiers avec un type de ressource. Voir [method get_recognized_extensions] " "et [method get_resource_type]. Ils peuvent aussi spécifier des préréglages " @@ -27139,6 +27912,11 @@ msgid "" "[code]default_value[/code], [code]property_hint[/code] (optional), " "[code]hint_string[/code] (optional), [code]usage[/code] (optional)." msgstr "" +"Retourne les options et les valeurs par défaut pour le préréglage à cet " +"index. Retourne un Array de Dictionnary avec les clés suivantes : " +"[code]name[/code], [code]default_value[/code], [code]property_hint[/code] " +"(optionnel), [code]hint_string[/code] (optionnel) et [code]usage[/code] " +"(optionnel)." #: doc/classes/EditorImportPlugin.xml msgid "" @@ -27268,10 +28046,8 @@ msgstr "" "surcharge de cette méthode." #: doc/classes/EditorInspector.xml -#, fuzzy msgid "A control used to edit properties of an object." -msgstr "" -"Contrôle personnalisé pour modifier les propriétés à ajouter à l’inspecteur." +msgstr "Un contrôle pour modifier les propriétés d'un objet." #: doc/classes/EditorInspector.xml msgid "" @@ -27360,10 +28136,13 @@ msgid "" "by clicking the \"key\" icon next to a property when the Animation panel is " "toggled." msgstr "" +"Émis lorsqu'une propriété est utilisée comme clé dans l'inspecteur. Les " +"propriétés peuvent être utilisées comme clé en cliquant sur l'icône \"clé\" " +"à côté d'une propriété lorsque le panneau \"Animation\" est ouvert." #: doc/classes/EditorInspector.xml msgid "Emitted when a property is selected in the inspector." -msgstr "" +msgstr "Émis lorsqu'une propriété est sélectionnée dans l'inspecteur." #: doc/classes/EditorInspector.xml msgid "" @@ -27372,6 +28151,11 @@ msgid "" "code] property enabled. Since this property is always enabled in the editor " "inspector, this signal is never emitted by the editor itself." msgstr "" +"Émis lorsqu'une propriété booléenne est basculée dans l'inspecteur.\n" +"[b]Note :[/b] Ce signal n'est jamais émis si la propriété interne " +"[code]autoclear[/code] est activée. Comme cette propriété est toujours " +"activée dans l'inspecteur de l'éditeur, ce signal n'est jamais émis par " +"l'éditeur lui-même." #: doc/classes/EditorInspector.xml msgid "Emitted when a resource is selected in the inspector." @@ -27426,18 +28210,24 @@ msgstr "Les greffons de l'inspecteur" #: doc/classes/EditorInspectorPlugin.xml msgid "Adds a custom control, which is not necessarily a property editor." msgstr "" +"Ajoute un contrôle personnalisé, qui n'est pas nécessairement un éditeur de " +"propriété." #: doc/classes/EditorInspectorPlugin.xml msgid "" "Adds a property editor for an individual property. The [code]editor[/code] " "control must extend [EditorProperty]." msgstr "" +"Ajoute un éditeur de propriétés pour une seule propriété. Le contrôle " +"[code]editor[/code] doit être une sous-classe de [EditorProperty]." #: doc/classes/EditorInspectorPlugin.xml msgid "" "Adds an editor that allows modifying multiple properties. The [code]editor[/" "code] control must extend [EditorProperty]." msgstr "" +"Ajoute un éditeur qui permet de modifier plusieurs propriétés. Le contrôle " +"[code]editor[/code] doit être une sous-classe de [EditorProperty]." #: doc/classes/EditorInspectorPlugin.xml msgid "Returns [code]true[/code] if this object can be handled by this plugin." @@ -27462,6 +28252,10 @@ msgid "" "built-in editor for this property, otherwise allows to insert a custom " "editor before the built-in one." msgstr "" +"Appelé pour autoriser l'ajout d'éditeurs spécifiques à la propriété dans " +"l'inspecteur. Habituellement, ils héritent de [EditorProperty]. Retourner " +"[code]true[/code] supprimera l'éditeur intégré pour cette propriété, c'est-à -" +"dire que ça permet d'insérer un éditeur personnalisé avant l'éditeur intégré." #: doc/classes/EditorInterface.xml msgid "Godot editor's interface." @@ -27499,6 +28293,9 @@ msgid "" "Edits the given [Resource]. If the resource is a [Script] you can also edit " "it with [method edit_script] to specify the line and column position." msgstr "" +"Modifie la [Resource] donnée. Si la ressource est un [Script], vous pouvez " +"également la modifier avec [method edit_script] en spécifiant la position de " +"la ligne et de la colonne." #: doc/classes/EditorInterface.xml msgid "" @@ -27506,6 +28303,10 @@ msgid "" "can also be specified. The script will be open with the user-configured " "editor for the script's language which may be an external editor." msgstr "" +"Modifie le [Script]. La ligne et la colonne à laquelle ce script s'ouvre " +"peut également être spécifiées. Le script sera ouvert avec l'éditeur " +"configuré par l'utilisateur pour ce type de langage, où un éditeur externe " +"peut être spécifié." #: doc/classes/EditorInterface.xml msgid "" @@ -27515,10 +28316,15 @@ msgid "" "[b]Warning:[/b] Removing and freeing this node will render the editor " "useless and may cause a crash." msgstr "" +"Retourne le conteneur principal de la fenêtre de l'éditeur de Godot. Par " +"exemple, vous pouvez l'utiliser pour récupérer la taille du conteneur et " +"placer vos contrôles en conséquence.\n" +"[b]Avertissement :[/b] Enlever et libérer ce nÅ“ud rend l'éditeur inutile et " +"peut causer un plantage." #: doc/classes/EditorInterface.xml msgid "Returns the current path being viewed in the [FileSystemDock]." -msgstr "" +msgstr "Retourne l'actuel chemin en train d'être vu dans le [FileSystemDock]." #: doc/classes/EditorInterface.xml msgid "Returns the edited (current) scene's root [Node]." @@ -27533,6 +28339,13 @@ msgid "" "code] and [code]interface/editor/custom_display_scale[/code] editor " "settings. Editor must be restarted for changes to be properly applied." msgstr "" +"Retourne l'échelle actuelle de l'interface de l'éditeur ([code]1.0[/code] " +"étant une échelle à 100%). Cela peut être utilisé pour régler la position et " +"les dimensions des interfaces utilisateurs ajoutées par les greffons.\n" +"[b]Note :[/b] Cette valeur est définie par [code]interface/editor/" +"display_scale[/code] et [code]interface/editor/custom_display_scale[/code]. " +"L'éditeur doit être redémarré pour que les changements soient complètement " +"appliqués." #: doc/classes/EditorInterface.xml msgid "Returns the editor's [EditorSettings] instance." @@ -27609,6 +28422,9 @@ msgid "" "[FileSystemDock]. If a file is selected, its base directory will be returned " "using [method String.get_base_dir] instead." msgstr "" +"Retourne le chemin du dossier actuellement sélectionné dans le " +"[FileSystemDock]. Si un fichier est sélectionné, son dossier de base sera " +"retourné en utilisant [method String.get_base_dir]." #: doc/classes/EditorInterface.xml msgid "Returns the editor's [EditorSelection] instance." @@ -27620,24 +28436,22 @@ msgid "" "Inspector dock. If [code]inspector_only[/code] is [code]true[/code], plugins " "will not attempt to edit [code]object[/code]." msgstr "" +"Affiche la propriété donnée sur le [code]object[/code] donné dans la barre " +"d'outils de l'inspecteur de l'éditeur. Si [code]inspector_only[/code] est " +"[code]true[/code], les greffons ne tenteront pas de modifier cet " +"[code]object[/code]." #: doc/classes/EditorInterface.xml -#, fuzzy msgid "" "Returns [code]true[/code] if a scene is currently being played, [code]false[/" "code] otherwise. Paused scenes are considered as being played." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères commence par la chaîne " -"de caractères donnée, ou [code]false[/code] le cas échéant." #: doc/classes/EditorInterface.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the specified [code]plugin[/code] is enabled. " "The plugin name is the same as its directory name." msgstr "" -"Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment " -"zéro." #: doc/classes/EditorInterface.xml msgid "" @@ -27693,6 +28507,10 @@ msgid "" "([code]2D[/code], [code]3D[/code], [code]Script[/code], [code]AssetLib[/" "code])." msgstr "" +"Spécifie l'écran principal courant de l'éditeur activé avec celui nommé " +"[code]name[/code]. [code]name[/code] doit correspondre exactement au texte " +"de l'onglet en question (soit [code]2D[/code], [code]3D[/code], " +"[code]Script[/code], ou [code]AssetLib[/code])." #: doc/classes/EditorInterface.xml msgid "" @@ -27711,6 +28529,8 @@ msgid "" "If [code]true[/code], enables distraction-free mode which hides side docks " "to increase the space available for the main view." msgstr "" +"Si [code]true[/code], active le mode sans distraction qui cache les barres " +"d'outils latérales pour augmenter l'espace disponible pour la vue principale." #: doc/classes/EditorPlugin.xml msgid "Used by the editor to extend its functionality." @@ -27723,6 +28543,10 @@ msgid "" "plugins and export plugins. See also [EditorScript] to add functions to the " "editor." msgstr "" +"Les greffons sont utilisés par l'éditeur pour étendre les fonctionnalités. " +"Les types les plus courants de greffons sont ceux qui modifient un nÅ“ud " +"donné ou un type de ressource, les greffons d'importation et d'exportation. " +"Voir aussi [EditorScript] pour ajouter des fonctions à l'éditeur." #: doc/classes/EditorPlugin.xml msgid "" @@ -27879,6 +28703,9 @@ msgid "" "Registers a new [EditorSceneImporter]. Scene importers are used to import " "custom 3D asset formats as scenes." msgstr "" +"Enregistre un nouveau [EditorSceneImporter]. Les importateurs de scène sont " +"utilisés pour importer des formats d'éléments 3D personnalisés comme des " +"scènes." #: doc/classes/EditorPlugin.xml msgid "" @@ -27886,6 +28713,11 @@ msgid "" "custom gizmos to the 3D preview viewport for a [Spatial].\n" "See [method add_inspector_plugin] for an example of how to register a plugin." msgstr "" +"Enregistre un nouveau [EditorSpatialGizmoPlugin]. Les greffons du " +"manipulateur sont utilisés pour ajouter des manipulateurs personnalisés dans " +"la fenêtre d'affichage 3D pour transformer un [Spatial].\n" +"Voir [method add_inspector_greffon] pour un exemple sur comment enregistrer " +"un greffon." #: doc/classes/EditorPlugin.xml msgid "" @@ -27909,6 +28741,13 @@ msgid "" "This is used, for example, in shader editors to let the plugin know that it " "must apply the shader code being written by the user to the object." msgstr "" +"Cette méthode est appelée lorsque l'éditeur est sur le point d'enregistrer " +"le projet, passer à un autre onglet, etc. Il demande au greffon d'appliquer " +"tout changement d'état qui serait en attente pour garder une certaine " +"cohérence.\n" +"Ceci est utilisé, par exemple, dans les éditeurs d'ombres pour signaler au " +"greffon qu'il doit appliquer le shader d'ombre écrit par l'utilisateur à " +"l'objet." #: doc/classes/EditorPlugin.xml msgid "" @@ -27918,6 +28757,13 @@ msgid "" "code], the project will not run. The run is aborted immediately, so this " "also prevents all other plugins' [method build] methods from running." msgstr "" +"Cette méthode est appelée lorsque l'éditeur est sur le point de lancer le " +"projet. Le greffon peut ensuite effectuer les opérations requises avant le " +"lancement du projet.\n" +"Cette méthode doit retourner un booléen. Si cette méthode retourne " +"[code]false[/code], le projet ne sera pas lancé. Le lancement sera " +"immédiatement annulé, ce qui empêche également toutes les autres méthodes de " +"fonctionnement des greffons." #: doc/classes/EditorPlugin.xml msgid "" @@ -27925,24 +28771,34 @@ msgid "" "your plugin does not keep editing a currently existing node, or a node from " "the wrong scene." msgstr "" +"Efface tout l'état et réinitialise à zéro l'objet modifié. Cela garantit que " +"votre greffon ne maintient pas l'édition d'un nÅ“ud existant ou d'une autre " +"scène." #: doc/classes/EditorPlugin.xml msgid "" "Called by the engine when the user disables the [EditorPlugin] in the Plugin " "tab of the project settings window." msgstr "" +"Appelé par le moteur lorsque l'utilisateur désactive le [EditorPlugin] dans " +"l'onglet Greffon de la fenêtre des paramètres du projet." #: doc/classes/EditorPlugin.xml msgid "" "This function is used for plugins that edit specific object types (nodes or " "resources). It requests the editor to edit the given object." msgstr "" +"Cette fonction est utilisée pour les greffons qui modifient des types " +"d'objets spécifiques (nÅ“uds ou ressources). Il demande à l'éditeur de " +"modifier l'objet spécifié." #: doc/classes/EditorPlugin.xml msgid "" "Called by the engine when the user enables the [EditorPlugin] in the Plugin " "tab of the project settings window." msgstr "" +"Appelé par le moteur lorsque l'utilisateur active le [EditorPlugin] dans " +"l'onglet Greffon de la fenêtre des paramètres du projet." #: doc/classes/EditorPlugin.xml msgid "" @@ -27989,6 +28845,11 @@ msgid "" "You need to enable calling of this method by using [method " "set_force_draw_over_forwarding_enabled]." msgstr "" +"Cette méthode est la même que [method forward_canvas_draw_over_viewport], " +"sauf qu'elle est dessinée au-dessus de tout le reste. Utile quand vous avez " +"besoin d'une calque supplémentaire qui s'affiche par dessus les autres.\n" +"Vous devez activer l'appel de cette méthode en utilisant [method " +"set_force_draw_over_forwarding_enabled]." #: doc/classes/EditorPlugin.xml msgid "" @@ -28079,6 +28940,11 @@ msgid "" "You need to enable calling of this method by using [method " "set_force_draw_over_forwarding_enabled]." msgstr "" +"Cette méthode est la même que [method forward_spatial_draw_over_viewport], " +"sauf qu'elle est dessinée au-dessus de tout le reste. Utile quand vous avez " +"besoin d'une calque supplémentaire qui s'affiche par dessus les autres.\n" +"Vous devez activer l'appel de cette méthode en utilisant [method " +"set_force_draw_over_forwarding_enabled]." #: doc/classes/EditorPlugin.xml msgid "" @@ -28132,6 +28998,9 @@ msgid "" "breakpoints in the format ([code]script:line[/code]), for example: " "[code]res://path_to_script.gd:25[/code]." msgstr "" +"C'est pour les éditeurs qui modifient des objets basés sur des scripts. Vous " +"pouvez retourner une liste de points d'arrêt avec le format ([code]script:" +"line[/code]), par exemple : [code]res://path_to_script.gd:25[/code]." #: doc/classes/EditorPlugin.xml msgid "" @@ -28318,6 +29187,11 @@ msgid "" "Remember that you have to manage the visibility of all your editor controls " "manually." msgstr "" +"Cette fonction sera appelée lorsqu'il est demandé à l'éditeur de devenir " +"visible. Il est utilisé pour les greffons qui modifient un type d'objet " +"spécifique.\n" +"Rappelez-vous que vous devez gérer manuellement la visibilité de tous les " +"contrôles de votre éditeur." #: doc/classes/EditorPlugin.xml msgid "Queue save the project's editor layout." @@ -28357,29 +29231,25 @@ msgid "Removes a custom type added by [method add_custom_type]." msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]." #: doc/classes/EditorPlugin.xml -#, fuzzy msgid "Removes an export plugin registered by [method add_export_plugin]." -msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]." +msgstr "" #: doc/classes/EditorPlugin.xml -#, fuzzy msgid "Removes an import plugin registered by [method add_import_plugin]." -msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]." +msgstr "" #: doc/classes/EditorPlugin.xml msgid "Removes an inspector plugin registered by [method add_import_plugin]" msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]" #: doc/classes/EditorPlugin.xml -#, fuzzy msgid "" "Removes a scene importer registered by [method add_scene_import_plugin]." -msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]." +msgstr "" #: doc/classes/EditorPlugin.xml -#, fuzzy msgid "Removes a gizmo plugin registered by [method add_spatial_gizmo_plugin]." -msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]." +msgstr "" #: doc/classes/EditorPlugin.xml msgid "Removes a menu [code]name[/code] from [b]Project > Tools[/b]." @@ -28390,6 +29260,9 @@ msgid "" "This method is called after the editor saves the project or when it's " "closed. It asks the plugin to save edited external scenes/resources." msgstr "" +"Cette méthode est appelée après que l'éditeur enregistre le projet ou " +"lorsqu'il est fermé. Il demande au greffon d'enregistrer les scènes et " +"ressources externes modifiées." #: doc/classes/EditorPlugin.xml msgid "" @@ -28398,6 +29271,11 @@ msgid "" "editor when their viewports are updated. You need to call this method only " "once and it will work permanently for this plugin." msgstr "" +"Permet d'appeler [method forward_canvas_force_draw_over_viewport] pour " +"l'éditeur 2D et [method forward_spatial_force_draw_over_viewport] pour " +"l'éditeur 3D lorsque leurs fenêtres d'affichage sont mises à jour. Vous " +"devez appeler cette méthode qu'une seule fois, et ça fonctionnera en " +"permanence pour ce greffon." #: doc/classes/EditorPlugin.xml msgid "" @@ -28405,6 +29283,9 @@ msgid "" "inside [method forward_spatial_gui_input]. It might be especially usable if " "your plugin will want to use raycast in the scene." msgstr "" +"Utilisez cette méthode si vous voulez toujours recevoir les entrées dans " +"l'écran d'aperçu 3D dans [method forward_spatial_gui_input]. Ça peut être " +"utile si votre greffon veut utiliser un Raycast dans la scène." #: doc/classes/EditorPlugin.xml msgid "" @@ -28461,6 +29342,11 @@ msgid "" "forward_spatial_draw_over_viewport] and [method " "forward_spatial_force_draw_over_viewport] to be called." msgstr "" +"Met à jour des sur-couches de l'éditeur 2D et 3D. Fait que les méthodes " +"[method forward_canvas_draw_over_viewport], [method " +"forward_canvas_force_draw_over_viewport], [method " +"forward_spatial_draw_over_viewport] et [method " +"forward_spatial_force_draw_over_port] seront appelées." #: doc/classes/EditorPlugin.xml msgid "" @@ -28477,6 +29363,9 @@ msgid "" "the root node of the scene that has just become active. If this scene is new " "and empty, the argument will be [code]null[/code]." msgstr "" +"Émis lorsque la scène est changée dans l'éditeur. L'argument retournera le " +"nÅ“ud racine de la scène qui vient de devenir active. Si cette scène est " +"nouvelle et vide, l'argument sera [code]null[/code]." #: doc/classes/EditorPlugin.xml msgid "" @@ -28508,6 +29397,8 @@ msgid "" "If any of the controls added can gain keyboard focus, add it here. This " "ensures that focus will be restored if the inspector is refreshed." msgstr "" +"Si l'un des contrôles ajoutés peut récupérer le focus du clavier, ajoutez-le " +"ici. Cela permettra de rétablir le focus si l'inspecteur est mis à jour." #: doc/classes/EditorProperty.xml msgid "" @@ -28517,6 +29408,11 @@ msgid "" "requesting this property to be refreshed (leave as [code]false[/code] if " "unsure)." msgstr "" +"Si une ou plusieurs propriétés ont changé, cela doit être appelé. " +"[code]field[/code] est utilisé au cas où votre éditeur peut modifier les " +"champs séparément (par exemple : Vector3.x) L'argument [code]changing[/code] " +"évite à l'éditeur de demander que cette propriété soit rafraîchie (laissez-" +"le à [code]false[/code] en cas de doute)." #: doc/classes/EditorProperty.xml msgid "Gets the edited object." @@ -28528,16 +29424,23 @@ msgid "" "[method EditorInspectorPlugin.parse_property]), then this will return the " "property." msgstr "" +"Retourne la propriété modifiée. Si votre éditeur n'est que pour une seule " +"propriété (ajouté par [method EditorInspectorPlugin.parse_property]), cela " +"retournera la propriété." #: doc/classes/EditorProperty.xml msgid "Must be implemented to provide a custom tooltip to the property editor." msgstr "" +"Doit être implémenté pour fournir un outil personnalisé dans l'éditeur de " +"propriété." #: doc/classes/EditorProperty.xml msgid "" "Puts the [code]editor[/code] control below the property label. The control " "must be previously added using [method Node.add_child]." msgstr "" +"Place le contrôle [code]editor[/code] sous le label de la propriété. Le " +"contrôle doit d'abord être ajouté avec [method Node.add_child]." #: doc/classes/EditorProperty.xml msgid "When this virtual function is called, you must update your editor." @@ -28550,11 +29453,15 @@ msgid "" "Used by the inspector, set to [code]true[/code] when the property is " "checkable." msgstr "" +"Utilisé par l'inspecteur, défini à [code]true[/code] lorsque la propriété " +"peut être cochée." #: doc/classes/EditorProperty.xml msgid "" "Used by the inspector, set to [code]true[/code] when the property is checked." msgstr "" +"Utilisé par l'inspecteur, défini à [code]true[/code] quand la propriété est " +"cochée." #: doc/classes/EditorProperty.xml msgid "" @@ -28562,6 +29469,9 @@ msgid "" "with the editor theme's warning color. This is used for editable children's " "properties." msgstr "" +"Utilisé par l'inspecteur, définit à [code]true[/code] quand la propriété est " +"affiché avec la couleur d'avertissement de l'éditeur. Ceci est utilisé pour " +"les propriétés modifiables pour les nÅ“uds enfants." #: doc/classes/EditorProperty.xml msgid "" @@ -28582,16 +29492,23 @@ msgid "" "Used by the inspector, set to [code]true[/code] when the property is read-" "only." msgstr "" +"Utilisé par l'inspecteur, défini à [code]true[/code] quand la propriété est " +"en lecture-seule." #: doc/classes/EditorProperty.xml msgid "" "Emit it if you want multiple properties modified at the same time. Do not " "use if added via [method EditorInspectorPlugin.parse_property]." msgstr "" +"Émettez-le si vous voulez plusieurs propriétés modifiées en même temps. Ne " +"pas utiliser s'il a été ajouté avec [method EditorInspectorPlugin." +"parse_property]." #: doc/classes/EditorProperty.xml msgid "Used by sub-inspectors. Emit it if what was selected was an Object ID." msgstr "" +"Utilisé par des sous-inspecteurs. Émettez-le si l'identifiant d'un Object a " +"été sélectionné." #: doc/classes/EditorProperty.xml msgid "" @@ -28609,10 +29526,14 @@ msgid "" "Emit it if you want to add this value as an animation key (check for keying " "being enabled first)." msgstr "" +"Émettez-le si vous voulez ajouter cette valeur comme clé d'animation " +"(vérifiez que la clé est d'abord activée)." #: doc/classes/EditorProperty.xml msgid "Emit it if you want to key a property with a single value." msgstr "" +"Emettez-le si vous voulez définir une clé pour cette propriété avec une " +"valeur unique." #: doc/classes/EditorProperty.xml msgid "" @@ -28622,6 +29543,11 @@ msgid "" "instantiated and can come from an ancestor scene in the inheritance/" "instancing chain, a script or a builtin class." msgstr "" +"Émettez-le si vous voulez marquer (ou dé-marquer) la valeur d'une propriété " +"pour être sauvegardée peu importe si elle est égale à la valeur par défaut.\n" +"La valeur par défaut est celle que la propriété obtiendra lorsque le nÅ“ud " +"est juste instancié et peut venir d'une scène instanciée ou héritée, d'un " +"script ou d'une classe intégrée." #: doc/classes/EditorProperty.xml msgid "" @@ -28649,6 +29575,13 @@ msgid "" "[b]Note:[/b] This [Control] does not include any editor for the resource, as " "editing is controlled by the Inspector dock itself or sub-Inspectors." msgstr "" +"Ce nÅ“ud [Control] est utilisé dans la barre d'outils de l'inspecteur de " +"l'éditeur pour permettre l'édition des propriétés de type [Resource]. Il " +"offre des options pour créer, charger, enregistrer et convertir des " +"ressources. Peut être utilisé avec [EditorInspectorPlugin] pour recréer le " +"même comportement.\n" +"[b]Note :[/b] Ce [Control] n'inclut aucun éditeur de la ressource, car " +"l'édition est contrôlée par l'inspecteur lui-même ou les sous-inspecteurs." #: doc/classes/EditorResourcePicker.xml msgid "" @@ -28656,12 +29589,17 @@ msgid "" "[member base_type]. If the [member base_type] is empty, an empty list is " "returned." msgstr "" +"Retourne une liste de tous les types et sous-types autorisés correspondant " +"au [member base_type]. Si le [member base_type] est vide, une liste vide est " +"retournée." #: doc/classes/EditorResourcePicker.xml msgid "" "This virtual method can be implemented to handle context menu items not " "handled by default. See [method set_create_options]." msgstr "" +"Cette méthode virtuelle peut être implémentée pour gérer les éléments du " +"menu contextuel non gérés par défaut. Voir [method set_create_options]." #: doc/classes/EditorResourcePicker.xml msgid "" @@ -28672,12 +29610,20 @@ msgid "" "[b]Note:[/b] Implement [method handle_menu_selected] to handle these custom " "items." msgstr "" +"Cette méthode virtuelle est appelée lors de la mise à jour du menu " +"contextuel de [EditorResourcePicker]. Implémenter cette méthode pour " +"remplacer les éléments dans « Nouveau... » par vos propres options. " +"[code]menu_nÅ“ud[/code] est une référence au nÅ“ud [PopupMenu].\n" +"[b]Note :[/b] Implémentez [method handle_menu_sélection] pour traiter ces " +"éléments personnalisés." #: doc/classes/EditorResourcePicker.xml msgid "" "Sets the toggle mode state for the main button. Works only if [member " "toggle_mode] is set to [code]true[/code]." msgstr "" +"Définit l'état du mode de basculement pour le bouton principal. Fonctionne " +"uniquement si [member toggle_mode] est défini à [code]true[/code]." #: doc/classes/EditorResourcePicker.xml msgid "" @@ -28700,11 +29646,13 @@ msgid "" "If [code]true[/code], the main button with the resource preview works in the " "toggle mode. Use [method set_toggle_pressed] to manually set the state." msgstr "" +"Si [code]true[/code], le bouton principal avec la prévisualisation des " +"ressources fonctionne avec le mode de basculement. Utilisez [method " +"set_toggle_pressed] pour définir manuellement cet état." #: doc/classes/EditorResourcePicker.xml -#, fuzzy msgid "Emitted when the value of the edited resource was changed." -msgstr "Émis à chaque fois que la ressource change." +msgstr "Émis quand le valeur d'une ressource modifiée a été changée." #: doc/classes/EditorResourcePicker.xml msgid "" @@ -28712,6 +29660,9 @@ msgid "" "[code]edit[/code] is [code]true[/code], the signal was caused by the context " "menu \"Edit\" option." msgstr "" +"Émis lorsque la valeur de ressource a été définie et que l'utilisateur a " +"cliqué pour la modifier. Lorsque [code]edit[/code] est [code]true[/code], le " +"signal a été causé par le menu contextuel \"Édition\"." #: doc/classes/EditorResourcePreview.xml msgid "Helper to generate previews of resources or files." @@ -28723,6 +29674,11 @@ msgid "" "[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access " "the singleton using [method EditorInterface.get_resource_previewer]." msgstr "" +"Cet objet est utilisé pour générer des aperçus pour les ressources de " +"fichiers.\n" +"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. " +"Accédez plutôt à l'instance unique en utilisant [method EditorInterface." +"get_resource_previewer]." #: doc/classes/EditorResourcePreview.xml msgid "Create an own, custom preview generator." @@ -28733,6 +29689,8 @@ msgid "" "Check if the resource changed, if so, it will be invalidated and the " "corresponding signal emitted." msgstr "" +"Vérifiez si la ressource a changé, si oui, elle sera invalidée et le signal " +"correspondant émis." #: doc/classes/EditorResourcePreview.xml msgid "" @@ -28792,6 +29750,8 @@ msgid "" "Emitted if a preview was invalidated (changed). [code]path[/code] " "corresponds to the path of the preview." msgstr "" +"Émis si un aperçu a été invalidé (c'est-à -dire changé). [code]path[/code] " +"correspond au chemin de l'aperçu." #: doc/classes/EditorResourcePreviewGenerator.xml msgid "Custom generator of previews." @@ -28803,6 +29763,9 @@ msgid "" "thumbnail_size[/code] in [EditorSettings] to find out the right size to do " "previews at." msgstr "" +"Le Code personnalisé pour générer des aperçus. Veuillez cocher " +"[code]file_dialog/thumbnail_size[/code] dans [EditorSettings] pour connaître " +"la taille correcte des prévisualisations." #: doc/classes/EditorResourcePreviewGenerator.xml msgid "" @@ -28925,6 +29888,10 @@ msgid "" "to [EditorSceneImporterGLTF] within a script will cause an error in an " "exported project." msgstr "" +"[b]Note :[/b] Cette classe n'est compilée que pour les éditeurs. Le " +"chargement et l'enregistrement au format glTF [i]n'est pas[/i] disponible " +"dans les projets exportés. Les références à [EditorSceneImporterGLTF] dans " +"un script provoquent une erreur dans un projet exporté." #: doc/classes/EditorScenePostImport.xml msgid "Post-processes scenes after import." @@ -29001,6 +29968,8 @@ msgid "" "Called after the scene was imported. This method must return the modified " "version of the scene." msgstr "" +"Appelé après l'importation de la scène. Cette méthode doit retourner la " +"version modifiée de la scène." #: doc/classes/EditorScript.xml msgid "Base script that can be used to add extension functions to the editor." @@ -29057,6 +30026,10 @@ msgid "" "Adds [code]node[/code] as a child of the root node in the editor context.\n" "[b]Warning:[/b] The implementation of this method is currently disabled." msgstr "" +"Ajoute [code]node[/code] comme enfant du nÅ“ud racine dans le contexte de " +"l'éditeur.\n" +"[b]Avertissement :[/b] L'implémentation de cette méthode est actuellement " +"désactivée." #: doc/classes/EditorScript.xml msgid "Returns the [EditorInterface] singleton instance." @@ -29071,6 +30044,8 @@ msgid "" "Godot editor's control for selecting the [code]script[/code] property of a " "[Node]." msgstr "" +"Le contrôle de l'éditeur Godot pour sélectionner la propriété [code]script[/" +"code] d'un [Node]." #: doc/classes/EditorScriptPicker.xml msgid "" @@ -29107,6 +30082,10 @@ msgid "" "[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access " "the singleton using [method EditorInterface.get_selection]." msgstr "" +"Cet objet gère la sélection dans le SceneTree dans l'éditeur.\n" +"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. " +"Accédez plutôt à l'instance unique en utilisant [method EditorInterface." +"get_selection]." #: doc/classes/EditorSelection.xml msgid "" @@ -29115,6 +30094,10 @@ msgid "" "inspector. If you want to edit a node, use [method EditorInterface." "edit_node]." msgstr "" +"Ajoute un nÅ“ud à la sélection.\n" +"[b]Note :[/b] Le nouveau nÅ“ud sélectionné ne sera pas automatiquement " +"modifié dans l'inspecteur. Si vous souhaitez modifier un nÅ“ud, utilisez " +"[method EditorInterface.edit_nÅ“ud]." #: doc/classes/EditorSelection.xml msgid "Clear the selection." @@ -29130,6 +30113,10 @@ msgid "" "moving them, rotating, etc). This list avoids situations where a node is " "selected and also child/grandchild." msgstr "" +"Retourne la liste des nÅ“uds sélectionnés, optimisés pour les opérations de " +"transformation (c'est-à -dire le fait de les déplacer, les faire pivoter, " +"etc.). Cette liste évite les situations où un nÅ“ud est sélectionné et mais " +"aussi ses descendants." #: doc/classes/EditorSelection.xml msgid "Removes a node from the selection." @@ -29244,6 +30231,10 @@ msgid "" "[code]key[/code] specified. If the metadata doesn't exist, [code]default[/" "code] will be returned instead. See also [method set_project_metadata]." msgstr "" +"Retourne les métadonnées spécifiques au projet pour la [code]section[/code] " +"et [code]key[/code] spécifiées. Si les métadonnées n'existent pas, " +"[code]default[/code] sera retourné à la place. Voir aussi [method " +"set_project_metadata]." #: doc/classes/EditorSettings.xml msgid "" @@ -29268,6 +30259,8 @@ msgid "" "Returns the value of the setting specified by [code]name[/code]. This is " "equivalent to using [method Object.get] on the EditorSettings instance." msgstr "" +"Retourne la valeur du paramètre spécifié par [code]name[/code]. Ceci est " +"équivalent à l'utiliser [method Object.get] sur l'instance EditorSettings." #: doc/classes/EditorSettings.xml msgid "" @@ -29297,6 +30290,10 @@ msgid "" "When this method returns [code]true[/code], a Revert button will display " "next to the setting in the Editor Settings." msgstr "" +"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] " +"peut avoir sa valeur rétablie à cette par défaut, ou [code]false[/code] " +"sinon. Lorsque cette méthode retourne [code]true[/code], un bouton Rétablir " +"s'affichera à côté du réglage dans les paramètres de l'éditeur." #: doc/classes/EditorSettings.xml msgid "" @@ -29304,6 +30301,9 @@ msgid "" "This is the value that would be applied when clicking the Revert button in " "the Editor Settings." msgstr "" +"Retourne la valeur par défaut du paramètre spécifié par [code]name[/code]. " +"C'est la valeur qui sera appliquée en cliquant sur le bouton Rétablir dans " +"les paramètres de l'éditeur." #: doc/classes/EditorSettings.xml msgid "Sets the list of favorite files and directories for this project." @@ -29329,6 +30329,11 @@ msgid "" "project folder and therefore won't be checked into version control. See also " "[method get_project_metadata]." msgstr "" +"Définit des métadonnées spécifiques au projet dans la [code]section[/code], " +"la [code]key[/code] et les [code]data[/code] spécifiées. Ces métadonnées " +"sont enregistrées à l'extérieur du dossier du projet, et donc pas dans le " +"système de contrôle de version (Git, etc.). Voir aussi [method " +"get_project_metadata]." #: doc/classes/EditorSettings.xml msgid "" @@ -29344,6 +30349,9 @@ msgid "" "This is equivalent to using [method Object.set] on the EditorSettings " "instance." msgstr "" +"Définit la [code]value[/code] du paramètre nommé [code]name[/code]. Cela " +"équivaut à l'utilisation de [method Object.set] sur l'instance " +"EditorSettings." #: doc/classes/EditorSettings.xml msgid "Emitted after any editor setting has changed." @@ -29355,6 +30363,9 @@ msgid "" "plugins to update their visuals on theme changes or logic on configuration " "changes." msgstr "" +"Émis après que n'importe quel réglage de l'édiateur a changé. Il est utilisé " +"par divers greffons de l'éditeurs pour mettre à jour leur affichage lors de " +"changements de thème ou de configuration." #: doc/classes/EditorSpatialGizmo.xml msgid "Custom gizmo for editing Spatial objects." @@ -29366,12 +30377,18 @@ msgid "" "(handles) for 3D Spatial objects. See [EditorSpatialGizmoPlugin] for more " "information." msgstr "" +"Un manipulateur personnalisé qui est utilisé pour la visualisation et " +"l'édition personnalisées (poignets) pour les objets 3D de type Spatial. Voir " +"[EditorSpatialGizmoPlugin] pour plus d'informations." #: doc/classes/EditorSpatialGizmo.xml msgid "" "Adds the specified [code]segments[/code] to the gizmo's collision shape for " "picking. Call this function during [method redraw]." msgstr "" +"Ajoute le [code]segments[/code] spécifié à la forme de collision du " +"manipulateur pour la sélection. Appelez cette fonction durant [method " +"redraw]." #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29379,6 +30396,9 @@ msgid "" "generated from a regular [Mesh] too. Call this function during [method " "redraw]." msgstr "" +"Ajoute des triangles de collision au manipulateur pour la sélection. Un " +"[TriangleMesh] peut être généré à partir d'un [Mesh] régulier. Appelez cette " +"fonction durant [method redraw]." #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29387,6 +30407,10 @@ msgid "" "There are virtual functions which will be called upon editing of these " "handles. Call this function during [method redraw]." msgstr "" +"Ajoute une liste de poignées (points) qui peuvent être utilisées pour " +"déformer l'objet en cours d'édition.\n" +"Il y a des fonctions virtuelles qui seront appelés à l'édition de ces " +"poignées. Appelez cette fonction durant [method redraw]." #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29394,6 +30418,9 @@ msgid "" "lines are used for visualizing the gizmo. Call this function during [method " "redraw]." msgstr "" +"Ajoute des lignes au gizmo (une liste de paires de points), avec un matériau " +"donné. Les lignes sont utilisées pour visualiser le manipulateur. Appelez " +"cette fonction durant [method redraw]." #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29402,6 +30429,11 @@ msgid "" "is [code]true[/code], the mesh will rotate to always face the camera. Call " "this function during [method redraw]." msgstr "" +"Ajoute un maillage au manipulateur avec l'état [code]billboard[/code] " +"spécifié, [code]skeleton[/code] et [code]material[/code]. Si " +"[code]billboard[/code] est [code]true[/code], le maillage tourne pour " +"toujours faire toujours face à la caméra. Appelez cette fonction durant " +"[method redraw]." #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29430,23 +30462,32 @@ msgid "" "by [method add_handles]).\n" "Handles can be named for reference to the user when editing." msgstr "" +"Retourne le nom d'une poignée modifiée (ces poignées doivent d'abord être " +"ajoutées avec [méthode add_handles]).\n" +"Les poignées peuvent être nommées pour référence à l'utilisateur lors de " +"l'édition." #: doc/classes/EditorSpatialGizmo.xml msgid "" "Gets actual value of a handle. This value can be anything and used for " "eventually undoing the motion when calling [method commit_handle]." msgstr "" +"Retourne la valeur réelle d'une poignée. Cette valeur peut être n'importe " +"quoi et utilisée pour finalement annuler le mouvement en appelant [method " +"commit_handle]." #: doc/classes/EditorSpatialGizmo.xml msgid "" "Returns the [EditorSpatialGizmoPlugin] that owns this gizmo. It's useful to " "retrieve materials using [method EditorSpatialGizmoPlugin.get_material]." msgstr "" +"Retourne le [EditorSpatialGizmoPlugin] qui possède ce manipulateur. Il est " +"utile de récupérer les matériaux en utilisant [method " +"EditorSpatialGizmoPlugin.get_material]." #: doc/classes/EditorSpatialGizmo.xml -#, fuzzy msgid "Returns the Spatial node associated with this gizmo." -msgstr "Retourne le chemin d’accès au nÅ“ud associé à l’os spécifié." +msgstr "" #: doc/classes/EditorSpatialGizmo.xml msgid "" @@ -29524,6 +30565,9 @@ msgid "" "nodes of your choice, return [code]null[/code] for the rest of nodes. See " "also [method has_gizmo]." msgstr "" +"Surchargez cette méthode pour retourner un [EditorSpatialGizmo] personnalisé " +"pour les nÅ“uds spatiaux de votre choix, retourner [code]null[/code] pour le " +"reste des nÅ“uds. Voir aussi [method has_gizmo]." #: doc/classes/EditorSpatialGizmoPlugin.xml msgid "" @@ -29533,6 +30577,12 @@ msgid "" "Should not be overridden.\n" "You can optionally provide a texture to use instead of the default icon." msgstr "" +"Crée un matériau de poignée avec ses variantes (sélectionnées et/ou " +"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent " +"ensuite être consultés avec [method get_material] et utilisés dans [method " +"EditorSpatialGizmo.add_handles] Ne devrait pas être surchargé.\n" +"Vous pouvez en option fournir une texture à utiliser à la place de l'icône " +"par défaut." #: doc/classes/EditorSpatialGizmoPlugin.xml msgid "" @@ -29541,6 +30591,10 @@ msgid "" "[method get_material] and used in [method EditorSpatialGizmo." "add_unscaled_billboard]. Should not be overridden." msgstr "" +"Crée un matériau d'icône avec ses variantes (sélectionnées et/ou " +"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent " +"ensuite être consultés avec [method get_material] et utilisés dans [method " +"EditorSpatialGizmo.add_unscaled_billboard]. Ne devrait pas être surchargé." #: doc/classes/EditorSpatialGizmoPlugin.xml msgid "" @@ -29549,6 +30603,11 @@ msgid "" "[method get_material] and used in [method EditorSpatialGizmo.add_mesh] and " "[method EditorSpatialGizmo.add_lines]. Should not be overridden." msgstr "" +"Crée un matériau non éclairé avec ses variantes (sélectionnées et/ou " +"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent " +"ensuite être consultés avec [method get_material] et utilisés dans [method " +"EditorSpatialGizmo.add_mesh] et [method EditorSpatialGizmo.add_lines]. Ne " +"devrait pas être dépassé." #: doc/classes/EditorSpatialGizmoPlugin.xml msgid "" @@ -29629,9 +30688,8 @@ msgid "" msgstr "" #: doc/classes/EditorSpinSlider.xml -#, fuzzy msgid "If [code]true[/code], the slider is hidden." -msgstr "Si [code]true[/code], la flèche de réduction est masquée." +msgstr "Si [code]true[/code], le glisseur est masqué." #: doc/classes/EditorVCSInterface.xml msgid "" @@ -29660,10 +30718,8 @@ msgstr "" "hériter de [EditorVCSInterface] et surcharger ces fonctions virtuelles." #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "Checks out a [code]branch_name[/code] in the VCS." msgstr "" -"Supprime un [code]name[/code] de chargement automatique à partir de la liste." #: doc/classes/EditorVCSInterface.xml msgid "" @@ -29672,9 +30728,8 @@ msgid "" msgstr "" #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "Creates a new branch named [code]branch_name[/code] in the VCS." -msgstr "Crée une instance de [code]class[/code]." +msgstr "" #: doc/classes/EditorVCSInterface.xml msgid "" @@ -29705,9 +30760,8 @@ msgid "" msgstr "" #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "Gets the current branch name defined in the VCS." -msgstr "Définit le trame présentement visible de l'animation." +msgstr "" #: doc/classes/EditorVCSInterface.xml msgid "" @@ -29771,9 +30825,8 @@ msgid "" msgstr "" #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "Remove a branch from the local VCS." -msgstr "Supprime un nÅ“ud de la sélection." +msgstr "" #: doc/classes/EditorVCSInterface.xml msgid "Remove a remote from the local VCS." @@ -29795,9 +30848,8 @@ msgid "" msgstr "" #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "Stages the file present at [code]file_path[/code] to the staged area." -msgstr "Ajoute un [Shape2D] au propriétaire de la forme." +msgstr "" #: doc/classes/EditorVCSInterface.xml msgid "" @@ -29907,9 +30959,8 @@ msgid "A commit is encountered from the commit area." msgstr "" #: doc/classes/EditorVCSInterface.xml -#, fuzzy msgid "A file is encountered from the staged area." -msgstr "Statut : Déconnecté du serveur." +msgstr "" #: doc/classes/EditorVCSInterface.xml msgid "A file is encountered from the unstaged area." @@ -30429,14 +31480,12 @@ msgid "The [Sky] resource's rotation expressed as a [Basis]." msgstr "La rotation du [Sky] exprimée par un [Basis]." #: doc/classes/Environment.xml -#, fuzzy msgid "The [Sky] resource's rotation expressed as Euler angles in radians." -msgstr "La rotation de la texture en radians." +msgstr "" #: doc/classes/Environment.xml -#, fuzzy msgid "The [Sky] resource's rotation expressed as Euler angles in degrees." -msgstr "La rotation de la texture en degrés." +msgstr "" #: doc/classes/Environment.xml msgid "The amount of far blur for the depth-of-field effect." @@ -30450,9 +31499,8 @@ msgstr "" "rendu." #: doc/classes/Environment.xml -#, fuzzy msgid "If [code]true[/code], enables the depth-of-field far blur effect." -msgstr "Si [code]true[/code], active le drapeau spécifié." +msgstr "Si [code]true[/code], active l'effet de flou de profondeur lointain." #: doc/classes/Environment.xml msgid "" @@ -30772,11 +31820,10 @@ msgid "" msgstr "" #: doc/classes/Environment.xml -#, fuzzy msgid "" "The secondary screen-space ambient occlusion intensity. See also [member " "ssao_radius2]." -msgstr "Le rayon d'occlusion ambiante de l'espace de l'écran primaire." +msgstr "" #: doc/classes/Environment.xml msgid "" @@ -30812,7 +31859,7 @@ msgstr "L’exposition par défaut utilisée pour tonifier." #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -31914,7 +32961,7 @@ msgstr "" #: doc/classes/FlowContainer.xml #, fuzzy msgid "Base class for flow containers." -msgstr "Classe de base pour les conteneurs de boîtes." +msgstr "La classe de base pour les conteneurs de flux." #: doc/classes/FlowContainer.xml msgid "" @@ -31925,7 +32972,6 @@ msgid "" msgstr "" #: doc/classes/FlowContainer.xml -#, fuzzy msgid "Returns the current line count." msgstr "Retourne le numéro de la ligne actuelle." @@ -31995,30 +33041,24 @@ msgid "" msgstr "" #: doc/classes/Font.xml -#, fuzzy msgid "Returns resource id of the cache texture containing the char." -msgstr "Retourne l'identifiant OpenGL de l'image de cette texture." +msgstr "" #: doc/classes/Font.xml -#, fuzzy msgid "Returns size of the cache texture containing the char." -msgstr "Retourne la position du contact sur le collisionneur." +msgstr "" #: doc/classes/Font.xml -#, fuzzy msgid "Returns char offset from the baseline." -msgstr "Retourne le décalage de la texture de la tuile." +msgstr "" #: doc/classes/Font.xml -#, fuzzy msgid "Returns size of the char." -msgstr "Renvoie le sinus du paramètre." +msgstr "Retourne la taille du caractère." #: doc/classes/Font.xml -#, fuzzy msgid "Returns rectangle in the cache texture containing the char." msgstr "" -"Retourne un rectangle englobant les tuiles utilisées (non vides) de la carte." #: doc/classes/Font.xml msgid "Returns the font descent (number of pixels below the baseline)." @@ -32054,9 +33094,8 @@ msgid "" msgstr "" #: doc/classes/Font.xml -#, fuzzy msgid "Contour point is on the curve." -msgstr "Supprime tous les points de la courbe." +msgstr "" #: doc/classes/Font.xml msgid "" @@ -32892,15 +33931,15 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" -"À partir d'un tableau de [Vector2] représentant des tuiles, construit un " +"À partir d'un tableau de [Vector2] représentant des tuiles, ça construit un " "atlas. Le dictionnaire retourné a deux clés : [code]points[/code] est un " "tableau de [Vector2] qui précise les positions de chaque tuile, et " -"[code]size[/code] contient la taille globale de l'atlas entier sous forme de " -"[Vector2]." +"[code]size[/code] contient la taille globale de l'atlas en entier sous forme " +"d'un [Vector2]." #: doc/classes/Geometry.xml msgid "" @@ -32945,19 +33984,20 @@ msgid "" msgstr "" "Gonfle ou dégonfle [code]polygon[/code] par la quantité [code]delta[/code] " "unités (pixels) dans toutes les directions. Si [code]delta[/code] est " -"positif, le polygone décale chaque sommet vers l'extérieur. Si [code]delta[/" -"code] est négatif, décale chaque sommet vers l'intérieur. Retourne une liste " -"des polygones parce que gonflage/dégonflage peut produire plusieurs " -"polygones distinctes. Retourne un tableau vide si [code]delta[/code] est " -"négatif et la valeur absolue de celui-ci dépasse approximativement les " -"dimensions du rectangle minimal englobant du polygone.\n" +"positif, le polygone décale chaque sommet vers l'extérieur. Si " +"[code]delta[/code] est négatif, décale chaque sommet vers l'intérieur. " +"Retourne une liste des polygones parce que gonflage/dégonflage peut produire " +"plusieurs polygones distinctes. Retourne un tableau vide si " +"[code]delta[/code] est négatif et la valeur absolue de celui-ci dépasse " +"approximativement les dimensions du rectangle minimal englobant du polygone." +"\n" "Les sommets de chaque polygone sont arrondis suivant [code]join_type[/code], " "voir [enum PolyJoinType].\n" "L'opération peut fournir un polygone extérieur (la limite extérieure) et " "plusieurs polygones à intérieur (représentant les trous) qui pourraient être " -"distingués en appelant [méthode is_polygon_clockwise].\n" -"[b]Note :[/b] Pour transformer les sommets en polygone, utilisez la méthode " -"[méthode Transform2D.xform]:\n" +"distingués en appelant [method is_polygon_clockwise].\n" +"[b]Note :[/b] Pour transformer les sommets en polygone, utilisez la méthode [" +"method Transform2D.xform]:\n" "[codeblock]\n" "var polygon = PoolVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, " "100), Vector2(0, 100)])\n" @@ -32982,15 +34022,16 @@ msgid "" "(hole) produced which could be distinguished by calling [method " "is_polygon_clockwise]." msgstr "" -"par la quantité [code]delta[/code] unités (pixels) dans toutes les " -"directions. Si [code]delta[/code] est positif, le polygone décale chaque " -"sommet vers l'extérieur. Retourne une liste des polygones parce que gonflage/" -"dégonflage peut produire plusieurs polygones distinctes. Si [code]delta[/" -"code] est négatif, retourne un tableau vide.\n" +"Gonfle ou dégonfle [code]polyline[/code] par la quantité [code]delta[/code] " +"d'unités (pixels) dans toutes les directions. Si [code]delta[/code] est " +"positif, le polygone décale chaque sommet vers l'extérieur. Retourne une " +"liste des polygones parce que gonflage/dégonflage peut produire plusieurs " +"polygones distinctes. Si [code]delta[/code] est négatif, retourne un tableau " +"vide.\n" "Les sommets de chaque polygone sont arrondis suivant [code]join_type[/code], " "voir [enum PolyJoinType].\n" -"Chaque point d'extrémité du polygone sera arrondi suivant [code]end_type[/" -"code], voir [enum PolyEndType].\n" +"Chaque point d'extrémité du polygone sera arrondi suivant " +"[code]end_type[/code], voir [enum PolyEndType].\n" "L'opération peut fournir un polygone extérieur (la limite extérieur) et " "plusieurs polygones à intérieur (représentant les trous) qui pourraient être " "distingués en appelant [method is_polygon_clockwise]." @@ -33233,39 +34274,35 @@ msgid "" msgstr "" #: doc/classes/GeometryInstance.xml -#, fuzzy msgid "" "The GeometryInstance's max LOD distance.\n" "[b]Note:[/b] This property currently has no effect." msgstr "" -"La distance min LOD de GeometryInstance3D.\n" +"La distance maximale pour ce LOD de la GeometryInstance.\n" "[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet." #: doc/classes/GeometryInstance.xml -#, fuzzy msgid "" "The GeometryInstance's max LOD margin.\n" "[b]Note:[/b] This property currently has no effect." msgstr "" -"La distance min LOD de GeometryInstance3D.\n" +"La marge maximale pour ce LOD de la GeometryInstance.\n" "[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet." #: doc/classes/GeometryInstance.xml -#, fuzzy msgid "" "The GeometryInstance's min LOD distance.\n" "[b]Note:[/b] This property currently has no effect." msgstr "" -"La distance min LOD de GeometryInstance3D.\n" +"La distance minimale pour ce LOD de la GeometryInstance.\n" "[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet." #: doc/classes/GeometryInstance.xml -#, fuzzy msgid "" "The GeometryInstance's min LOD margin.\n" "[b]Note:[/b] This property currently has no effect." msgstr "" -"La distance min LOD de GeometryInstance3D.\n" +"La marge minimale pour ce LOD de la GeometryInstance.\n" "[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet." #: doc/classes/GeometryInstance.xml @@ -33802,13 +34839,10 @@ msgstr "" "[code]false[/code] sinon." #: modules/mono/doc_classes/GodotSharp.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the Mono runtime is shutting down, [code]false[/" "code] otherwise." msgstr "" -"Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment " -"zéro." #: modules/mono/doc_classes/GodotSharp.xml msgid "" @@ -34490,14 +35524,12 @@ msgid "Returns the type of the output connection [code]idx[/code]." msgstr "Retourne le type de connexion pour la sortie [code]idx[/code]." #: doc/classes/GraphNode.xml -#, fuzzy msgid "Returns the left (input) [Color] of the slot [code]idx[/code]." -msgstr "Retourne le type du nÅ“ud à [code]idx[/code]." +msgstr "" #: doc/classes/GraphNode.xml -#, fuzzy msgid "Returns the right (output) [Color] of the slot [code]idx[/code]." -msgstr "Retourne le type du nÅ“ud à [code]idx[/code]." +msgstr "" #: doc/classes/GraphNode.xml msgid "Returns the left (input) type of the slot [code]idx[/code]." @@ -34540,17 +35572,17 @@ msgid "" "methods. You must enable at least one side of the slot to do so." msgstr "" "Définit les propriétés de l'emplacement avec identifiant [code]idx[/code].\n" -"Si [code]enable_left[code]/[code]right[/code], un port apparaîtra et " +"Si [code]enable_left[/code]/[code]right[/code], un port apparaîtra et " "l'emplacement pourra être connectée de ce côté.\n" -"[code]type_left[code]/[code]right[/code] est un type arbitraire du port. " +"[code]type_left[/code]/[code]right[/code] est un type arbitraire du port. " "Seuls les ports avec le même type peuvent être connectés.\n" -"[code]color_left[code]/[code]right[/code] est la teinte de l'icône du port " +"[code]color_left[/code]/[code]right[/code] est la teinte de l'icône du port " "de ce côté.\n" -"[code]custom_left[code]/[code]right[/code] est une texture personnalisée " +"[code]custom_left[/code]/[code]right[/code] est une texture personnalisée " "pour le port de ce côté.\n" "[b]Note :[/b] Cette méthode ne définit que les propriétés de l'emplacement. " -"Pour créer l'emplacement, ajoutez un enfant dérivé de [Control] au " -"GraphNode.\n" +"Pour créer l'emplacement, ajoutez un enfant dérivé de [Control] au GraphNode." +"\n" "Les propriétés individuelles peuvent être définies en utilisant l'une des " "méthodes [code]set_slot_*[/code]. Vous devez activer au moins un côté de " "l'emplacement pour le faire." @@ -34919,13 +35951,10 @@ msgstr "" "dans la grille." #: modules/gridmap/doc_classes/GridMap.xml -#, fuzzy msgid "" "Returns an array of all cells with the given item index specified in " "[code]item[/code]." msgstr "" -"Renvoie la texture de l’atlas de police de caractères à l’index [code]idx[/" -"code]." #: modules/gridmap/doc_classes/GridMap.xml msgid "" @@ -34962,13 +35991,10 @@ msgid "" msgstr "" #: modules/gridmap/doc_classes/GridMap.xml -#, fuzzy msgid "" "If [code]true[/code], this GridMap uses cell navmesh resources to create " "navigation regions." msgstr "" -"Si [code]true[/code], met à jour les animations en réponse aux notifications " -"liées au processus." #: modules/gridmap/doc_classes/GridMap.xml msgid "If [code]true[/code], grid items are centered on the X axis." @@ -35180,9 +36206,8 @@ msgid "The horizontal space between the [HBoxContainer]'s elements." msgstr "L'espace horizontal entre les éléments du [HBoxContainer]." #: doc/classes/HeightMapShape.xml -#, fuzzy msgid "Height map shape for 3D physics." -msgstr "Forme de polygone convexe pour la physique 3D." +msgstr "La forme de carte de hauteurs pour la physique 3D." #: doc/classes/HeightMapShape.xml msgid "" @@ -35455,14 +36480,13 @@ msgid "Displayed when the decrement button is being pressed." msgstr "Affiché quand le bouton de reduction est appuyé." #: doc/classes/HScrollBar.xml -#, fuzzy msgid "" "Icon used as a button to scroll the [ScrollBar] right. Supports custom step " "using the [member ScrollBar.custom_step] property." msgstr "" -"Icône utilisée comme bouton pour faire défiler la [ScrollBar] correctement. " -"Supporte l'étape personnalisée en utilisant la propriété [member ScrollBar." -"custom_step]." +"L'icône utilisée comme bouton pour faire défiler la [ScrollBar] vers la " +"droite. Supporte une étape personnalisée en utilisant la propriété [member " +"ScrollBar.custom_step]." #: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml msgid "Displayed when the mouse cursor hovers over the increment button." @@ -35481,7 +36505,7 @@ msgstr "" #: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml #, fuzzy msgid "Used when the mouse hovers over the grabber." -msgstr "Utilisé lorsque la souris survole le grappin." +msgstr "Utilisé lorsque la souris survole le glisseur." #: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml msgid "Used when the grabber is being dragged." @@ -36572,7 +37596,6 @@ msgid "A node with the ability to send HTTP(S) requests." msgstr "Un nÅ“ud qui permet d'envoyer des requêtes HTTP(S)." #: doc/classes/HTTPRequest.xml -#, fuzzy msgid "" "A node with the ability to send HTTP requests. Uses [HTTPClient] " "internally.\n" @@ -36652,28 +37675,28 @@ msgstr "" "des fichiers ou du contenu web via HTTP.\n" "[b]Avertissement :[/b] Voir les notes et avertissements du [HTTPClient] pour " "les limites, notamment concernant la sécurité SSL.\n" -"[b]Exemple pour contacter une API REST et afficher les champs retournés :[/" -"b]\n" +"[b]Exemple pour contacter une API REST et afficher les champs retournés :[/b]" +"\n" "[codeblock]\n" "func _ready():\n" -" # Créer un nÅ“ud de requête HTTP et le connecter au signal de " -"complétion.\n" +" # Créer un nÅ“ud de requête HTTP et le connecter au signal de complétion." +"\n" " var http_request = HTTPRequest.new()\n" " add_child(http_request)\n" " http_request.connect(\"request_completed\", self, " "\"_http_request_completed\")\n" "\n" -" # Lancer une requête GET. L'URL en-dessous retourne un JSON au moment de " +" # Lancer une requête GET. L'URL en dessous retourne un JSON au moment de " "l'écriture de ce tutoriel.\n" " var error = http_request.request(\"https://httpbin.org/get\")\n" " if error != OK:\n" " push_error(\"Une erreur est survenue dans la requête HTTP.\")\n" "\n" -" # Lancer une requête POST. L'URL en-dessous retourne un JSON au moment " +" # Lancer une requête POST. L'URL en dessous retourne un JSON au moment " "de l'écriture de ce tutoriel.\n" " # Note : Don't make simultaneous requests using a single HTTPRequest " "node.\n" -" # Le code en-dessous est uniquement donné comme exemple.\n" +" # Le code en dessous est uniquement donné comme exemple.\n" " var body = {\"nom\": \"Godette\"}\n" " error = http_request.request(\"https://httpbin.org/post\", [], true, " "HTTPClient.METHOD_POST, body)\n" @@ -36693,14 +37716,14 @@ msgstr "" "HTTPRequest:[/b]\n" "[codeblock]\n" "func _ready():\n" -" # Créer un nÅ“ud de requête HTTP et le connecter au signal de " -"complétion.\n" +" # Créer un nÅ“ud de requête HTTP et le connecter au signal de complétion." +"\n" " var http_request = HTTPRequest.new()\n" " add_child(http_request)\n" " http_request.connect(\"request_completed\", self, " "\"_http_request_completed\")\n" "\n" -" # Lancer une requête HTTP. L'URL en-dessous retourne une image PNG au " +" # Lancer une requête HTTP. L'URL en dessous retourne une image PNG au " "moment de l'écriture de ce tutoriel.\n" " var error = http_request.request(\"https://via.placeholder.com/512\")\n" " if error != OK:\n" @@ -36807,21 +37830,23 @@ msgid "" msgstr "" #: doc/classes/HTTPRequest.xml -#, fuzzy msgid "" "Maximum number of allowed redirects. This is used to prevent endless " "redirect loops." -msgstr "Nombre maximal de redirections autorisées." +msgstr "" +"Le nombre maximal de redirections autorisées. C'est utilisé pour éviter les " +"redirections infinies." #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -37024,9 +38049,8 @@ msgid "Fills [code]rect[/code] with [code]color[/code]." msgstr "Remplis le [code]rect[/code] avec la [code]color[/code]." #: doc/classes/Image.xml -#, fuzzy msgid "Blends low-alpha pixels with nearby pixels." -msgstr "Mélange les pixels à faible alpha avec les pixels à proximité." +msgstr "Mélange les pixels à faible opacité avec ceux proches." #: doc/classes/Image.xml msgid "Flips the image horizontally." @@ -37808,9 +38832,8 @@ msgid "" msgstr "" #: doc/classes/ImageTexture.xml -#, fuzzy msgid "Returns the format of the texture, one of [enum Image.Format]." -msgstr "Renvoie l'inverse de la racine carrée du paramètre." +msgstr "" #: doc/classes/ImageTexture.xml msgid "" @@ -38055,11 +39078,10 @@ msgid "" msgstr "" #: doc/classes/Input.xml -#, fuzzy msgid "" "Returns the current value of the joypad axis at given index (see [enum " "JoystickList])." -msgstr "Retourne l'état actuel de ce canal, voir [enum ChannelState]." +msgstr "" #: doc/classes/Input.xml msgid "Returns the index of the provided axis name." @@ -38359,10 +39381,9 @@ msgid "" msgstr "" #: doc/classes/Input.xml -#, fuzzy msgid "Controls the mouse mode. See [enum MouseMode] for more information." msgstr "" -"Définit le mode de la souris. Voir les constantes pour plus d'informations." +"Définit le mode de la souris. Voir [enum MouseMode] pour plus d'informations." #: doc/classes/Input.xml msgid "" @@ -38376,9 +39397,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -38679,9 +39700,8 @@ msgid "" msgstr "" #: doc/classes/InputEventAction.xml -#, fuzzy msgid "InputEvent: Actions" -msgstr "Type d’évènement d’entrée pour les actions." +msgstr "Évènements d’entrée : les actions" #: doc/classes/InputEventAction.xml msgid "The action's name. Actions are accessed via this [String]." @@ -38860,9 +39880,8 @@ msgid "Wikipedia General MIDI Instrument List" msgstr "" #: doc/classes/InputEventMIDI.xml -#, fuzzy msgid "Wikipedia Piano Key Frequencies List" -msgstr "https://en.wikipedia.org/wiki/Piano_key_frequencies#List" +msgstr "La liste des fréquences des touches de piano sur Wikipédia" #: doc/classes/InputEventMIDI.xml msgid "" @@ -39018,10 +40037,13 @@ msgstr "Type d’évènement d’entrée pour les évènements de mouvement de s msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -39034,6 +40056,15 @@ msgstr "Les coordonnées de la souris" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"Retourne [code]true[/code] lors de l'utilisation de la gomme (l'autre " +"extrémité) d'un stylet.\n" +"[b]Note :[/b] Cette méthode est implémentée sous Linux, macOS et Windows." + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -39391,11 +40422,11 @@ msgstr "" "automatiquement." #: doc/classes/InterpolatedCamera.xml -#, fuzzy msgid "" "The camera's process callback. See [enum InterpolatedCameraProcessMode]." msgstr "" -"La méthode de mise à jour de la camera. Voir [enum Camera2DProcessMode]." +"La méthode de mise à jour de la camera. Voir [enum " +"InterpolatedCameraProcessMode]." #: doc/classes/InterpolatedCamera.xml msgid "" @@ -40661,14 +41692,14 @@ msgid "" msgstr "" #: doc/classes/KinematicBody.xml doc/classes/KinematicBody2D.xml -#, fuzzy msgid "" "Returns the number of times the body collided and changed direction during " "the last call to [method move_and_slide] or [method " "move_and_slide_with_snap]." msgstr "" -"Renvoie le nombre de fois où le corps est entré en collision et a changé de " -"direction au cours du dernier appel vers [method move_and_slide]." +"Retourne le nombre de fois où le corps est entré en collision et a changé de " +"direction au cours du dernier appel vers [method move_and_slide] ou [method " +"move_and_slide_with_snap]." #: doc/classes/KinematicBody.xml doc/classes/KinematicBody2D.xml msgid "" @@ -41270,9 +42301,8 @@ msgid "Background [StyleBox] for the [Label]." msgstr "Le [StyleBox] d'arrière-plan pour le [Label]." #: doc/classes/Label3D.xml -#, fuzzy msgid "Displays plain text in a 3D world." -msgstr "NÅ“ud de sprite en 2D dans un monde en 3D." +msgstr "Affiche du texte dans un monde en 3D." #: doc/classes/Label3D.xml msgid "" @@ -41287,78 +42317,67 @@ msgid "" msgstr "" #: doc/classes/Label3D.xml -#, fuzzy msgid "" "If [code]true[/code], the specified flag will be enabled. See [enum Label3D." "DrawFlags] for a list of flags." msgstr "" -"Si [code]true[/code], active l'option donné. Voir [enum Flags] pour ces " -"options." +"Si [code]true[/code], active le drapeau spécifié. Voir [enum Label3D." +"DrawFlags] pour la liste des drapeaux." #: doc/classes/Label3D.xml -#, fuzzy msgid "" "The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for " "possible values." msgstr "" -"Le mode d'orientation de la TileMap. Voir [enum Mode] pour les valeurs " -"possibles." #: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml msgid "Threshold at which the alpha scissor will discard values." msgstr "Le seuil à partir duquel le ciseau alpha ignorera les valeurs." #: doc/classes/Label3D.xml -#, fuzzy msgid "If [code]true[/code], wraps the text to the [member width]." -msgstr "Si [code]true[/code], cache la ligne à l'index spécifié." +msgstr "" #: doc/classes/Label3D.xml -#, fuzzy msgid "" "The billboard mode to use for the label. See [enum SpatialMaterial." "BillboardMode] for possible values." msgstr "" -"La direction de remplissage. Voir [enum FillMode] pour les valeurs possibles." #: doc/classes/Label3D.xml -#, fuzzy msgid "" "If [code]true[/code], text can be seen from the back as well, if " "[code]false[/code], it is invisible when looking at it from behind." msgstr "" -"Si [code]true[/code], la ligne sera verticale. Si [code]false[/code], elle " -"sera horizontale." #: doc/classes/Label3D.xml doc/classes/SpriteBase3D.xml -#, fuzzy msgid "" "If [code]true[/code], the label is rendered at the same size regardless of " "distance." msgstr "" -"Si [code]true[/code], l'objet est affiché à la même taille indépendamment de " -"sa distance à la caméra." +"Si [code]true[/code], le label est affiché à la même taille indépendamment " +"de sa distance à la caméra." #: doc/classes/Label3D.xml -#, fuzzy msgid "[Font] used for the [Label3D]'s text." -msgstr "[Font] utilisée pour le texte du [Label]." +msgstr "La [Font] utilisée pour le texte du [Label3D]." #: doc/classes/Label3D.xml msgid "" "Controls the text's horizontal alignment. Supports left, center, right. Set " "it to one of the [enum Align] constants." msgstr "" +"Control l'alignement horizontal du texte. Supporte à gauche, au centre, ou à " +"droite. Réglez-le à l'une des constantes de [enum Align]." #: doc/classes/Label3D.xml -#, fuzzy msgid "Vertical space between lines in multiline [Label3D]." -msgstr "L'espace vertical entre les lignes en multiligne [Label]." +msgstr "" +"L'espacement vertical entre les lignes en mode multi-ligne d'un [Label3D]." #: doc/classes/Label3D.xml -#, fuzzy msgid "Text [Color] of the [Label3D]." -msgstr "La [Color] par défaut du texte du [Label]." +msgstr "La [Color] du texte du [Label3D]." #: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml #: doc/classes/SpriteBase3D.xml @@ -41366,73 +42385,94 @@ msgid "" "If [code]true[/code], depth testing is disabled and the object will be drawn " "in render order." msgstr "" +"Si [code]true[/code], les tests de profondeur sont désactivés et l'objet " +"sera dessiné suivant son ordre de rendu et non suivant sa distance." #: doc/classes/Label3D.xml -#, fuzzy msgid "The text drawing offset (in pixels)." -msgstr "Le décalage du dessin de la texture." +msgstr "" #: doc/classes/Label3D.xml -#, fuzzy msgid "The tint of [Font]'s outline." -msgstr "La hauteur du cylindre." +msgstr "Le teinte du contour de la [Font]." #: doc/classes/Label3D.xml msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " "This is because opaque objects are not sorted, while transparent objects are " "sorted from back to front (subject to priority)." msgstr "" +"Définit la priorité de rendu pour la bordure du texte. Les objets les plus " +"prioritaires seront affichés par-dessus des objets les moins prioritaires.\n" +"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à [" +"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n" +"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela " +"n'affectera pas la façon dont les objets transparents sont triés par rapport " +"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, " +"alors que les objets transparents sont triés de l'arrière vers l'avant (et " +"suivant leur priorité)." #: doc/classes/Label3D.xml -#, fuzzy msgid "The size of one pixel's width on the label to scale it in 3D." -msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D." +msgstr "La taille d'un des pixels du label pour définir sa taille en 3D." #: doc/classes/Label3D.xml msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " "This is because opaque objects are not sorted, while transparent objects are " "sorted from back to front (subject to priority)." msgstr "" +"Définit la priorité de rendu pour le texte. Les objets les plus prioritaires " +"seront affichés par-dessus des objets les moins prioritaires.\n" +"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à [" +"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n" +"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela " +"n'affectera pas la façon dont les objets transparents sont triés par rapport " +"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, " +"alors que les objets transparents sont triés de l'arrière vers l'avant (et " +"suivant leur priorité)." #: doc/classes/Label3D.xml -#, fuzzy msgid "" "If [code]true[/code], the [Light] in the [Environment] has effects on the " "label." -msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible." +msgstr "" #: doc/classes/Label3D.xml msgid "" "Controls the text's vertical alignment. Supports top, center, bottom. Set it " "to one of the [enum VAlign] constants." msgstr "" +"Control l'alignement vertical du texte. Supports en haut, au centre, et en " +"bas. Réglez-le à l'une des constantes de [enum VAlign]." #: doc/classes/Label3D.xml msgid "Text width (in pixels), used for autowrap and fill alignment." msgstr "" +"La largeur de texte (en pixels), utilisée pour les retours à la ligne et " +"l'alignement de remplissage." #: doc/classes/Label3D.xml -#, fuzzy msgid "If set, lights in the environment affect the label." -msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible." +msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" +"Si défini, le texte sera aussi visible de derrière. Sinon, la texture ne " +"sera visible que de face." #: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml #: doc/classes/SpriteBase3D.xml @@ -41440,11 +42480,16 @@ msgid "" "Disables the depth test, so this object is drawn on top of all others. " "However, objects drawn after it in the draw order may cover it." msgstr "" +"Désactive le test de profondeur, de sorte que cet objet sera dessiné devant " +"tous les autres. Cependant, les objets dessinés après lui dans l'ordre " +"d'affichage peuvent être devant." #: doc/classes/Label3D.xml msgid "" "Label is scaled by depth so that it always appears the same size on screen." msgstr "" +"L'étiquette est mise à l'échelle suivant la distance pour qu'elle apparaisse " +"toujours à la même taille à l'écran." #: doc/classes/Label3D.xml doc/classes/SpriteBase3D.xml msgid "Represents the size of the [enum DrawFlags] enum." @@ -41456,6 +42501,9 @@ msgid "" "areas, but transparency sorting issues may be visible when multiple " "transparent materials are overlapping." msgstr "" +"Ce mode réalise un mélange l'opacité standard. Il peut afficher des zones " +"translucides, mais des problèmes de tri selon la transparence peuvent être " +"visibles lorsque plusieurs matériaux transparents se chevauchent." #: doc/classes/Label3D.xml msgid "" @@ -41467,6 +42515,15 @@ msgid "" "scripts), this mode might have transparency sorting issues between the main " "text and the outline." msgstr "" +"Ce mode ne permet que les pixels transparents ou alors entièrement opaques. " +"Ce mode est également connu sous le nom de [i]alpha testing[/i] ou " +"[i]transparence 1 bit[/i].\n" +"[b]Note :[/b] Ce mode peut avoir des problèmes avec des polices avec " +"anticrénelage et des contours, essayez d'ajuster [member " +"alpha_scisor_threshold] ou en utilisant la police avec SDF.\n" +"[b]Note :[/b] Lors de l'utilisation de texte avec des caractères superposés " +"(par exemple des cursives), ce mode pourrait avoir des problèmes de tri de " +"la transparence entre le texte principal et le contour." #: doc/classes/Label3D.xml msgid "" @@ -41478,6 +42535,13 @@ msgid "" "scripts), this mode might have transparency sorting issues between the main " "text and the outline." msgstr "" +"Ce mode dessine des pixels entièrement opaques lors de la pré-passe de " +"profondeur. Ceci est plus lent que [constant ALPHA_CUT_DISABLED] ou " +"[constant ALPHA_CUT_DISCARD], mais ça permet d'afficher des zones " +"translucides et des bords lisses tout en utilisant le tri approprié.\n" +"[b]Note :[/b] Lors de l'utilisation de texte avec des caractères superposés " +"(par exemple des cursives), ce mode pourrait avoir des problèmes de tri de " +"la transparence entre le texte principal et le contour." #: doc/classes/LargeTexture.xml msgid "" @@ -41494,6 +42558,10 @@ msgid "" "You can dynamically add pieces ([Texture]s) to this [LargeTexture] using " "different offsets." msgstr "" +"[i]Obsolète (elle sera retiré dans Godot 4.0).[/i] Une [Texture] capable de " +"stocker de nombreuses textures plus petites avec des décalages.\n" +"Vous pouvez ajouter dynamiquement des [Texture] à ce [LargeTexture] en " +"utilisant différents décalages." #: doc/classes/LargeTexture.xml msgid "" @@ -41516,9 +42584,8 @@ msgid "Returns the offset of the piece with the index [code]idx[/code]." msgstr "Retourne le décalage de la pièce à l'index [code]idx[/code]." #: doc/classes/LargeTexture.xml -#, fuzzy msgid "Returns the [Texture] of the piece with the index [code]idx[/code]." -msgstr "Retourne la position du point à l'index [code]point[/code]." +msgstr "" #: doc/classes/LargeTexture.xml msgid "" @@ -41529,12 +42596,10 @@ msgstr "" "code]." #: doc/classes/LargeTexture.xml -#, fuzzy msgid "" "Sets the [Texture] of the piece with index [code]idx[/code] to " "[code]texture[/code]." msgstr "" -"Déplace l’élément de l’index [code]from_idx[/code] à [code]to_idx[/code]." #: doc/classes/LargeTexture.xml msgid "Sets the size of this [LargeTexture]." @@ -41551,6 +42616,11 @@ msgid "" "from it. Light contains the common variables and parameters used for " "lighting." msgstr "" +"Light est la classe de base [i]abstraite[/i] pour les lumières. Puisque ça " +"ne peut être instancié, ça ne devrait pas être utilisé directement. D'autres " +"types de nÅ“uds de lumière héritent de cette classe, qui contient les " +"variables communes aux sous-classes, et les paramètres utilisés pour " +"l'éclairage." #: doc/classes/Light.xml doc/classes/SpotLight.xml msgid "3D lights and shadows" @@ -41569,6 +42639,8 @@ msgid "" "If [code]true[/code], the light only appears in the editor and will not be " "visible at runtime." msgstr "" +"Si [code]true[/code], la lumière n'apparaît que dans l'éditeur et ne sera " +"pas visible au lancement du jeu." #: doc/classes/Light.xml msgid "The light's bake mode. See [enum BakeMode]." @@ -41579,6 +42651,9 @@ msgid "" "The light's color. An [i]overbright[/i] color can be used to achieve a " "result equivalent to increasing the light's [member light_energy]." msgstr "" +"La couleur de la lumière. Une couleur [i]sur-brillante[/i] peut être " +"utilisée pour un résultant équivalent à augmenter l'énergie [member " +"light_energy] de la lumière." #: doc/classes/Light.xml msgid "The light will affect objects in the selected layers." @@ -41590,18 +42665,26 @@ msgid "" "[OmniLight] and [SpotLight], changing this value will only change the light " "color's intensity, not the light's radius." msgstr "" +"Le multiplicateur de force de la lumière (ça n'a aucune unité physique). " +"Pour [OmniLight] et [SpotLight], changer cette valeur ne changera que " +"l'intensité de la constante de couleur de la lumière, et non le rayon de la " +"lumière." #: doc/classes/Light.xml msgid "" "Secondary multiplier used with indirect light (light bounces). This works on " "both [BakedLightmap] and [GIProbe]." msgstr "" +"Le multiplicateur secondaire utilisé pour la lumière indirecte (les rebonds " +"de lumière). Cela fonctionne avec [BakedLightmap] et aussi [GIProbe]." #: doc/classes/Light.xml msgid "" "If [code]true[/code], the light's effect is reversed, darkening areas and " "casting bright shadows." msgstr "" +"Si [code]true[/code], l'effet de la lumière est inversé, assombrissant les " +"zones et lançant des ombres lumineuses." #: doc/classes/Light.xml msgid "" @@ -41618,6 +42701,11 @@ msgid "" "emission, this can be used to avoid unrealistic reflections when placing " "lights above an emissive surface." msgstr "" +"L'intensité du reflet spéculaire dans les objets touchés par la lumière. " +"Avec [code]0[/code], la lumière devient une lumière purement diffuse. Si ça " +"n'est pas une émission pré-calculée, cela peut être utilisé pour éviter des " +"reflets irréalistes lorsqu'on place des lumières au-dessus d'une surface " +"émise." #: doc/classes/Light.xml msgid "" @@ -41625,6 +42713,10 @@ msgid "" "shadowing (\"shadow acne\"), while too large a value causes shadows to " "separate from casters (\"peter-panning\"). Adjust as needed." msgstr "" +"Utilisé pour ajuster l'apparence de l'ombre. Une valeur trop petite résulte " +"au auto-ombrage (« shadow acne »), et quqand trop grande, ça provoque des " +"ombres séparées de l'objet qui crée l'ombre (« peter-panning »). Réglez " +"selon les besoins." #: doc/classes/Light.xml msgid "The color of shadows cast by this light." @@ -41638,6 +42730,11 @@ msgid "" "[b]Note:[/b] Contact shadows can look broken, so leaving this property to " "[code]0.0[/code] is recommended." msgstr "" +"Tente de réduire l'écart [member shadow_bias] en rendant les ombres de " +"contact en fonction de l'espace-écran. Cela a un impact sur les " +"performances, surtout avec des valeurs élevées.\n" +"[b]Note :[/b] Les ombres de contact peuvent sembler brisées, donc laisser " +"cette propriété à [code]0.0[/code] est plutôt recommandé." #: doc/classes/Light.xml msgid "If [code]true[/code], the light will cast shadows." @@ -41650,6 +42747,11 @@ msgid "" "cast a shadow on both sides of the mesh, set the mesh to use double-sided " "shadows with [constant GeometryInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED]." msgstr "" +"Si [code]true[/code], inverse la face arrière du maillage. Cela peut être " +"utile lorsque vous avez un maillage plat qui a une lumière derrière elle. Si " +"vous avez besoin de lancer une ombre sur les deux côtés du maillage, " +"définissez le maillage pour utiliser les deux faces avec [constant " +"GeometryInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED]." #: doc/classes/Light.xml msgid "Constant for accessing [member light_energy]." @@ -41749,10 +42851,13 @@ msgid "" "Light is ignored when baking.\n" "[b]Note:[/b] Hiding a light does [i]not[/i] affect baking." msgstr "" +"La lumière est ignorée lors du pré-calcul.\n" +"[b]Note :[/b] L'enregistrement d'une lumière ne [i]n'affecte pas[/i] le pré-" +"calcul." #: doc/classes/Light.xml msgid "Only indirect lighting will be baked (default)." -msgstr "" +msgstr "Seul l'éclairage indirect sera pré-calculé (choix par défaut)." #: doc/classes/Light.xml msgid "" @@ -41760,6 +42865,9 @@ msgid "" "[b]Note:[/b] You should hide the light if you don't want it to appear twice " "(dynamic and baked)." msgstr "" +"La lumière directe et indirecte sera pré-calculée.\n" +"[b]Note :[/b] Vous devriez cacher la lumière si vous ne voulez pas qu'elle " +"apparaisse deux fois (une fois dynamique et une autre pour le pré-calcul)." #: doc/classes/Light2D.xml msgid "Casts light in a 2D environment." @@ -41772,6 +42880,11 @@ msgid "" "parameters (range and shadows-related).\n" "[b]Note:[/b] Light2D can also be used as a mask." msgstr "" +"Montre la lumière dans un environnement 2D. La lumière est définie par une " +"texture (généralement grise), une couleur, une valeur énergétique, un mode " +"(voir les constantes), et divers autres paramètres (relatifs à la portée et " +"aux ombres).\n" +"[b]Note :[/b] Light2D peut aussi être utilisée comme masque." #: doc/classes/Light2D.xml msgid "The Light2D's [Color]." @@ -41796,20 +42909,23 @@ msgstr "" #: doc/classes/Light2D.xml msgid "The Light2D's mode. See [enum Mode] constants for values." msgstr "" +"Le mode de la Light2D. Voir les constantes [enum Mode] pour les valeurs." #: doc/classes/Light2D.xml msgid "The offset of the Light2D's [code]texture[/code]." -msgstr "" +msgstr "Le décalage de la [code]texture[/code] de la Light2D." #: doc/classes/Light2D.xml msgid "The height of the Light2D. Used with 2D normal mapping." -msgstr "" +msgstr "La hauteur du Light2D. Utilisé avec une mapping de normale 2D." #: doc/classes/Light2D.xml msgid "" "The layer mask. Only objects with a matching mask will be affected by the " "Light2D." msgstr "" +"Le masque de calque. Seuls les objets avec un masque correspondant seront " +"sous l'influence de ce Light2D." #: doc/classes/Light2D.xml msgid "Maximum layer value of objects that are affected by the Light2D." @@ -41836,7 +42952,6 @@ msgstr "" "les Light2D." #: doc/classes/Light2D.xml -#, fuzzy msgid "Shadow buffer size." msgstr "Taille du tampon d'ombre." @@ -41860,13 +42975,16 @@ msgstr "Valeur de lissage pour les ombres." #: doc/classes/Light2D.xml msgid "Smooth shadow gradient length." -msgstr "" +msgstr "Longeur de lissage du dégradé d'ombre." #: doc/classes/Light2D.xml msgid "" "The shadow mask. Used with [LightOccluder2D] to cast shadows. Only occluders " "with a matching light mask will cast shadows." msgstr "" +"Le masque d'ombre. Utilisé avec [LightOccluder2D] pour lancer des ombres. " +"Seuls les occulteurs avec un masque de lumière correspondant lanceront des " +"ombres." #: doc/classes/Light2D.xml msgid "[Texture] used for the Light2D's appearance." @@ -41881,18 +42999,24 @@ msgid "" "Adds the value of pixels corresponding to the Light2D to the values of " "pixels under it. This is the common behavior of a light." msgstr "" +"Ajoute la valeur des pixels correspondant à la Light2D aux valeurs des " +"pixels sous elle. C'est le comportement classique des lumières." #: doc/classes/Light2D.xml msgid "" "Subtracts the value of pixels corresponding to the Light2D to the values of " "pixels under it, resulting in inversed light effect." msgstr "" +"Soustrait la valeur des pixels correspondant à la Light2D aux valeurs des " +"pixels sous elle, ce qui entraîne un effet de lumière inversé." #: doc/classes/Light2D.xml msgid "" "Mix the value of pixels corresponding to the Light2D to the values of pixels " "under it by linear interpolation." msgstr "" +"Mélange la valeur des pixels correspondant à la Light2D aux valeurs des " +"pixels sous elle, via une interpolation linéaire." #: doc/classes/Light2D.xml msgid "" @@ -41900,40 +43024,54 @@ msgid "" "parts of the screen underneath depending on the value of each pixel of the " "light (mask) texture." msgstr "" +"La texture de lumière de la Light2D est utilisée comme masque, cache ou " +"révèle des parties de l'écran sous la valeur de chaque pixel de la texture " +"de la lumière (masque)." #: doc/classes/Light2D.xml msgid "No filter applies to the shadow map. See [member shadow_filter]." msgstr "" +"Aucun filtre ne s'applique à la carte d'ombre. Voir [member Shadow_filter]." #: doc/classes/Light2D.xml msgid "" "Percentage closer filtering (3 samples) applies to the shadow map. See " "[member shadow_filter]." msgstr "" +"Le pourcentage de filtrage proche (3 échantillons) s'applique à la carte de " +"l'ombre. Voir [member Shadow_filter]." #: doc/classes/Light2D.xml msgid "" "Percentage closer filtering (5 samples) applies to the shadow map. See " "[member shadow_filter]." msgstr "" +"Le pourcentage de filtrage proche (5 échantillons) s'applique à la carte de " +"l'ombre. Voir [member Shadow_filter]." #: doc/classes/Light2D.xml msgid "" "Percentage closer filtering (7 samples) applies to the shadow map. See " "[member shadow_filter]." msgstr "" +"Le pourcentage de filtrage proche (7 échantillons) s'applique à la carte de " +"l'ombre. Voir [member Shadow_filter]." #: doc/classes/Light2D.xml msgid "" "Percentage closer filtering (9 samples) applies to the shadow map. See " "[member shadow_filter]." msgstr "" +"Le pourcentage de filtrage proche (9 échantillons) s'applique à la carte de " +"l'ombre. Voir [member Shadow_filter]." #: doc/classes/Light2D.xml msgid "" "Percentage closer filtering (13 samples) applies to the shadow map. See " "[member shadow_filter]." msgstr "" +"Le pourcentage de filtrage proche (13 échantillons) s'applique à la carte de " +"l'ombre. Voir [member Shadow_filter]." #: doc/classes/LightOccluder2D.xml msgid "Occludes light cast by a Light2D, casting shadows." @@ -41951,10 +43089,12 @@ msgid "" "The LightOccluder2D's light mask. The LightOccluder2D will cast shadows only " "from Light2D(s) that have the same light mask(s)." msgstr "" +"Le masque de lumière du LightOccluder2D. Le LightOccluder2D ne lancera que " +"des ombres que sur les Light2D qui ont le même masque de lumière." #: doc/classes/LightOccluder2D.xml msgid "The [OccluderPolygon2D] used to compute the shadow." -msgstr "" +msgstr "Le [OccluderPolygon2D] utilisé pour calculer l'ombre." #: doc/classes/Line2D.xml msgid "A 2D line." @@ -41970,6 +43110,14 @@ msgid "" "[member ProjectSettings.rendering/limits/buffers/" "canvas_polygon_index_buffer_size_kb]." msgstr "" +"Une ligne à travers plusieurs points dans l'espace 2D. Supporte une largeur " +"et une couleur différentes sur la longueur, la texture et plusieurs types " +"d'embout et de jointure.\n" +"[b]Note :[/b] Par défaut, Godot ne peut dessiner que 4 096 points de " +"polygone à la fois. Pour augmenter cette limite, ouvrez les paramètres du " +"projet et augmentez [member ProjectSettings.rendering/limits/buffers/" +"canvas_polygon_buffer_size_kb] et [member ProjectSettings.rendering/limits/" +"buffers/canvas_polygon_index_buffer_size_kb]." #: doc/classes/Line2D.xml msgid "" @@ -41982,10 +43130,18 @@ msgid "" "get_point_count][/code]), the point will be appended at the end of the point " "list." msgstr "" +"Ajoute un point au [code]position[/code]. Ajoute le point à la fin de la " +"ligne.\n" +"Si [code]at_position[/code] est donné, le point est inséré avant l'indice " +"[code]at_position[/code], en déplaçant ce point (et chaque point après) " +"après le point inséré. Si [code]at_position[/code] n'est pas donné, ou est " +"une valeur invalide ([code]at_position < 0[/code] ou [code]at_position >= " +"[method get_point_count][/code]), le point sera ajouté à la fin de la liste " +"des points." #: doc/classes/Line2D.xml msgid "Removes all points from the line." -msgstr "" +msgstr "Retire tous les points de la ligne." #: doc/classes/Line2D.xml msgid "Returns the Line2D's amount of points." @@ -42021,6 +43177,19 @@ msgid "" "perform antialiasing. 2D batching is also still supported with those " "antialiased lines." msgstr "" +"Si [code]true[/code], la bordure de la ligne essayera d'activer " +"anticrénelage en dessinant de fines lignes en OpenGL sur les bords de la " +"ligne.\n" +"[b]Note :[/b] Line2D n'est pas accéléré par lots si [code]antialiased[/code] " +"est [code]true[/code].\n" +"[b]Note :[/b] En raison de son fonctionnement, l'anticrénelage calculé en " +"interne n'est pas correct pour les lignes semi-transparents voire peut ne " +"pas fonctionner sur certaines plateformes. Vous pouvez corriger ce problème " +"en installant le greffon [url=https://github.com/godot-extended-libraries/" +"godot-antialiased-line2d]Antialiased Line2D[/url] puis créez un nÅ“ud " +"\"AntialiasedPolygon2D\". Ce nÅ“ud utilise des texture avec des mipmaps " +"personnalisés pour afficher l'anticrénelage. L'accélération par lot est " +"toujours supporté même avec les lignes avec anticrénelage." #: doc/classes/Line2D.xml msgid "" @@ -42047,6 +43216,8 @@ msgid "" "The gradient is drawn through the whole line from start to finish. The " "default color will not be used if a gradient is set." msgstr "" +"Le dégradé est dessiné par toute la ligne du début à la fin. La couleur par " +"défaut ne sera pas utilisée si un dégradé est défini." #: doc/classes/Line2D.xml msgid "The style for the points between the start and the end." @@ -42057,6 +43228,9 @@ msgid "" "The points that form the lines. The line is drawn between every point set in " "this array. Points are interpreted as local vectors." msgstr "" +"Les points qui forment les lignes. La ligne est tracée entre chaque point " +"défini dans ce tableau. Les points sont interprétés comme des vecteurs " +"locaux." #: doc/classes/Line2D.xml msgid "" @@ -42067,24 +43241,37 @@ msgid "" "width]. For thin lines, this value should be reduced to a number between " "[code]2[/code] and [code]4[/code] to improve performance." msgstr "" +"Le lissage des coins et des bouts. Les valeurs plus élevées affichent des " +"coins plus lisses, mais demandent plus de ressources pour le rendu. Ceci " +"n'est utilisé que si un coin ou un bout est défini comme arrondi.\n" +"[b]Note :[/b] La valeur par défaut est réglée pour les lignes avec la " +"largeur [member width] par défaut. Pour les lignes fines, cette valeur " +"devrait être réduite à entre [code]2[/code] et [code]4[/code] pour améliorer " +"les performances." #: doc/classes/Line2D.xml msgid "" "The direction difference in radians between vector points. This value is " "only used if [member joint_mode] is set to [constant LINE_JOINT_SHARP]." msgstr "" +"La différence de direction entre les points vectoriels. Cette valeur n'est " +"utilisée que si [member joint_mode] est [constant LINE_JOINT_SHARP]." #: doc/classes/Line2D.xml msgid "" "The texture used for the line's texture. Uses [code]texture_mode[/code] for " "drawing style." msgstr "" +"La texture utilisée pour la texture de la ligne. Utilise " +"[code]texture_mode[/code] pour le style de dessin." #: doc/classes/Line2D.xml msgid "" "The style to render the [code]texture[/code] on the line. Use [enum " "LineTextureMode] constants." msgstr "" +"Le style de rendu de la [code]texture[/code] sur la ligne. Utilisez une des " +"constantes [enum LineTextureMode]." #: doc/classes/Line2D.xml msgid "The line's width." @@ -42095,12 +43282,16 @@ msgid "" "The line's width varies with the curve. The original width is simply " "multiply by the value of the Curve." msgstr "" +"La largeur de la ligne dépend selon la courbe. La largeur originale est " +"simplement multipliée par la valeur de la Curve." #: doc/classes/Line2D.xml msgid "" "The line's joints will be pointy. If [code]sharp_limit[/code] is greater " "than the rotation of a joint, it becomes a bevel joint instead." msgstr "" +"Les coins de la ligne sont pointus. Si [code]sharp_limit[/code] est plus " +"grand que l'angle d'un coin, ça devient un biseau." #: doc/classes/Line2D.xml msgid "The line's joints will be bevelled/chamfered." @@ -42108,7 +43299,7 @@ msgstr "" #: doc/classes/Line2D.xml msgid "The line's joints will be rounded." -msgstr "" +msgstr "Les coins de la ligne seront arrondis." #: doc/classes/Line2D.xml msgid "Don't draw a line cap." @@ -42126,6 +43317,7 @@ msgstr "Dessine le bout de la ligne avec un arrondi." msgid "" "Takes the left pixels of the texture and renders it over the whole line." msgstr "" +"Utilise les pixels de gauche de la texture pour le rendu de toute la ligne." #: doc/classes/Line2D.xml msgid "" @@ -42138,10 +43330,12 @@ msgid "" "Stretches the texture across the line. Import the texture with [b]Repeat[/b] " "disabled for best results." msgstr "" +"Étire la texture à travers la ligne. Importez la texture avec la " +"[b]répétition[/b] désactivée pour de meilleurs résultats." #: doc/classes/LineEdit.xml msgid "Control that provides single-line string editing." -msgstr "" +msgstr "Le Control qui fournit l'édition d'un texte d'une seule ligne." #: doc/classes/LineEdit.xml msgid "" @@ -42229,6 +43423,9 @@ msgid "" "[code]from_column[/code] to [code]to_column[/code]. Both parameters should " "be within the text's length." msgstr "" +"Supprime une section du [member text] allant de la position " +"[code]from_column[/code] à [code]to_column[/code]. Les deux paramètres " +"doivent être de la longueur du texte." #: doc/classes/LineEdit.xml doc/classes/RichTextLabel.xml msgid "Clears the current selection." @@ -42242,12 +43439,19 @@ msgid "" "may cause a crash. If you wish to hide it or any of its children, use their " "[member CanvasItem.visible] property." msgstr "" +"Retourne le [PopupMenu] de ce [LineEdit]. Par défaut, ce menu s'affiche " +"lorsque le clic-droit sur le [LineEdit].\n" +"[b]Avertissement :[/b] Il s'agit d'un nÅ“ud interne requis, le retirer et le " +"supprimer peut causer un plantage. Si vous voulez le cacher, lui ou un de " +"ses enfants, utilisez la propriété [member CanvasItem.visible]." #: doc/classes/LineEdit.xml msgid "" "Returns the scroll offset due to [member caret_position], as a number of " "characters." msgstr "" +"Retourne le décalage du défilement suivant [member caret_position], en tant " +"que nombre de caractères." #: doc/classes/LineEdit.xml doc/classes/TextEdit.xml msgid "Returns the selection begin column." @@ -42258,9 +43462,8 @@ msgid "Returns the selection end column." msgstr "Retourne la colonne de fin de sélection." #: doc/classes/LineEdit.xml -#, fuzzy msgid "Returns [code]true[/code] if the user has selected text." -msgstr "Retourne [code]true[/code] si le minuteur est arrêté." +msgstr "Retourne [code]true[/code] si l'utilisateur a sélectionné du texte." #: doc/classes/LineEdit.xml msgid "Executes a given action as defined in the [enum MenuItems] enum." @@ -42279,6 +43482,15 @@ msgid "" "select(2, 5) # Will select \"lco\".\n" "[/codeblock]" msgstr "" +"Sélectionne les caractères à l'intérieur du [LineEdit] entre [code]from[/" +"code] et [code]to[/code]. Par défaut, [code]from[/code] est au début et " +"[code]to[/code] à la fin.\n" +"[codeblock]\n" +"text = \"Bienvenue\"\n" +"select() # Will select \"Bienvenue\".\n" +"select(5) # Will select \"venue\".\n" +"select(2, 7) # Will select \"enven\".\n" +"[/codeblock]" #: doc/classes/LineEdit.xml msgid "Selects the whole [String]." @@ -42301,6 +43513,8 @@ msgid "" "The cursor's position inside the [LineEdit]. When set, the text may scroll " "to accommodate it." msgstr "" +"La position du curseur dans le [LineEdit]. Lorsqu'il est défini, le texte " +"peut défiler pour l'afficher." #: doc/classes/LineEdit.xml msgid "" @@ -42317,13 +43531,12 @@ msgstr "Si [code]true[/code], le menu contextuel apparaitra au clic-droit." #: doc/classes/LineEdit.xml doc/classes/RichTextLabel.xml #: doc/classes/TextEdit.xml -#, fuzzy msgid "" "If [code]true[/code], the selected text will be deselected when focus is " "lost." msgstr "" -"Si [code]true[/code], la cellule actuellement sélectionnée peut être " -"sélectionnée à nouveau." +"Si [code]true[/code], le texte actuellement sélectionné sera désélectionné " +"quand le focus sera perdu." #: doc/classes/LineEdit.xml msgid "" @@ -43041,35 +44254,58 @@ msgid "" "add_constant_override(\"margin_right\", margin_value)\n" "[/codeblock]" msgstr "" +"Ajoute une marge supérieure, gauche, inférieure et droite à tous les nÅ“uds " +"[Control] qui sont des enfants directs du conteneur. Pour contrôler la marge " +"du [MarginContainer], utilisez les propriétés [code]margin_*[/code] du " +"thèmes listées ci-dessous.\n" +"[b]Note :[/b] Soyez prudent, les valeurs des marges de [Control] sont " +"différentes des valeurs de marge constante. Si vous souhaitez modifier les " +"valeurs de marge personnalisées du [MarginContainer] par code, vous devez " +"utiliser les exemples suivants :\n" +"[codeblock]\n" +"# Cet exemple suppose que ce script hérite de MarginContainer.\n" +"var margin_value = 100\n" +"add_constant_override(\"margin_top\", margin_value)\n" +"add_constant_override(\"margin_left\", margin_value)\n" +"add_constant_override(\"margin_bottom\", margin_value)\n" +"add_constant_override(\"margin_right\", margin_value)\n" +"[/codeblock]" #: doc/classes/MarginContainer.xml msgid "" "All direct children of [MarginContainer] will have a bottom margin of " "[code]margin_bottom[/code] pixels." msgstr "" +"Tous les enfants directs de [MarginContainer] auront la marge du bas de " +"[code]margin_bottom[/code] pixels." #: doc/classes/MarginContainer.xml msgid "" "All direct children of [MarginContainer] will have a left margin of " "[code]margin_left[/code] pixels." msgstr "" +"Tous les enfants directs de [MarginContainer] auront la marge gauche de " +"[code]margin_left[/code] pixels." #: doc/classes/MarginContainer.xml msgid "" "All direct children of [MarginContainer] will have a right margin of " "[code]margin_right[/code] pixels." msgstr "" +"Tous les enfants directs de [MarginContainer] auront la marge droite de " +"[code]margin_right[/code] pixels." #: doc/classes/MarginContainer.xml msgid "" "All direct children of [MarginContainer] will have a top margin of " "[code]margin_top[/code] pixels." msgstr "" +"Tous les enfants directs de [MarginContainer] auront la marge du haut de " +"[code]margin_top[/code] pixels." #: doc/classes/Marshalls.xml -#, fuzzy msgid "Data transformation (marshalling) and encoding helpers." -msgstr "Transformation de données (marshalling) et assistants d'encodage." +msgstr "Transformation de données (\"marshalling\") et assistants d'encodage." #: doc/classes/Marshalls.xml msgid "Provides data transformation and encoding utility functions." @@ -43078,13 +44314,12 @@ msgstr "" "données." #: doc/classes/Marshalls.xml -#, fuzzy msgid "" "Returns a decoded [PoolByteArray] corresponding to the Base64-encoded string " "[code]base64_str[/code]." msgstr "" -"Renvoie un [PoolByteArray] décodé correspondant à la chaîne de caractères " -"encodée en Base64 [code]base64_str[/code]." +"Retourne un [PoolByteArray] décodé correspondant à la chaîne de caractères " +"[code]base64_str[/code] encodée en Base64." #: doc/classes/Marshalls.xml msgid "" @@ -43218,6 +44453,9 @@ msgid "" "text color of the button. Disabled, hovered, and pressed states take " "precedence over this color." msgstr "" +"Le texte [Color] utilisé quand le [MenuButton] a le focus. Il suffit de " +"remplacer la couleur de texte normale du bouton. Les états désactivés, " +"survolés et pressés sont prioritaires sur cette couleur." #: doc/classes/MenuButton.xml msgid "Text [Color] used when the [MenuButton] is being hovered." @@ -43245,6 +44483,9 @@ msgid "" "current [StyleBox], so using [StyleBoxEmpty] will just disable the focus " "visual effect." msgstr "" +"La [StyleBox] utilisée quand le [MenuButton] a le focus. Elle est affichée " +"par dessus l'actuelle [StyleBox], donc utiliser [StyleBoxEmpty] va tout " +"simplement désactiver l'effet visuel du focus." #: doc/classes/MenuButton.xml msgid "[StyleBox] used when the [MenuButton] is being hovered." @@ -43271,6 +44512,12 @@ msgid "" "surfaces is preferred to a single surface, because objects created in 3D " "editing software commonly contain multiple materials." msgstr "" +"Mesh est un type de [Resource] qui contient la géométrie à base de tableaux " +"de sommets, divisé en [i]surfaces[/i]. Chaque surface contient un tableau " +"complètement séparé et un matériau utilisé pour le dessiner. Au niveau du " +"design, un maillage avec plusieurs surfaces est préféré à une seule surface, " +"car les objets créés dans le logiciel d'édition 3D contiennent généralement " +"plusieurs matériaux." #: doc/classes/Mesh.xml msgid "" @@ -43281,6 +44528,13 @@ msgid "" "If [code]simplify[/code] is [code]true[/code], the geometry can be further " "simplified to reduce the amount of vertices. Disabled by default." msgstr "" +"Calcule la [ConvexPolygonShape] du maillage.\n" +"Si [code]clean[/code] est [code]true[/code] (par défaut), les sommets " +"intérieurs et en double sont automatiquement supprimés. Vous pouvez le " +"définir à [code]false[/code] pour rendre le processus plus rapide si " +"nécessaire.\n" +"Si [code]simplify[/code] est [code]true[/code], la géométrie peut être plus " +"simplifiée pour réduire la quantité de sommets. Désactivé par défaut." #: doc/classes/Mesh.xml msgid "" @@ -43289,6 +44543,10 @@ msgid "" "[b]Note:[/b] This method typically returns the vertices in reverse order (e." "g. clockwise to counterclockwise)." msgstr "" +"Calcule un maillage de contour avec un décalage défini (marge) du maillage " +"d'origine.\n" +"[b]Note :[/b] Cette méthode renvoie généralement les sommets en ordre " +"inverse (par ex., du sens horaire au sens anti-horaire)." #: doc/classes/Mesh.xml msgid "Calculate a [ConcavePolygonShape] from the mesh." @@ -43305,6 +44563,10 @@ msgid "" "get_transformed_aabb].\n" "[b]Note:[/b] This is only implemented for [ArrayMesh] and [PrimitiveMesh]." msgstr "" +"Retourne le plus petit [AABB] englobant ce maillage dans l'espace local. Non " +"affecté par [code]custom_aabb[/code]. Voir aussi [method VisualInstance." +"get_transformed_aabb]\n" +"[b]Note :[/b] Ceci n'est implémenté que pour [ArrayMesh] et [PrimitiveMesh]." #: doc/classes/Mesh.xml msgid "" @@ -43629,6 +44891,9 @@ msgid "" "Uses specified surface of given [Mesh] to populate data for MeshDataTool.\n" "Requires [Mesh] with primitive type [constant Mesh.PRIMITIVE_TRIANGLES]." msgstr "" +"Utiliser la surface spécifiée de [Mesh] pour construire les données pour le " +"MeshDataTool.\n" +"Nécessite un [Mesh] de type primitif [constant Mesh.PRIMITIVE_TRIANGES]." #: doc/classes/MeshDataTool.xml msgid "Returns the number of edges in this [Mesh]." @@ -43648,6 +44913,9 @@ msgid "" "Vertex argument can only be 0 or 1 because edges are comprised of two " "vertices." msgstr "" +"Retourne l'index des sommet spécifiés reliés au bord donné.\n" +"L'argument du sommet ne peut être que 0 ou 1 car les bords ne sont composés " +"que de deux sommets." #: doc/classes/MeshDataTool.xml msgid "Returns the number of faces in this [Mesh]." @@ -43658,6 +44926,9 @@ msgid "" "Returns specified edge associated with given face.\n" "Edge argument must be either 0, 1, or 2 because a face only has three edges." msgstr "" +"Retourne le bord spécifié associé au face donné.\n" +"L'argument du bord doit être soit 0, 1 ou 2 parce qu'une face n'a que trois " +"bords." #: doc/classes/MeshDataTool.xml msgid "Returns the metadata associated with the given face." @@ -43673,6 +44944,9 @@ msgid "" "Vertex argument must be either 0, 1, or 2 because faces contain three " "vertices." msgstr "" +"Retourne le vertx spécifié du face donné.\n" +"L'argument du sommet doit être soit 0, 1 ou 2 parce que les faces ne " +"contiennent que trois sommets." #: doc/classes/MeshDataTool.xml msgid "" @@ -43683,6 +44957,12 @@ msgid "" "ARRAY_FORMAT_NORMAL] is [code]2[/code].\n" "See [enum ArrayMesh.ArrayFormat] for a list of format flags." msgstr "" +"Retourne le format du [Mesh]. Le format est un entier composé des drapeaux " +"de format du [Mesh]. Par exemple, un maillage contenant à la fois des " +"sommets et des normales retournerait un format de [code]3[/code] parce que [" +"constant ArrayMesh.ARRAY_FORMAT_VERTEX] est [code]1[/code] et [constant " +"ArrayMesh.ARRAY_FORMAT_NORMAL] est [code]2[/code].\n" +"Voir [enum ArrayMesh.ArrayFormat] pour une liste de drapeaux de format." #: doc/classes/MeshDataTool.xml msgid "Returns the material assigned to the [Mesh]." @@ -43797,6 +45077,13 @@ msgid "" "[Mesh] has to be instanced more than thousands of times at close proximity, " "consider using a [MultiMesh] in a [MultiMeshInstance] instead." msgstr "" +"MeshInstance est un nÅ“ud qui prend une ressource [Mesh] et l'ajoute au " +"scénario actuel en créant une instance. C'est la classe la plus souvent " +"utilisée pour obtenir la géométrie 3D pour le rendu et peut être utilisé " +"pour l'instance d'un seul [Mesh] dans de nombreux endroits. Cela permet de " +"réutiliser la géométrie et d'économiser des ressources. Lorsqu'un [Mesh] " +"doit être instancié plusieurs milliers de fois les uns proches des autres, " +"préférez plutôt un [MultiMesh] dans un [MultiMeshInstance]." #: doc/classes/MeshInstance.xml msgid "" @@ -43809,6 +45096,16 @@ msgid "" "If [code]simplify[/code] is [code]true[/code], the geometry can be further " "simplified to reduce the amount of vertices. Disabled by default." msgstr "" +"Cette aide crée un nÅ“ud [StaticBody] enfant avec une forme de collision " +"[ConvexPolygonShape] calculée à partir de la géométrie du maillage. Elle est " +"principalement utilisée pour les essais.\n" +"Si [code]clean[/code] est [code]true[/code] (par défaut), les doublons et " +"les sommets intérieurs sont automatiquement supprimés. Vous pouvez le " +"définir à [code]false[/code] pour rendre le processus de création plus " +"rapide.\n" +"Si [code]simplify[/code] est [code]true[/code], la géométrie pourra être " +"simplifiée pour réduire la quantité de sommets, ce qui est désactivé par " +"défaut." #: doc/classes/MeshInstance.xml msgid "" @@ -43847,11 +45144,15 @@ msgid "" "[method Mesh.surface_get_material] to get materials associated with the " "[Mesh] resource." msgstr "" +"Retourne la surcharge [Material] pour une surface de la ressource [Mesh].\n" +"[b]Note :[/b] Cette fonction ne retourne que les matériaux associés à la " +"[i]surchage[/i] de la [MeshInstance]. Préférez [method get_active_material] " +"ou [method Mesh.surface_get_material] pour obtenir des matériaux associés à " +"la ressource [Mesh]." #: doc/classes/MeshInstance.xml -#, fuzzy msgid "Returns the number of surface override materials." -msgstr "Retourne le nombre de surfaces du matériau." +msgstr "Retourne le nombre de surcharges des surfaces du matériau." #: doc/classes/MeshInstance.xml msgid "" @@ -43861,6 +45162,12 @@ msgid "" "In order to be mergeable, properties of the [MeshInstance] must match, and " "each surface must match, in terms of material, attributes and vertex format." msgstr "" +"Retourne [code]true[/code] si cette [MeshInstance] peut être fusionnée avec " +"l'autre instance [code]other_mesh_instance[/code], en utilisant la fonction [" +"method MeshInstance.merge_meshes].\n" +"Pour pouvoir être fusionnées, les propriétés des [MeshInstance] doivent " +"correspondre, et chaque surface doit correspondre, en termes de matériau, " +"d'attributs et de format des sommets." #: doc/classes/MeshInstance.xml msgid "" @@ -43885,6 +45192,26 @@ msgid "" "Also note that any initial data in the destination [MeshInstance] data will " "be discarded." msgstr "" +"Cette fonction peut fusionner les données de plusieurs [MeshInstance] " +"sources en une seule [MeshInstance] finale (le MeshInstance sur laquel la " +"fonction est appelée). Ceci est principalement utile pour améliorer les " +"performances en réduisant le nombre de appels de dessin et de [Node].\n" +"Le fusions ne doivent être faites que sur des maillages simples et ne " +"contenant pas d'animation.\n" +"Les sommets finaux peuvent soit être retournés dans l'espace global, soit " +"dans l'espace local par rapport à la transformation globale de la " +"[MeshInstance] finale (ce nÅ“ud doit être à l'intérieur du [SceneTree] pour " +"l'espace local pour fonctionner).\n" +"La fonction effectuera un contrôle final de compatibilité entre les " +"[MeshInstance] par défaut, cela devrait toujours être utilisé à moins que " +"vous n'ayez préalablement vérifié la compatibilité avec [method MeshInstance." +"is_mergeable_with]. Si la vérification est ignorée et que les maillages sont " +"fusionnés, vous pouvez voir des erreurs de rendu.\n" +"[b]Note :[/b] Les exigences de similitude entre les maillages sont assez " +"strictes. Elles peuvent être vérifiés avec [method MeshInstance." +"is_mergeable_with], avant d'appeler [method MeshInstance.merge_meshes]\n" +"Notez également que toutes les données initiales dans la [MeshInstance] " +"finale seront supprimées." #: doc/classes/MeshInstance.xml msgid "" @@ -43892,6 +45219,9 @@ msgid "" "resource. This material is associated with this [MeshInstance] rather than " "with the [Mesh] resource." msgstr "" +"Définit la surcharge [Material] pour la surface spécifiée de la ressource " +"[Mesh]. Ce matériel est associé à cette ressource [MeshInstance] plutôt qu'à " +"la ressource [Mesh]." #: doc/classes/MeshInstance.xml msgid "The [Mesh] resource for the instance." @@ -43984,9 +45314,8 @@ msgid "Returns the item's mesh." msgstr "Retourne le maillage de l'élément." #: doc/classes/MeshLibrary.xml -#, fuzzy msgid "Returns the transform applied to the item's mesh." -msgstr "Retourne la matrice de transformation de la toile de cet objet." +msgstr "" #: doc/classes/MeshLibrary.xml msgid "Returns the item's name." @@ -44029,9 +45358,8 @@ msgid "Sets the item's mesh." msgstr "Définit le maillage de l'élément." #: doc/classes/MeshLibrary.xml -#, fuzzy msgid "Sets the transform to apply to the item's mesh." -msgstr "Retourne la matrice de transformation de la toile de cet objet." +msgstr "" #: doc/classes/MeshLibrary.xml msgid "" @@ -44160,12 +45488,16 @@ msgid "" "The height at which the camera is placed in relation to the ground (i.e. " "[ARVROrigin] node)." msgstr "" +"La hauteur à laquelle la caméra est placée par rapport au sol (c'est-à -dire " +"au nÅ“ud [ARVROrigin])." #: modules/mobile_vr/doc_classes/MobileVRInterface.xml msgid "" "The interocular distance, also known as the interpupillary distance. The " "distance between the pupils of the left and right eye." msgstr "" +"La distance interoculaire, aussi appelée la distance interpupillaire. La " +"distance entre la pupille de l'Å“il gauche et celle du l'Å“il droit." #: modules/mobile_vr/doc_classes/MobileVRInterface.xml msgid "" @@ -44178,7 +45510,7 @@ msgstr "" #: modules/mobile_vr/doc_classes/MobileVRInterface.xml msgid "The k2 lens factor, see k1." -msgstr "" +msgstr "Le facteur k2 de lentille, voir k1." #: modules/mobile_vr/doc_classes/MobileVRInterface.xml msgid "" @@ -44251,6 +45583,18 @@ msgid "" "(4 bytes as is) and [code]COLOR_FLOAT[/code] / [code]CUSTOM_DATA_FLOAT[/" "code] is stored as 4 floats." msgstr "" +"Définit toutes les données relatives aux instances en une seule fois. Ceci " +"est particulièrement utile lors du chargement des données du disque ou de la " +"préparation des données de GDNative.\n" +"Toutes les données sont empaquetées dans un grand tableau flottant. Un " +"tableau peut ressembler à ceci : la Transform pour l'instance 1, les données " +"de couleur pour l'instance 1, des données personnalisées pour l'instance 1, " +"la Transform pour l'instance 2, les données de couleur pour l'instance 2, " +"etc.\n" +"[Transform] est enregistré avec 12 flottants, [Transform2D] avec 8 " +"flottants, [code]COLOR_8BIT[/code] / [code]CUSTOM_DATA_8BIT[/code] avec 1 " +"flottant (4 octets en général) et [code]COLOR_FLOAT[/code] / " +"[code]CUSTOM_DATA_FLOAT[/code] avec 4 flottants." #: doc/classes/MultiMesh.xml msgid "" @@ -44263,6 +45607,16 @@ msgid "" "When the order of instances is coherent, the simpler [method MultiMesh." "set_as_bulk_array] can still be used with interpolation." msgstr "" +"Une version alternative de [method MultiMesh.set_as_bulk_array] qui peut " +"être utilisée avec [i]l'interpolation physique[/i]. Cette méthode prend deux " +"tableaux, et peut définir les données pour la trame actuelle et précédente " +"en une seule fois. Le rendu interpolera automatiquement les données entre " +"ces deux trames.\n" +"Ceci est utile pour les situations où l'ordre des instances peut changer " +"d'une trame physique à l'autre, comme les systèmes de particules.\n" +"Lorsque l'ordre des instances est cohérent, la méthode [method MultiMesh." +"set_as_bulk_array] plus simple peut encore être utilisée avec " +"l'interpolation." #: doc/classes/MultiMesh.xml msgid "" @@ -44272,6 +45626,11 @@ msgid "" "[code]null[/code] on the [MultiMesh] and [member SpatialMaterial." "vertex_color_use_as_albedo] is [code]true[/code] on the material." msgstr "" +"Définit la couleur d'une instance spécifique en [i]multipliant[/i] les " +"couleurs des sommets existants du maillage.\n" +"Pour que la couleur soit modifiée, assurez-vous que [member color_format] " +"n'est pas [code]null[/code] pour le [MultiMesh] et [member SpatialMaterial." +"vertex_color_use_as_albedo] est [code]true[/code] dans le matériau." #: doc/classes/MultiMesh.xml msgid "" @@ -44279,6 +45638,10 @@ msgid "" "just a container for 4 floating point numbers. The format of the number can " "change depending on the [enum CustomDataFormat] used." msgstr "" +"Définit des données personnalisées pour une instance spécifique. Bien que " +"[Color] soit utilisée, ce n'est qu'un conteneur pour 4 flottants qui peut " +"servir à autre chose. Le format du nombre peut changer en fonction du [enum " +"CustomDataFormat] utilisé." #: doc/classes/MultiMesh.xml msgid "Sets the [Transform] for a specific instance." @@ -44290,11 +45653,11 @@ msgstr "Définit la [Transform2D] pour l'instance spécifiée." #: doc/classes/MultiMesh.xml msgid "Format of colors in color array that gets passed to shader." -msgstr "" +msgstr "Le format des couleurs dans le tableau de couleurs passé au shader." #: doc/classes/MultiMesh.xml msgid "Format of custom data in custom data array that gets passed to shader." -msgstr "" +msgstr "Le format des données personnalisées dans ce tableau passé au shader." #: doc/classes/MultiMesh.xml msgid "" @@ -44302,6 +45665,9 @@ msgid "" "buffers. By default, all instances are drawn but you can limit this with " "[member visible_instance_count]." msgstr "" +"Le nombre de cas qui seront affichés. Cela effacera et re-dimensionnera les " +"mémoires tampons. Par défaut, toutes les instantes sont dessinées mais vous " +"pouvez les limiter avec [member visible_instance_count]." #: doc/classes/MultiMesh.xml msgid "Mesh to be drawn." @@ -44316,6 +45682,14 @@ msgid "" "special cases mentioned above, the quality should be comparable to high " "quality." msgstr "" +"Choisis si vous utilisez une méthode d'interpolation qui favorise la vitesse " +"ou la qualité.\n" +"Lors de l'utilisation de faibles taux de trames physiques (généralement " +"inférieur à 20) ou de taux élevés de rotation d'objets, vous pouvez obtenir " +"de meilleurs résultats à partir du réglage de haute qualité.\n" +"[b]Note :[/b] La qualité rapide ne correspond pas à la qualité basse. Sauf " +"dans les cas particuliers mentionnés ci-dessus, la qualité devrait être " +"comparable à la qualité." #: doc/classes/MultiMesh.xml msgid "Format of transform used to transform mesh, either 2D or 3D." @@ -44328,6 +45702,8 @@ msgid "" "Limits the number of instances drawn, -1 draws all instances. Changing this " "does not change the sizes of the buffers." msgstr "" +"Limite le nombre d'instances affichées, et -1 les dessine toutes. Changer " +"cela ne change pas la taille des mémoires tampons." #: doc/classes/MultiMesh.xml msgid "Use this when using 2D transforms." @@ -44346,12 +45722,17 @@ msgid "" "Compress [Color] data into 8 bits when passing to shader. This uses less " "memory and can be faster, but the [Color] loses precision." msgstr "" +"Compresse les données [Color] en 8 bits quand elles seront passées au " +"shader. Cela utilise moins de mémoire et peut être plus rapide, mais les " +"[Color] perdent en précision." #: doc/classes/MultiMesh.xml msgid "" "The [Color] passed into [method set_instance_color] will use 4 floats. Use " "this for highest precision [Color]." msgstr "" +"La [Color] passée dans [method set_instance_color] utilisera 4 flottants. " +"Utilisez ceci pour la plus haute précision [Color]." #: doc/classes/MultiMesh.xml msgid "Use when you are not using per-instance custom data." @@ -44543,12 +45924,16 @@ msgid "" "Emitted when this MultiplayerAPI's [member network_peer] successfully " "connected to a server. Only emitted on clients." msgstr "" +"Émis lorsque le [member network_peer] de ce MultijoueurAPI est connecté avec " +"succès à un serveur. Seulement émis aux clients." #: doc/classes/MultiplayerAPI.xml msgid "" "Emitted when this MultiplayerAPI's [member network_peer] fails to establish " "a connection to a server. Only emitted on clients." msgstr "" +"Émis lorsque le [member network_peer] de ce MultijoueurAPI ne parvient pas à " +"établir une connexion à un serveur. Seulement émis aux clients." #: doc/classes/MultiplayerAPI.xml msgid "" @@ -44557,6 +45942,11 @@ msgid "" "clients connect to the same server. Upon connecting to a server, a client " "also receives this signal for the server (with ID being 1)." msgstr "" +"Émis lorsque le [member network_peer] de ce MultiplayerAPI se connecte à un " +"nouveau pair. L'identifiant est celui du nouveau pair. Les clients sont " +"informés lorsque d'autres clients se connectent au même serveur. En se " +"connectant à un serveur, un client reçoit également ce signal pour le " +"serveur (avec identifiant étant à 1)." #: doc/classes/MultiplayerAPI.xml msgid "" @@ -44564,6 +45954,9 @@ msgid "" "peer. Clients get notified when other clients disconnect from the same " "server." msgstr "" +"Émis lorsque le [member network_peer] de ce MultiplayerAPI se déconnecte " +"d'un pair. Les clients sont informés lorsque d'autres clients se " +"déconnectent du même serveur." #: doc/classes/MultiplayerAPI.xml msgid "" @@ -44571,12 +45964,18 @@ msgid "" "[code]packet[/code] with custom data (see [method send_bytes]). ID is the " "peer ID of the peer that sent the packet." msgstr "" +"Émis lorsque le [member network_peer] de ce MultijoueurAPI reçoit un " +"[code]packet[/code] avec des données personnalisées (voir [method " +"send_bytes)]. L'identifiant est l'identifiant par les pairs de l'équipe qui " +"a envoyé le paquet." #: doc/classes/MultiplayerAPI.xml msgid "" "Emitted when this MultiplayerAPI's [member network_peer] disconnects from " "server. Only emitted on clients." msgstr "" +"Émis lorsque le [member network_peer] de ce MultijoueurAPI se déconnecte du " +"serveur. Seulement émis sur les clients." #: doc/classes/MultiplayerAPI.xml msgid "" @@ -44617,34 +46016,47 @@ msgid "" "[i]Deprecated.[/i] Use [constant RPC_MODE_PUPPET] instead. Analogous to the " "[code]slave[/code] keyword." msgstr "" +"[i]Obsolète.[/i] Utilisez plutôt [constant RPC_MODE_PUPPET]. Similaire au " +"mot-clé [code]slave[/code]." #: doc/classes/MultiplayerAPI.xml msgid "" "Behave like [constant RPC_MODE_REMOTE] but also make the call or property " "change locally. Analogous to the [code]remotesync[/code] keyword." msgstr "" +"Se comporte comme [constant RPC_MODE_REMOTE] mais fait aussi l'appel ou le " +"changement d'un propriété en local. Similaire au mot-clé " +"[code]remotesync[/code]." #: doc/classes/MultiplayerAPI.xml msgid "" "[i]Deprecated.[/i] Use [constant RPC_MODE_REMOTESYNC] instead. Analogous to " "the [code]sync[/code] keyword." msgstr "" +"[i]Obsolète.[/i] Utilisez plutôt [constant RPC_MODE_REMOTESYNC]. Similaire " +"au mot-clé [code]sync[/code]." #: doc/classes/MultiplayerAPI.xml msgid "" "Behave like [constant RPC_MODE_MASTER] but also make the call or property " "change locally. Analogous to the [code]mastersync[/code] keyword." msgstr "" +"Se comporte comme [constant RPC_MODE_MASTER] mais fait aussi l'appel ou le " +"changement d'une propriété en local. Similaire au mot-clé " +"[code]mastersync[/code]." #: doc/classes/MultiplayerAPI.xml msgid "" "Behave like [constant RPC_MODE_PUPPET] but also make the call or property " "change locally. Analogous to the [code]puppetsync[/code] keyword." msgstr "" +"Se comporte comme [constant RPC_MODE_PUPPET] mais fait aussi l'appel ou le " +"changement d'une propriété en local. Similaire au mot-clé " +"[code]puppetsync[/code]." #: doc/classes/Mutex.xml msgid "A synchronization mutex (mutual exclusion)." -msgstr "" +msgstr "Un mutex de synchronisation (exclusion mutuelle)." #: doc/classes/Mutex.xml msgid "" @@ -44761,6 +46173,9 @@ msgid "" "Returns the owner of the [NavigationMesh] which contains the navigation " "point closest to the point given. This is usually a [NavigationMeshInstance]." msgstr "" +"Retourne le propriétaire du [NavigationMesh] qui contient le point de " +"navigation le plus proche du point donné. C'est généralement une " +"[NavigationMeshInstance]." #: doc/classes/Navigation.xml msgid "" @@ -44771,9 +46186,8 @@ msgid "" msgstr "" #: doc/classes/Navigation.xml -#, fuzzy msgid "Returns the [RID] of the navigation map on the [NavigationServer]." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "" #: doc/classes/Navigation.xml msgid "" @@ -44785,6 +46199,13 @@ msgid "" "agent properties associated with each [NavigationMesh] (radius, height, " "etc.) are considered in the path calculation, otherwise they are ignored." msgstr "" +"[i]Obsolète.[/i] Le nÅ“ud [Navigation] la méthode [method get_simple_path] " +"sont obsolètes se seront retiré dans une prochaine version. Utilisez plutôt [" +"method NavigationServer.map_get_path].\n" +"Retourne le chemin entre deux points donnés. Les points sont des coordonées " +"locales. Si [code]optimize[/code] est [code]true[/code] (par défaut), les " +"propriétés de l'agent associées à chaque [NavigationMesh] (rayon, hauteur, " +"etc.) sont considérés dans le calcul du chemin, sinon ils sont ignorés." #: doc/classes/Navigation.xml msgid "The cell height to use for fields." @@ -44810,12 +46231,16 @@ msgid "" "Defines which direction is up. By default, this is [code](0, 1, 0)[/code], " "which is the world's \"up\" direction." msgstr "" +"Définit la direction. Par défaut, il s'agit de [code](0, 1, 0)[/code], qui " +"est la direction du haut (\"up\")." #: doc/classes/Navigation.xml doc/classes/Navigation2DServer.xml #: doc/classes/NavigationServer.xml msgid "" "Emitted when a navigation map is updated, when a region moves or is modified." msgstr "" +"Émis quand une carte de navigation est mise à jour, ou quand une région se " +"déplace ou est modifiée." #: doc/classes/Navigation2D.xml msgid "2D navigation and pathfinding node." @@ -44864,9 +46289,8 @@ msgid "" msgstr "" #: doc/classes/Navigation2DServer.xml -#, fuzzy msgid "Server interface for low-level 2D navigation access." -msgstr "Interface de serveur pour l'accès audio de bas niveau." +msgstr "" #: doc/classes/Navigation2DServer.xml #, fuzzy @@ -44904,16 +46328,16 @@ msgstr "" "de navigation. Ensemble, ces cartes définissent les aires navigables dans le " "monde 2D. Pour que deux régions soient connectées entre elles, elles doivent " "avoir une bordure en commun. Une bordure (\"edge\") est considérée connectée " -"à une autre si elles ont deux sommets rapprochés de moins de la distance " -"[member Navigation.edge_connection_margin].\n" +"à une autre si elles ont deux sommets rapprochés de moins de la distance [" +"member Navigation.edge_connection_margin].\n" "Pour utiliser le système d'évitement, vous devez utiliser des agents. Vous " "pouvez définir la vitesse cible d'un agent, puis le serveur émettra une " "méthode de rappel avec la vitesse modifiée.\n" "[b]Note :[/b] Le système d'évitement des collisions ignorent les régions. " "Utiliser la vitesse modifiée telle quelle peut déplacer un agent hors de la " -"surface de navigable. C'est une limite du système d'évitement des collision, " -"et certaines situations plus complexes peuvent nécessiter l'utilisation du " -"moteur physique.\n" +"surface de navigable. C'est une limite du système d'évitement des " +"collisions, et certaines situations plus complexes peuvent nécessiter " +"l'utilisation du moteur physique.\n" "Le serveur garde en mémoire tous les appels et les exécutent durant la phase " "de synchronisation. Cela veut dire que vous pouvez demander n'importe quel " "changement sur l'ensemble des cartes, via n'importe quel fil d'exécution, " @@ -44928,11 +46352,12 @@ msgid "" "Returns the navigation map [RID] the requested [code]agent[/code] is " "currently assigned to." msgstr "" +"Retourne le [RID] de la carte de navigation auquel le [code]agent[/code] " +"spécifié est actuellement assigné." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns [code]true[/code] if the map got changed the previous frame." -msgstr "Renvoie [code]true[/code] si le chemin donné est filtré." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -44958,11 +46383,13 @@ msgid "" "navigation. The larger this number, the longer the running time of the " "simulation. If the number is too low, the simulation will not be safe." msgstr "" +"Définit le nombre maximal d'autres agents que cet agent prend en compte dans " +"la navigation. Plus ce nombre est grand, plus la durée de la simulation est " +"longue. Si le nombre est trop bas, la simulation ne sera pas fiable." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the maximum speed of the agent. Must be positive." -msgstr "Obtient le nom d'un entrée par son index." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -44970,11 +46397,14 @@ msgid "" "the navigation. The larger this number, the longer the running time of the " "simulation. If the number is too low, the simulation will not be safe." msgstr "" +"Définit la distance maximale avec d'autres agents que cet agent prend en " +"compte dans la navigation. Plus ce nombre est grand, plus la durée de la " +"simulation est longue. Si le nombre est trop bas, la simulation ne sera pas " +"fiable." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the position of the agent in world space." -msgstr "Définit la position du nÅ“ud spécifié." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Sets the radius of the agent." @@ -44992,11 +46422,14 @@ msgid "" "agents, but the less freedom this agent has in choosing its velocities. Must " "be positive." msgstr "" +"La quantité minimale de temps pour laquelle les vitesses de l'agent " +"calculées par la simulation sont fiables pour les autres agents. Plus ce " +"nombre est grand, plus tôt cet agent répondra à la présence d'autres agents, " +"mais moins il aura de liberté pour choisir sa vitesse. Ça doit être positif." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the current velocity of the agent." -msgstr "Définit le trame présentement visible de l'animation." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Destroys the given RID." @@ -45008,6 +46441,9 @@ msgid "" "returns both 2D and 3D created navigation maps as there is technically no " "distinction between them." msgstr "" +"Retourne tous les [RID] des cartes de navigation créées sur le " +"NavigationServer. Cela renvoie les cartes de navigation 2D et aussi 3D car " +"il n'y a techniquement aucune distinction entre eux." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Create a new map." @@ -45041,19 +46477,47 @@ msgid "" "but it can also introduce bugs if used inappropriately without much " "foresight." msgstr "" +"Cette fonction force immédiatement la synchronisation de la navigation " +"spécifiée par le [RID] spécifié par [code]map[/code]. Par défaut, les cartes " +"de navigation ne sont synchronisées qu'à la fin de chaque trame physique. " +"Cette fonction peut être utilisée pour calculer immédiatement tous les " +"maillages de navigation et les connexions entre les régions de la carte de " +"navigation. Cela permet d'interroger un chemin de navigation pour une carte " +"modifiée immédiatement et dans la même trame (plusieurs fois si nécessaire)." +"\n" +"En raison de restrictions techniques, la file de commandes actuelle de " +"NavigationServer sera exécutée aussitôt. Cela signifie que toutes les " +"commandes de mise à jour en attente pour cette trame de physique seront " +"exécutées, même celles destinées à d'autres cartes, régions et agents qui ne " +"font pas partie de la carte spécifiée. Le calcul coûteux des maillages de " +"navigation et des connexions de régions d'une carte ne sera fait que pour la " +"carte spécifiée. D'autres cartes recevront la synchronisation normale à la " +"fin de la trame physique. Si la carte spécifiée reçoit des changements après " +"la mise à jour forcée, elle sera à nouveau mise à jour aussi bien lorsque " +"les autres cartes recevront leur mise à jour.\n" +"Le traitement d'évitement et l'envoi des signaux [code]safe_velocity[/code] " +"ne sont pas affectés par cette fonction et continuent de se produire pour " +"tous les cartes et agents à la fin de la trame physique.\n" +"[b]Note :[/b] Une grande pouvoir implique une grande responsabilité. Cette " +"fonction ne devrait être utilisée que par les utilisateurs qui savent " +"vraiment ce qu'ils font et ont une bonne raison de l'utiliser. Pour " +"effectuer une mise à jour immédiate d'une carte de navigation, il faut " +"verrouiller le NavigationServer et exécuter toute la file de commandes du " +"NavigationServer. Non seulement cela peut affecter sévèrement les " +"performances du jeu, mais il peut également introduire des bugs si ça n'est " +"pas fait avec le plus grand soin." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" "Returns all navigation agents [RID]s that are currently assigned to the " "requested navigation [code]map[/code]." msgstr "" +"Retourne tous [RID] des agents de navigation qui sont actuellement affectés " +"à la navigation [code]map[/code] spécifiée." #: doc/classes/Navigation2DServer.xml -#, fuzzy msgid "Returns the map cell height. [b]Note:[/b] Currently not implemented." msgstr "" -"Retourne l'actuelle ligne du fichier interprété (actuellement non " -"implémenté)." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Returns the map cell size." @@ -45072,12 +46536,16 @@ msgid "" "Returns the owner region RID for the point returned by [method " "map_get_closest_point]." msgstr "" +"Retourne la région propriétaire du RID pour le point retourné par [method " +"map_get_closest_point]." #: doc/classes/Navigation2DServer.xml msgid "" "Returns the edge connection margin of the map. The edge connection margin is " "a distance used to connect two regions." msgstr "" +"Retourne la marge de raccordement du bord de la carte. La marge de " +"raccordement est une distance utilisée pour relier deux régions." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -45085,38 +46553,42 @@ msgid "" "[code]navigation_layers[/code] is a bitmask of all region layers that are " "allowed to be in the path." msgstr "" +"Retourne le chemin de navigation pour atteindre la destination de l'origine. " +"[code]navigation_layers[/code] est un bitmask de toutes les calques de la " +"région qui sont autorisées à être dans le chemin." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" "Returns all navigation regions [RID]s that are currently assigned to the " "requested navigation [code]map[/code]." msgstr "" +"Retourne toutes les régions de navigation [RID] qui sont actuellement " +"affectées à la navigation demandée [code]map[/code]." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns [code]true[/code] if the map is active." -msgstr "Retourne [code]true[/code] si l'[AABB] est vide." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Sets the map active." msgstr "Définit la carte comme active." #: doc/classes/Navigation2DServer.xml -#, fuzzy msgid "" "Set the map cell height used to weld the navigation mesh polygons. [b]Note:[/" "b] Currently not implemented." -msgstr "Définit le polygone de navigation de la tuile." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Set the map cell size used to weld the navigation mesh polygons." -msgstr "Définit le polygone de navigation de la tuile." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" "Set the map edge connection margin used to weld the compatible region edges." msgstr "" +"Définit la marge de connexion de bord de la carte utilisée pour fusionner " +"les bords compatibles de la région." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Creates a new region." @@ -45128,6 +46600,8 @@ msgid "" "index between 0 and the return value of [method " "region_get_connections_count]." msgstr "" +"Retourne le point de fin d'une porte de connexion. [code]connection[/code] " +"est un indice entre 0 et la valeur de [method region_get_connections_count]." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -45135,33 +46609,36 @@ msgid "" "an index between 0 and the return value of [method " "region_get_connections_count]." msgstr "" +"Retourne le point de départ d'une porte de connexion. [code]connection[/code]" +" est un indice entre 0 et la valeur de [method region_get_connections_count]." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" "Returns how many connections this [code]region[/code] has with other regions " "in the map." msgstr "" +"Retourne le nombre de connexions ce [code]region[/code] a avec les autres " +"régions de la carte." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns the [code]enter_cost[/code] of this [code]region[/code]." -msgstr "Retourne [code]true[/code] si le [code]signal[/code] donné existe." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" "Returns the navigation map [RID] the requested [code]region[/code] is " "currently assigned to." msgstr "" +"Retourne le [RID] de la carte de navigation à laquelle la [code]region[/code]" +" spécifiée est actuellement assignée." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns the region's navigation layers." -msgstr "Retourne le maillage de navigation de l'élément." +msgstr "Retourne les calques de navigation de la région." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns the [code]travel_cost[/code] of this [code]region[/code]." -msgstr "Retourne [code]true[/code] si le [code]signal[/code] donné existe." +msgstr "" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -45179,41 +46656,49 @@ msgid "" "(which should be avoided in general) the result might not be what is " "expected." msgstr "" +"Retourne [code]true[/code] si la coordonnée [code]point[/code] global " +"appartient actuellement à la [code]region[/code] de la navigation. Dans ce " +"contexte, l'une des faces du polygone de maillages de navigation de la " +"région a une position possible à la distance la plus proche de ce point par " +"rapport à tous les autres maillages de navigation provenant d'autres régions " +"de navigation également enregistrées sur la carte de navigation de la région " +"donnée.\n" +"Si plusieurs maillages de navigation ont des positions à égale distance, la " +"région de navigation dont les polygones sont traités en premier sont " +"retournés. Les polygones sont traités dans l'ordre d'ajout des régions dans " +"le serveur de navigation.\n" +"[b]Note :[/b] Si les maillages de navigation provenant de différentes " +"régions de navigation se chevauchent (qui doivent être évités en général), " +"le résultat peut être inattendu." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the [code]enter_cost[/code] for this [code]region[/code]." msgstr "" -"Définit la [code]position[/code] du point avec l'identifiant [code]id[/code] " -"spécifié." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the map for the region." -msgstr "Retourne la hauteur du contenu." +msgstr "Définit la carte de la région." #: doc/classes/Navigation2DServer.xml msgid "" "Set the region's navigation layers. This allows selecting regions from a " "path request (when using [method Navigation2DServer.map_get_path])." msgstr "" +"Définit les calques de navigation de la région. Cela permet de sélectionner " +"les régions à partir d'une requête de chemin (en utilisant [method " +"Navigation2DServer.map_get_path])." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the navigation mesh for the region." -msgstr "Définit le polygone de navigation de la tuile." +msgstr "Définit le polygone de navigation de la région." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the global transformation for the region." -msgstr "Retourne la matrice de transformation globale de cet élément." +msgstr "Retourne la transformation globale de cette région." #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml -#, fuzzy msgid "Sets the [code]travel_cost[/code] for this [code]region[/code]." msgstr "" -"Définit la [code]position[/code] du point avec l'identifiant [code]id[/code] " -"spécifié." #: doc/classes/NavigationAgent.xml msgid "3D agent used in navigation for collision avoidance." @@ -45235,6 +46720,21 @@ msgid "" "position from this function should be used as the next movement position for " "the agent's parent Node." msgstr "" +"Agent 3D utilisé dans la navigation pour atteindre un emplacement tout en " +"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont " +"évités en utilisant la méthode RVO (Reciprocal Velocity Obstacles). L'agent " +"a besoin de données de navigation pour fonctionner correctement. Par défaut " +"ce nÅ“ud s'enregistrera à la carte de navigation par défaut du [World]. Si ce " +"nÅ“ud est un enfant d'un nÅ“ud [Navigation] il s'inscrira à la carte de " +"navigation du nÅ“ud de navigation ou la fonction [method set_navigation] peut " +"être utilisée pour définir le nÅ“ud de navigation directement. " +"[NavigationAgent] est sûr lors du traitement physique.\n" +"[b]Note :[/b] Après que [method set_target_location] est utilisé, il est " +"nécessaire d'utiliser la fonction [method get_next_location] une fois par " +"trame physique pour mettre à jour la logique de chemin interne du " +"NavigationAgent. La position vectorielle retournée de cette fonction devrait " +"être utilisée comme position de mouvement suivante pour le Node parent de " +"l'agent principal." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45242,6 +46742,9 @@ msgid "" "position. The user must set the target location with [method " "set_target_location] in order for this to be accurate." msgstr "" +"Retourne la distance jusqu'à l'emplacement cible, en utilisant la position " +"globale de l'agent observé. L'utilisateur doit définir l'emplacement de la " +"cible avec [method set_target_location] afin d'être précis." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45249,6 +46752,9 @@ msgid "" "if the navigation path is altered in any way. Because of this, it would be " "best to check this each frame." msgstr "" +"Retourne l'emplacement final accessible dans les coordonnées globales. Cela " +"peut changer si le chemin de navigation est modifié de quelque manière que " +"ce soit. Pour cette raison, il serait préférable de vérifier chaque trame." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45261,6 +46767,15 @@ msgid "" "for the agents movement as this function also updates the internal path " "logic." msgstr "" +"Retourne le chemin actuel de l'agent du début jusqu'à la fin, dans les " +"coordonnées globales. Le chemin ne met à jour que lorsque l'emplacement de " +"la cible est modifié ou que l'agent demande un re-calcul du chemin. Le " +"réseau de chemin n'est pas destiné à être utilisé dans le mouvement de " +"chemin direct car l'agent a sa propre logique de chemin interne qui serait " +"corrompu en changeant le réseau de chemin manuellement. Utilisez la [method " +"get_next_location] voulue une fois chaque trame de physique pour recevoir le " +"point de chemin suivant pour le mouvement des agents car cette fonction met " +"également à jour la logique du chemin interne." #: doc/classes/NavigationAgent.xml msgid "" @@ -45273,6 +46788,8 @@ msgid "" "Returns the [Navigation] node that the agent is using for its navigation " "system." msgstr "" +"Retourne le nÅ“ud [Navigation] que l'agent utilise pour son système de " +"navigation." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45284,6 +46801,14 @@ msgid "" "the navigation map for the NavigationAgent and also update the agent on the " "NavigationServer." msgstr "" +"Retourne le [RID] de la carte de navigation pour ce nÅ“ud NavigationAgent. " +"Cette fonction retourne toujours la carte définie sur le nÅ“ud " +"NavigationAgent et non la carte de l'agent abstrait sur le serveur " +"Navigation. Si la carte de l'agent est changée directement avec l'API de " +"NavigationServer, le nÅ“ud NavigationAgent ne sera pas au courant du " +"changement de carte. Utilisez [method set_navigation_map] pour changer la " +"carte de navigation pour le NavigationAgent et mettre à jour l'agent sur le " +"NavigationServer." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45293,25 +46818,28 @@ msgid "" "use of this function once every physics frame is required to update the " "internal path logic of the NavigationAgent." msgstr "" +"Retourne l'emplacement suivant dans les coordonnées globales qui peuvent " +"être déplacées, en s'assurant qu'il n'y a pas d'objets statiques dans le " +"chemin. Si l'agent n'a pas de chemin de navigation, il retourne la position " +"du parent de l'agent. L'utilisation de cette fonction une fois chaque trame " +"physique est nécessaire pour mettre à jour la logique de chemin interne de " +"la NavigationAgent." #: doc/classes/NavigationAgent.xml -#, fuzzy msgid "Returns the [RID] of this agent on the [NavigationServer]." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "Retourne le [RID] de cet agent dans le [NavigationServer]." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "" "Returns the user-defined target location (set with [method " "set_target_location])." -msgstr "Renvoie le mode de remplacement de l’espace pour la zone." +msgstr "" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the navigation path's final location has been " "reached." -msgstr "Renvoie [code]true[/code] si le chemin donné est filtré." +msgstr "" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45334,18 +46862,25 @@ msgid "" "Sets the [Navigation] node used by the agent. Useful when you don't want to " "make the agent a child of a [Navigation] node." msgstr "" +"Définit le nÅ“ud [Navigation] utilisé par l'agent. Utile lorsque vous ne " +"voulez pas faire de l'agent un enfant d'un nÅ“ud [Navigation]." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" "Sets the [RID] of the navigation map this NavigationAgent node should use " "and also updates the [code]agent[/code] on the NavigationServer." msgstr "" +"Définit le [RID] de la carte de navigation que ce nÅ“ud NavigationAgent " +"devrait utiliser et met à jour le [code]agent[/code] sur le serveur de " +"navigation." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" "Sets the user desired final location. This will clear the current navigation " "path." msgstr "" +"Définit l'emplacement final souhaité de l'utilisateur. Cela permettra " +"d'effacer le chemin de navigation actuel." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45353,6 +46888,9 @@ msgid "" "adjust the velocity to avoid collisions. Once the adjustment to the velocity " "is complete, it will emit the [signal velocity_computed] signal." msgstr "" +"Envoie la vitesse spécifiée à l'algorithme d'évitement de collision. Celui-" +"ci ajustera la vitesse pour éviter les collisions. Une fois le réglage de la " +"vitesse terminée, il émettra le signal [signal velocity_computed]." #: doc/classes/NavigationAgent.xml msgid "" @@ -45363,6 +46901,14 @@ msgid "" "that the developer baked with appropriate agent radius or height values are " "required to support different-sized agents." msgstr "" +"La hauteur du NavigationAgent est soustraite de la valeur de l'axe Y de " +"toute position de chemin vectoriel pour ce NavigationAgent. Le décalage de " +"hauteur du NavigationAgent ne change pas ou n'influence pas le résultat de " +"la requête du maillage de navigation ou du cheminement. Des cartes de " +"navigation supplémentaires qui utilisent des régions avec des maillages de " +"navigation que le développeur a pré-calculé avec un rayon d'agent approprié " +"ou des valeurs de hauteur sont nécessaires pour supporter des agents de " +"taille différente." #: doc/classes/NavigationAgent.xml msgid "" @@ -45373,22 +46919,29 @@ msgid "" "with many registered agents has a significant performance cost and should " "only be enabled on agents that currently require it." msgstr "" +"Si [code]true[/code] l'agent est enregistré pour un rappel d'évitement RVO " +"sur le [NavigationServer]. Lorsque [method set_velocity] est utilisé et que " +"le traitement est terminé, un Vector3 [code]safe_velocity[/code] est reçu " +"avec une connexion du signal [signal velocity_computed]. Le traitement de " +"l'évitement avec de nombreux agents enregistrés a un coût de performance " +"important et ne devrait être activé que pour les agents qui en ont " +"actuellement besoin." #: doc/classes/NavigationAgent.xml msgid "" "Ignores collisions on the Y axis. Must be [code]true[/code] to move on a " "horizontal plane." msgstr "" +"Ignore les collisions sur l'axe Y. Doit être [code]true[/code] pour se " +"déplacer sur un plan horizontal." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "The maximum number of neighbors for the agent to consider." -msgstr "La valeur de luminance maximale pour l'exposition automatique." +msgstr "" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "The maximum speed that an agent can move." -msgstr "Rotation maximale à travers la charnière." +msgstr "La vitesse maximale à laquelle un agent peut se déplacer." #: doc/classes/NavigationAgent.xml msgid "" @@ -45396,11 +46949,14 @@ msgid "" "belongs to. On path requests the agent will ignore navmeshes without at " "least one matching layer." msgstr "" +"Un masque de bit déterminant toutes les calque de carte de navigation " +"auxquels ce [NavigationAgent] appartient. Lors de requête de chemin, l'agent " +"va ignorer les maillages de navigation qui n'ont pas au moins un calque " +"correspondant." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "The distance to search for other agents." -msgstr "L’instance n’a pas de type." +msgstr "" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45412,6 +46968,14 @@ msgid "" "it will constantly overshoot or undershoot the distance to the next point on " "each physics frame update." msgstr "" +"Le seuil de distance avant qu'un point de chemin soit considéré comme " +"atteint. Cela permettra à un agent de ne pas avoir à atteindre un point de " +"chemin exactement sur le chemin, mais uniquement un zone autour. Si cette " +"valeur est élevée, la NavigationAgent sautera des points sur le chemin qui " +"peut conduire à quitter le maillage de navigation. Si cette valeur est trop " +"faible, le NavigationAgent sera coincé dans une boucle de chemin parce qu'il " +"va constamment mal estimer la distance jusqu'au point suivant à chaque mise " +"à jour de la trame physique." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45419,6 +46983,9 @@ msgid "" "final location. This can happen due to trying to avoid collisions. When the " "maximum distance is exceeded, it recalculates the ideal path." msgstr "" +"La distance maximale de l'agent est permise loin du chemin idéal jusqu'à " +"l'emplacement final. Cela peut arriver en essayant d'éviter les collisions. " +"Lorsque la distance maximale est dépassée, cela recalcule le chemin idéal." #: doc/classes/NavigationAgent.xml msgid "" @@ -45429,6 +46996,13 @@ msgid "" "bake [NavigationMesh] resources with a different [member NavigationMesh." "agent_radius] property and use different navigation maps for each actor size." msgstr "" +"Le rayon d'évitement de l'agent. Il s'agit du « corps » de l'agent " +"d'évitement et non le rayon de la manÅ“uvre d'évitement (qui est contrôlé par " +"[member neighbor_dist)].\n" +"N'affecte pas le cheminement normal. Pour changer les ressources " +"[NavigationMesh] de rayon de pré-calcul de cheminement d'un acteur avec la " +"propriété [member NavigationMesh.agent_radius] différente et utiliser " +"différentes cartes de navigation pour chaque acteur." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45439,6 +47013,12 @@ msgid "" "overshoot or undershoot the distance to the final target point on each " "physics frame update." msgstr "" +"Le seuil de distance avant qu'un point de chemin soit considéré comme " +"atteint. Cela permettra à un agent de ne pas avoir à atteindre un point de " +"chemin exactement sur le chemin, mais uniquement un zone autour. Si cette " +"valeur est trop faible, le NavigationAgent sera coincé dans une boucle de " +"chemin parce qu'il va constamment mal estimer la distance jusqu'au point " +"suivant à chaque mise à jour de la trame physique." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45448,29 +47028,39 @@ msgid "" "other agents, but the less freedom in choosing its velocities. Must be " "positive." msgstr "" +"La quantité minimale de temps pour laquelle les vitesses de cet agent, " +"calculées avec l'algorithme d'évitement de collision, sont sûres pour les " +"autres agents. Plus le nombre est élevé, plus tôt l'agent répondra à " +"d'autres agents, mais moins il aura la liberté de choisir sa vitesse. Ça " +"doit être positif." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "Notifies when the final location is reached." -msgstr "Avertit quand une animation commence à jouer." +msgstr "" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" "Notifies when the navigation path changes. This can be triggered by the " "navigation system or by the user changing the path." msgstr "" +"Notifie quand le chemin de navigation change. Cela peut être déclenché par " +"le système de navigation ou par l'utilisateur qui change le chemin." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" "Notifies when the player-defined target, set with [method " "set_target_location], is reached." msgstr "" +"Notifie quand la cible définie par le joueur, définie avec [method " +"set_target_location], est atteinte." #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" "Notifies when the collision avoidance velocity is calculated after a call to " "[method set_velocity]." msgstr "" +"Notifie quand la vitesse d'évitement de collision est calculée après un " +"appel à [method set_velocity]." #: doc/classes/NavigationAgent2D.xml msgid "2D agent used in navigation for collision avoidance." @@ -45492,6 +47082,21 @@ msgid "" "position from this function should be used as the next movement position for " "the agent's parent Node." msgstr "" +"L'agent 2D utilisé dans la navigation pour atteindre un emplacement tout en " +"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont " +"évités en utilisant l'évitement de collision RVO (Reciprocal Velocity " +"Obstacles). L'agent a besoin de données de navigation pour fonctionner " +"correctement. Par défaut ce nÅ“ud s'enregistrera à la carte de navigation par " +"défaut du [World2D]. Si ce nÅ“ud est un enfant d'un nÅ“ud [Navigation2D] il " +"s'inscrira à la carte de navigation du nÅ“ud de navigation ou la fonction " +"[method set_navigation] peut être utilisé pour définir le nÅ“ud de navigation " +"directement. [NavigationAgent2D] est sûr lors des trames physiques.\n" +"[b]Note :[/b] Après que [method set_target_location] est utilisé, il est " +"nécessaire d'utiliser la fonction [method get_next_location] une fois chaque " +"trame physique pour mettre à jour la logique interne de chemin du " +"NavigationAgent. La position vectorielle retournée de cette fonction devrait " +"être utilisée comme position de mouvement suivante pour le Node parent de " +"l'agent principal." #: doc/classes/NavigationAgent2D.xml msgid "" @@ -45504,17 +47109,20 @@ msgid "" "Returns the [Navigation2D] node that the agent is using for its navigation " "system." msgstr "" +"Retourne le nÅ“ud [Navigation2D] que l'agent utilise pour son système de " +"navigation." #: doc/classes/NavigationAgent2D.xml -#, fuzzy msgid "Returns the [RID] of this agent on the [Navigation2DServer]." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "Retourne le [RID] de cet agent dans le [Navigation2DServer]." #: doc/classes/NavigationAgent2D.xml msgid "" "Sets the [Navigation2D] node used by the agent. Useful when you don't want " "to make the agent a child of a [Navigation2D] node." msgstr "" +"Définit le nÅ“ud [Navigation2D] utilisé par l'agent. Utile lorsque vous ne " +"voulez pas faire de l'agent un enfant d'un nÅ“ud [Navigation2D]." #: doc/classes/NavigationAgent2D.xml msgid "" @@ -45525,6 +47133,13 @@ msgid "" "with many registered agents has a significant performance cost and should " "only be enabled on agents that currently require it." msgstr "" +"Si [code]true[/code] l'agent est enregistré pour un rappel d'évitement RVO " +"sur le [Navigation2DServer]. Lorsque [method set_velocity] est utilisé et " +"que le traitement est terminé, un Vector2 [code]safe_velocity[/code] est " +"reçu avec une connexion au signal [signal velocity_computed]. Le traitement " +"de l'évitement avec de nombreux agents enregistrés a un coût de performance " +"important et ne devrait être activé que pour les agents qui en ont " +"actuellement besoin." #: doc/classes/NavigationAgent2D.xml msgid "" @@ -45532,6 +47147,10 @@ msgid "" "belongs to. On path requests the agent will ignore navmeshes without at " "least one matching layer." msgstr "" +"Un masque de bit déterminant toutes les calque de carte de navigation " +"auxquels ce [NavigationAgent2D] appartient. Lors de requête de chemin, " +"l'agent va ignorer les maillages de navigation qui n'ont pas au moins un " +"calque correspondant." #: doc/classes/NavigationAgent2D.xml msgid "" @@ -45540,6 +47159,10 @@ msgid "" "[member neighbor_dist]).\n" "Does not affect normal pathfinding." msgstr "" +"Le rayon d'évitement de l'agent. Il s'agit du « corps » de l'agent " +"d'évitement et non le rayon de la manÅ“uvre d'évitement (qui est contrôlé par " +"[member neighbor_dist)].\n" +"N'affecte pas le cheminement normal." #: doc/classes/NavigationMesh.xml msgid "A mesh to approximate the walkable areas and obstacles." @@ -45571,11 +47194,10 @@ msgid "" msgstr "" #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "" "Returns whether the specified [code]bit[/code] of the [member " "geometry_collision_mask] is set." -msgstr "Retourne si la [code]class[/code] spécifiée est disponible ou non." +msgstr "" #: doc/classes/NavigationMesh.xml doc/classes/NavigationPolygon.xml msgid "" @@ -45586,9 +47208,8 @@ msgstr "" "créé." #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "Returns the number of polygons in the navigation mesh." -msgstr "Renvoie le nombre de points sur l'axe de mélange." +msgstr "" #: doc/classes/NavigationMesh.xml msgid "" @@ -45599,17 +47220,16 @@ msgstr "" "créé." #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "" "If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/" "code] in the [member geometry_collision_mask].\n" "If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/" "code] in the [member geometry_collision_mask]." msgstr "" -"Si [code]value[/code] est [code]true[/code]], définit le [code]bit[/code] " -"spécifié dans le masque [nom collision_mask].\n" -"Si [code]value[/code] est [code]false[/code], rétablit le [code]bit[/code] " -"spécifié dans le masque [nom collision_mask]." +"Si [code]value[/code] est [code]true[/code], définit le [code]bit[/code] " +"spécifié dans le masque [member geometry_collision_mask].\n" +"Si [code]value[/code] est [code]false[/code], efface le [code]bit[/code] " +"spécifié dans le masque [member geometry_collision_mask]." #: doc/classes/NavigationMesh.xml doc/classes/NavigationPolygon.xml msgid "" @@ -45633,9 +47253,8 @@ msgid "" msgstr "" #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "The maximum slope that is considered walkable, in degrees." -msgstr "Rotation maximale à travers la charnière." +msgstr "" #: doc/classes/NavigationMesh.xml msgid "" @@ -45684,9 +47303,8 @@ msgid "The position offset applied to the [member filter_baking_aabb] [AABB]." msgstr "" #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "If [code]true[/code], marks spans that are ledges as non-walkable." -msgstr "Si [code]true[/code], les titres des colonnes sont visibles." +msgstr "" #: doc/classes/NavigationMesh.xml msgid "" @@ -45695,13 +47313,10 @@ msgid "" msgstr "" #: doc/classes/NavigationMesh.xml -#, fuzzy msgid "" "If [code]true[/code], marks walkable spans as not walkable if the clearance " "above the span is less than [member agent_height]." msgstr "" -"Si [code]true[/code], les particules sera émise une seule fois puis " -"arrêtées. Équivalent à [member Particles.one_shot]." #: doc/classes/NavigationMesh.xml msgid "" @@ -45709,12 +47324,17 @@ msgid "" "Only used when [member geometry_parsed_geometry_type] is [constant " "PARSED_GEOMETRY_STATIC_COLLIDERS] or [constant PARSED_GEOMETRY_BOTH]." msgstr "" +"Les calques de physique pour scanner les collisions statiques.\n" +"Seulement utilisé quand [member geometry_parsed_geometry_type] est [constant " +"PARSED_GEOMETRY_STATIC_COLLIDERS] ou [constant] PARSED_GEOMETRY_BOTH]." #: doc/classes/NavigationMesh.xml msgid "" "Determines which type of nodes will be parsed as geometry. See [enum " "ParsedGeometryType] for possible values." msgstr "" +"Détermine quel type de nÅ“uds seront interprétés comme géométrie. Voir [enum " +"ParsedGeometryType] pour les valeurs possibles." #: doc/classes/NavigationMesh.xml msgid "" @@ -45729,12 +47349,18 @@ msgid "" "SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] or [constant " "SOURCE_GEOMETRY_GROUPS_EXPLICIT]." msgstr "" +"Le nom du groupe pour scanner la géométrie.\n" +"Seulement utilisé lorsque [member geometry_source_geometry_mode] est " +"[constant SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] ou [constant] " +"SOURCE_GEOMETRY_GROUPS_EXPLICIT]." #: doc/classes/NavigationMesh.xml msgid "" "The maximum number of vertices allowed for polygons generated during the " "contour to polygon conversion process." msgstr "" +"Le nombre maximal de sommets permis pour les polygones générés pendant le " +"contour du processus de conversion en polygones." #: doc/classes/NavigationMesh.xml msgid "" @@ -45743,6 +47369,10 @@ msgid "" "[b]Note:[/b] This value will be squared to calculate the number of cells. " "For example, a value of 20 will set the number of cells to 400." msgstr "" +"Toutes les régions ayant une taille inférieure à celle-ci seront fusionnées " +"avec des régions plus grandes si possible.\n" +"[b]Note :[/b] Cette valeur sera carrée pour calculer le nombre de cellules. " +"Par exemple, une valeur de 20 définira le nombre de cellules à 400." #: doc/classes/NavigationMesh.xml msgid "" @@ -45751,12 +47381,18 @@ msgid "" "cells allowed to form isolated island areas. For example, a value of 8 will " "set the number of cells to 64." msgstr "" +"La taille minimale d'une région pour qu'elle soit créée.\n" +"[b]Note :[/b] Cette valeur sera fixée pour calculer le nombre minimum de " +"cellules autorisées à former des zones insulaires isolées. Par exemple, une " +"valeur de 8 définira le nombre de cellules à 64." #: doc/classes/NavigationMesh.xml msgid "" "Partitioning algorithm for creating the navigation mesh polys. See [enum " "SamplePartitionType] for possible values." msgstr "" +"Algorithme de partitionnement pour la création des polygones de maillage de " +"navigation. Voir [enum SamplePartitionType] pour les valeurs possibles." #: doc/classes/NavigationMesh.xml msgid "" @@ -45768,12 +47404,16 @@ msgstr "" msgid "" "Monotone partitioning. Use this if you want fast navigation mesh generation." msgstr "" +"Partage monotone. Utilisez ceci si vous voulez une génération de maillages " +"de navigation rapide." #: doc/classes/NavigationMesh.xml msgid "" "Layer partitioning. Good choice to use for tiled navigation mesh with medium " "and small sized tiles." msgstr "" +"Le partitionnement du calque. Un bon choix à utiliser pour la maillage de " +"navigation en carreaux de taille moyenne et petite." #: doc/classes/NavigationMesh.xml msgid "Represents the size of the [enum SamplePartitionType] enum." @@ -45792,6 +47432,9 @@ msgid "" "Parses [StaticBody] colliders as geometry. The collider should be in any of " "the layers specified by [member geometry_collision_mask]." msgstr "" +"Interprète l'élément de collision [StaticBody] comme géométrie. Cet élément " +"doit être dans l'un des calques spécifiés par [member " +"geometry_collision_mask]." #: doc/classes/NavigationMesh.xml msgid "" @@ -45809,18 +47452,24 @@ msgstr "Représente la taille de l’enum [enum ParsedGeometryType]." msgid "" "Scans the child nodes of [NavigationMeshInstance] recursively for geometry." msgstr "" +"Scanne les nÅ“uds d'enfants de [NavigationMeshInstance] récursivement pour la " +"géométrie." #: doc/classes/NavigationMesh.xml msgid "" "Scans nodes in a group and their child nodes recursively for geometry. The " "group is specified by [member geometry_source_group_name]." msgstr "" +"Scanne les nÅ“uds dans un groupe et leurs nÅ“uds enfants récursivement pour la " +"géométrie. Le groupe est spécifié par [member geometry_source_group_name]." #: doc/classes/NavigationMesh.xml msgid "" "Uses nodes in a group for geometry. The group is specified by [member " "geometry_source_group_name]." msgstr "" +"Utilise des nÅ“uds dans un groupe de géométrie. Le groupe est spécifié par " +"[member geometry_source_group_name]." #: doc/classes/NavigationMesh.xml msgid "Represents the size of the [enum SourceGeometryMode] enum." @@ -45829,6 +47478,7 @@ msgstr "Représente la taille de l'énumération [enum SourceGeometryMode]." #: doc/classes/NavigationMeshGenerator.xml msgid "Helper class for creating and clearing navigation meshes." msgstr "" +"Classe d'aide pour la création et la suppression des maillages de navigation." #: doc/classes/NavigationMeshGenerator.xml msgid "" @@ -45871,6 +47521,52 @@ msgid "" "inside, the baking will generate navigation mesh areas that are inside the " "obstructing source geometry mesh." msgstr "" +"Cette classe est responsable de la création et du la suppression des " +"maillages de navigation 3D utilisés comme [NavigationMesh] ressources à " +"l'intérieur des [NavigationMeshInstance]. Le [NavigationMeshGenerator] est " +"très limité voire n'a aucune utilisation pour 2D car le processus de " +"navigation de pré-calcule de maillages s'attend à des types de nÅ“uds 3D et " +"la géométrie source en 3D.\n" +"L'ensemble du pré-calcule de maillages de navigation est préférable dans un " +"autre fil d'exécution puisque les étapes de voxelisation, de collision et " +"d'optimisation de maillages impliquées sont des opérations, sont très " +"couteuses en temps processeur.\n" +"Le pré-calcule de maillage de navigation se produit en plusieurs étapes et " +"le résultat dépend de la géométrie source 3D et des propriétés de la " +"ressource [NavigationMesh]. Dans la première étape, à partir d'un nÅ“ud " +"racine et selon les propriétés [NavigationMesh], tous les nÅ“uds de géométrie " +"de source 3D valides sont collectés à partir du [SceneTree]. Deuxièmement, " +"tous les nÅ“uds collectés sont interprétés pour obtenir les données de " +"géométrie 3D pertinentes et un maillage 3D combiné est construit. En raison " +"des différents types d'objets à interpréter, des [MeshInstance] normaux aux " +"[CSGShape] ou divers [CollisionObject], certaines opérations de collecte de " +"données de géométrie peuvent déclencher des synchronisations du " +"[VisualServer] et du [PhysicsServer]. La synchronisation du serveur peut " +"avoir un effet négatif sur le temps de pré-calcule car elle implique souvent " +"le verrouillage de [Mutex] dans le fil d'exécution. De nombreux objets à " +"interpréter et de nombreuses synchronisations des serveurs peuvent augmenter " +"considérablement le temps de pré-calcule. D'un autre côté, seulement " +"quelques objets, mais très grands et complexes, prendront du temps de " +"préparation des serveurs ce qui peuvent bloquer le rendu suivant. De règle " +"générale, la quantité totale d'objets à interpréter, leur taille et leur " +"complexité individuelles devraient être équilibrées pour éviter les " +"problèmes de fluidité ou des temps de pré-calcule très longs. Le maillage " +"combiné est ensuite transmis à l'Object Recast Navigation pour tester la " +"géométrie source pour le terrain à parcourir adapté aux propriétés des " +"agents [NavigationMesh] en créant un monde de voxel autour de la zone de " +"maillage.\n" +"Le maillage de navigation finalisé est ensuite retourné et enregistré à " +"l'intérieur du [NavigationMesh] pour être utilisé comme ressource à " +"l'intérieur des nÅ“uds [NavigationMeshInstance].\n" +"[b]Note :[/b] L'utilisation de maillages ne définissen pas seulement les " +"surfaces à parcourir mais peut aussi empêcher le pré-calcul de fonctionner. " +"La navigation n'a pas de concept de ce qu'est une géométrie \"à " +"l'intérieur\" quand on traite de la géométrie de source de maillage et c'est " +"intentionnel. Selon les paramètres de pré-calcule actuels, dès que le " +"maillage obstructif est assez grande pour s'adapter à une zone de maillage " +"de navigation à l'intérieur, le pré-calcule générera des zones de maillage " +"de navigation qui sont à l'intérieur du maillage de géométrie de source " +"obstructif." #: doc/classes/NavigationMeshGenerator.xml msgid "" @@ -45881,13 +47577,18 @@ msgid "" "NavigationMesh.geometry_source_geometry_mode] properties on the " "[NavigationMesh] resource." msgstr "" +"Pré-calcule les données de navigation du [code]nav_mesh[/code] donné en " +"interprétant les nÅ“uds enfants dans le [code]root_node[/code] spécifié ou un " +"groupe spécifique de nÅ“uds pour la géométrie de source potentielle. Le " +"comportement d'interprétation peut être contrôlé avec les propriétés [member " +"NavigationMesh.geometry_parsed_geometry_type] et [member NavigationMesh." +"geometry_source_geometry_mode] de la ressource [NavigationMesh]." #: doc/classes/NavigationMeshGenerator.xml -#, fuzzy msgid "" "Removes all polygons and vertices from the provided [code]nav_mesh[/code] " "resource." -msgstr "Supprime l’animation avec la touche [code]name[/code]." +msgstr "" #: doc/classes/NavigationMeshInstance.xml msgid "An instance of a [NavigationMesh]." @@ -45907,11 +47608,29 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." msgstr "" +"Une instance de [NavigationMesh]. Il signale au nÅ“ud [Navigation] ce qui " +"peut être navigué et ce qui ne peut pas, basé sur la ressource " +"[NavigationMesh].\n" +"Par défaut ce nÅ“ud s'enregistrera à la carte de navigation du [World] par " +"défaut. Si ce nÅ“ud est un enfant d'un nÅ“ud [Navigation], il s'inscrira à la " +"carte de navigation du nÅ“ud de navigation.\n" +"Deux régions peuvent être reliées l'une à l'autre si elles partagent un même " +"bord. Vous pouvez définir la distance minimale entre deux sommets " +"nécessaires pour connecter deux bords en utilisant [method NavigationServer." +"map_set_edge_connection_margin]\n" +"[b]Note :[/b] Le chevauchement de deux régions n'est pas suffisant pour " +"relier deux régions. Ils doivent partager un même bord.\n" +"Le coût d'entrée dans cette région d'une autre région peut être contrôlé " +"avec la valeur [member enter_cost].\n" +"[b]Note :[/b] Cette valeur n'est pas ajoutée au coût du chemin lorsque la " +"position de départ est déjà dans cette région.\n" +"Le coût des distances de voyage dans cette région peut être contrôlé avec le " +"multiplicateur [member travel_cost]." #: doc/classes/NavigationMeshInstance.xml msgid "" @@ -45925,6 +47644,18 @@ msgid "" "operating systems that cannot use threads (such as HTML5 with threads " "disabled)." msgstr "" +"Pré-calcule le [NavigationMesh]. Si [code]on_thread[/code] est défini à " +"[code]true[/code] (par défaut), le pré-calcul est fait sur un fil " +"d'exécution séparé. Le pré-calcul sur un fil d'exécution séparé est utile " +"parce que la navigation est une opération relativement coûteuse. Lorsqu'il " +"est terminé, il définit automatiquement ce nouveau [NavigationMesh]. " +"Veuillez noter que le pré-calcul sur le fil d'exécution séparé peut être " +"très lent si la géométrie est composée de plein de maillages puisque l'accès " +"asynchrone à chaque maillage nécessite une lourde synchronisation. De plus, " +"veuillez noter que le pré-calculs sur un fil d'exécution séparé est " +"automatiquement désactivée sur les systèmes d'exploitation qui ne peuvent " +"pas utiliser des fils d'exécution (comme HTML5 si cette fonction est " +"désactivée)." #: doc/classes/NavigationMeshInstance.xml msgid "" @@ -45933,6 +47664,10 @@ msgid "" "identify the [NavigationMeshInstance] closest to a point on the merged " "navigation map." msgstr "" +"Retourne le [RID] de cette région sur [NavigationServer]. Combiné avec [" +"method NavigationServer.map_get_closest_point_owner], peut être utilisé pour " +"identifier le [NavigationMeshInstance] le plus proche d'un point d'une carte " +"de navigation fusionnée." #: doc/classes/NavigationMeshInstance.xml msgid "Determines if the [NavigationMeshInstance] is enabled or disabled." @@ -45965,11 +47700,13 @@ msgid "" "are multiplied with [code]travel_cost[/code] for determining the shortest " "path." msgstr "" +"Lorsque le cheminement se déplace à l'intérieur de cette région, les " +"distances parcourues sont multipliées par [code]travel_cost[/code] pour " +"déterminer le chemin le plus court." #: doc/classes/NavigationMeshInstance.xml -#, fuzzy msgid "Notifies when the navigation mesh bake operation is completed." -msgstr "Avertit quand une animation commence à jouer." +msgstr "" #: doc/classes/NavigationMeshInstance.xml msgid "Notifies when the [NavigationMesh] has changed." @@ -45988,12 +47725,22 @@ msgid "" "[b]Note:[/b] Obstacles are intended as a last resort option for constantly " "moving objects that cannot be (re)baked to a navigation mesh efficiently." msgstr "" +"Obstacle 3D utilisé dans la navigation pour éviter les collisions. " +"L'obstacle a besoin de données de navigation pour fonctionner correctement. " +"Cela peut être fait avec l'obstacle comme enfant d'un nÅ“ud [Navigation], ou " +"en utilisant [method set_navigation]. [NavigationObstacle] est sûr lors des " +"trames physiques.\n" +"[b]Note :[/b] Les obstacles sont conçus comme dernière option pour les " +"objets constamment mobiles qui ne peuvent pas être pré-calculés efficacement " +"dans un maillage de navigation." #: doc/classes/NavigationObstacle.xml msgid "" "Returns the [Navigation] node that the obstacle is using for its navigation " "system." msgstr "" +"Retourne le nÅ“ud [Navigation] que l'obstacle utilise pour son système de " +"navigation." #: doc/classes/NavigationObstacle.xml msgid "Returns the [RID] of this obstacle on the [NavigationServer]." @@ -46004,18 +47751,24 @@ msgid "" "Sets the [Navigation] node used by the obstacle. Useful when you don't want " "to make the obstacle a child of a [Navigation] node." msgstr "" +"Définit le nÅ“ud [Navigation] utilisé par l'obstacle. Utile lorsque vous ne " +"voulez pas faire l'obstacle un enfant d'un nÅ“ud [Navigation]." #: doc/classes/NavigationObstacle.xml doc/classes/NavigationObstacle2D.xml msgid "" "Enables radius estimation algorithm which uses parent's collision shapes to " "determine the obstacle radius." msgstr "" +"Active l'algorithme d'estimation de rayon qui utilise les formes de " +"collision des parents pour déterminer le rayon des obstacles." #: doc/classes/NavigationObstacle.xml doc/classes/NavigationObstacle2D.xml msgid "" "The radius of the agent. Used only if [member estimate_radius] is set to " "[code]false[/code]." msgstr "" +"Le rayon de l'agent. Utilisé uniquement si [member estimate_radius] est " +"[code]false[/code]." #: doc/classes/NavigationObstacle2D.xml msgid "2D obstacle used in navigation for collision avoidance." @@ -46030,12 +47783,22 @@ msgid "" "[b]Note:[/b] Obstacles are intended as a last resort option for constantly " "moving objects that cannot be (re)baked to a navigation mesh efficiently." msgstr "" +"L'obstacle 2D utilisé dans la navigation pour éviter les collisions. " +"L'obstacle a besoin de données de navigation pour fonctionner correctement. " +"Cela peut être fait avec l'obstacle comme enfant d'un nÅ“ud [Navigation2D], " +"ou en utilisant [method set_navigation]. [NavigationObstacle2D] est sûr lors " +"des trames physiques.\n" +"[b]Note :[/b] Les obstacles sont conçus comme dernière option pour les " +"objets constamment mobiles qui ne peuvent pas être pré-calculés efficacement " +"dans un maillage de navigation." #: doc/classes/NavigationObstacle2D.xml msgid "" "Returns the [Navigation2D] node that the obstacle is using for its " "navigation system." msgstr "" +"Retourne le nÅ“ud [Navigation2D] que l'obstacle utilise pour son système de " +"navigation." #: doc/classes/NavigationObstacle2D.xml msgid "Returns the [RID] of this obstacle on the [Navigation2DServer]." @@ -46046,12 +47809,16 @@ msgid "" "Sets the [Navigation2D] node used by the obstacle. Useful when you don't " "want to make the obstacle a child of a [Navigation2D] node." msgstr "" +"Définit le nÅ“ud [Navigation2D] utilisé par l'obstacle. Utile lorsque vous ne " +"voulez pas faire l'obstacle un enfant d'un nÅ“ud [Navigation2D]." #: doc/classes/NavigationPolygon.xml msgid "" "A node that has methods to draw outlines or use indices of vertices to " "create navigation polygons." msgstr "" +"Un nÅ“ud qui a des méthodes pour dessiner des contours ou utiliser des " +"indices de sommets pour créer des polygones de navigation." #: doc/classes/NavigationPolygon.xml msgid "" @@ -46077,6 +47844,27 @@ msgid "" "$NavigationPolygonInstance.navpoly = polygon\n" "[/codeblock]" msgstr "" +"Il y a deux façons de créer des polygones. Soit en utilisant la méthode [" +"method add_outline], soit en utilisant la méthode [method add_polygon].\n" +"Avec [method add_outline] :\n" +"[codeblock]\n" +"var polygon = NavigationPolygon.new()\n" +"var outline = PoolVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, " +"50), Vector2(50, 0)])\n" +"polygon.add_outline(outline)\n" +"polygon.make_polygons_from_outlines()\n" +"$NavigationPolygonInstance.navpoly = polygon\n" +"[/codeblock]\n" +"Avec [method add_polygon] et les indices du tableau des sommets :\n" +"[codeblock]\n" +"var polygon = NavigationPolygon.new()\n" +"var vertices = PoolVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, " +"50), Vector2(50, 0)])\n" +"polygon.set_vertices(vertices)\n" +"var indices = PoolIntArray([0, 1, 2, 3])\n" +"polygon.add_polygon(indices)\n" +"$NavigationPolygonInstance.navpoly = polygon\n" +"[/codeblock]" #: doc/classes/NavigationPolygon.xml msgid "" @@ -46085,6 +47873,10 @@ msgid "" "make_polygons_from_outlines] in order for this array to be converted to " "polygons that the engine will use." msgstr "" +"Ajoute un [PoolVector2Array] qui contient les sommets d'un contour au " +"tableau interne qui contient tous les contours. Vous devez appeler [method " +"make_polygons_from_outlines] afin que ce tableau soit converti en polygones " +"que le moteur pourra utiliser." #: doc/classes/NavigationPolygon.xml msgid "" @@ -46093,18 +47885,26 @@ msgid "" "to call [method make_polygons_from_outlines] in order for this array to be " "converted to polygons that the engine will use." msgstr "" +"Ajoute un [PoolVector2Array] qui contient les sommets d'un contour au " +"tableau interne qui contient tous les contours à une position fixe. Vous " +"devez appeler [method make_polygons_from_outlines] afin que ce tableau soit " +"converti en polygones que le pourra utiliser." #: doc/classes/NavigationPolygon.xml msgid "" "Clears the array of the outlines, but it doesn't clear the vertices and the " "polygons that were created by them." msgstr "" +"Efface le tableau des contours, mais ça n'efface pas les sommets et les " +"polygones qui ont été créés par eux." #: doc/classes/NavigationPolygon.xml msgid "" "Clears the array of polygons, but it doesn't clear the array of outlines and " "vertices." msgstr "" +"Efface le tableau des polygones, mais ça n'effacera pas le tableau des " +"contours et des sommets." #: doc/classes/NavigationPolygon.xml msgid "" @@ -46113,17 +47913,25 @@ msgid "" "NavigationServer.region_set_navmesh] API directly (as 2D uses the 3D server " "behind the scene)." msgstr "" +"Retourne le [NavigationMesh] résultant de ce polygone de navigation. Ce " +"navmesh peut être utilisé pour mettre à jour le navmesh d'une région avec " +"l'API [method NavigationServer.region_set_navmesh] directement (comme la 2D " +"utilise le serveur 3D en interne)." #: doc/classes/NavigationPolygon.xml msgid "" "Returns a [PoolVector2Array] containing the vertices of an outline that was " "created in the editor or by script." msgstr "" +"Retourne un [PoolVector2Array] contenant les sommets d'un contour qui a été " +"créé dans l'éditeur ou par un script." #: doc/classes/NavigationPolygon.xml msgid "" "Returns the number of outlines that were created in the editor or by script." msgstr "" +"Retourne le nombre de contours qui ont été créés dans l'éditeur ou par un " +"script." #: doc/classes/NavigationPolygon.xml msgid "Returns the count of all polygons." @@ -46134,27 +47942,33 @@ msgid "" "Returns a [PoolVector2Array] containing all the vertices being used to " "create the polygons." msgstr "" +"Retourne un [PoolVector2Array] contenant tous les sommets utilisés pour " +"créer les polygones." #: doc/classes/NavigationPolygon.xml msgid "Creates polygons from the outlines added in the editor or by script." msgstr "" +"Crée des polygones des contours ajoutés dans l'éditeur ou par un script." #: doc/classes/NavigationPolygon.xml msgid "" "Removes an outline created in the editor or by script. You have to call " "[method make_polygons_from_outlines] for the polygons to update." msgstr "" +"Enlève un aperçu créé dans l'éditeur ou par un script. Vous devez appeler [" +"method make_polygons_from_outlines] pour mettre à jour les polygones." #: doc/classes/NavigationPolygon.xml msgid "" "Changes an outline created in the editor or by script. You have to call " "[method make_polygons_from_outlines] for the polygons to update." msgstr "" +"Change un aperçu créé dans l'éditeur ou par un script. Vous devez appeler [" +"method make_polygons_from_outlines] pour mettre à jour les polygones." #: doc/classes/NavigationPolygonInstance.xml -#, fuzzy msgid "A region of the 2D navigation map." -msgstr "Prépare le maillage de navigation." +msgstr "" #: doc/classes/NavigationPolygonInstance.xml msgid "" @@ -46170,11 +47984,29 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." msgstr "" +"Une région de la carte de navigation. Il indique au [Navigation2DServer] ce " +"qui peut être navigué et ce qui ne peut pas l'être, en fonction de sa " +"ressource [NavigationPolygon].\n" +"Par défaut ce nÅ“ud s'enregistrera à la carte de navigation du [World2D] par " +"défaut. Si ce nÅ“ud est un enfant d'un nÅ“ud [Navigation2D], il s'inscrirea à " +"la carte de navigation du nÅ“ud de navigation.\n" +"Deux régions peuvent être reliées l'une à l'autre si elles partagent un bord " +"similaire. Vous pouvez définir la distance minimale entre deux sommets " +"nécessaires pour connecter deux bords en utilisant [method Navigation2DServer" +".map_set_edge_connection_margin]\n" +"[b]Note :[/b] Embiquer deux régions ne suffit pas pour relier ces deux " +"régions. Elles doivent partager un bord similaire.\n" +"Le coût de cheminement de cette région vers une autre peut être contrôlé " +"avec la valeur [member enter_cost].\n" +"[b]Note :[/b] Cette valeur n'est pas ajoutée au coût du chemin lorsque la " +"position de départ est déjà dans cette région.\n" +"Le coût de parcours des distances de cheminement à l'intérieur de cette " +"région peut être contrôlé avec le multiplicateur [member travel_cost]." #: doc/classes/NavigationPolygonInstance.xml msgid "" @@ -46183,11 +48015,14 @@ msgid "" "identify the [NavigationPolygonInstance] closest to a point on the merged " "navigation map." msgstr "" +"Retourne le [RID] de cette région sur le [Navigation2DServer]. Combiné avec [" +"method Navigation2DServer.map_get_closest_point_propriétaire] peut permettre " +"d'identifier le [NavigationPolygonInstance] le plus proche d'un point sur la " +"carte de navigation fusionnée." #: doc/classes/NavigationPolygonInstance.xml -#, fuzzy msgid "Determines if the [NavigationPolygonInstance] is enabled or disabled." -msgstr "Détermine si le [NavigationMeshInstance] est actif ou non." +msgstr "Détermine si la [NavigationPolygonInstance] est active ou non." #: doc/classes/NavigationPolygonInstance.xml msgid "" @@ -46198,14 +48033,12 @@ msgid "" msgstr "" #: doc/classes/NavigationPolygonInstance.xml -#, fuzzy msgid "The [NavigationPolygon] resource to use." -msgstr "La ressource [NavigationMesh] à utiliser." +msgstr "La ressource [NavigationPolygon] à utiliser." #: doc/classes/NavigationServer.xml -#, fuzzy msgid "Server interface for low-level 3D navigation access." -msgstr "Interface de serveur pour l'accès audio de bas niveau." +msgstr "" #: doc/classes/NavigationServer.xml #, fuzzy @@ -46255,15 +48088,13 @@ msgstr "" "sans soucis." #: doc/classes/NavigationServer.xml -#, fuzzy msgid "Returns the map cell height." -msgstr "Retourne la taille du tableau." +msgstr "" #: doc/classes/NavigationServer.xml -#, fuzzy msgid "" "Returns the normal for the point returned by [method map_get_closest_point]." -msgstr "Renvoie l'inverse de la racine carrée du paramètre." +msgstr "" #: doc/classes/NavigationServer.xml msgid "" @@ -46277,15 +48108,16 @@ msgid "" "Returns the edge connection margin of the map. This distance is the minimum " "vertex distance needed to connect two edges from different regions." msgstr "" +"Retourne la marge de raccordement du bord de la carte. Cette distance est la " +"distance minimale nécessaire pour relier deux bords de différentes régions." #: doc/classes/NavigationServer.xml msgid "Returns the map's up direction." msgstr "Retourne la direction haut de la carte." #: doc/classes/NavigationServer.xml -#, fuzzy msgid "Set the map cell height used to weld the navigation mesh polygons." -msgstr "Définit le polygone de navigation de la tuile." +msgstr "" #: doc/classes/NavigationServer.xml msgid "Sets the map up direction." @@ -46298,6 +48130,10 @@ msgid "" "called in the main thread.\n" "[b]Note:[/b] This function is not thread safe." msgstr "" +"Traite les agents d'évitement de collision.\n" +"Le résultat de ce processus est nécessaire par le serveur de physique, de " +"sorte que cela doit être appelé dans le fil d'exécution principal.\n" +"[b]Note :[/b] Cette fonction n'est pas sûre entre plusieurs fils d'exécution." #: doc/classes/NavigationServer.xml msgid "Bakes the navigation mesh." @@ -46308,11 +48144,62 @@ msgid "" "Set the region's navigation layers. This allows selecting regions from a " "path request (when using [method NavigationServer.map_get_path])." msgstr "" +"Définir les calques de navigation de la région. Cela permet de sélectionner " +"les régions à partir d'une requête de chemin (en utilisant [method " +"NavigationServer.map_get_path])." #: doc/classes/NavigationServer.xml msgid "Control activation of this server." msgstr "Contrôle l'activation de ce serveur." +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" +"Retourne l'état actuel de la connexion. Voir [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -46333,6 +48220,18 @@ msgid "" "the server port in UDP. You can use the [UPNP] class to try to forward the " "server port automatically when starting the server." msgstr "" +"Une implémentation de PacketPeer qui devrait être passée au [member " +"SceneTree.network_peer] après avoir été initialisé en tant que client ou " +"serveur. Les événements peuvent ensuite être gérés en se connectant aux " +"signaux de [SceneTree].\n" +"L'intêret de ENet est de fournir un calque de communication à travers le " +"réseau relativement léger, simple et robuste par dessus UDP (User Datagram " +"Protocol).\n" +"[b]Note :[/b] ENet utilise seulement UDP, et non TCP. Lors du branchement du " +"port serveur pour rendre votre serveur accessible sur internet, vous n'avez " +"besoin que d'envoyer le port serveur en UDP. Vous pouvez utiliser la classe " +"[UPNP] pour essayer d'envoyer automatiquement le port serveur dès le " +"démarrage du serveur." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46341,6 +48240,10 @@ msgid "" "disconnecting them. If this is a client it simply closes the connection to " "the server." msgstr "" +"Ferme la connexion. Ignoré si aucune connexion n'est actuellement établie. " +"Si c'est un serveur, il essaie de notifier tous les clients avant de les " +"déconnecter de force. Si c'est un client, il ferme simplement la connexion " +"au serveur." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46363,6 +48266,25 @@ msgid "" "code] is specified, the client will also listen to the given port; this is " "useful for some NAT traversal techniques." msgstr "" +"Créer un client qui se connecte au serveur à [code]address[/code] donnée via " +"le [code]port[/code]. L'adresse donnée doit être soit un nom de domaine " +"entièrement qualifié (ex.: [code]\"www.example.com\"[/code]) ou une adresse " +"IP en format IPv4 ou IPv6 (par exemple [code]\"192.168.1.1\"[/code]). Le " +"[code]port[/code] est le port que le serveur écoute. Les paramètres " +"[code]in_bandwidth[/code] et [code]out_bandwidth[/code] peuvent être " +"utilisés pour limiter la bande passante entrante et sortante, en octets par " +"seconde. Le défaut de 0 signifie que la bande passante ne sera pas limitée. " +"Notez que ENet ignorera stratégiquement des paquets d'une connexion entre " +"pairs pour s'assurer que la bande passante par les pairs n'est pas dépassée. " +"Les paramètres de bande passante déterminent également la taille de la " +"fenêtre d'une connexion qui limite la quantité de paquets fiables qui " +"peuvent être envoyés à tout moment donné. Retourne [constant OK] si un " +"client a été créé, [constant ERR_ALREADY_IN_USE] si ce " +"NetworkedMultiplayerENet a déjà une connexion ouverte (dans quel cas vous " +"devez appeler [method close_connection] d'abord) ou [constant " +"ERR_CANT_CREATE] si le client ne peut pas être créé. Si " +"[code]client_port[/code] est spécifié, le client écoutera également le port " +"donné ; ceci est utile pour certaines techniques NAT transversale." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46381,12 +48303,29 @@ msgid "" "case you need to call [method close_connection] first) or [constant " "ERR_CANT_CREATE] if the server could not be created." msgstr "" +"Créer un serveur qui écoute les connexions via [code]port[/code]. Le port " +"doit être un port disponible et inutilisé entre 0 et 65535. Notez que les " +"ports inférieurs à 1024 sont réservés et peuvent nécessiter des " +"autorisations élevées en fonction de la plateforme. Pour modifier " +"l'interface que le serveur écoute, utilisez [method set_bind_ip]. L'IP par " +"défaut est le joker [code]\"*\"[/code], qui écoute toutes les interfaces " +"disponibles. [code]max_clients[/code] est le nombre maximum de clients " +"autorisés en même temps, tout nombre jusqu'à 4095 peut être utilisé, même si " +"le nombre possible de clients simultanés peut être beaucoup plus faible et " +"dépend de l'application. Pour plus de détails sur les paramètres de bande " +"passante, voir [method create_client]. Retourne [constant OK] si un serveur " +"a été créé, [constant ERR_ALREADY_IN_USE] si ce NetworkedMultiplayerENet a " +"déjà une connexion ouverte (dans quel cas vous devez appeler [method " +"close_connection] d'abord) ou [constant ERR_CANT_CREATE] si le serveur ne " +"peut pas être créé." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "Disconnect the given peer. If \"now\" is set to [code]true[/code], the " "connection will be closed immediately without flushing queued messages." msgstr "" +"Déconnecte le pair donné. Si \"maintenant\" est [code]true[/code], la " +"connexion sera fermée immédiatement sans envoyer les messages en attente." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46401,6 +48340,8 @@ msgid "" "Returns the channel of the next packet that will be retrieved via [method " "PacketPeer.get_packet]." msgstr "" +"Retourne le canal du prochain paquet qui sera récupéré via [method PacketPeer" +".get_packet]." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml #: modules/websocket/doc_classes/WebSocketServer.xml @@ -46419,6 +48360,10 @@ msgid "" "needs to be in IPv4 or IPv6 address format, for example: " "[code]\"192.168.1.1\"[/code]." msgstr "" +"L'adresse IP utilisée lors de la création d'un serveur. Ceci est défini le " +"joker [code]\"*\"[/code] par défaut, qui se connecte à toutes les interfaces " +"disponibles. L'adresse donnée doit être au format IPv4 ou IPv6, par " +"exemple : [code]\"192.168.1.1\"[/code]." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46426,6 +48371,9 @@ msgid "" "code]. For servers, you must also setup the [CryptoKey] via [method " "set_dtls_key]." msgstr "" +"Configure le [X509Certificate] à utiliser lorsque [member use_dtls] est " +"[code]true[/code]. Pour les serveurs, vous devez également configurer le " +"[CryptoKey] via [method set_dtls_key]." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46433,6 +48381,9 @@ msgid "" "code]. Remember to also call [method set_dtls_certificate] to setup your " "[X509Certificate]." msgstr "" +"Configure la [CryptoKey] à utiliser lorsque [member use_dtls] est " +"[code]true[/code]. N'oubliez pas d'appeler [method set_dtls_certificate] " +"pour configurer votre [X509Certificate]." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46447,6 +48398,17 @@ msgid "" "other hand, defines a fixed timeout for which any packet must be " "acknowledged or the peer will be dropped." msgstr "" +"Définit les paramètres de limite de temps pour un pair. Les paramètres de " +"limite de temps contrôlent comment et quand un pair estimera que le traffic " +"n'est pas assez fiable. Les valeurs de limite de temps sont exprimées en " +"millisecondes.\n" +"La [code]timeout_limit[/code] est un facteur qui, multiplié par une valeur " +"basée sur le temps d'envoi moyen, déterminera la limite de temps pour un " +"paquet fiable. Lorsque cette limite est atteinte, la limite de temps sera " +"doublée, et le pair sera déconnecté si cette limite atteint " +"[code]timeout_min[/code]. Le paramètre [code]timeout_max[/code], d'autre " +"part, définit une limite de temps fixe pour lequel tout paquet doit estimé " +"comme fiable, ou alors le pair sera supprimé." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46455,6 +48417,11 @@ msgid "" "NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE_ORDERED]). This is the " "only way to use ordering with the RPC system." msgstr "" +"Force le tri des paquets lors de l'utilisation de [constant " +"NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE] (ce qui se comporte de la " +"même manière [constant NetworkedMultiplayerPeer." +"TRANSFER_MODE_UNRELIABLE_ORDERED]). C'est le seul moyen d'utiliser le tri " +"avec un système RPC." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46465,6 +48432,12 @@ msgid "" "status of a packet in one channel won't stall the delivery of other packets " "in another channel." msgstr "" +"Le nombre de canaux à utiliser par ENet. Les canaux sont utilisés pour " +"séparer différents types de données. En mode fiable ou ordonné, par exemple, " +"l'ordre d'envoi des paquets est assuré sur une base par canal. Ceci est fait " +"pour lutter contre la latence et réduit les restrictions d'ordre sur les " +"paquets. L'état d'envoi d'un paquet d'un canal a été décalé dans l'envoi " +"d'autres paquets dans un autre canal." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46481,6 +48454,21 @@ msgid "" "COMPRESS_NONE]. Nonetheless, mixing engine versions between clients and " "server is not recommended and not officially supported." msgstr "" +"La méthode de compression utilisée pour les paquets réseau. Ceux-ci ont " +"différents compromis de vitesse de compression par rapport à la bande " +"passante, vous pouvez avoir besoin quelle méthode fonctionne le mieux pour " +"votre cas d'utilisation si vous utilisez la compression pour tout.\n" +"[b]Note :[/b] La conception réseau de la plupart des jeux nécessite l'envoi " +"de nombreux petits paquets fréquemment (moins de 4 KB chacun). Dans le " +"doute, il est recommandé de garder l'algorithme de compression par défaut " +"car il fonctionne le mieux avec ces petits paquets.\n" +"[b]Note :[/b] [member compression_mode] doit être défini à la même valeur " +"sur le serveur et sur tous ses clients. Les clients ne se connecteront pas " +"si le [member compression_mode] d'un client diffère de celui du serveur. " +"Avant Godot 3.4, la valeur par défaut de [member compression_mode] était " +"[constant COMPRESS_NONE]. Néanmoins, il n'est pas recommandé, ni " +"officiellement supporté, d'utiliser différentes versions du moteur entre les " +"clients et le serveur." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46489,9 +48477,12 @@ msgid "" "When set to an empty string, the [code]address[/code] parameter passed to " "[method create_client] is used instead." msgstr "" +"Le nom d'hôte utilisé pour la vérification DTLS, à comparer à la valeur « CN " +"» du certificat fourni par le serveur.\n" +"Si la chaîne est vide, le paramètre [code]address[/code] passé à [method " +"create_client] est utilisé à la place." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml -#, fuzzy msgid "" "Enable or disable certificate verification when [member use_dtls] is " "[code]true[/code]." @@ -46506,6 +48497,11 @@ msgid "" "is [code]false[/code], clients won't be automatically notified of other " "peers and won't be able to send them packets through the server." msgstr "" +"Activer ou désactiver la fonction serveur qui notifie les clients de la " +"connexion/déconnection des autres pairs enregistrés, et relaye les messages " +"entre eux. Lorsque cette option est [code]false[/code], les clients ont " +"obtenu la notification automatique d'autres pairs et ont obtenu la " +"possibilité de les envoyer par le serveur." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46517,6 +48513,14 @@ msgid "" "that channel for sending data. See [member channel_count] for more " "information about ENet channels." msgstr "" +"Définit le canal par défaut à utiliser pour transférer les données. Par " +"défaut, cette valeur est [code]-1[/code] ce qui signifie que ENet " +"n'utilisera que 2 canaux : un pour les paquets fiables, et un pour les " +"paquets non fiables. Le canal [code]0[/code] est réservé et ne peut pas être " +"utilisé. Définit cette propriété à n'importe quelle valeur entre [code]0[/" +"code] et [member channel_count] (exclus) forcera ENet à utiliser ce canal " +"pour envoyer les données. Voir [member channel_count] pour plus " +"d'informations sur les canaux ENet." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46530,6 +48534,16 @@ msgid "" "dtls_verify] option, and configure the certificate accordingly via [method " "set_dtls_certificate]." msgstr "" +"Quand activé, le client ou le serveur créé par ce pair utilisera " +"[PacketPeerDTLS] au lieu des sockets UDP bruts pour communiquer avec le pair " +"distant. Cela permettra de chiffrer la communication avec DTLS avec une " +"utilisation plus importante des ressources mais aussi peut-être de la taille " +"des paquets.\n" +"[b]Note :[/b] Lors de la création d'un serveur DTLS, assurez-vous de " +"configurer à la fois la clé et le certificat avec [method set_dtls_key] et " +"[method set_dtls_certificate]. Pour les clients DTLS, regardez l'option " +"[member dtls_verify] et configurez le certificat en conséquence avec [method " +"set_dtls_certificate]." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46537,12 +48551,17 @@ msgid "" "requiring the fewest CPU resources. This option may also be used to make " "network debugging using tools like Wireshark easier." msgstr "" +"Aucune compression. Cela utilise le plus de bande passante, mais moins de " +"ressource du CPU. Cette option peut également être utilisée pour faciliter " +"le débogage du réseau en utilisant des outils comme Wireshark." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "ENet's built-in range encoding. Works well on small packets, but is not the " "most efficient algorithm on packets larger than 4 KB." msgstr "" +"L'encodage intégré d'ENet. Fonctionne bien sur les petits paquets, mais " +"n'est pas l'algorithme le plus efficace pour les paquets de plus de 4 KB." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46550,6 +48569,9 @@ msgid "" "resources compared to [constant COMPRESS_ZLIB], at the expense of using more " "bandwidth." msgstr "" +"L'algorithme de compression [url=http://fastlz.org/]FastLZ[/url]. Cette " +"option utilise moins de ressources CPU par rapport à [constant " +"COMPRESS_ZLIB] mais utilise plus de bande passante." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" @@ -46559,6 +48581,11 @@ msgid "" "packets smaller than 4 KB. Therefore, it's recommended to use other " "compression algorithms in most cases." msgstr "" +"L'algorithme de compression [url=https://www.zlib.net/]Zlib[/url]. Cette " +"option utilise moins de bande passante par rapport à [constant " +"COMPRESS_FASTLZ] mais utilise plus le CPU. Notez que cet algorithme n'est " +"pas très efficace pour les paquets de moins de 4 KB. Il est donc souvent " +"recommandé d'utiliser d'autres algorithmes de compression." #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "[url=https://facebook.github.io/zstd/]Zstandard[/url] compression." @@ -46578,6 +48605,11 @@ msgid "" "detail and isn't meant to be used by non-Godot servers. It may change " "without notice." msgstr "" +"Gère la connexion aux pairs du réseau. Attribue des identifiants uniques à " +"chaque client connecté au serveur. Voir aussi [MultiplayerAPI].\n" +"[b]Note :[/b] Le protocole de l'API multijoueur de haut niveau dépend de son " +"implémentation et n'est pas destiné à être utilisé par des serveurs en " +"dehors de Godot. Ce protocole peut changer dans une future version." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "High-level multiplayer" @@ -46585,7 +48617,7 @@ msgstr "API multijoueur de haut niveau" #: doc/classes/NetworkedMultiplayerPeer.xml msgid "WebRTC Signaling Demo" -msgstr "" +msgstr "Démo des signaux WebRTC" #: doc/classes/NetworkedMultiplayerPeer.xml msgid "" @@ -46617,6 +48649,13 @@ msgid "" "peer ID to send to all peers except that one. By default, the target peer is " "[constant TARGET_PEER_BROADCAST]." msgstr "" +"Définit le pair auquel les paquets seront envoyés.\n" +"L'identifiant [code]id[/code] peut être : [constant TARGET_PEER_BROADCAST] " +"pour envoyer à tous les pairs connectés, [constant TARGET_PEER_SERVER] pour " +"envoyer au pair agissant en tant que serveur, un identifiant de pairs valide " +"pour envoyer à ce pair spécifique, ou un identifiant négatif pour envoyer à " +"tous les pairs sauf celui-ci. Par défaut, le pair cible est [constant " +"TARGET_PEER_BROADCAST]." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "" @@ -46631,6 +48670,8 @@ msgid "" "The manner in which to send packets to the [code]target_peer[/code]. See " "[enum TransferMode]." msgstr "" +"La manière d'envoyer des paquets au [code]target_peer[/code]. Voir [enum " +"TransferMode]." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "Emitted when a connection attempt fails." @@ -46659,6 +48700,11 @@ msgid "" "TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always " "consider whether the order matters." msgstr "" +"Les paquets ne sont pas reconnus, aucune tentative de ré-envoi n'est faite " +"pour les paquets perdus. Les paquets peuvent arriver dans n'importe quelle " +"commande. Peut être plus rapide que [constant " +"TRANSFER_MODE_UNRELIABLE_ORDERED]. À utiliser pour des données non " +"critiques, et toujours à considérer si l'ordre compte." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "" @@ -46668,6 +48714,12 @@ msgid "" "would be outdated if received late due to resend attempt(s) anyway, for " "example movement and positional data." msgstr "" +"Les paquets ne sont pas reconnus, aucune tentative de ré-envoi n'est faite " +"pour les paquets perdus. Les paquets sont reçus dans l'ordre où ils ont été " +"envoyés. Peut être plus rapide que [constant TRANSFER_MODE_RELIABLE]. À " +"utiliser pour les données non critiques ou qui seraient périmées si elles " +"étaient reçues tardivement à cause du ré-envoi, par exemple pour les données " +"de mouvement et de positionnement." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "" @@ -46678,6 +48730,14 @@ msgid "" "order, for example an ability being triggered or a chat message. Consider " "carefully if the information really is critical, and use sparingly." msgstr "" +"Les paquets doivent être reçus et les tentatives de ré-envoi doivent être " +"faites jusqu'à ce que les paquets soient reconnus. Les paquets doivent être " +"reçus dans l'ordre où ils ont été envoyés. C'est le mode de transfert le " +"plus fiable, mais potentiellement le plus lent en cause de la surcharge. À " +"utiliser pour les données critiques qui doivent être transmises et arriver " +"en ordre, par exemple un élément activé ou un message de discussion. À " +"considérez soigneusement si l'information est vraiment critique, et à " +"utiliser avec parcimonie." #: doc/classes/NetworkedMultiplayerPeer.xml msgid "The ongoing connection disconnected." @@ -46719,30 +48779,40 @@ msgid "" "Returns the size of the margin identified by the given [enum Margin] " "constant." msgstr "" +"Retourne la taille de la marge identifiée par la constante [enum Margin] " +"donnée." #: doc/classes/NinePatchRect.xml msgid "" "Sets the size of the margin identified by the given [enum Margin] constant " "to [code]value[/code] in pixels." msgstr "" +"Définit la taille de la marge identifiée par la constante [enum Margin] " +"donnée à [code]value[/code] en pixels." #: doc/classes/NinePatchRect.xml msgid "" "The stretch mode to use for horizontal stretching/tiling. See [enum " "NinePatchRect.AxisStretchMode] for possible values." msgstr "" +"Le mode d'étirement à utiliser pour l'étirement horizontal. Voir [enum " +"NinePatchRect.AxisStretchMode] pour les valeurs possibles." #: doc/classes/NinePatchRect.xml msgid "" "The stretch mode to use for vertical stretching/tiling. See [enum " "NinePatchRect.AxisStretchMode] for possible values." msgstr "" +"Le mode d'étirement à utiliser pour l'étirement vertical. Voir [enum " +"NinePatchRect.AxisStretchMode] pour les valeurs possibles." #: doc/classes/NinePatchRect.xml msgid "" "If [code]true[/code], draw the panel's center. Else, only draw the 9-slice's " "borders." msgstr "" +"Si [code]true[/code], dessine le centre du panneau. Sinon, ne dessine que " +"les bordures des 9 parties." #: doc/classes/NinePatchRect.xml msgid "" @@ -46750,6 +48820,10 @@ msgid "" "bottom corners and side will have a height of 16 pixels. You can set all 4 " "margin values individually to create panels with non-uniform borders." msgstr "" +"La hauteur de la ligne du bas des 9 parties. Une marge de 16 signifie que " +"les angles du bas des 9 parties et les côtés auront une hauteur de 16 " +"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour " +"créer des panneaux avec des bordures non uniformes." #: doc/classes/NinePatchRect.xml msgid "" @@ -46757,6 +48831,10 @@ msgid "" "left corners and side will have a width of 16 pixels. You can set all 4 " "margin values individually to create panels with non-uniform borders." msgstr "" +"La largeur de la colonne gauche des 9 parties. Une marge de 16 signifie que " +"les angles de gauche des 9 parties et les côtés auront une largeur de 16 " +"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour " +"créer des panneaux avec des bordures non uniformes." #: doc/classes/NinePatchRect.xml msgid "" @@ -46764,6 +48842,10 @@ msgid "" "right corners and side will have a width of 16 pixels. You can set all 4 " "margin values individually to create panels with non-uniform borders." msgstr "" +"La largeur de la colonne droite de 9 parties. Une marge de 16 signifie que " +"les angles de droite des 9 parties et le côté auront une largeur de 16 " +"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour " +"créer des panneaux avec des bordures non uniformes." #: doc/classes/NinePatchRect.xml msgid "" @@ -46771,6 +48853,10 @@ msgid "" "corners and side will have a height of 16 pixels. You can set all 4 margin " "values individually to create panels with non-uniform borders." msgstr "" +"La hauteur de la ligne du haut de 9 parties. Une marge de 16 signifie que " +"les angles du haut des 9 parties et le côté auront une hauteur de 16 pixels. " +"Vous pouvez définir les 4 valeurs de marge individuellement pour créer des " +"panneaux avec des bordures non uniformes." #: doc/classes/NinePatchRect.xml msgid "" @@ -46779,6 +48865,10 @@ msgid "" "other properties are relative to this one. If the rect is empty, " "NinePatchRect will use the whole texture." msgstr "" +"La région rectangulaire de la texture à utiliser. Si vous travaillez avec un " +"atlas, utilisez cette propriété pour définir la zone à utiliser. Toutes les " +"autres propriétés sont par rapport à celle-ci. Si le rectangle est vide, le " +"NinePatchRect utilisera la texture dans son entièreté." #: doc/classes/NinePatchRect.xml msgid "The node's texture resource." @@ -46793,6 +48883,8 @@ msgid "" "Stretches the center texture across the NinePatchRect. This may cause the " "texture to be distorted." msgstr "" +"Étire la texture du centre sur tout le NinePatchRect. Cela peut entraîner " +"une distorsion de cette texture." #: doc/classes/NinePatchRect.xml msgid "" @@ -46802,6 +48894,11 @@ msgid "" "[b]Note:[/b] Only supported when using the GLES3 renderer. When using the " "GLES2 renderer, this will behave like [constant AXIS_STRETCH_MODE_STRETCH]." msgstr "" +"Répète la texture centrale sur tout le NinePatchRect. Cela ne provoque " +"aucune distorsion visible. La texture doit être transparente pour que cela " +"fonctionne sans afficher d'artefacts entre les bords.\n" +"[b]Note :[/b] Seulement pris en charge avec GLES3. Avec GLES2, cela se " +"comportera comme [constant AXIS_STRETCH_MODE_STRETCH]." #: doc/classes/NinePatchRect.xml msgid "" @@ -46813,6 +48910,13 @@ msgid "" "[b]Note:[/b] Only supported when using the GLES3 renderer. When using the " "GLES2 renderer, this will behave like [constant AXIS_STRETCH_MODE_STRETCH]." msgstr "" +"Répète la texture centrale sur tout le NinePatchRect, mais étirera également " +"la texture pour s'assurer que chaque tuile est visible entièrement. Cela " +"peut causer une distorsion de la texture, mais moins que [constant " +"AXIS_STRETCH_MODE_STRETCH]. La texture doit être transparente pour que cela " +"fonctionne sans afficher d'artefacts entre les bords.\n" +"[b]Note :[/b] Seulement pris en charge avec GLES3. Avec GLES2, cela se " +"comportera comme [constant AXIS_STRETCH_MODE_STRETCH]." #: doc/classes/Node.xml msgid "Base class for all [i]scene[/i] objects." @@ -46878,6 +48982,69 @@ msgid "" "(make sure node names are the same on all peers). Also, take a look at the " "high-level networking tutorial and corresponding demos." msgstr "" +"Les nÅ“uds sont les blocs de construction de Godot. Ils peuvent être assignés " +"comme enfant d'un autre nÅ“ud, ce qui entraîne définit l'arborescence. Un " +"nÅ“ud donné peut contenir n'importe quel nombre de nÅ“uds enfants mais tous " +"ces enfants doivent avoir des noms différents.\n" +"Une arborescence de nÅ“uds est appelé une [i]scène[/i]. Les scènes peuvent " +"être sauvegardées sur le disque et ensuite instanciées dans d'autres scènes. " +"Cela permet une très grande flexibilité dans l'architecture et le modèle de " +"données des projets Godot.\n" +"[b]Arbre de scène :[/b] Le [SceneTree] contient l'arborescence des nÅ“uds. " +"Lorsqu'un nÅ“ud est ajouté à l'arborescence de scène, il reçoit la " +"notification [constant NOTIFICATION_ENTER_TREE] et sa méthode [method " +"enter_tree] est appelée. Les nÅ“uds d'enfants sont toujours ajoutés [i]après[/" +"i] leur nÅ“ud parent, c'est-à -dire la méthode [method enter_tree] d'un nÅ“ud " +"parent sera appelée avant celle de son enfant.\n" +"Une fois que tous les nÅ“uds ont été ajoutés dans l'arborescence de la scène, " +"ils reçoivent la notification [constante NOTIFICATION_READY] et leurs " +"méthodes respectives [method _ready] sont appelées. Pour les groupes de " +"nÅ“uds, la méthode [method _ready] est appelée avec un ordre inversé, en " +"commençant par les enfants et en allant jusqu'aux nÅ“uds parent.\n" +"Cela signifie qu'en ajoutant un nÅ“ud à l'arborescence de la scène, l'ordre " +"suivant sera utilisé pour les appels des méthodes: [method enter_tree] du " +"parent, [method enter_tree] des enfants, [method _ready] des enfants et " +"enfin [method _ready] du parent (recursivement pour l'arborescence complète " +"de la scène).\n" +"[b]Processus :[/b] Les nÅ“uds peuvent surcharger l'état du processus, de " +"sorte qu'ils reçoivent un appel à chaque trame demandant un traitement (de " +"faire quelque chose). Le traitement normal (la méthode [method _process], " +"activée avec [method set_process]) se produit aussi vite que possible et " +"dépend du nombre de trames par seconde, de sorte que le temps de traitement " +"[i]delta[/i] (en secondes) est passé en argument. Le traitement physique (la " +"méthode [method physical_process], activée avec [method " +"set_physics_process]) est appelée un nombre fixe de fois par seconde (60 " +"fois par défaut) et est utile pour le code lié au moteur physique.\n" +"Les nÅ“uds peuvent également traiter les événements d'entrée. À l'heure " +"actuelle, la fonction [method _input] sera appelée pour chaque entrée que le " +"programme reçoit. Dans de nombreux cas, cela peut faire trop d'informations " +"(sauf pour des projets simples), et la fonction [method unhandled_input] " +"peut être préférée ; elle est appelée lorsque l'événement d'entrée n'a été " +"traité par aucun élément (généralement, des nÅ“uds d'interface [Control]), " +"pour s'assurer que le nÅ“ud ne reçoit que les événements qui lui sont " +"destinés.\n" +"Pour garder la trace de l'arborescence de la scène (surtout lorsque vous " +"instanciez des scènes dans d'autres scènes), un \"propriétaire\" peut être " +"défini pour le nÅ“ud avec la propriété [member owner]. Cela garde une trace " +"de quel élément a instancié quel autre élément. Cela est surtout utile " +"lorsque vous écrivez des éditeurs et des outils.\n" +"Enfin, quand un nÅ“ud est libéré avec [method Object.free] ou [method " +"queue_free], il va également libérer tous ses enfants.\n" +"[b]Les groupes : [/b] Les nÅ“uds peuvent être ajoutés à autant de groupes que " +"vous voulez, vous pouvez créer des groupes comme « ennemis » ou « " +"récupérables » par exemple, selon votre jeu. Voir [method add_to_group], " +"[method is_in_group] et [method remove_from_group]. Vous pouvez ensuite " +"récupérer tous les nÅ“uds d'un groupe, lister les groupes et même appeler des " +"méthodes sur les groupes via des méthodes de [SceneTree].\n" +"[b]Faire communiquer les nÅ“ud via le réseau :[/b] Après s'être connecté à un " +"serveur (ou en faire un, voir [NetworkedMultiplayerENet]), il est possible " +"d'utiliser le système RPC intégré (\"Remote Procedure Call\") pour " +"communiquer sur le réseau. En appelant [method rpc] avec un nom de méthode, " +"il sera appelé localement et pour tous les pairs connectés (un pair = un " +"client et le serveur qui accepte les connexions). Pour identifier quel nÅ“ud " +"reçoit l'appel RPC, Godot utilisera son [NodePath] (s'assurant que les noms " +"de nÅ“uds sont les mêmes sur tous les pairs). Consultez également le tutoriel " +"pour les réseaux à haut niveau et les démos correspondantes." #: doc/classes/Node.xml msgid "Nodes and Scenes" @@ -46896,6 +49063,12 @@ msgid "" "Corresponds to the [constant NOTIFICATION_ENTER_TREE] notification in " "[method Object._notification]." msgstr "" +"Appelé lorsque le nÅ“ud entre dans la [SceneTree] (par exemple en étant " +"instancié, au changement de scène, ou après avoir appelé [method add_child] " +"dans un script). Si le nÅ“ud a des enfants, sa méthode [méthod enter_tree] " +"sera appelée d'abord, puis ensuite celle de ses enfants.\n" +"Correspond à la notification [constant NOTIFICATION_ENTER_TREE] dans [method " +"Object._notification]." #: doc/classes/Node.xml msgid "" @@ -46908,6 +49081,15 @@ msgid "" "the node has already left the active tree, connect to the [signal " "tree_exited]." msgstr "" +"Appelé lorsque le nÅ“ud va quitter la [SceneTree] (par exemple sur la " +"suppression, au changement de scène, ou après avoir appelé [method " +"remove_child] dans un script). Si le nÅ“ud a des enfants, sa méthode [method " +"exit_tree] sera appelée en dernier, quand tous ses enfants auront quitté " +"l'arborescence.\n" +"Correspond à la notification [constant NOTIFICATION_EXIT_TREE] dans [method " +"Object._notification] et signal [signal tree_exiting]. Pour être notifié " +"lorsque le nÅ“ud a déjà quitté l'arborescence active, connectez-vous à " +"[signal tree_exited]." #: doc/classes/Node.xml msgid "" @@ -46917,6 +49099,12 @@ msgid "" "Call [method update_configuration_warning] when the warning needs to be " "updated for this node." msgstr "" +"La chaîne retournée de cette méthode est affichée comme un avertissement " +"dans la barre d'outil Scène si le script qui la modifie est un script " +"[code]tool[/code].\n" +"Retourner une chaîne vide ne produit aucun avertissement.\n" +"Appelez [method update_configuration_warning] lorsque l'avertissement doit " +"être mis à jour pour ce nÅ“ud." #: doc/classes/Node.xml msgid "" @@ -47015,6 +49203,21 @@ msgid "" "call with [method request_ready], which may be called anywhere before adding " "the node again." msgstr "" +"Appelé lorsque le nÅ“ud est « prêt », c'est-à -dire lorsque le nÅ“ud et ses " +"enfants sont entrés dans l'arborescence de la scène. Si le nÅ“ud a des " +"enfants, leur méthode [method _ready] sera appelée en premier, et le nÅ“ud " +"parent recevra la notification après.\n" +"Correspond à la notification [constant NOTIFICATION_READY] dans [method " +"Object._notification]. Voir aussi le mot-clé [code]onready[/code] pour les " +"variables.\n" +"Habituellement utilisé pour l'initialisation. Pour encore avant cela, " +"[method Object._init] peut être utilisé. Voir aussi [méthod enter_tree].\n" +"[b]Note :[/b] [method _ready] ne peut être appelée qu'une seule fois pour " +"chaque nÅ“ud. Après avoir retiré un nÅ“ud de l'arborescence de scène et " +"l'ajouter à nouveau, [code]_ready[/code] ne sera pas appelé une deuxième " +"fois. Cela peut être changé en demandant un autre appel avec [method " +"request_ready], qui peut être appelé n'importe où avant d'ajouter le nÅ“ud à " +"nouveau." #: doc/classes/Node.xml msgid "" @@ -47104,6 +49307,30 @@ msgid "" "will not be visible in the scene tree, though it will be visible in the " "2D/3D view." msgstr "" +"Ajoute un nÅ“ud enfant. Les nÅ“uds peuvent avoir autant d'enfants que voulu, " +"mais chaque enfant doit avoir un nom unique. Les nÅ“uds d'enfants sont " +"automatiquement supprimés lorsque le nÅ“ud parent est supprimé, de sorte " +"qu'une scène entière peut être supprimée en supprimant juste son nÅ“ud le " +"plus haut.\n" +"Si [code]legible_unique_name[/code] est [code]true[/code], le nÅ“ud d'enfant " +"aura un nom clairement lisible basé sur le nom du nÅ“ud étant analysé au lieu " +"de son type.\n" +"[b]Note :[/b] Si le nÅ“ud enfant a déjà un parent, la fonction échouera. " +"Utilisez [method remove_child] d'abord pour retirer le nÅ“ud de son parent " +"actuel. Par exemple :\n" +"[codeblock]\n" +"if child_node.get_parent():\n" +" child_node.get_parent().remove_child(child_node)\n" +"add_child(child_node)\n" +"[/codeblock]\n" +"[b]Note :[/b] Si vous voulez qu'un enfant soit persiste dans un " +"[PackedScene], vous devez définir [member owner] après avoir appelé [method " +"add_child]. Ceci est généralement pertinent pour [url=$DOCS_URL/tutorials/" +"plugins/running_code_in_the_editor.html]scripts d'outil[/url] et " +"[url=$DOCS_URL/tutorials/plugins/editor/index.html]greffons d'éditeur[/url]. " +"Si [method add_child] est appelé sans définir [member owner], le nouveau " +"[Node] ajouté ne sera pas visible dans l'arborescence de la scène, bien " +"qu'il sera visible dans la vue 2D/3D." #: doc/classes/Node.xml msgid "" @@ -47113,6 +49340,10 @@ msgid "" "will have a human-readable name based on the name of the node being " "instanced instead of its type." msgstr "" +"Ajoute [code]child_nÅ“ud[/code] en tant qu'enfant. L'enfant est placé sous le " +"[code]nÅ“ud[/code] donné dans la liste des enfants.\n" +"Si [code]legible_unique_name[/code] est [code]true[/code], le nÅ“ud d'enfant " +"aura un nom lisible humainement basé sur le nom du nÅ“ud plutôt que son type." #: doc/classes/Node.xml msgid "" @@ -47135,6 +49366,10 @@ msgid "" "scene tree is not paused, and [code]false[/code] if the node is not in the " "tree." msgstr "" +"Retourne [code]true[/code] si le nÅ“ud peut traiter pendant que " +"l'arborescence de scène est interrompue (voir [member pause_mode)]. Retourne " +"toujours [code]true[/code] si l'arborescence de scène n'est pas interrompue, " +"et [code]false[/code] si le nÅ“ud n'est pas dans l'arborescence." #: doc/classes/Node.xml msgid "" @@ -47144,6 +49379,10 @@ msgid "" "get_tree().create_tween().bind_node(self)\n" "[/codeblock]" msgstr "" +"Crée un nouveau [SceneTreeTween] et le lie à ce nÅ“ud. Cela équivaut à :\n" +"[codeblock]\n" +"get_tree().create_tween().bind_node(self)\n" +"[/codeblock]" #: doc/classes/Node.xml msgid "" @@ -47154,6 +49393,13 @@ msgid "" "constructor arguments (i.e. needs to supply arguments to [method Object." "_init] method). In that case, the node will be duplicated without a script." msgstr "" +"Duplique le nÅ“ud, retournant un nouveau nÅ“ud.\n" +"Vous pouvez affiner le comportement en utilisant des drapeaux dans " +"[code]flags[/code] (voir [enum DuplicateFlags)].\n" +"[b]Note :[/b] Ça ne fonctionnera pas correctement si le nÅ“ud contient un " +"script avec des arguments de constructeur (c'est-à -dire qu'on doit fournir " +"des arguments à la méthode [method Object._init]). Dans ce cas, le nÅ“ud sera " +"dupliqué sans script." #: doc/classes/Node.xml msgid "" @@ -47172,6 +49418,23 @@ msgid "" "consider using [method get_node] instead. To avoid using [method find_node] " "too often, consider caching the node reference into a variable." msgstr "" +"Trouve un descendant de ce nÅ“ud dont le nom correspond à [code]mask[/code] " +"suivant le même fonctionnement que pour [method String.match] (c'est-à -dire " +"sensible à la casse, que [code]\"*\"[/code] correspond à un zéro au un seul " +"caractère, et que [code]\"?\"[/code] correspond à n'importe quel unique " +"caractère sauf [code]\".\"[/code]). Retourne [code]null[/code] si aucun " +"[Node] correspondant n'est trouvée.\n" +"[b]Note :[/b] La correspondance ne se fait pas sur le chemin complet mais " +"juste les noms des nÅ“uds.\n" +"Si [code]owned[/code] est [code]true[/code], cette méthode ne trouve que des " +"nÅ“uds dont le propriétaire est ce nÅ“ud. Ceci est particulièrement important " +"pour les scènes instanciée par un script, parce que ces scènes n'ont pas de " +"propriétaire.\n" +"[b]Note :[/b] Comme cette méthode liste tous les descendants d'un nÅ“ud, " +"c'est le moyen le plus lent d'obtenir une référence à un autre nÅ“ud. Dans la " +"mesure du possible, essayez plutôt d'utiliser [method get_node]. Pour éviter " +"d'utiliser [method find_node] trop souvent, essayez de mettre en chache la " +"référence de ce nÅ“ud dans une variable." #: doc/classes/Node.xml msgid "" @@ -47186,6 +49449,18 @@ msgid "" "[method get_node] instead. To avoid using [method find_parent] too often, " "consider caching the node reference into a variable." msgstr "" +"Trouve le premier parent de ce nÅ“ud dont le nom correspond à " +"[code]mask[/code] suivant le même fonctionnement que pour [method String." +"match] (c'est-à -dire sensible à la casse, que [code]\"*\"[/code] correspond " +"à un zéro au un seul caractère, et que [code]\"?\"[/code] correspond à " +"n'importe quel unique caractère sauf [code]\".\"[/code]).\n" +"[b]Note :[/b] La correspondance ne se fait pas sur le chemin complet mais " +"juste les noms des nÅ“uds.\n" +"[b]Note :[/b] Comme cette méthode liste tous les parents d'un nÅ“ud, c'est le " +"moyen le plus lent d'obtenir une référence à un autre nÅ“ud. Dans la mesure " +"du possible, essayez plutôt d'utiliser [method get_node]. Pour éviter " +"d'utiliser [method find_node] trop souvent, essayez de mettre en chache la " +"référence de ce nÅ“ud dans une variable." #: doc/classes/Node.xml msgid "" @@ -47193,6 +49468,9 @@ msgid "" "method is often used for iterating all children of a node.\n" "To access a child node via its name, use [method get_node]." msgstr "" +"Retourne un nÅ“ud enfant par son index (voir [method get_child_count)]. Cette " +"méthode est souvent utilisée pour itérer tous les enfants d'un nÅ“ud.\n" +"Pour accéder à un nÅ“ud enfant par son nom, utilisez [method get_node]." #: doc/classes/Node.xml msgid "Returns the number of child nodes." @@ -47220,17 +49498,38 @@ msgid "" " non_internal_groups.push_back(group)\n" "[/codeblock]" msgstr "" +"Retourne un tableau énumérant les groupes dont ce nÅ“ud est membre.\n" +"[b]Note :[/b] Pour des raisons de performance, l'ordre des groupes de nÅ“uds " +"n'est [i]pas[/i] garanti. cet ordre des groupes de nÅ“uds ne devrait pas être " +"utilisé car il peut varier entre les différents projets.\n" +"[b]Note :[/b] Le moteur utilise des noms de groupe en l'interne (tous " +"commençent par \"_\"). Pour éviter les conflits avec des groupes internes, " +"n'ajoutez pas de groupes personnalisés dont le nom commence par \"_\". Pour " +"exclure les groupes internes en boucle sur [method get_groups], utiliser le " +"code suivant:\n" +"[codeblock]\n" +"# Enregistre tous les nÅ“uds des groupes non internes au moteur (dans un " +"tableau de String).\n" +"var non_internal_groups = []\n" +"for group in get_groups():\n" +" if not group.begins_with(\"_\"):\n" +" non_internal_groups.push_back(group)\n" +"[/codeblock]" #: doc/classes/Node.xml msgid "" "Returns the node's index, i.e. its position among the siblings of its parent." msgstr "" +"Retourne l'indice du nÅ“ud, c'est-à -dire sa position parmi les enfants de son " +"parent." #: doc/classes/Node.xml msgid "" "Returns the peer ID of the network master for this node. See [method " "set_network_master]." msgstr "" +"Retourne l'identifiant du pair du maître du réseau pour ce nÅ“ud. Voir " +"[method set_network_master]." #: doc/classes/Node.xml msgid "" @@ -47309,12 +49608,33 @@ msgid "" "[[CollisionShape2D:1161], [RectangleShape2D:1156], :extents]\n" "[/codeblock]" msgstr "" +"Récupère un nÅ“ud et une de ses ressources comme spécifié par le sous-nom de " +"son [NodePath] (ex.: [code]Area2D/CollisionShape2D:shape[/code]). Si " +"plusieurs ressources imbriquées sont spécifiées dans le [NodePath], seul le " +"dernier sera récupéré.\n" +"La valeur de retour est un tableau de 3 éléments : le premier élément est le " +"[Node] (ou [code]null[/code] s'il n'est pas trouvé), le deuxième élément est " +"la [Resource] (ou [code]null[/code] si elle n'est pas trouvée), et le " +"troisième élément est le reste du [NodePath], le cas échéant.\n" +"Par exemple, en supposant que [code]Area2D/CollisionShape2D[/code] est un " +"nÅ“ud valide et que sa propriété [code]shape[/code] a été assignée à une " +"ressource [RectangleShape2D], on pourrait avoir ce type de sortie:\n" +"[codeblock]\n" +"print(get_node_and_resource(\"Area2D/CollisionShape2D\")) # " +"[[CollisionShape2D:1161], Null, ]\n" +"print(get_node_and_resource(\"Area2D/CollisionShape2D:shape\")) # " +"[[CollisionShape2D:1161], [RectangleShape2D:1156], ]\n" +"print(get_node_and_resource(\"Area2D/CollisionShape2D:shape:extents\")) # " +"[[CollisionShape2D:1161], [RectangleShape2D:1156], :extents]\n" +"[/codeblock]" #: doc/classes/Node.xml msgid "" "Similar to [method get_node], but does not log an error if [code]path[/code] " "does not point to a valid [Node]." msgstr "" +"Semblable à [method get_node], mais n'affiche pas d'erreur si [code]path[/" +"code] ne pointe pas vers une valeur valide [Node]." #: doc/classes/Node.xml msgid "" @@ -47329,12 +49649,18 @@ msgid "" "Returns the absolute path of the current node. This only works if the " "current node is inside the scene tree (see [method is_inside_tree])." msgstr "" +"Retourne le chemin absolu du nÅ“ud actuel. Cela ne fonctionne que si le nÅ“ud " +"actuel est à l'intérieur de l'arborescence de la scène (voir [method " +"is_inside_tree)]." #: doc/classes/Node.xml msgid "" "Returns the relative [NodePath] from this node to the specified [code]node[/" "code]. Both nodes must be in the same scene or the function will fail." msgstr "" +"Retourne le chemin [NodePath] relatif de ce nÅ“ud par rapport au nÅ“ud " +"[code]nÅ“ud[/code] spécifié. Les deux nÅ“uds doivent être dans la même scène " +"sinon la fonction échouera." #: doc/classes/Node.xml msgid "" @@ -47343,18 +49669,26 @@ msgid "" "processing unless the frames per second is changed via [member Engine." "iterations_per_second]." msgstr "" +"Retourne le temps écoulé (en secondes) depuis la dernière trame physique (" +"voir [method _physics_process]). C'est toujours une valeur constante dans le " +"traitement de la physique à moins que les trames par seconde ne soient " +"changés via [member Engine.iterations_per_second]." #: doc/classes/Node.xml msgid "" "Returns the node's order in the scene tree branch. For example, if called on " "the first child node the position is [code]0[/code]." msgstr "" +"Retourne l'ordre du nÅ“ud dans la branche de la scène. Par exemple, si on " +"l'appelle sur le premier nÅ“ud enfant, la position est [code]0[/code]." #: doc/classes/Node.xml msgid "" "Returns the time elapsed (in seconds) since the last process callback. This " "value may vary from frame to frame." msgstr "" +"Retourne le temps écoulé (en secondes) depuis le dernier rappel de process. " +"Cette valeur peut varier d'une trame à l'autre." #: doc/classes/Node.xml msgid "" @@ -47385,12 +49719,19 @@ msgid "" "shape[/code]. Properties with a non-[Resource] type (e.g. nodes or primitive " "math types) are not considered resources." msgstr "" +"Retourne [code]true[/code] si le [NodePath] désigne un nÅ“ud valide et son " +"sous-nom désigne une ressource valide, par exemple [code]Area2D/" +"CollisionShape2D:shape[/code]. Les propriétés avec un type qui n'est pas une " +"[Resource] (par exemple les nÅ“uds ou les types mathématiques primitifs) ne " +"sont pas considérées comme des ressources." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if the given node is a direct or indirect child of " "the current node." msgstr "" +"Retourne [code]true[/code] si le nÅ“ud donné est un enfant direct ou indirect " +"du nÅ“ud actuel." #: doc/classes/Node.xml msgid "" @@ -47411,6 +49752,8 @@ msgid "" "Returns [code]true[/code] if this node is in the specified group. See notes " "in the description, and the group methods in [SceneTree]." msgstr "" +"Retourne [code]true[/code] si ce nÅ“ud est dans le groupe spécifié. Voir les " +"notes dans la description, et les méthodes de groupe dans [SceneTree]." #: doc/classes/Node.xml msgid "" @@ -47422,6 +49765,7 @@ msgstr "" msgid "" "Returns [code]true[/code] if the local system is the master of this node." msgstr "" +"Retourne [code]true[/code] si le système local est le maître de ce nÅ“ud." #: doc/classes/Node.xml msgid "" @@ -47431,6 +49775,11 @@ msgid "" "[b]and[/b] physics interpolation is enabled within the [SceneTree]. This can " "be tested using [method is_physics_interpolated_and_enabled]." msgstr "" +"Retourne [code]true[/code] si le drapeau interpolé de la physique est défini " +"pour ce nÅ“ud (voir [member physics_interpolation_mode)].\n" +"[b]Note :[/b] L'interpolation ne sera active que si le drapeau est défini " +"[b]et[/b] que l'interpolation physique est activée dans [SceneTree]. Ceci " +"peut être testé en utilisant [method is_physics_interpolated_and_enabled]." #: doc/classes/Node.xml msgid "" @@ -47441,36 +49790,52 @@ msgid "" "See [member SceneTree.physics_interpolation] and [member ProjectSettings." "physics/common/physics_interpolation]." msgstr "" +"Retourne [code]true[/code] si l'interpolation physique est activée (voir [" +"member physics_interpolation_mode]) [b]et[/b] activée dans [SceneTree].\n" +"Il s'agit d'une version pratique de [method is_physics_interpolated] qui " +"vérifie également si l'interpolation physique est activée globalement.\n" +"Voir [member SceneTree.physics_interpolation] et [member ProjectSettings." +"physics/common/physics_interpolation]." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if physics processing is enabled (see [method " "set_physics_process])." msgstr "" +"Retourne [code]true[/code] si le traitement physique est activé (voir " +"[method set_physics_process)]." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if internal physics processing is enabled (see " "[method set_physics_process_internal])." msgstr "" +"Retourne [code]true[/code] si le traitement physique interne est activé " +"(voir [method set_physics_process_internal)]." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if processing is enabled (see [method " "set_process])." msgstr "" +"Retourne [code]true[/code] si le traitement est activé (voir [method " +"set_process)]." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if the node is processing input (see [method " "set_process_input])." msgstr "" +"Retourne [code]true[/code] si le nÅ“ud gère l'entrée (voir [method " +"set_process_input)]." #: doc/classes/Node.xml msgid "" "Returns [code]true[/code] if internal processing is enabled (see [method " "set_process_internal])." msgstr "" +"Retourne [code]true[/code] si le traitement interne est activé (voir [method " +"set_process_internal)]." #: doc/classes/Node.xml msgid "" @@ -47485,6 +49850,8 @@ msgid "" "Returns [code]true[/code] if the node is processing unhandled key input (see " "[method set_process_unhandled_key_input])." msgstr "" +"Retourne [code]true[/code] si le nÅ“ud gère l'entrée de touche non traitée " +"(voir [method set_process_unhandled_key_input)]." #: doc/classes/Node.xml msgid "" @@ -47492,12 +49859,17 @@ msgid "" "Since calls, signals, etc are performed by tree order, changing the order of " "children nodes may be useful." msgstr "" +"Déplace un nÅ“ud enfant à une position différente (ordre) parmi les autres " +"enfants. Comme les appels, les signaux, etc. sont effectués par l'ordre des " +"arborescences, changer l'ordre des nÅ“uds d'enfants peut être utile." #: doc/classes/Node.xml msgid "" "Prints all stray nodes (nodes outside the [SceneTree]). Used for debugging. " "Works only in debug builds." msgstr "" +"Imprime tous les nÅ“uds égarés (sauf le [SceneTree)]. Utilisé pour le " +"débogage. Fonctionne seulement dans les versions de débogage." #: doc/classes/Node.xml msgid "" @@ -47514,6 +49886,18 @@ msgid "" "TheGame/SplashScreen/Camera2D\n" "[/codeblock]" msgstr "" +"Imprime l'arborescence dans la console. Utilisé principalement à des fins de " +"débogage. Cette version affiche le chemin par rapport au nÅ“ud actuel, ce qui " +"est utile pour le copier/coller dans la fonction [method get_node].\n" +"[b]Exemple de sortie:[/b]\n" +"[codeblock]\n" +"TheGame\n" +"TheGame/Menu\n" +"TheGame/Menu/Label\n" +"TheGame/Menu/Camera2D\n" +"TheGame/SplashScreen\n" +"TheGame/SplashScreen/Camera2D\n" +"[/codeblock]" #: doc/classes/Node.xml msgid "" @@ -47530,6 +49914,19 @@ msgid "" " â”–â•´Camera2D\n" "[/codeblock]" msgstr "" +"Comme [method print_tree], cela imprime l'arborescence dans la console. " +"Cette version affiche une représentation plus graphique semblable à ce qui " +"est affiché dans l'inspecteur de scène. C'est utile pour inspecter les " +"grands arborescences.\n" +"[b]Exemple de sortie:[/b]\n" +"[codeblock]\n" +" â”–â•´TheGame\n" +" â” â•´Menu\n" +" ┃ â” â•´Label\n" +" ┃ â”–â•´Camera2D\n" +" â”–â•´SplashScreen\n" +" â”–â•´Camera2D\n" +"[/codeblock]" #: doc/classes/Node.xml msgid "" @@ -47540,12 +49937,20 @@ msgid "" "[code]parent_first[/code] is [code]false[/code], the children will be called " "first." msgstr "" +"Appelle la méthode donnée (si présente) avec les arguments spécifiés dans " +"[code]args[/code] sur ce nÅ“ud et récursivement sur tous ses enfants. Si " +"l'argument [code]parent_first[/code] est [code]true[/code], la méthode sera " +"appelée d'abord sur le nÅ“ud courant, puis sur tous ses enfants. Si " +"[code]parent_first[/code] est [code]false[/code], les enfants seront appelés " +"en premier." #: doc/classes/Node.xml msgid "" "Notifies the current node and all its children recursively by calling " "[method Object.notification] on all of them." msgstr "" +"Notifie le nÅ“ud actuel et tous ses enfants de façon récursive en les " +"appelant [method Object.notification] sur tous." #: doc/classes/Node.xml msgid "" @@ -47560,6 +49965,17 @@ msgid "" "[method @GDScript.is_instance_valid] before attempting to call its methods " "or access its properties." msgstr "" +"Place le nÅ“ud dans une file d'attente pour la suppression à la fin de la " +"trame actuel. Lorsque supprimé, tous ses nÅ“uds d'enfants seront supprimés " +"aussi. Cette méthode s'assure qu'il est sûr de supprimer le nÅ“ud, " +"contrairement [method Object.free]. Utilisez [method Object." +"is_queued_for_deletion] pour vérifier si un nÅ“ud sera supprimé à la fin de " +"la trame.\n" +"[b]Important:[/b] Si vous avez une variable pointant vers un nÅ“ud, il ne " +"sera [i]pas[/i] attribué à [code]null[/code] une fois le nÅ“ud libéré. Au " +"lieu de cela, il va pointer vers [i]l'instance précédemment libérée[/i] et " +"vous devez le valider avec [method @GDScript.is_instance_valid] avant de " +"risquer d'appeler des méthodes dessus ou d'accéder à ses propriétés." #: doc/classes/Node.xml msgid "" @@ -47570,6 +49986,12 @@ msgid "" "of it. After using [code]raise[/code], a Control will be drawn on top of its " "siblings." msgstr "" +"Déplace ce nÅ“ud vers le bas de la hiérarchie des enfants. Cela est souvent " +"utile dans les nÅ“uds d'interface ([Control]), parce que leur ordre de dessin " +"dépend de leur ordre dans l'arborescence. Le Node en haut est dessiné " +"d'abord, puis les nÅ“uds en dessous dans la hiérarchie qui sont " +"successivement dessinés. Après avoir utilisé [code]raise[/code], un contrôle " +"sera affiché par dessus les autres enfants." #: doc/classes/Node.xml msgid "" @@ -47577,6 +49999,9 @@ msgid "" "it exists). All event subscriptions that pass by the removed node will be " "unsubscribed." msgstr "" +"Retire un nÅ“ud et fixe tous ses enfants comme enfants du nÅ“ud parent (s'il " +"existe). Tous les souscriptions d'événement qui passent par le nÅ“ud retiré " +"seront aussi retirées." #: doc/classes/Node.xml msgid "" @@ -47585,12 +50010,19 @@ msgid "" "(or its descendants) to be [code]null[/code], if that [member owner] is no " "longer a parent or ancestor." msgstr "" +"Retire un nÅ“ud d'enfant. Le nÅ“ud n'est PAS supprimé et doit être supprimé " +"manuellement.\n" +"[b]Note :[/b] Cette fonction peut définir le [member owner] du nÅ“ud enlevé " +"(ou ses descendants) comme [code]null[/code], si ce [member owner] n'est " +"plus un parent." #: doc/classes/Node.xml msgid "" "Removes a node from a group. See notes in the description, and the group " "methods in [SceneTree]." msgstr "" +"Retire un nÅ“ud d'un groupe. Voir les notes dans la description, et les " +"méthodes de groupe dans [SceneTree]." #: doc/classes/Node.xml msgid "" @@ -47602,6 +50034,13 @@ msgid "" "need to keep it in a variable for later use or free it using [method Object." "free]." msgstr "" +"Remplace un nÅ“ud dans une scène par celui donné. Les souscriptions qui " +"passent par ce nÅ“ud seront perdus.\n" +"[b]Note :[/b] Le nÅ“ud donné deviendra le nouveau parent de tous les nÅ“uds " +"d'enfants que le nÅ“ud remplacé avait.\n" +"[b]Note :[/b] Le nÅ“ud remplacé n'est pas automatiquement libéré, donc vous " +"devez le garder dans une variable pour une utilisation ultérieure ou le " +"libérer en utilisant [method Object.free]." #: doc/classes/Node.xml msgid "" @@ -47613,6 +50052,13 @@ msgid "" "which case, [code]_ready[/code] will be called in the same order as it would " "normally)." msgstr "" +"Demande que [code]_ready[/code] soit de nouveau appelé. Notez que la méthode " +"va s'appeler immédiatement, mais qu'elle est prévue lorsque le nÅ“ud est " +"ajouté à l'arborescence de scène à nouveau (voir [method _ready)]. " +"[code]_ready[/code] est appelé seulement pour le nÅ“ud qui l'a demandé, ce " +"qui signifie que vous devez le demander pour chaque enfant si vous voulez " +"qu'ils appellent [code]_ready[/code] aussi (dans quel cas, [code]_ready[/" +"code] sera appelé dans le même ordre que normalement)." #: doc/classes/Node.xml msgid "" @@ -47628,6 +50074,17 @@ msgid "" "[b]Note:[/b] This function should be called [b]after[/b] moving the node, " "rather than before." msgstr "" +"Lorsque l'interpolation de la physique est active, déplacer un nÅ“ud vers une " +"transformation radicalement différente (comme le placement dans un niveau) " +"peut entraîner un glissement visible car l'objet est rendu lors de son " +"déplacement lors de la trame physique.\n" +"Ce glitch peut être évité en appelant [code]reset_physics_interpolation[/" +"code], qui annule temporairement l'interpolation jusqu'à ce que la trame " +"physique soit complète.\n" +"[constant NOTIFICATION_RESET_PHYSICS_INTERPOLATION] sera reçu par le nÅ“ud et " +"tous les enfants de façon récursive.\n" +"[b]Note :[/b] Cette fonction doit être appelée [b]après[/b] le déplacement " +"du nÅ“ud, plutôt qu'avant." #: doc/classes/Node.xml msgid "" @@ -47645,6 +50102,20 @@ msgid "" "like [code]server_disconnected[/code] or by checking [code]SceneTree." "network_peer.get_connection_status() == CONNECTION_CONNECTED[/code]." msgstr "" +"Envoie une requête d'appel de procédure à distance pour la [code]method[/" +"code] donnée aux pairs sur le réseau (et localement), en option en envoyant " +"tous les arguments supplémentaires comme arguments à la méthode appelée par " +"le RPC. La requête d'appel ne sera reçue que par des nÅ“uds ayant le même " +"[NodePath], y compris le même nom de nÅ“ud. Le comportement dépend de la " +"configuration RPC pour la méthode donnée, voir [method rpc_config]. Les " +"méthodes ne sont pas exposées aux RPC par défaut. Voir aussi [method rset] " +"et [method rset_config] pour les propriétés. Retourne [code]null[/code].\n" +"[b]Note :[/b] Vous pouvez seulement utiliser RPC en toute sécurité sur les " +"clients après avoir reçu le signal [code]connected_to_server[/code] du " +"[SceneTree]. Vous devez également suivre l'état de connexion, soit par les " +"signaux [SceneTree] comme [code]server_disconnected[/code] ou en vérifiant " +"[code]SceneTree.network_peer.get_connection_status() == " +"CONNECTION_CONNECTED[/code]." #: doc/classes/Node.xml msgid "" @@ -47656,6 +50127,13 @@ msgid "" "By default, methods are not exposed to networking (and RPCs). See also " "[method rset] and [method rset_config] for properties." msgstr "" +"Change le mode RPC pour la [code]method[/code] donné pour le " +"[code]mode[/code] spécifié. Voir [enum MultiplayerAPI.RPCMode]. Une " +"alternative est d'annoter les méthodes et les propriétés avec les mots-clés " +"correspondants ([code]remote[/code], [code]master[/code], [code]puppet[/code]" +", [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code])" +". Par défaut, les méthodes ne sont pas exposées au réseaut (et aux RPC). " +"Voir aussi [method rset] et [method rset_config] pour les propriétés." #: doc/classes/Node.xml msgid "" @@ -47663,6 +50141,9 @@ msgid "" "(see [method NetworkedMultiplayerPeer.set_target_peer]). Returns [code]null[/" "code]." msgstr "" +"Envoie un [method rpc] à un pair spécifique identifié par [code]peer_id[/" +"code] (voir [method NetworkedMultiplayerPeer.set_target_peer]). Retourne " +"[code]null[/code]." #: doc/classes/Node.xml msgid "" @@ -47677,6 +50158,9 @@ msgid "" "using an unreliable protocol (see [method NetworkedMultiplayerPeer." "set_target_peer]). Returns [code]null[/code]." msgstr "" +"Envoie un [method rpc] à un pair spécifique identifié par [code]peer_id[/" +"code] en utilisant un protocole non fiable (voir [method " +"NetworkedMultiplayerPeer.set_target_peer]). Retourne [code]null[/code]." #: doc/classes/Node.xml msgid "" @@ -47685,6 +50169,10 @@ msgid "" "rset_config]. See also [method rpc] for RPCs for methods, most information " "applies to this method as well." msgstr "" +"Change une propriété distante sur d'autres pairs (et localement). Le " +"comportement dépend de la configuration du RPC pour la propriété donnée, " +"voir [method rset_config]. Voir aussi [method rpc] pour les RPC sur les " +"méthodes, la plupart des informations s'appliquent aussi à cette méthode." #: doc/classes/Node.xml msgid "" @@ -47696,6 +50184,13 @@ msgid "" "By default, properties are not exposed to networking (and RPCs). See also " "[method rpc] and [method rpc_config] for methods." msgstr "" +"Change le mode RPC pour la [code]property[/code] donnée au [code]mode[/code] " +"spécifié. Voir [enum MultiplayerAPI.RPCMode]. Une alternative est " +"l'annotation des méthodes et des propriétés avec les mots-clés " +"correspondants ([code]remote[/code], [code]master[/code], [code]puppet[/code]" +", [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code])" +". Par défaut, les propriétés ne sont pas exposées au réseau (et au RPC). " +"Voir aussi [method rpc] et [method rpc_config] pour les méthodes." #: doc/classes/Node.xml msgid "" @@ -47943,11 +50438,13 @@ msgid "" msgstr "" #: doc/classes/Node.xml -#, fuzzy msgid "" "Notification received when the node is about to exit a [SceneTree].\n" "This notification is emitted [i]after[/i] the related [signal tree_exiting]." -msgstr "La notification reçue quand le nÅ“ud va quitter le [SceneTree]." +msgstr "" +"La notification reçue quand le nÅ“ud va quitter le [SceneTree].\n" +"Cette notification est émise [i]après[/i] le signal [signal tree_exiting] " +"correspondant." #: doc/classes/Node.xml msgid "Notification received when the node is moved in the parent." @@ -48241,9 +50738,8 @@ msgid "" msgstr "" #: doc/classes/NodePath.xml -#, fuzzy msgid "Pre-parsed scene tree path." -msgstr "Chemin de l'arborescence des scènes pré-analysé." +msgstr "Le chemin pré-analysé de l'arborescence des scènes." #: doc/classes/NodePath.xml msgid "" @@ -49274,19 +51770,16 @@ msgid "Sets an individual hole point position." msgstr "Définit la position d'un trou simple." #: doc/classes/OccluderShapePolygon.xml -#, fuzzy msgid "Sets an individual polygon point position." -msgstr "Définit la position d'un polygone simple." +msgstr "Définit la position d'un seul point d'un polygone." #: doc/classes/OccluderShapePolygon.xml -#, fuzzy msgid "Allows changing the hole geometry from code." -msgstr "Dessine une géométrie simple à partir du code." +msgstr "" #: doc/classes/OccluderShapePolygon.xml -#, fuzzy msgid "Allows changing the polygon geometry from code." -msgstr "Dessine une géométrie simple à partir du code." +msgstr "" #: doc/classes/OccluderShapePolygon.xml msgid "" @@ -49360,8 +51853,14 @@ msgid "See [enum ShadowDetail]." msgstr "Voir [enum ShadowDetail]." #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." -msgstr "Voir [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." +msgstr "" #: doc/classes/OmniLight.xml msgid "" @@ -49372,7 +51871,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -49549,18 +52049,16 @@ msgid "Returns the text of the item at index [code]idx[/code]." msgstr "Retourne le texte de l'élément à l'index [code]idx[/code]." #: doc/classes/OptionButton.xml -#, fuzzy msgid "Returns the tooltip of the item at index [code]idx[/code]." -msgstr "Retourne le texte de l'élément à l'index [code]idx[/code]." +msgstr "Retourne l'infobulle de l'élément à l'index [code]idx[/code]." #: doc/classes/OptionButton.xml -#, fuzzy msgid "" "Returns the ID of the selected item, or [code]-1[/code] if no item is " "selected." msgstr "" -"Retourne la position de l’élément qui a actuellement le focus. Ou retourne " -"[code]-1[/code] si aucun n'a le focus." +"Retourne l'identifiant de l’élément sélectionné, ou [code]-1[/code] si aucun " +"n'est sélectionné." #: doc/classes/OptionButton.xml msgid "" @@ -49613,9 +52111,8 @@ msgid "Sets the text of the item at index [code]idx[/code]." msgstr "Définit le texte pour l'élément à l'index [code]idx[/code]." #: doc/classes/OptionButton.xml -#, fuzzy msgid "Sets the tooltip of the item at index [code]idx[/code]." -msgstr "Définit le texte pour l'élément à l'index [code]idx[/code]." +msgstr "Définit l'infobulle pour l'élément à l'index [code]idx[/code]." #: doc/classes/OptionButton.xml msgid "" @@ -49738,9 +52235,8 @@ msgstr "" "fils d'exécutions." #: doc/classes/OS.xml -#, fuzzy msgid "Centers the window on the screen if in windowed mode." -msgstr "Définit la position du nÅ“ud spécifié." +msgstr "" #: doc/classes/OS.xml msgid "" @@ -49899,18 +52395,16 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "Returns the scancode of the given string (e.g. \"Escape\")." -msgstr "Renvoie le reste de deux vecteurs." +msgstr "" #: doc/classes/OS.xml msgid "Returns the total number of available audio drivers." msgstr "Retourne le nombre total de périphériques audio." #: doc/classes/OS.xml -#, fuzzy msgid "Returns the audio driver name for the given index." -msgstr "Retourne le sommet à l’index donné." +msgstr "" #: doc/classes/OS.xml msgid "" @@ -50329,14 +52823,13 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "Returns the epoch time of the operating system in milliseconds." -msgstr "Retourne le temps epoch du système d'exploitation en millisecondes." +msgstr "" +"Retourne l'heure de l'époque du système d'exploitation en millisecondes." #: doc/classes/OS.xml -#, fuzzy msgid "Returns the epoch time of the operating system in seconds." -msgstr "Retourne le temps epoch du système d'exploitation en secondes." +msgstr "Retourne l'heure de l'époque du système d'exploitation en secondes." #: doc/classes/OS.xml msgid "" @@ -50453,9 +52946,8 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "Returns the number of video drivers supported on the current platform." -msgstr "Renvoie le nombre de points sur l'axe de mélange." +msgstr "" #: doc/classes/OS.xml msgid "" @@ -50503,9 +52995,8 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "Returns [code]true[/code] if there is content on the clipboard." -msgstr "Retourne [code]true[/code] si l'[AABB] est plate ou vide." +msgstr "Retourne [code]true[/code] si le presse-papiers n'est pas vide." #: doc/classes/OS.xml msgid "" @@ -50527,19 +53018,19 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the device has a touchscreen or emulates one." -msgstr "Retourne [code]true[/code] (vrai) si la chaîne de caractères est vide." +msgstr "" +"Retourne [code]true[/code] si le périphérique à un écran tactile ou en " +"simule un." #: doc/classes/OS.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the platform has a virtual keyboard, " "[code]false[/code] otherwise." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide, ou " -"[code]false[/code] le cas échéant." +"Retourne [code]true[/code] si la plateforme à un clavier virtuel (non " +"physique), ou [code]false[/code] sinon." #: doc/classes/OS.xml msgid "Hides the virtual keyboard if it is shown, does nothing otherwise." @@ -50574,11 +53065,10 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the input scancode corresponds to a Unicode " "character." -msgstr "Retourne [code]true[/code] si l'[AABB] chevauche une autre." +msgstr "" #: doc/classes/OS.xml msgid "" @@ -50883,7 +53373,6 @@ msgstr "" "Windows." #: doc/classes/OS.xml -#, fuzzy msgid "" "Requests the OS to open a resource with the most appropriate program. For " "example:\n" @@ -50910,12 +53399,12 @@ msgstr "" "d'accueil de Godot dans le navigateur web par défaut.\n" "- [code]OS.shell_open(\"mailto:example@example.com\")[/code] ouvrira le " "client mail par défaut avec le champs destinataire définit à " -"[code]example@example.com[/code]. Voir [url=https://blog.escapecreative.com/" -"customizing-mailto-links/]Personnaliser les liens [code]mailto:[/code][/url] " -"pour la liste des champs qui peuvent être ajoutés.\n" +"[code]example@example.com[/code]. Voir [url=https://datatracker.ietf.org/doc/" +"html/rfc2368]RFC 2368 - The [code]mailto[/code] URL scheme[/url] pour la " +"liste des champs qui peuvent être ajoutés.\n" "Utilisez [method ProjectSettings.globalize_path] pour convertir un chemin " -"[code]res://[/code] ou [code]user://[/code] en chemin système pour utiliser " -"avec cette méthode.\n" +"[code]res://[/code] ou [code]user://[/code] en chemin système qui peut être " +"utilisé avec cette méthode.\n" "[b]Note :[/b] Cette méthode est implémentée sous Android, iOS, HTML5, Linux, " "macOS et Windows." @@ -50959,12 +53448,12 @@ msgid "" msgstr "" #: doc/classes/OS.xml -#, fuzzy msgid "" "If [code]true[/code], the engine tries to keep the screen on while the game " "is running. Useful on mobile." msgstr "" -"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité." +"Si [code]true[/code], Le moteur tente de garder l'écran allumé quand le jeu " +"est lancé. Utile sur les mobiles." #: doc/classes/OS.xml msgid "" @@ -52022,9 +54511,8 @@ msgid "" msgstr "" #: doc/classes/Particles.xml -#, fuzzy msgid "Maximum number of draw passes supported." -msgstr "Nombre maximal de passes de tirage prises en charge." +msgstr "Le nombre maximal de passes de dessin supporté." #: doc/classes/Particles2D.xml msgid "GPU-based 2D particle emitter." @@ -52702,11 +55190,10 @@ msgstr "" "dans les versions finales." #: doc/classes/Performance.xml -#, fuzzy msgid "Available static memory. Not available in release builds." msgstr "" "La mémoire statique disponible. N'est pas utilisable dans les versions " -"finales." +"exportés sans le mode débogage." #: doc/classes/Performance.xml msgid "Available dynamic memory. Not available in release builds." @@ -53539,9 +56026,8 @@ msgid "" msgstr "" #: doc/classes/Physics2DServer.xml -#, fuzzy msgid "Returns the value of a damped spring joint parameter." -msgstr "Renvoie la valeur opposée du paramètre." +msgstr "" #: doc/classes/Physics2DServer.xml #, fuzzy @@ -53549,8 +56035,8 @@ msgid "" "Sets a damped spring joint parameter. See [enum DampedStringParam] for a " "list of available parameters." msgstr "" -"Définit la valeur d’un paramètre de zone. Voir [enum AreaParameter] pour une " -"liste de paramètres disponibles." +"Définit la valeur d’un paramètre de zone. Voir [enum DampedStringParam] pour " +"une liste de paramètres disponibles." #: doc/classes/Physics2DServer.xml msgid "" @@ -54518,18 +57004,16 @@ msgid "Creates a [SliderJoint]." msgstr "Crée un [SliderJoint]." #: doc/classes/PhysicsServer.xml -#, fuzzy msgid "Gets the priority value of the Joint." -msgstr "Renvoie la valeur opposée du paramètre." +msgstr "" #: doc/classes/PhysicsServer.xml msgid "Returns the type of the Joint." msgstr "Retourne le type de Joint." #: doc/classes/PhysicsServer.xml -#, fuzzy msgid "Sets the priority value of the Joint." -msgstr "Renvoie la valeur opposée du paramètre." +msgstr "Définit la priorité de la valeur du Joint." #: doc/classes/PhysicsServer.xml msgid "" @@ -54810,20 +57294,17 @@ msgid "" msgstr "" #: doc/classes/PhysicsServer.xml -#, fuzzy msgid "If set, linear motion is possible within the given limits." msgstr "" -"Si [code]set[/code] il y a un mouvement linéaire possible dans les limites " -"données." +"Si définit, le mouvement linéaire est possible dans les limites données." #: doc/classes/PhysicsServer.xml msgid "If set, rotational motion is possible." msgstr "Si définit, la rotation est possible." #: doc/classes/PhysicsServer.xml -#, fuzzy msgid "If set, there is a rotational motor across these axes." -msgstr "La vitesse de toutes les rotations à travers l’axe X." +msgstr "" #: doc/classes/PhysicsServer.xml msgid "" @@ -54884,14 +57365,12 @@ msgid "Sets the [Shape] that will be used for collision/intersection queries." msgstr "" #: doc/classes/PhysicsShapeQueryParameters.xml -#, fuzzy msgid "If [code]true[/code], the query will take [Area]s into account." -msgstr "Si [code]true[/code], la texture sera centrée." +msgstr "Si [code]true[/code], le requête prendra les [Area] en compte." #: doc/classes/PhysicsShapeQueryParameters.xml -#, fuzzy msgid "If [code]true[/code], the query will take [PhysicsBody]s into account." -msgstr "Si [code]true[/code], la texture sera centrée." +msgstr "Si [code]true[/code], le requête prendra les [PhysicsBody] en compte." #: doc/classes/PinJoint.xml #, fuzzy @@ -54917,13 +57396,10 @@ msgid "" msgstr "" #: doc/classes/PinJoint.xml -#, fuzzy msgid "" "If above 0, this value is the maximum value for an impulse that this Joint " "produces." msgstr "" -"Retourne quand la mot clé [code]keyword[/code] spécifié a une couleur de " -"défini ou non." #: doc/classes/PinJoint2D.xml #, fuzzy @@ -54962,11 +57438,8 @@ msgid "" msgstr "" #: doc/classes/Plane.xml -#, fuzzy msgid "Creates a plane from the three points, given in clockwise order." -msgstr "" -"Crée un plan à partir des trois points, donné dans le sens des aiguilles " -"d’une montre." +msgstr "Crée un plan à partir de trois points, spécifiés dans le sens horaire." #: doc/classes/Plane.xml msgid "Creates a plane from the normal and the plane's distance to the origin." @@ -55194,9 +57667,8 @@ msgid "Returns the path to the node associated with the specified bone." msgstr "Retourne le chemin d’accès au nÅ“ud associé à l’os spécifié." #: doc/classes/Polygon2D.xml -#, fuzzy msgid "Returns the height values of the specified bone." -msgstr "Retourne la hauteur de l'os spécifié." +msgstr "Retourne les valeurs de hauteur de l'os spécifié." #: doc/classes/Polygon2D.xml msgid "Sets the path to the node associated with the specified bone." @@ -55463,6 +57935,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "Change l'octet à la position donnée." +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "Tris les éléments du tableau dans l'ordre croissant." + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -55473,7 +57952,6 @@ msgstr "" "nouveau [PoolByteArray]. Chaque index négatif partira de la fin du tableau." #: doc/classes/PoolColorArray.xml -#, fuzzy msgid "A pooled array of [Color]s." msgstr "Un tableau compacté de [Color]." @@ -55638,9 +58116,8 @@ msgid "Changes the int at the given index." msgstr "Modifie le [int] à l’index donné." #: doc/classes/PoolRealArray.xml -#, fuzzy msgid "A pooled array of real numbers ([float])." -msgstr "Un tableau compacté de flottants ([float])." +msgstr "Un tableau compacté de nombres réels (des flottants, [float])." #: doc/classes/PoolRealArray.xml msgid "" @@ -55719,7 +58196,6 @@ msgid "Changes the float at the given index." msgstr "Change la flottant à la position donnée." #: doc/classes/PoolStringArray.xml -#, fuzzy msgid "A pooled array of [String]s." msgstr "Un tableau compacté de [String]." @@ -55798,7 +58274,6 @@ msgid "Changes the [String] at the given index." msgstr "Change la [String] à la position donnée." #: doc/classes/PoolVector2Array.xml -#, fuzzy msgid "A pooled array of [Vector2]s." msgstr "Un tableau compacté de [Vector2]." @@ -55880,7 +58355,6 @@ msgid "A pooled array of [Vector3]." msgstr "Un tableau compacté de [Vector3]." #: doc/classes/PoolVector3Array.xml -#, fuzzy msgid "" "An array specifically designed to hold [Vector3]. Optimized for memory " "usage, does not fragment the memory.\n" @@ -56043,9 +58517,8 @@ msgstr "" "[WindowDialog]." #: doc/classes/PopupDialog.xml -#, fuzzy msgid "Sets a custom [StyleBox] for the panel of the [PopupDialog]." -msgstr "[StyleBox] par défaut pour le [Button]." +msgstr "" #: doc/classes/PopupMenu.xml msgid "PopupMenu displays a list of options." @@ -56275,7 +58748,6 @@ msgid "" msgstr "" #: doc/classes/PopupMenu.xml -#, fuzzy msgid "" "Returns the tooltip associated with the specified index [code]idx[/code]." msgstr "Retourne l'infobulle associée avec l'index [code]idx[/code] spécifié." @@ -56338,9 +58810,8 @@ msgid "" msgstr "" #: doc/classes/PopupMenu.xml -#, fuzzy msgid "Sets the currently focused item as the given [code]index[/code]." -msgstr "Retourne la position du point à l'index [code]point[/code]." +msgstr "" #: doc/classes/PopupMenu.xml msgid "Hides the [PopupMenu] when the window loses focus." @@ -56430,11 +58901,10 @@ msgstr "" "spécifié." #: doc/classes/PopupMenu.xml -#, fuzzy msgid "" "Toggles the check state of the item of the specified index [code]idx[/code]." msgstr "" -"Active l'état de contrôle de l'élément de l'index spécifié [code]idx[/code]." +"Bascule l'état de contrôle de l'élément de l'index [code]idx[/code] spécifié." #: doc/classes/PopupMenu.xml msgid "" @@ -56848,9 +59318,8 @@ msgid "" msgstr "" #: doc/classes/ProceduralSky.xml -#, fuzzy msgid "Amount of energy contribution from the sun." -msgstr "Montant de la contribution énergétique du ciel." +msgstr "La quantité de contribution énergétique du ciel." #: doc/classes/ProceduralSky.xml msgid "The sun's height using polar coordinates." @@ -57102,6 +59571,16 @@ msgid "" "specify the offset in bytes to the start of the resource pack. This is only " "supported for .pck files." msgstr "" +"Charge le contenu du fichier .pck ou .zip spécifié par [code]pack[/code] " +"dans le système de fichiers de ressources ([code]res://[/code]). Retourne " +"[code]true[/code] en cas de succès.\n" +"[b]Note :[/b] Si un fichier de [code]pack[/code] partage le même chemin " +"qu'un fichier déjà dans le système de fichiers de ressources, toute " +"tentative de charger ce fichier utilisera le fichier de [code]pack[/code] " +"sauf si [code]replace_files[/code] est défini à [code]false[/code].\n" +"[b]Note :[/b] Le paramètre optionnel [code]offset[/code] peut être utilisé " +"pour spécifier le décalage en octets au début du pack de ressources. Ceci " +"n'est pris en charge que pour les fichiers .pck." #: doc/classes/ProjectSettings.xml msgid "" @@ -57109,18 +59588,25 @@ msgid "" "to the absolute, native OS [code]path[/code]. See also [method " "globalize_path]." msgstr "" +"Retourne le chemin localisé (démarrant par [code]res://[/code]) " +"correspondant au chemin [code]path[/code] absolu et natif du système " +"d'exploitation. Voir aussi [method globalize_path]." #: doc/classes/ProjectSettings.xml msgid "" "Returns [code]true[/code] if the specified property exists and its initial " "value differs from the current value." msgstr "" +"Retourne [code]true[/code] si la propriété spécifiée existe et sa valeur " +"initiale diffère de la valeur actuelle." #: doc/classes/ProjectSettings.xml msgid "" "Returns the specified property's initial value. Returns [code]null[/code] if " "the property does not exist." msgstr "" +"Retourne la valeur initiale de la propriété spécifiée. Retourne " +"[code]null[/code] si la propriété n'existe pas." #: doc/classes/ProjectSettings.xml msgid "" @@ -57130,6 +59616,12 @@ msgid "" "want to change project settings in exported projects, use [method " "save_custom] to save [code]override.cfg[/code] file." msgstr "" +"Enregistre la configuration du fichier [code]project.godot[/code].\n" +"[b]Note :[/b] Cette méthode est destinée à être utilisée par les greffons de " +"l'éditeur, puisque [ProjectSettings] ne peut pas être modifié puis chargé " +"directement dans une application lancée. Si vous voulez modifier les " +"paramètres de projet depuis un projet exporté, utilisez [method save_custom] " +"pour enregistrer le fichier [code]override.cfg[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -57139,18 +59631,28 @@ msgid "" "code] file, which is also text, but can be used in exported projects unlike " "other formats." msgstr "" +"Enregistre la configuration vers un fichier personnalisé. L'extension de " +"fichier doit être [code].godot[/code] (pour enregistrer dans le format " +"[ConfigFile] au format texte) ou [code].binary[/code] (pour enregistrer au " +"format binaire). Vous pouvez également enregistrer le fichier [code]override." +"cfg[/code], qui est également au format texte, mais peut être utilisé dans " +"des projets exportés contrairement aux autres formats." #: doc/classes/ProjectSettings.xml msgid "" "Sets the specified property's initial value. This is the value the property " "reverts to." msgstr "" +"Définit la valeur initiale de la propriété spécifiée. C'est cette valeur qui " +"sera rétablie pour cette propriété." #: doc/classes/ProjectSettings.xml msgid "" "Sets the order of a configuration value (influences when saved to the config " "file)." msgstr "" +"Définit l'ordre d'une valeur de configuration (qui a une influence quand " +"sauvegardée dans le fichier de configuration)." #: doc/classes/ProjectSettings.xml msgid "" @@ -57162,6 +59664,14 @@ msgid "" "This can also be used to erase custom project settings. To do this change " "the setting value to [code]null[/code]." msgstr "" +"Définit la valeur d'un réglage.\n" +"[b]Exemple :[/b]\n" +"[codeblock]\n" +"ProjectSettings.set_setting(\"application/config/name\", \"Example\")\n" +"/[codeblock]\n" +"Cela peut également être utilisé pour effacer les paramètres de projet " +"personnalisés. Pour ce faire, utilisez la valeur [code]null[/code] pour le " +"réglage." #: doc/classes/ProjectSettings.xml msgid "" @@ -57186,6 +59696,9 @@ msgid "" "(preserving the aspect ratio) when the engine starts. If [code]false[/code], " "the engine will leave it at the default pixel size." msgstr "" +"Si [code]true[/code], étire l'image au lancement du jeu suivant la taille de " +"la fenêtre (et préserve le ratio). Si [code]false[/code], l'image sera " +"affichée par défaut suivant sa taille en pixels." #: doc/classes/ProjectSettings.xml msgid "" @@ -57194,6 +59707,10 @@ msgid "" "[b]Note:[/b] Only effective if [member application/boot_splash/show_image] " "is [code]true[/code]." msgstr "" +"Le chemin vers une image utilisée au lancement du jeu. Si vide, l'image avec " +"le logo de Godot sera affichée à la place.\n" +"[b]Note :[/b] Ne fonctionne que si [member application/boot_splash/" +"show_image] est [code]true[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -57202,6 +59719,10 @@ msgid "" "displays the plain color specified in [member application/boot_splash/" "bg_color]." msgstr "" +"Si [code]true[/code], affiche l'image spécifiée dans [member application/" +"boot_splash/image] lorsque le moteur démarre. Si [code]false[/code], affiche " +"seulement la couleur spécifiée dans [member application/boot_splash/" +"bg_color]." #: doc/classes/ProjectSettings.xml msgid "" @@ -57209,6 +59730,10 @@ msgid "" "(recommended for high-resolution artwork). If [code]false[/code], uses " "nearest-neighbor interpolation (recommended for pixel art)." msgstr "" +"Si [code]true[/code], applique le filtrage linéaire pour l'étirement de " +"l'image (recommandé pour les images à haute résolution.) Si " +"[code]false[/code], utilise l'interpolation la plus proche (recommandée pour " +"le pixel-art)." #: doc/classes/ProjectSettings.xml msgid "" @@ -57222,24 +59747,41 @@ msgid "" "The [member application/config/use_custom_user_dir] setting must be enabled " "for this to take effect." msgstr "" +"Ce dossier utilisateur est utilisé pour stocker des données persistantes (le " +"système de fichiers [code]user://[/code]). Si laissé vide, " +"[code]user://[/code] va pointer vers un dossier spécifique au projet suivant " +"la configuration de Godot (voir [method OS.get_user_data_dir]). Si un nom de " +"dossier personnalisé est défini, ce nom sera utilisé à la place, puis ajouté " +"au dossier de données utilisateur spécifique au système (le même dossier " +"parent que celui configuration Godot documenté dans [method OS." +"get_user_data_dir]).\n" +"Le paramètre [member application/config/use_custom_user_dir] doit être actif " +"pour que cela fonctionne." #: doc/classes/ProjectSettings.xml msgid "" "The project's description, displayed as a tooltip in the Project Manager " "when hovering the project." msgstr "" +"La description du projet, affichée en tant qu'infobulle dans le Gestionnaire " +"de projet quand le projet est survolé." #: doc/classes/ProjectSettings.xml msgid "" "Icon used for the project, set when project loads. Exporters will also use " "this icon when possible." msgstr "" +"L'icône utilisée pour le projet, défini au chargement du projet. Les " +"exportateurs utiliseront également cette icône si possible." #: doc/classes/ProjectSettings.xml msgid "" "Icon set in [code].icns[/code] format used on macOS to set the game's icon. " "This is done automatically on start by calling [method OS.set_native_icon]." msgstr "" +"L'icône définit dans le format [code].icns[/code] utilisé sur macOS pour " +"définir l'icône du jeu. Ceci est fait automatiquement au lancement en " +"appelant [method OS.set_native_icon]." #: doc/classes/ProjectSettings.xml msgid "" @@ -57288,12 +59830,28 @@ msgid "" "default can impact compatibility with some external tools or plugins which " "expect the default [code].import[/code] folder." msgstr "" +"Si [code]true[/code], le projet utilisera un dossier caché ([code]." +"import[/code]) pour stocker des données spécifiques au projet (métadonnées, " +"cache des shaders, etc.)\n" +"Si [code]false[/code], un dossier non caché ([code]import[/code]) sera " +"utilisé à la place.\n" +"[b]Note :[/b] Vous devez redémarrer l'application après avoir modifié ce " +"réglage.\n" +"[b]Note :[/b] Changer cette valeur peut aider sur les plateformes ou avec " +"des outils tiers où les modèles de dossier cachés ne sont pas autorisés. Il " +"suffit de modifier ce paramètre si vous savez que votre environnement " +"l'exige, car le changer par défaut peut impacter la compatibilité avec " +"certains outils ou greffons externes qui s'attendent à ce que le dossier par " +"défaut soit [code].import[/code]." #: doc/classes/ProjectSettings.xml msgid "" "Icon set in [code].ico[/code] format used on Windows to set the game's icon. " "This is done automatically on start by calling [method OS.set_native_icon]." msgstr "" +"L'icône définit dans le format [code].ico[/code] utilisé sur Windows pour " +"définir l'icône du jeu. Ceci est fait automatiquement au lancement en " +"appelant [method OS.set_native_icon]." #: doc/classes/ProjectSettings.xml msgid "" @@ -57523,11 +60081,10 @@ msgstr "" "ne généreront pas d'avertissements." #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "If [code]true[/code], enables warnings when the type of the default value " "set to an exported variable is different than the specified export type." -msgstr "Si [code]true[/code], le filtrage est activé." +msgstr "" #: doc/classes/ProjectSettings.xml msgid "" @@ -57679,17 +60236,14 @@ msgstr "" "qui n'est pas garantie d'exister dans la classe à la compilation." #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "If [code]true[/code], enables warnings when a function parameter is unused." msgstr "" -"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité." #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "If [code]true[/code], enables warnings when a member variable is unused." -msgstr "Si [code]true[/code], le filtrage est activé." +msgstr "" #: doc/classes/ProjectSettings.xml msgid "If [code]true[/code], enables warnings when a signal is unused." @@ -57779,42 +60333,57 @@ msgstr "" #: doc/classes/ProjectSettings.xml msgid "Maximum call stack in visual scripting, to avoid infinite recursion." msgstr "" +"Le nombre maximal de la pile d'appels dans le script visuel, pour éviter une " +"récursion infinie." #: doc/classes/ProjectSettings.xml msgid "" "Color of the contact points between collision shapes, visible when \"Visible " "Collision Shapes\" is enabled in the Debug menu." msgstr "" +"La couleur des points de contact entre les formes de collision, visible " +"lorsque \"Formes de collision visibles\" est activé dans le menu Débogage." #: doc/classes/ProjectSettings.xml msgid "" "Sets whether 2D physics will display collision outlines in game when " "\"Visible Collision Shapes\" is enabled in the Debug menu." msgstr "" +"Définit si la physique 2D affichera les contours de collision dans le jeu " +"lorsque \"Formes de collision visibles\" est activé dans le menu Débogage." #: doc/classes/ProjectSettings.xml msgid "" "Maximum number of contact points between collision shapes to display when " "\"Visible Collision Shapes\" is enabled in the Debug menu." msgstr "" +"Le nombre maximal de points de contact entre les formes de collision à " +"afficher lorsque \"Formes de collision visibles\" est activé dans le menu " +"Débogage." #: doc/classes/ProjectSettings.xml msgid "" "Color of the collision shapes, visible when \"Visible Collision Shapes\" is " "enabled in the Debug menu." msgstr "" +"La couleur des formes de collision, visible lorsque \"Formes de collision " +"visibles\" est activé dans le menu Débogage." #: doc/classes/ProjectSettings.xml msgid "" "Color of the disabled navigation geometry, visible when \"Visible " "Navigation\" is enabled in the Debug menu." msgstr "" +"La couleur de la géométrie de navigation désactivée, visible lorsque " +"\"Navigation visible\" est activée dans le menu Débogage." #: doc/classes/ProjectSettings.xml msgid "" "Color of the navigation geometry, visible when \"Visible Navigation\" is " "enabled in the Debug menu." msgstr "" +"La couleur de la géométrie de navigation, visible lorsque \"Navigation " +"visible\" est activée dans le menu Débogage." #: doc/classes/ProjectSettings.xml msgid "Custom image for the mouse cursor (limited to 256×256)." @@ -58011,18 +60580,25 @@ msgid "" "Load the previously opened VCS plugin when the editor starts up. This is set " "to [code]true[/code] whenever a new VCS plugin is initialized." msgstr "" +"Charge le greffon VCS précédemment ouvert dès que l'éditeur démarre. Ceci " +"est défini à [code]true[/code] chaque fois qu'un nouveau greffon VCS est " +"initialisé." #: doc/classes/ProjectSettings.xml msgid "" "Last loaded VCS plugin name. Used to autoload the plugin when the editor " "starts up." msgstr "" +"Le dernier nom de greffon VCS chargé. Utilisé pour recharger le greffon dès " +"que l'éditeur démarre." #: doc/classes/ProjectSettings.xml msgid "" "Default value for [member ScrollContainer.scroll_deadzone], which will be " "used for all [ScrollContainer]s unless overridden." msgstr "" +"La valeur par défaut pour [member ScrollContainer.scroll_deadzone], qui sera " +"utilisé pour tous les [ScrollContainer] à moins d'être surchargé." #: doc/classes/ProjectSettings.xml msgid "" @@ -58042,6 +60618,8 @@ msgid "" "If [code]true[/code], swaps OK and Cancel buttons in dialogs on Windows and " "UWP to follow interface conventions." msgstr "" +"Si [code]true[/code], échange des boutons OK et Annuler dans les dialogues " +"sur Windows et UWP pour suivre les conventions d'interface." #: doc/classes/ProjectSettings.xml msgid "" @@ -58054,6 +60632,8 @@ msgid "" "Path to a custom [Font] resource to use as default for all GUI elements of " "the project." msgstr "" +"Le chemin vers une [Font] personnalisée à utiliser par défaut pour tous les " +"éléments graphiques du projet." #: doc/classes/ProjectSettings.xml msgid "If [code]true[/code], makes sure the theme used works with HiDPI." @@ -58257,208 +60837,278 @@ msgid "" "If [code]true[/code], sends mouse input events when tapping or swiping on " "the touchscreen." msgstr "" +"Si [code]true[/code], envoie des événements d'entrée de la souris lorsque " +"vous tapez ou glissez sur l'écran tactile." #: doc/classes/ProjectSettings.xml msgid "" "If [code]true[/code], sends touch input events when clicking or dragging the " "mouse." msgstr "" +"Si [code]true[/code], envoie des événements d'entrée tactile lorsque vous " +"cliquez ou faites glisser la souris." #: doc/classes/ProjectSettings.xml msgid "Default delay for touch events. This only affects iOS devices." msgstr "" +"Un retard par défaut pour les événements tactiles. Cela n'affecte que les " +"appareils iOS." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 1. If left empty, the layer will " "display as \"Layer 1\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 1. Si vide, le " +"calque s'affichera comme \"Calque 1\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 10. If left empty, the layer will " "display as \"Layer 10\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 10. Si vide, la " +"calque s'affichera comme \"Calque 10\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 11. If left empty, the layer will " "display as \"Layer 11\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 11. Si vide, la " +"calque s'affichera comme \"Calque 11\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 12. If left empty, the layer will " "display as \"Layer 12\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 12. Si vide, la " +"calque s'affichera comme \"Calque 12\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 13. If left empty, the layer will " "display as \"Layer 13\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 13. Si vide, la " +"calque s'affichera comme \"Calque 13\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 14. If left empty, the layer will " "display as \"Layer 14\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 14. Si vide, la " +"calque s'affichera comme \"Calque 14\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 15. If left empty, the layer will " "display as \"Layer 15\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 15. Si vide, la " +"calque s'affichera comme \"Calque 15\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 16. If left empty, the layer will " "display as \"Layer 16\"." msgstr "" +"Nom facultatif pour la calque de navigation 2D numéro 16. Si vide, la calque " +"s'affichera comme \"Calque 16\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 17. If left empty, the layer will " "display as \"Layer 17\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 17. Si vide, la " +"calque s'affichera comme \"Calque 17\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 18. If left empty, the layer will " "display as \"Layer 18\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 18. Si vide, la " +"calque s'affichera comme \"Calque 18\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 19. If left empty, the layer will " "display as \"Layer 19\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 19. Si vide, la " +"calque s'affichera comme \"Calque 19\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 2. If left empty, the layer will " "display as \"Layer 2\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 2. Si vide, la " +"calque affichera comme « calque 2 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 20. If left empty, the layer will " "display as \"Layer 20\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 20. Si vide, la " +"calque s'affichera comme \"Calque 20\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 21. If left empty, the layer will " "display as \"Layer 21\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 21. Si vide, la " +"calque s'affichera comme \"Calque 21\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 22. If left empty, the layer will " "display as \"Layer 22\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 22. Si vide, la " +"calque s'affichera comme \"Calque 22\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 23. If left empty, the layer will " "display as \"Layer 23\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 23. Si vide, la " +"calque s'affichera comme \"Calque 23\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 24. If left empty, the layer will " "display as \"Layer 24\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 24. Si vide, la " +"calque s'affichera comme \"Calque 24\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 25. If left empty, the layer will " "display as \"Layer 25\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 25. Si vide, la " +"calque s'affichera comme \"Calque 25\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 26. If left empty, the layer will " "display as \"Layer 26\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 26. Si vide, la " +"calque s'affichera comme \"Calque 26\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 27. If left empty, the layer will " "display as \"Layer 27\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 27. Si vide, la " +"calque s'affichera comme \"Calque 27\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 28. If left empty, the layer will " "display as \"Layer 28\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 28. Si vide, la " +"calque s'affichera comme \"Calque 28\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 29. If left empty, the layer will " "display as \"Layer 29\"." msgstr "" +"Nom facultatif pour la calque de navigation 2D numéro 29. Si vide, la calque " +"s'affichera comme \"Calque 29\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 3. If left empty, the layer will " "display as \"Layer 3\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 3. Si vide, la " +"calque s'affichera comme « calque 3 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 30. If left empty, the layer will " "display as \"Layer 30\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 30. Si vide, la " +"calque s'affichera comme \"Calque 30\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 31. If left empty, the layer will " "display as \"Layer 31\"." msgstr "" +"Nom facultatif pour la calque de navigation 2D numéro 31. Si vide, la calque " +"s'affichera comme \"Calque 31\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 32. If left empty, the layer will " "display as \"Layer 32\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 32. Si vide, la " +"calque s'affichera comme \"Calque 32\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 4. If left empty, the layer will " "display as \"Layer 4\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 4. Si vide, la " +"calque apparaîtra comme \"Calque 4\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 5. If left empty, the layer will " "display as \"Layer 5\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 5. Si vide, le " +"calque affichera comme \"Calque 5\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 6. If left empty, the layer will " "display as \"Layer 6\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 6. Si vide, la " +"calque apparaîtra comme \"Calque 6\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 7. If left empty, the layer will " "display as \"Layer 7\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 7. Si vide, la " +"calque s'affichera comme « calque 7 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 8. If left empty, the layer will " "display as \"Layer 8\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 8. Si vide, la " +"calque s'affichera comme \"Calque 8\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 2D navigation layer 9. If left empty, the layer will " "display as \"Layer 9\"." msgstr "" +"Le nom optionnel pour la calque de navigation 2D numéro 9. Si vide, la " +"calque s'affichera comme \"Calque 9\"." #: doc/classes/ProjectSettings.xml msgid "Optional name for the 2D physics layer 1." @@ -58673,192 +61323,256 @@ msgid "" "Optional name for the 3D navigation layer 1. If left empty, the layer will " "display as \"Layer 1\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 1. Si vide, le " +"calque s'affichera comme \"Calque 1\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 10. If left empty, the layer will " "display as \"Layer 10\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 10. Si vide, la " +"calque s'affichera comme \"Calque 10\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 11. If left empty, the layer will " "display as \"Layer 11\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 11. Si vide, la " +"calque s'affichera comme \"Calque 11\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 12. If left empty, the layer will " "display as \"Layer 12\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 12. Si vide, la " +"calque s'affichera comme \"Calque 12\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 13. If left empty, the layer will " "display as \"Layer 13\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 13. Si vide, la " +"calque s'affichera comme \"Calque 13\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 14. If left empty, the layer will " "display as \"Layer 14\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 14. Si vide, la " +"calque s'affichera comme \"Calque 14\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 15. If left empty, the layer will " "display as \"Layer 15\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 15. Si vide, la " +"calque s'affichera comme \"Calque 15\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 16. If left empty, the layer will " "display as \"Layer 16\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 16. Si vide, la " +"calque s'affichera comme \"Calque 16\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 17. If left empty, the layer will " "display as \"Layer 17\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 17. Si vide, la " +"calque s'affichera comme \"Calque 17\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 18. If left empty, the layer will " "display as \"Layer 18\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 18. Si vide, la " +"calque s'affichera comme \"Calque 18\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 19. If left empty, the layer will " "display as \"Layer 19\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 19. Si vide, la " +"calque s'affichera comme \"Calque 19\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 2. If left empty, the layer will " "display as \"Layer 2\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 2. Si vide, la " +"calque affichera comme « calque 2 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 20. If left empty, the layer will " "display as \"Layer 20\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 20. Si vide, la " +"calque s'affichera comme \"Calque 20\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 21. If left empty, the layer will " "display as \"Layer 21\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 21. Si vide, la " +"calque s'affichera comme \"Calque 21\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 22. If left empty, the layer will " "display as \"Layer 22\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 22. Si vide, la " +"calque s'affichera comme \"Calque 22\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 23. If left empty, the layer will " "display as \"Layer 23\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 23. Si vide, la " +"calque s'affichera comme \"Calque 23\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 24. If left empty, the layer will " "display as \"Layer 24\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 24. Si vide, la " +"calque s'affichera comme \"Calque 24\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 25. If left empty, the layer will " "display as \"Layer 25\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 25. Si vide, la " +"calque s'affichera comme \"Calque 25\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 26. If left empty, the layer will " "display as \"Layer 26\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 26. Si vide, la " +"calque s'affichera comme \"Calque 26\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 27. If left empty, the layer will " "display as \"Layer 27\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 27. Si vide, la " +"calque s'affichera comme \"Calque 27\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 28. If left empty, the layer will " "display as \"Layer 28\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 28. Si vide, la " +"calque s'affichera comme \"Calque 28\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 29. If left empty, the layer will " "display as \"Layer 29\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 29. Si vide, la " +"calque s'affichera comme \"Calque 29\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 3. If left empty, the layer will " "display as \"Layer 3\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 3. Si vide, la " +"calque s'affichera comme « calque 3 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 30. If left empty, the layer will " "display as \"Layer 30\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 30. Si vide, la " +"calque s'affichera comme \"Calque 30\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 31. If left empty, the layer will " "display as \"Layer 31\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 31. Si vide, la " +"calque s'affichera comme \"Calque 31\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 32. If left empty, the layer will " "display as \"Layer 32\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 32. Si vide, la " +"calque s'affichera comme \"Calque 32\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 4. If left empty, the layer will " "display as \"Layer 4\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 4. Si vide, la " +"calque apparaîtra comme \"Calque 4\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 5. If left empty, the layer will " "display as \"Layer 5\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 5. Si vide, le " +"calque affichera comme \"Calque 5\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 6. If left empty, the layer will " "display as \"Layer 6\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 6. Si vide, la " +"calque apparaîtra comme \"Calque 6\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 7. If left empty, the layer will " "display as \"Layer 7\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 7. Si vide, la " +"calque s'affichera comme « calque 7 »." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 8. If left empty, the layer will " "display as \"Layer 8\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 8. Si vide, la " +"calque s'affichera comme \"Calque 8\"." #: doc/classes/ProjectSettings.xml msgid "" "Optional name for the 3D navigation layer 9. If left empty, the layer will " "display as \"Layer 9\"." msgstr "" +"Le nom optionnel pour la calque de navigation 3D numéro 9. Si vide, la " +"calque s'affichera comme \"Calque 9\"." #: doc/classes/ProjectSettings.xml msgid "Optional name for the 3D physics layer 1." @@ -59009,9 +61723,8 @@ msgid "Optional name for the 3D render layer 13." msgstr "Le nom facultatif pour le calque 13 de rendu 3D." #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "Optional name for the 3D render layer 14." -msgstr "Le nom facultatif pour le calque 14 de rendu 3D" +msgstr "Le nom facultatif pour le calque 14 de rendu 3D." #: doc/classes/ProjectSettings.xml msgid "Optional name for the 3D render layer 15." @@ -59074,6 +61787,8 @@ msgid "" "The locale to fall back to if a translation isn't available in a given " "language. If left empty, [code]en[/code] (English) will be used." msgstr "" +"Le langage de repli si une traduction n'est pas disponible dans une langue " +"donnée. Si laissé vide, [code]en[/code] (anglais) sera utilisé." #: doc/classes/ProjectSettings.xml msgid "" @@ -59092,6 +61807,9 @@ msgid "" "Desktop override for [member logging/file_logging/enable_file_logging], as " "log files are not readily accessible on mobile/Web platforms." msgstr "" +"Le surcharge du bureau pour [member logging/file_logging/enable_file_logging]" +", car les fichiers de journaux ne sont pas facilement accessibles sur les " +"plateformes mobiles et web." #: doc/classes/ProjectSettings.xml msgid "" @@ -59892,6 +62610,12 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]." msgstr "" +"La valeur par défaut est une surcharge très conservatrice pour [member " +"rendering/gles3/shaders/max_simultaneous_compiles].\n" +"Selon les appareils spécifiques que vous ciblez, vous pouvez vouloir " +"l'augmenter.\n" +"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/" +"shader_compilation_mode] n'est [b]pas[/b] à [code]Synchrone[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -59902,6 +62626,12 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]." msgstr "" +"La valeur par défaut est une surcharge très conservatrice pour [member " +"rendering/gles3/shaders/max_simultaneous_compiles].\n" +"Selon les navigateurs spécifiques que vous ciblez, vous pouvez vouloir " +"l'augmenter.\n" +"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/" +"shader_compilation_mode] n'est [b]pas[/b] à [code]Synchrone[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -59911,6 +62641,11 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]." msgstr "" +"La taille maximale, en mégaoctets, que le cache de ubershader peut " +"atteindre. Au démarrage, les entrées les moins récemment utilisées seront " +"supprimées jusqu'à ce que la taille totale soit dans les limites.\n" +"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/" +"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -59920,6 +62655,11 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]." msgstr "" +"Une surcharge pour [member rendering/gles3/shaders/shader_cache_size_mb], de " +"sorte qu'une taille maximale plus petite peut être configurée pour les " +"plates-formes mobiles, où l'espace de stockage est plus limité.\n" +"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/" +"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -59931,6 +62671,13 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]." msgstr "" +"Une surcharge pour [member rendering/gles3/shaders/shader_cache_size_mb], de " +"sorte qu'une taille maximale plus petite peut être configurée pour les " +"plateformes web, où l'espace de stockage est plus limité.\n" +"[b]Note :[/b] Actuellement, le caisson d'ombrage n'est généralement pas " +"disponible sur les plateformes Web.\n" +"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/" +"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]." #: doc/classes/ProjectSettings.xml msgid "" @@ -59980,24 +62727,33 @@ msgid "" "Max buffer size for blend shapes. Any blend shape bigger than this will not " "work." msgstr "" +"La capacité maximale de la mémoire tampon pour les formes de mélange. Toute " +"forme de mélange plus grande que cela ne fonctionnera pas." #: doc/classes/ProjectSettings.xml msgid "" "Max buffer size for drawing polygons. Any polygon bigger than this will not " "work." msgstr "" +"La capacity maximale de la mémoire tampon pour dessiner des polygones. Tout " +"polygone plus grand que cela ne fonctionnera pas." #: doc/classes/ProjectSettings.xml msgid "" "Max index buffer size for drawing polygons. Any polygon bigger than this " "will not work." msgstr "" +"La capacity maximale de la mémoire tampon pour le dessin des polygones. Tout " +"polygone plus grand que cela ne fonctionnera pas." #: doc/classes/ProjectSettings.xml msgid "" "Max buffer size for drawing immediate objects (ImmediateGeometry nodes). " "Nodes using more than this size will not work." msgstr "" +"La capacity maximale de la mémoire tampon pour le dessin d'objets immédiats (" +"les nÅ“uds ImmediateGeometry). Les nÅ“uds utilisant plus que cette taille ne " +"fonctionneront pas." #: doc/classes/ProjectSettings.xml msgid "" @@ -60043,13 +62799,10 @@ msgid "" msgstr "" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "If [code]true[/code], the texture importer will import lossless textures " "using the PNG format. Otherwise, it will default to using WebP." msgstr "" -"Si [code]true[/code], la [SpinBox] sera modifiable. Sinon, elle sera en " -"lecture seule." #: doc/classes/ProjectSettings.xml msgid "" @@ -60059,6 +62812,12 @@ msgid "" "Note that compression levels above 6 are very slow and offer very little " "savings." msgstr "" +"Le niveau de compression par défaut pour le format WebP sans perte. Des " +"niveaux plus élevés entraînent des fichiers plus petits mais une plus lente " +"vitesse de compression. La vitesse de décompression ne dépend pas du niveau " +"de compression. Les valeurs supportées vont de 0 à 9. Notez que les niveaux " +"de compression supérieurs à 6 sont très lents et offrent une très petite " +"réduction du poids du fichier." #: doc/classes/ProjectSettings.xml msgid "" @@ -60067,6 +62826,11 @@ msgid "" "attributes data. Recommended to be enabled if targeting mobile devices. " "Requires manual reimport of meshes after toggling." msgstr "" +"À l'importation, les données des sommets de maillage seront divisées en deux " +"flux dans une seule mémoire tampon pour les sommets, l'une pour les données " +"de position et l'autre pour les données d'attributs. Recommandé si vous " +"ciblez des appareils mobiles. Nécessite de réimporter manuellement toutes " +"les meshes après l'activation." #: doc/classes/ProjectSettings.xml msgid "" @@ -60078,6 +62842,14 @@ msgid "" "A greater number of polygons can potentially cull more objects, however the " "cost of culling calculations scales with the number of occluders." msgstr "" +"Détermine le nombre maximal d'occulteurs de polygones qui seront utilisés à " +"tout moment.\n" +"Même si vous pouvez avoir de nombreux occulteurs dans une même scène, à " +"chaque trame, le système choisira parmi ces plus pertinents basés sur une " +"métrique de l'espace à l'écran, afin de donner la meilleure performance " +"globale.\n" +"Un plus grand nombre de polygones peut potentiellement masquer plus " +"d'objets, cependant les performances baissent avec le nombre d'occulteurs." #: doc/classes/ProjectSettings.xml msgid "" @@ -60087,6 +62859,12 @@ msgid "" "choose from these the most relevant based on a screen space metric, in order " "to give the best overall performance." msgstr "" +"Détermine le nombre maximal d'occulteurs de sphère qui seront utilisés à " +"tout moment.\n" +"Même si vous pouvez avoir de nombreux occulteurs dans une même scène, à " +"chaque trame, le système choisira parmi ces plus pertinents basés sur une " +"métrique de l'espace à l'écran, afin de donner la meilleure performance " +"globale." #: doc/classes/ProjectSettings.xml msgid "" @@ -60097,6 +62875,12 @@ msgid "" "It will flip named portal meshes (i.e. [code]-portal[/code]) on the initial " "conversion to [Portal] nodes." msgstr "" +"La convention par défaut est de pointer vers l'extérieur (la face vers " +"l'extérieur) de la salle source.\n" +"Si vous construisez accidentellement votre niveau avec des portails faisant " +"face de la mauvaise manière, ce réglage peut corriger le problème.\n" +"Cela va inverser le maillages nommés de portail (c'est-à -dire finissant par " +"[code]-portal[/code]) pour les nÅ“uds [Portal]." #: doc/classes/ProjectSettings.xml msgid "" @@ -60107,14 +62891,11 @@ msgstr "" "[b]Note :[/b] Cela sera automatiquement désactivé dans les exports." #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "If [code]true[/code], gameplay callbacks will be sent as [code]signals[/" "code]. If [code]false[/code], they will be sent as [code]notifications[/" "code]." msgstr "" -"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], " -"l’état de la clé est libéré." #: doc/classes/ProjectSettings.xml msgid "" @@ -60130,6 +62911,8 @@ msgid "" "Show logs during PVS generation.\n" "[b]Note:[/b] This will automatically be disabled in exports." msgstr "" +"Afficher les journaux pendant la génération du PVS.\n" +"[b]Note :[/b] Cela sera automatiquement désactivé dans les exportations." #: doc/classes/ProjectSettings.xml msgid "" @@ -60464,6 +63247,9 @@ msgid "" "Lower-end override for [member rendering/quality/shadows/filter_mode] on " "mobile devices, due to performance concerns or driver support." msgstr "" +"Surcharge pour les appareils bas de gamme pour [le rendu de membre/qualité/" +"shadows/filter_mode] sur les appareils mobiles, en raison de performance " +"plus faibles ou du support des pilotes." #: doc/classes/ProjectSettings.xml msgid "" @@ -60624,6 +63410,8 @@ msgid "" "Objects can use this signal to restrict reading of settings only to " "situations where a change has been made." msgstr "" +"Les objets peuvent utiliser ce signal pour restreindre leur lecture aux " +"seuls paramètres modifiés." #: doc/classes/PropertyTweener.xml msgid "Interpolates an [Object]'s property over time." @@ -60637,6 +63425,11 @@ msgid "" "to create [PropertyTweener]. Any [PropertyTweener] created manually will not " "function correctly." msgstr "" +"[PropertyTweener] est utilisé pour interpoler une propriété dans un objet. " +"Voir [method SceneTreeTween.tween_property] pour plus d'informations.\n" +"[b]Note :[/b] [method SceneTreeTween.tween_property] est le seul moyen " +"correct de créer un [PropertyTweener]. Les [PropertyTweener] créés " +"manuellement ne fonctionneront pas correctement." #: doc/classes/PropertyTweener.xml msgid "" @@ -60648,6 +63441,13 @@ msgid "" "as_relative() #the node will move by 100 pixels to the right\n" "[/codeblock]" msgstr "" +"Quand appellé, la valeur finale sera utilisée comme valeur relative. Par " +"exemple :\n" +"[codeblock]\n" +"var tween = get_tree().create_tween()\n" +"tween.tween_property(self, \"position\", Vector2.RIGHT * 100, 1)." +"as_relative() # Le nÅ“ud sera déplacé de 100 pixels sur la droite\n" +"/[codeblock]" #: doc/classes/PropertyTweener.xml msgid "" @@ -60659,6 +63459,14 @@ msgid "" "(200, 100)\n" "[/codeblock]" msgstr "" +"Définit une valeur initiale personnalisée pour le [PropertyTweener]. Par " +"exemple :\n" +"[codeblock]\n" +"var tween = get_tree().create_tween()\n" +"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from(Vector2(" +"100, 100) # Ça déplacera le nÅ“ud de la position (100, 100) jusqu'à (200, 100)" +"\n" +"/[codeblock]" #: doc/classes/PropertyTweener.xml msgid "" @@ -60673,6 +63481,16 @@ msgid "" "from_current()\n" "[/codeblock]" msgstr "" +"Fait que ce [PropertyTweener] utilisera la valeur de propriété actuelle " +"(c'est-à -dire au moment de créer ce [PropertyTweener]) comme point de " +"départ. Ceci est pareil que [method from] avec la valeur actuelle. Ces deux " +"appels sont identiques :\n" +"[codeblock]\n" +"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from(position)" +"\n" +"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from_current()" +"\n" +"/[codeblock]" #: doc/classes/PropertyTweener.xml msgid "" @@ -60683,9 +63501,8 @@ msgstr "" "interpolation. Par défaut, il n'y a pas de délai." #: doc/classes/ProximityGroup.xml -#, fuzzy msgid "General-purpose 3D proximity detection node." -msgstr "NÅ“ud de détection de proximité pour usage général." +msgstr "Un nÅ“ud de détection de proximité 3D pour un usage général." #: doc/classes/ProximityGroup.xml msgid "" @@ -60757,11 +63574,16 @@ msgid "" "If the [member dispatch_mode] is set to [constant MODE_PROXY] (the default), " "all calls are delegated to their respective parent [Node]." msgstr "" +"Appelle la méthode et les paramètres donnés à tous les [ProximityGroup] qui " +"s'intersectent.\n" +"Si le [member dispatch_mode] est [constant MODE_PROXY] (par défaut), tous " +"les appels sont délégués à leur parent [Node] respectif." #: doc/classes/ProximityGroup.xml msgid "" "Specifies which node gets contacted on a call of method [method broadcast]." msgstr "" +"Spécifie quel nÅ“ud est contacté sur un appel de méthode [method broadcast]." #: doc/classes/ProximityGroup.xml msgid "" @@ -60771,6 +63593,11 @@ msgid "" "proximity checks at the cost of performance, since more groups will be " "created." msgstr "" +"La taille de l'espace en unités 3D. Cela définit également la quantité de " +"coordonnées requises pour calculer si deux nÅ“uds [ProximityGroup] sont en " +"intersection ou non. Des valeurs plus petites de [member grid_radius] " +"peuvent être utilisées pour des vérifications de proximité plus précises " +"mais avec de moins bonnes performances, car plus de groupes seront créés." #: doc/classes/ProximityGroup.xml msgid "" @@ -60797,13 +63624,15 @@ msgstr "" #: doc/classes/ProximityGroup.xml msgid "This [ProximityGroup]'s parent will be target of [method broadcast]." -msgstr "" +msgstr "Le parent de ce [ProximityGroup] sera la cible de [method broadcast]." #: doc/classes/ProximityGroup.xml msgid "" "This [ProximityGroup] will emit the [signal broadcast] [i]signal[/i] when " "calling the [method broadcast] [i]method[/i]." msgstr "" +"Ce [ProximityGroup] émettra le [i]signal[/i] [signal broadcast] lors de " +"l'appel de la [i]méthode[/i] [method broadcast]." #: doc/classes/QuadMesh.xml msgid "Class representing a square mesh." @@ -60866,9 +63695,8 @@ msgstr "" "spécifié. L'axe doit être un vecteur normalisé." #: doc/classes/Quat.xml -#, fuzzy msgid "Constructs a quaternion defined by the given values." -msgstr "Construit une nouvelle chaîne de caractères à partir du [Plane] donné." +msgstr "" #: doc/classes/Quat.xml msgid "" @@ -60886,6 +63714,9 @@ msgid "" "code], this vector, [code]b[/code], and [code]post_b[/code], by the given " "amount [code]weight[/code]." msgstr "" +"Exécute une interpolation sphérique cubique entre les quaternions " +"[code]pre_a[/code], ce vecteur, [code]b[/code], et [code]post_b[/code], par " +"la quantité [code]weight[/code] spécifiée." #: doc/classes/Quat.xml msgid "Returns the dot product of two quaternions." @@ -60898,6 +63729,10 @@ msgid "" "quaternion. Returned vector contains the rotation angles in the format (X " "angle, Y angle, Z angle)." msgstr "" +"Retourne les angles d'Euler (selon la convention YXZ : lors de la " +"décomposition, d'abord Z, puis X, et enfin Y) correspondant à la rotation " +"représentée par un quaternion d'unité. Le vecteur retourné contient les " +"angles de rotation dans le format (angle X, angle Y, angle Z)." #: doc/classes/Quat.xml msgid "Returns the inverse of the quaternion." @@ -60934,6 +63769,8 @@ msgid "" "Sets the quaternion to a rotation which rotates around axis by the specified " "angle, in radians. The axis must be a normalized vector." msgstr "" +"Définit le quaternion avec une rotation qui tourne autour de l'axe par " +"l'angle spécifié, en radians. L'axe doit être un vecteur normalisé." #: doc/classes/Quat.xml msgid "" @@ -60941,6 +63778,9 @@ msgid "" "convention: when decomposing, first Z, then X, and Y last), given in the " "vector format as (X angle, Y angle, Z angle)." msgstr "" +"Définit le quaternion avec une rotation spécifiée par les angles d'Euler (" +"selon la convention YXZ : lors de la décomposition, d'abord Z, puis X, et " +"enfin Y), donnée dans le format vectoriel comme (angle X, angle Y, angle Z)." #: doc/classes/Quat.xml msgid "" @@ -60948,6 +63788,10 @@ msgid "" "quaternion and [code]to[/code] by amount [code]weight[/code].\n" "[b]Note:[/b] Both quaternions must be normalized." msgstr "" +"Retourne le résultat de l'interpolation linéaire sphérique entre ce " +"quaternion et [code]to[/code] par la quantité [code]weight[/code] spécifiée." +"\n" +"[b]Note :[/b] Les deux quaternions doivent être normalisés." #: doc/classes/Quat.xml msgid "" @@ -60955,6 +63799,9 @@ msgid "" "quaternion and [code]to[/code] by amount [code]weight[/code], but without " "checking if the rotation path is not bigger than 90 degrees." msgstr "" +"Retourne le résultat de l'interpolation linéaire sphérique entre ce " +"quaternion et [code]to[/code] par la quantité [code]weight[/code] spécifiée, " +"mais sans vérifier si la rotation n'est pas supérieure à 90 degrés." #: doc/classes/Quat.xml msgid "Returns a vector transformed (multiplied) by this quaternion." @@ -60998,6 +63845,9 @@ msgid "" "[Basis] matrix. If a vector is transformed by an identity quaternion, it " "will not change." msgstr "" +"La quaternion d'identité, sans rotation. Équivalent à la matrice [Basis] " +"d'identité. Si un vecteur est transformé par un quaternion d'identité, il ne " +"changera pas." #: doc/classes/RandomNumberGenerator.xml msgid "A class for generating pseudo-random numbers." @@ -61163,22 +64013,21 @@ msgstr "" "avec une valeur personnalisée, utilisez plutôt [member seed]." #: doc/classes/Range.xml -#, fuzzy msgid "Abstract base class for range-based controls." -msgstr "Classe de base abstraite pour les contrôles basés sur la portée." +msgstr "Une classe de base abstraite pour les contrôles basés sur la portée." #: doc/classes/Range.xml -#, fuzzy msgid "" "Range is a base class for [Control] nodes that change a floating-point " "[member value] between a [member min_value] and [member max_value], using a " "configured [member step] and [member page] size. See e.g. [ScrollBar] and " "[Slider] for examples of higher level nodes using Range." msgstr "" -"Range est une classe de base des nÅ“uds [Control] qui change une [code]value[/" -"code] flottante entre le [code]minimum[/code] et le [code]maximum[/code], " -"par étape [code]step[/code] et par [code]page[/code], par exemple un " -"[ScrollBar]." +"Range est une classe de base des nÅ“uds [Control] qui change une " +"[code]value[/code] flottante entre le [code]minimum[/code] et le " +"[code]maximum[/code], par étape [code]step[/code] et par [code]page[/code], " +"par exemple un [ScrollBar]. Voir [ScrollBar] et [Slider] pour des exemples " +"de nÅ“uds de haut niveau utilisant des Range." #: doc/classes/Range.xml msgid "" @@ -61189,7 +64038,7 @@ msgstr "" #: doc/classes/Range.xml msgid "Stops the [Range] from sharing its member variables with any other." -msgstr "" +msgstr "Arrête le [Range] de partager ses variables membres avec les autres." #: doc/classes/Range.xml msgid "" @@ -61210,6 +64059,9 @@ msgid "" "If [code]true[/code], and [code]min_value[/code] is greater than 0, " "[code]value[/code] will be represented exponentially rather than linearly." msgstr "" +"Si [code]true[/code], et [code]min_value[/code] est supérieur à 0, " +"[code]value[/code] sera représenté de façon exponentielle plutôt que " +"linéaire." #: doc/classes/Range.xml msgid "" @@ -61233,6 +64085,9 @@ msgid "" "multiplied by [code]page[/code] over the difference between [code]min_value[/" "code] and [code]max_value[/code]." msgstr "" +"La taille de la page. Utilisé principalement pour [ScrollBar]. La longueur " +"de la barre de défilement est multipliée par [code]page[/code] divisé par la " +"différence entre [code]min_value[/code] et [code]max_value[/code]." #: doc/classes/Range.xml msgid "The value mapped between 0 and 1." @@ -61337,12 +64192,17 @@ msgid "" "[code]0[/code] if no object is intersecting the ray (i.e. [method " "is_colliding] returns [code]false[/code])." msgstr "" +"Retourne l'identifiant de forme du premier objet que le rayon intersecte, ou " +"[code]0[/code] si aucun objet n'intersecte le rayon (c'est-à -dire [method " +"is_colliding] renvoie [code]false[/code])." #: doc/classes/RayCast.xml msgid "" "Returns [code]true[/code] if the bit index passed is turned on.\n" "[b]Note:[/b] Bit indices range from 0-19." msgstr "" +"Retourne [code]true[/code] si l'index de bit est activé.\n" +"[b]Note :[/b] Les indices de bit vont de 0 à 19." #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -61354,6 +64214,10 @@ msgid "" "Returns the collision point at which the ray intersects the closest object.\n" "[b]Note:[/b] This point is in the [b]global[/b] coordinate system." msgstr "" +"Retourne le point de collision où le rayon intersecte l'objet le plus proche." +"\n" +"[b]Note :[/b] Ce point se trouve dans le système de coordonnées " +"[b]global[/b]." #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -61384,21 +64248,24 @@ msgid "" "Sets the bit index passed to the [code]value[/code] passed.\n" "[b]Note:[/b] Bit indexes range from 0-19." msgstr "" +"Définit l'index de bit transmis à la [code]valeur[/code] passée.\n" +"[b]Note :[/b] Les index de bit vont de 0-19." #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" "The ray's destination point, relative to the RayCast's [code]position[/code]." msgstr "" +"Le point de destination du rayon, par rapport à la [code]position[/code] du " +"RayCast." #: doc/classes/RayCast.xml -#, fuzzy msgid "If [code]true[/code], collision with [Area]s will be reported." -msgstr "Si [code]true[/code], les collisions seront signalées." +msgstr "Si [code]true[/code], les collisions avec les [Area] seront signalées." #: doc/classes/RayCast.xml -#, fuzzy msgid "If [code]true[/code], collision with [PhysicsBody]s will be reported." -msgstr "Si [code]true[/code], les collisions seront signalées." +msgstr "" +"Si [code]true[/code], les collisions avec les [PhysicsBody] seront signalées." #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -61431,11 +64298,12 @@ msgid "If [code]true[/code], collisions will be reported." msgstr "Si [code]true[/code], les collisions seront signalées." #: doc/classes/RayCast.xml -#, fuzzy msgid "" "If [code]true[/code], collisions will be ignored for this RayCast's " "immediate parent." -msgstr "Si [code]true[/code], les collisions seront signalées." +msgstr "" +"Si [code]true[/code], les collisions seront ignorées avec le parent direct " +"de ce RayCast." #: doc/classes/RayCast2D.xml msgid "" @@ -61461,6 +64329,8 @@ msgid "" "Sets or clears individual bits on the collision mask. This makes selecting " "the areas scanned easier." msgstr "" +"Définit ou efface des bits individuels sur le masque de collision. Cela " +"facilite le choix des aires scannées." #: doc/classes/RayCast2D.xml msgid "If [code]true[/code], collision with [Area2D]s will be reported." @@ -61492,6 +64362,10 @@ msgid "" "itself from whatever is touching its far endpoint. It's often useful for " "characters." msgstr "" +"Une forme en rayon pour les collisions en 3D, qui peuvt être placée dans un " +"[PhysicsBody] ou une [Area]. Un rayon n'est pas vraiment un corps de " +"collision ; il tente plutôt de se séparer de ce qui touche son point " +"d'extrémité lointain. Il est souvent utile pour les caractères." #: doc/classes/RayShape.xml doc/classes/RayShape2D.xml msgid "The ray's length." @@ -61513,11 +64387,13 @@ msgid "" "it tries to separate itself from whatever is touching its far endpoint. It's " "often useful for characters." msgstr "" +"Une forme en rayon pour les collisions 2D. Un rayon n'est pas vraiment un " +"corps de collision ; il tente plutôt de se séparer de ce qui touche son " +"point d'extrémité lointain. Il est souvent utile pour les caractères." #: doc/classes/Rect2.xml -#, fuzzy msgid "2D axis-aligned bounding box." -msgstr "Boîte de délimitation alignée sur l'axe." +msgstr "La boîte de délimitation 2D alignée sur les axes." #: doc/classes/Rect2.xml msgid "" @@ -61545,6 +64421,9 @@ msgid "" "top-left corner is the origin and [code]width[/code] and [code]height[/code] " "are positive." msgstr "" +"Retourne un [Rect2] avec la même position et aire, modifié de sorte que le " +"coin supérieur gauche est l'origine et [code]width[/code] et " +"[code]height[/code] soient positifs." #: doc/classes/Rect2.xml msgid "Returns the intersection of this [Rect2] and b." @@ -61566,11 +64445,19 @@ msgid "" "var rect2 = rect.expand(Vector2(0, -1))\n" "[/codeblock]" msgstr "" +"Retourne une copie de ce [Rect2] élargi pour inclure le point donné.\n" +"[b]Exemple :[/b]\n" +"[codeblock]\n" +"# position (-3, 2), size (1, 1)\n" +"var rect = Rect2(Vector2(-3, 2), Vector2(1, 1))\n" +"# position (-3, -1), size (3, 4), contient donc à la fois `rect` et Vector2(" +"0, -1)\n" +"var rect2 = rect.expand(Vector2(0, -1))\n" +"/[codeblock]" #: doc/classes/Rect2.xml -#, fuzzy msgid "Returns the area of the [Rect2]. See also [method has_no_area]." -msgstr "Retourne la zone du [Rect2]." +msgstr "Retourne l'aire du [Rect2]. Voir aussi [method has_no_area]." #: doc/classes/Rect2.xml msgid "" @@ -61585,12 +64472,16 @@ msgid "" "Returns a copy of the [Rect2] grown a given amount of units towards all the " "sides." msgstr "" +"Retourne une copie du [Rect2] aggrandi par une quantité donnée d'unités vers " +"tous les côtés." #: doc/classes/Rect2.xml msgid "" "Returns a copy of the [Rect2] grown a given amount of units towards each " "direction individually." msgstr "" +"Retourne une copie du [Rect2] aggrandi par une quantité donnée d'unités vers " +"chaque direction individuellement." #: doc/classes/Rect2.xml msgid "" @@ -61607,6 +64498,10 @@ msgid "" "[b]Note:[/b] If the [Rect2] has a negative size and is not flat or empty, " "[method has_no_area] will return [code]true[/code]." msgstr "" +"Retourne [code]true[/code] si le [Rect2] est plat ou vide, ou " +"[code]false[/code] sinon. Voir aussi [method get_area].\n" +"[b]Note :[/b] Si le [Rect2] a une taille négative et n'est pas plat ou vide, " +"[method has_no_area] retournera [code]true[/code]." #: doc/classes/Rect2.xml msgid "" @@ -61625,6 +64520,11 @@ msgid "" "If [code]include_borders[/code] is [code]true[/code], they will also be " "considered overlapping if their borders touch, even without intersection." msgstr "" +"Retourne [code]true[/code] si le [Rect2] se chevauche avec [code]b[/code] " +"(c'est-à -dire qu'ils ont au moins un point en commun).\n" +"Si [code]include_borders[/code] est [code]true[/code], ils seront également " +"considérés comme se chevauchant si leurs bordures touchent, même sans " +"intersection." #: doc/classes/Rect2.xml msgid "" @@ -61632,6 +64532,9 @@ msgid "" "approximately equal, by calling [code]is_equal_approx[/code] on each " "component." msgstr "" +"Retourne [code]true[/code] si ce [Rect2] et [code]rect[/code] sont " +"approximativement égaux, en appelant [code]is_equal_approx[/code] sur chaque " +"composant." #: doc/classes/Rect2.xml msgid "Returns a larger [Rect2] that contains this [Rect2] and [code]b[/code]." @@ -61648,12 +64551,16 @@ msgid "" "Rectangle shape for 2D collisions. This shape is useful for modeling box-" "like 2D objects." msgstr "" +"Une forme rectangulaire pour les collisions 2D. Cette forme est utile pour " +"les objets 2D de type boîte." #: doc/classes/RectangleShape2D.xml msgid "" "The rectangle's half extents. The width and height of this shape is twice " "the half extents." msgstr "" +"La demi-taille du rectangle. La largeur et la hauteur de cette forme sont " +"deux fois plus grandes." #: doc/classes/Reference.xml msgid "Base class for reference-counted objects." @@ -61682,6 +64589,9 @@ msgid "" "what you are doing.\n" "Returns whether the initialization was successful." msgstr "" +"Initialise le compteur de référence interne. Utilisez ceci seulement si vous " +"savez vraiment ce que vous faites.\n" +"Retourne si l'initialisation a été réussie." #: doc/classes/Reference.xml msgid "" @@ -61690,6 +64600,10 @@ msgid "" "Returns [code]true[/code] if the increment was successful, [code]false[/" "code] otherwise." msgstr "" +"Augmente le compteur de référence interne. Utilisez ceci seulement si vous " +"savez vraiment ce que vous faites.\n" +"Retourne [code]true[/code] si l'augmentation a réussi, [code]false[/code] " +"sinon." #: doc/classes/Reference.xml msgid "" @@ -61698,6 +64612,10 @@ msgid "" "Returns [code]true[/code] if the decrement was successful, [code]false[/" "code] otherwise." msgstr "" +"Diminue le compteur de référence interne. Utilisez ceci seulement si vous " +"savez vraiment ce que vous faites.\n" +"Retourne [code]true[/code] si la diminution a réussi, [code]false[/code] " +"sinon." #: doc/classes/ReferenceRect.xml msgid "Reference frame for GUI." @@ -61710,6 +64628,10 @@ msgid "" "display a rectangle filled with a solid color, consider using [ColorRect] " "instead." msgstr "" +"Une boîte rectangulaire qui n'affiche que la couleur [member border_color] " +"sur ses bordures. [ReferenceRect] n'a pas de [Color] de remplissage. Si vous " +"devez afficher un rectangle rempli avec une couleur, utilisez plutôt " +"[ColorRect]." #: doc/classes/ReferenceRect.xml msgid "Sets the border [Color] of the [ReferenceRect]." @@ -61720,19 +64642,24 @@ msgid "" "Sets the border width of the [ReferenceRect]. The border grows both inwards " "and outwards with respect to the rectangle box." msgstr "" +"Définit la largeur de la bordure du [ReferenceRect]. La bordure va à la fois " +"vers l'intérieur et vers l'extérieur par rapport aux limites du rectangle." #: doc/classes/ReferenceRect.xml msgid "" "If set to [code]true[/code], the [ReferenceRect] will only be visible while " "in editor. Otherwise, [ReferenceRect] will be visible in game." msgstr "" +"Si définit à [code]true[/code], le [ReferenceRect] ne sera visible que dans " +"l'éditeur. Sinon, [ReferenceRect] sera aussi visible dans le jeu." #: doc/classes/ReflectionProbe.xml -#, fuzzy msgid "" "Captures its surroundings to create fast, accurate reflections from a given " "point." -msgstr "Capture son environnement pour créer des réflexions." +msgstr "" +"Capture son environnement pour créer des réflexions rapides et précises " +"depuis un point donné." #: doc/classes/ReflectionProbe.xml msgid "" @@ -61808,6 +64735,8 @@ msgid "" "Sets the ambient light color to be used when this probe is set to [member " "interior_enable]." msgstr "" +"Définit la couleur de la lumière ambiante à utiliser lorsque cette sonde est " +"définie à [membrer interior_enable]." #: doc/classes/ReflectionProbe.xml msgid "" @@ -61815,22 +64744,25 @@ msgid "" "light for this reflection probe when set to [member interior_enable]. Useful " "so that ambient light matches the color of the room." msgstr "" +"Définit la valeur de contribution pour la quantité de lumière ambiante " +"affectée par la réflexion pour cette sonde que [member interior_enable] est " +"activé. Utile pour que la lumière ambiante corresponde à la couleur de la " +"pièce." #: doc/classes/ReflectionProbe.xml msgid "" "Sets the energy multiplier for this reflection probe's ambient light " "contribution when set to [member interior_enable]." msgstr "" +"Définit le multiplicateur d'énergie pour cette sonde de réflexion de la " +"lumière ambiante quand défini à [member interior_enable]." #: doc/classes/ReflectionProbe.xml -#, fuzzy msgid "" "If [code]true[/code], reflections will ignore sky contribution. Ambient " "lighting is then controlled by the [code]interior_ambient_*[/code] " "properties." msgstr "" -"Retourne la profondeur de la texture. La profondeur est la 3ème dimension " -"(généralement l'axe Z)." #: doc/classes/ReflectionProbe.xml msgid "" @@ -62378,9 +65310,8 @@ msgid "" msgstr "" #: doc/classes/ResourceImporter.xml -#, fuzzy msgid "Base class for the implementation of core resource importers." -msgstr "Classe de base pour une implémentation d’interface AR / VR." +msgstr "" #: doc/classes/ResourceImporter.xml msgid "" @@ -62394,9 +65325,8 @@ msgid "Import plugins" msgstr "Importer des plugins" #: doc/classes/ResourceImporter.xml -#, fuzzy msgid "The default import order." -msgstr "La police par défaut du thème." +msgstr "" #: doc/classes/ResourceImporter.xml msgid "" @@ -62419,13 +65349,10 @@ msgid "" msgstr "" #: doc/classes/ResourceInteractiveLoader.xml -#, fuzzy msgid "" "Returns the loaded resource if the load operation completed successfully, " "[code]null[/code] otherwise." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères commence par la chaîne " -"de caractères donnée, ou [code]false[/code] le cas échéant." #: doc/classes/ResourceInteractiveLoader.xml msgid "" @@ -62827,9 +65754,8 @@ msgid "" msgstr "" #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "Returns the current selection text. Does not include BBCodes." -msgstr "Retourne le numéro de la ligne actuelle." +msgstr "" #: doc/classes/RichTextLabel.xml msgid "" @@ -63125,24 +66051,20 @@ msgid "Makes text fill width." msgstr "Rempli le texte en largeur." #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "Aligns top of the inline image to the top of the text." -msgstr "La hauteur de la boite mesuré depuis son centre." +msgstr "" #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "Aligns center of the inline image to the center of the text." -msgstr "Aligne les enfants avec le centre du conteneur." +msgstr "" #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "Aligns bottom of the inline image to the baseline of the text." -msgstr "La hauteur de la boite mesuré depuis son centre." +msgstr "" #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "Aligns bottom of the inline image to the bottom of the text." -msgstr "Aligne les enfants avec le centre du conteneur." +msgstr "" #: doc/classes/RichTextLabel.xml msgid "Each list item has a number marker." @@ -63223,7 +66145,6 @@ msgid "The default text font." msgstr "La police par défaut du texte." #: doc/classes/RichTextLabel.xml -#, fuzzy msgid "The background used when the [RichTextLabel] is focused." msgstr "L'arrière-plan utilisé quand le [RichTextLabel] a le focus." @@ -63365,16 +66286,15 @@ msgid "Locks the specified linear or rotational axis." msgstr "Verrouille l'axe linéaire et de rotation spécifié." #: doc/classes/RigidBody.xml -#, fuzzy msgid "" "Damps the body's rotational forces. If this value is different from -1.0 it " "will be added to any angular damp derived from the world or areas.\n" "See [member ProjectSettings.physics/3d/default_angular_damp] for more " "details about damping." msgstr "" -"La vitesse à laquelle les objets arrêtent de tourner dans cette zone. " -"Représente la vitesse angulaire perdue par seconde.\n" -"Voir [membre ProjectSettings.physics/2d/default_angular_damp] pour plus de " +"Amortit les forces de rotation du corps. Si cette valeur est différente de -" +"1.0, elle sera ajoutée aux amortissements obtenues du monde et des aires.\n" +"Voir [membre ProjectSettings.physics/3d/default_angular_damp] pour plus de " "détails sur l'amortissement." #: doc/classes/RigidBody.xml @@ -63697,9 +66617,8 @@ msgid "The body's total applied force." msgstr "La force appliquée totale du corps." #: doc/classes/RigidBody2D.xml -#, fuzzy msgid "The body's total applied torque." -msgstr "La force appliquée totale du corps." +msgstr "La force totale appliquée au corps." #: doc/classes/RigidBody2D.xml msgid "" @@ -64261,9 +67180,8 @@ msgid "Path to an [AnimationTree] node to use as a basis for root motion." msgstr "" #: doc/classes/RootMotionView.xml -#, fuzzy msgid "The grid's cell size in 3D units." -msgstr "La taille de cellule du TileMap." +msgstr "La taille de cellule de la grille en unités 3D." #: doc/classes/RootMotionView.xml msgid "The grid's color." @@ -64276,14 +67194,11 @@ msgid "" msgstr "" #: doc/classes/RootMotionView.xml -#, fuzzy msgid "" "If [code]true[/code], the grid's points will all be on the same Y coordinate " "([i]local[/i] Y = 0). If [code]false[/code], the points' original Y " "coordinate is preserved." msgstr "" -"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], " -"l’état de la clé est libéré." #: doc/classes/SceneState.xml msgid "A script interface to a scene file's data." @@ -64680,13 +67595,11 @@ msgid "" msgstr "" #: doc/classes/SceneTree.xml -#, fuzzy msgid "" "If [code]true[/code], the application automatically accepts quitting.\n" "For mobile platforms, see [member quit_on_go_back]." msgstr "" -"Si [code]true[/code], l'application accepte automatiquement de se fermer. " -"Activé par défaut.\n" +"Si [code]true[/code], l'application accepte automatiquement de se fermer.\n" "Pour les plateformes mobiles, voir [method set_quit_on_go_back]." #: doc/classes/SceneTree.xml @@ -64773,9 +67686,8 @@ msgstr "" "les nouvelles connexions entrantes." #: doc/classes/SceneTree.xml -#, fuzzy msgid "The [SceneTree]'s root [Viewport]." -msgstr "La [Window] racine de [SceneTree]." +msgstr "La [Viewport] racine du [SceneTree]." #: doc/classes/SceneTree.xml msgid "" @@ -64813,9 +67725,8 @@ msgid "" msgstr "" #: doc/classes/SceneTree.xml -#, fuzzy msgid "Emitted whenever global menu item is clicked." -msgstr "Émis lorsqu’un élément est sélectionné." +msgstr "Émis quand le menu global est cliqué." #: doc/classes/SceneTree.xml msgid "" @@ -64857,9 +67768,8 @@ msgid "Emitted whenever a node is removed from the [SceneTree]." msgstr "Émit quand un nÅ“ud est retiré du [SceneTree]." #: doc/classes/SceneTree.xml -#, fuzzy msgid "Emitted whenever a node is renamed." -msgstr "Émis chaque fois qu’un nÅ“ud est renommé." +msgstr "Émis quand un nÅ“ud est renommé." #: doc/classes/SceneTree.xml msgid "" @@ -64959,7 +67869,6 @@ msgid "One-shot timer." msgstr "Minuteur à un coup." #: doc/classes/SceneTreeTimer.xml -#, fuzzy msgid "" "A one-shot timer managed by the scene tree, which emits [signal timeout] on " "completion. See also [method SceneTree.create_timer].\n" @@ -64985,16 +67894,16 @@ msgstr "" " yield(get_tree().create_timer(1.0), \"timeout\")\n" " print(\"Minuteur terminé.\")\n" "[/codeblock]\n" -"Le minuteur sera automatiquement une fois terminé." +"Le minuteur sera automatiquement une fois terminé. Pour garder le minuteur, " +"vous pouvez maintenir une référence vers lui. Voir [Reference]." #: doc/classes/SceneTreeTimer.xml msgid "The time remaining (in seconds)." msgstr "Le temps restant (en secondes)." #: doc/classes/SceneTreeTimer.xml doc/classes/Timer.xml -#, fuzzy msgid "Emitted when the timer reaches 0." -msgstr "Émis lorsque la minuterie atteint 0." +msgstr "Émis quand le minuteur atteint 0." #: doc/classes/SceneTreeTween.xml msgid "" @@ -65245,7 +68154,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -65285,15 +68195,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -65370,7 +68281,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Creates and appends an [IntervalTweener]. This method can be used to create " "delays in the tween animation, as an alternative to using the delay in other " @@ -65400,7 +68310,7 @@ msgstr "" "délais des autres [Tweener] ou quand il n'y a pas d'animation (dans ce cas " "le [SceneTreeTween] se comportement comme un minuteur). [code]time[/code] " "est le durée du délai, en secondes.\n" -"Exemple : créer un délai de 2s dans l'exécution du code.\n" +"Exemple : créer un délai dans l'exécution du code.\n" "[codeblock]\n" "# ... du code\n" "yield(create_tween().tween_interval(2), \"finished\")\n" @@ -65474,7 +68384,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Creates and appends a [PropertyTweener]. This method tweens a " "[code]property[/code] of an [code]object[/code] between an initial value and " @@ -65516,14 +68425,14 @@ msgstr "" "tween.tween_property($Sprite, \"position\", Vector2(200, 300), 1)\n" "[/codeblock]\n" "déplacera la sprite de sa position actuelle à la position (100, 200) puis " -"ensuite à (200, 300). Si vous utilisez [method PropertyTweener.from] ou " -"[method PropertyTweener.from_current], la position de départ sera celle " +"ensuite à (200, 300). Si vous utilisez [method PropertyTweener.from] ou [" +"method PropertyTweener.from_current], la position de départ sera celle " "spécifiée et non l'actuelle. Voir les autres méthodes de [PropertyTweener] " "pour connaitre les possibilités.\n" "[b]Note :[/b] Vous pouvez trouver les noms corrects des propriétés en " "survolant ces propriétés dans l'inspecteur de Godot. Vous pouvez aussi " -"fournir un seul composant de cette propriété directement en utilisant " -"[code]\"property:component\"[/code] (ex. [code]position:x[/code]), alors " +"fournir un seul composant de cette propriété directement en utilisant [code]" +"\"property:component\"[/code] (ex. [code]position:x[/code]), alors " "l'interpolation ne se fera que sur cet unique composant.\n" "Exemple : déplacer un objet deux fois depuis la même position vers " "différentes positions, avec différents types de transition.\n" @@ -65571,11 +68480,10 @@ msgid "If [SceneTree] is paused, the [SceneTreeTween] will also pause." msgstr "Si le [SceneTree] est en pause, le [SceneTreeTween] le sera aussi." #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "The [SceneTreeTween] will process regardless of whether [SceneTree] is " "paused." -msgstr "Arrête la mise à jour quand le [SceneTree] est en pause." +msgstr "" #: doc/classes/Script.xml msgid "A class stored as a resource." @@ -65911,7 +68819,6 @@ msgid "" msgstr "" #: doc/classes/Shader.xml -#, fuzzy msgid "A custom shader program." msgstr "Un programme de shader personnalisé." @@ -66261,9 +69168,8 @@ msgid "" msgstr "" #: doc/classes/Skeleton.xml -#, fuzzy msgid "Sets the pose transform for bone [code]bone_idx[/code]." -msgstr "Définit le décalage à partir de [code]0.5[/code]." +msgstr "" #: doc/classes/Skeleton.xml msgid "Sets the rest transform for bone [code]bone_idx[/code]." @@ -66603,14 +69509,12 @@ msgid "" msgstr "" #: doc/classes/SoftBody.xml -#, fuzzy msgid "Returns local translation of a vertex in the surface array." -msgstr "Renvoie la matrice de transformation d’une forme dans une zone." +msgstr "" #: doc/classes/SoftBody.xml -#, fuzzy msgid "Returns [code]true[/code] if vertex is set to pinned." -msgstr "Retourne [code]true[/code] si l'[AABB] est plate ou vide." +msgstr "" #: doc/classes/SoftBody.xml msgid "" @@ -66646,13 +69550,10 @@ msgid "[NodePath] to a [CollisionObject] this SoftBody should avoid clipping." msgstr "" #: doc/classes/SoftBody.xml -#, fuzzy msgid "" "If [code]true[/code], the [SoftBody] is simulated in physics. Can be set to " "[code]false[/code] to pause the physics simulation." msgstr "" -"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], " -"l’état de la clé est libéré." #: doc/classes/SoftBody.xml msgid "If [code]true[/code], the [SoftBody] will respond to [RayCast]s." @@ -66922,11 +69823,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "La [Transform] globale de ce nÅ“ud." #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -67354,7 +70274,6 @@ msgstr "" "à un point donné." #: doc/classes/SpatialMaterial.xml -#, fuzzy msgid "" "Forces a conversion of the [member albedo_texture] from sRGB space to linear " "space." @@ -67546,11 +70465,10 @@ msgid "" msgstr "" #: doc/classes/SpatialMaterial.xml -#, fuzzy msgid "" "If [code]true[/code], enables the vertex grow setting. See [member " "params_grow_amount]." -msgstr "Si [code]true[/code], active le drapeau spécifié." +msgstr "" #: doc/classes/SpatialMaterial.xml msgid "Grows object vertices in the direction of their normals." @@ -67837,9 +70755,8 @@ msgid "Texture specifying per-pixel depth." msgstr "La texture spécifiant la profondeur par pixel." #: doc/classes/SpatialMaterial.xml -#, fuzzy msgid "Texture specifying per-pixel subsurface scattering." -msgstr "La texture spécifiant par pixel de diffusion souterraine." +msgstr "La texture spécifiant la transluminescence par pixel." #: doc/classes/SpatialMaterial.xml msgid "Texture specifying per-pixel transmission color." @@ -68051,10 +70968,9 @@ msgstr "" "emission_texture]." #: doc/classes/SpatialMaterial.xml -#, fuzzy msgid "Use alpha scissor. Set by [member params_use_alpha_scissor]." msgstr "" -"Utilise un ciseau pour l'alpha. Définit par [member " +"Utilise un ciseau pour l'opacité. Définit par [member " "params_use_alpha_scissor]." #: doc/classes/SpatialMaterial.xml @@ -68478,9 +71394,8 @@ msgstr "" "collision." #: doc/classes/SpringArm.xml -#, fuzzy msgid "Returns the spring arm's current length." -msgstr "Retourne la chaîne de caractères convertie en minuscules." +msgstr "" #: doc/classes/SpringArm.xml msgid "" @@ -68708,20 +71623,28 @@ msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D." msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " "This is because opaque objects are not sorted, while transparent objects are " "sorted from back to front (subject to priority)." msgstr "" +"Définit la priorité de rendu pour le texte. Les objets plus prioritaires " +"seront affichés par-dessus les objets les moins prioritaites.\n" +"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à [" +"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n" +"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela " +"n'affectera pas la façon dont les objets transparents sont triés par rapport " +"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, " +"alors que les objets transparents sont triés de l'arrière vers l'avant (et " +"suivant leur priorité)." #: doc/classes/SpriteBase3D.xml -#, fuzzy msgid "" "If [code]true[/code], the [Light] in the [Environment] has effects on the " "sprite." -msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible." +msgstr "" #: doc/classes/SpriteBase3D.xml msgid "" @@ -68781,13 +71704,10 @@ msgid "Removes all animations. A \"default\" animation will be created." msgstr "Retire toutes les animations. Une animation \"défaut\" sera créée." #: doc/classes/SpriteFrames.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the given animation is configured to loop when " "it finishes playing. Otherwise, returns [code]false[/code]." msgstr "" -"Retourne [code]true[/code] si la piste donnée est importée. Sinon retourne " -"[code]false[/code]." #: doc/classes/SpriteFrames.xml msgid "" @@ -69109,9 +72029,8 @@ msgid "" msgstr "" #: doc/classes/StreamPeerBuffer.xml -#, fuzzy msgid "Data buffer stream peer." -msgstr "Homologue de flux SSL." +msgstr "" #: doc/classes/StreamPeerBuffer.xml msgid "" @@ -70010,22 +72929,20 @@ msgstr "" "répétitions est donné en argument." #: doc/classes/String.xml -#, fuzzy msgid "" "Replaces occurrences of a case-sensitive substring with the given one inside " "the string." msgstr "" -"Remplacer les occurrences d'une sous-chaine sensible à la casse avec l'autre " -"donnée." +"Remplace les occurrences sensibles à la casse à l'intérieur d'une chaine par " +"la sous-chaine donnée." #: doc/classes/String.xml -#, fuzzy msgid "" "Replaces occurrences of a case-insensitive substring with the given one " "inside the string." msgstr "" -"Remplacer les occurrences d'une sous-chaine insensible à la casse avec " -"l'autre donnée." +"Remplace les occurrences insensibles à la casse à l'intérieur d'une chaine " +"par la sous-chaine donnée." #: doc/classes/String.xml msgid "" @@ -70542,7 +73459,6 @@ msgstr "" "[code]corner[/code] spécifié. Voir [enum Corner] pour les valeurs possibles." #: doc/classes/StyleBoxFlat.xml -#, fuzzy msgid "Sets the corner radius to [code]radius[/code] pixels for all corners." msgstr "" "Définit le rayon d’angle sur [code]radius[/code] pixels pour tous les coins." @@ -71278,11 +74194,11 @@ msgstr "" "est désactivé." #: doc/classes/TabContainer.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is hidden." msgstr "" -"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active." +"Retourne [code]true[/code] si l'onglet à l'index [code]tab_idx[/code] est " +"masqué." #: doc/classes/TabContainer.xml doc/classes/Tabs.xml msgid "" @@ -71350,13 +74266,10 @@ msgid "" msgstr "" #: doc/classes/TabContainer.xml -#, fuzzy msgid "" "If [code]true[/code], all tabs are drawn in front of the panel. If " "[code]false[/code], inactive tabs are drawn behind the panel." msgstr "" -"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], " -"l’état de la clé est libéré." #: doc/classes/TabContainer.xml msgid "" @@ -71507,12 +74420,11 @@ msgid "Tabs control." msgstr "Contrôle des onglets." #: doc/classes/Tabs.xml -#, fuzzy msgid "" "Simple tabs control, similar to [TabContainer] but is only in charge of " "drawing tabs, not interacting with children." msgstr "" -"Contrôle des onglets simples, similaire à [TabContainer] mais il est " +"Un contrôle simple des onglets, similaire à [TabContainer] mais il est " "uniquement chargé du dessin des onglets, et non de l’interaction avec les " "enfants." @@ -71590,12 +74502,10 @@ msgid "Select tab at index [code]tab_idx[/code]." msgstr "Sélectionne l'onglet à l'index [code]tab_idx[/code]." #: doc/classes/Tabs.xml -#, fuzzy msgid "" "if [code]true[/code], the mouse's scroll wheel can be used to navigate the " "scroll view." msgstr "" -"Si [code]true[/code], l’état du bouton de la souris est un double-clic." #: doc/classes/Tabs.xml msgid "The alignment of all tabs. See [enum TabAlign] for details." @@ -71838,9 +74748,8 @@ msgid "Returns the amount of total lines in the text." msgstr "Retourne le nombre total de lignes dans le texte." #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns the height of a largest line." -msgstr "Retourne la hauteur du contenu." +msgstr "" #: doc/classes/TextEdit.xml msgid "" @@ -71851,14 +74760,12 @@ msgstr "" "code]." #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns the number of times the given line is wrapped." -msgstr "Renvoie le nombre de lignes visibles." +msgstr "" #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns an array of [String]s representing each wrapped index." -msgstr "Retourne une représentation [String] de l'évènement." +msgstr "" #: doc/classes/TextEdit.xml msgid "" @@ -71903,19 +74810,16 @@ msgid "Returns the selection end line." msgstr "Retourne la ligne de fin de sélection." #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns the total width of all gutters and internal padding." -msgstr "Retourne le nombre de pistes dans l'animation." +msgstr "" #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns the total amount of lines that could be drawn." -msgstr "Retourne la position du contact sur le collisionneur." +msgstr "" #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns the number of visible lines, including wrapped text." -msgstr "Renvoie le nombre de lignes visibles." +msgstr "" #: doc/classes/TextEdit.xml msgid "" @@ -71958,34 +74862,26 @@ msgstr "" "marque-page." #: doc/classes/TextEdit.xml -#, fuzzy msgid "" "Returns [code]true[/code] when the specified [code]line[/code] has a " "breakpoint." msgstr "" -"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active." #: doc/classes/TextEdit.xml -#, fuzzy msgid "" "Returns [code]true[/code] when the specified [code]line[/code] is marked as " "safe." msgstr "" -"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active." #: doc/classes/TextEdit.xml -#, fuzzy msgid "Returns if the given line is wrapped." -msgstr "Renvoie le texte de la colonne donnée." +msgstr "" #: doc/classes/TextEdit.xml -#, fuzzy msgid "" "Returns whether the mouse is over selection. If [code]edges[/code] is " "[code]true[/code], the edges are considered part of the selection." msgstr "" -"Renvoie [code]true[/code] (vrai) si [code]a[/code] et [code]b[/code] sont " -"approximativement égaux l'un à l'autre." #: doc/classes/TextEdit.xml msgid "Returns [code]true[/code] if the selection is active." @@ -72062,13 +74958,13 @@ msgstr "Définit le texte pour la ligne spécifiée." #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" -"Ajoute un marque-page pour la ligne [code]line[/code] si [code]bookmark[/" -"code] est [code]true[/code]. Supprime le marque-page si [code]bookmark[/" -"code] est [code]false[/code].\n" +"Ajoute un marque-page pour la ligne [code]line[/code] si " +"[code]bookmark[/code] est [code]true[/code]. Supprime le marque-page si " +"[code]bookmark[/code] est [code]false[/code].\n" "Les marque-pages sont affichés dans [member breakpoint_gutter]." #: doc/classes/TextEdit.xml @@ -72134,9 +75030,8 @@ msgid "If [code]true[/code], a right-click displays the context menu." msgstr "Si [code]true[/code], un clic droit affiche le menu contextuel." #: doc/classes/TextEdit.xml -#, fuzzy msgid "If [code]true[/code], allow drag and drop of selected text." -msgstr "Si [code]true[/code], la valeur peut être sélectionnée et modifiée." +msgstr "" #: doc/classes/TextEdit.xml msgid "" @@ -72240,13 +75135,10 @@ msgid "" msgstr "" #: doc/classes/TextEdit.xml -#, fuzzy msgid "" "If [code]true[/code], any custom color properties that have been set for " "this [TextEdit] will be visible." msgstr "" -"Si [code]true[/code], les présélections de couleurs enregistrées sont " -"visibles." #: doc/classes/TextEdit.xml msgid "String value of the [TextEdit]." @@ -72396,9 +75288,8 @@ msgstr "" "Définit le [StyleBox] de ce [TextEdit] quand [member readonly] est activé." #: doc/classes/TextMesh.xml -#, fuzzy msgid "Generate an [PrimitiveMesh] from the text." -msgstr "Générer un [TriangleMesh] à partir du maillage." +msgstr "Génère un [PrimitiveMesh] à partir du texte." #: doc/classes/TextMesh.xml msgid "" @@ -72423,9 +75314,8 @@ msgid "" msgstr "" #: doc/classes/TextMesh.xml -#, fuzzy msgid "[Font] used for the [TextMesh]'s text." -msgstr "[Font] utilisée pour le texte du [Label]." +msgstr "La [Font] utilisée pour le texte du [TextMesh]." #: doc/classes/TextMesh.xml msgid "" @@ -72434,14 +75324,12 @@ msgid "" msgstr "" #: doc/classes/TextMesh.xml -#, fuzzy msgid "The size of one pixel's width on the text to scale it in 3D." -msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D." +msgstr "La taille d'un des pixels du texte pour définir sa taille en 3D." #: doc/classes/TextMesh.xml -#, fuzzy msgid "The text to generate mesh from." -msgstr "Le type à partir duquel obtenir la constante." +msgstr "" #: doc/classes/Texture.xml msgid "Texture for 2D and 3D." @@ -72499,9 +75387,8 @@ msgid "Returns the texture width." msgstr "Renvoie la largeur de texture." #: doc/classes/Texture.xml -#, fuzzy msgid "Returns [code]true[/code] if this [Texture] has an alpha channel." -msgstr "Retourne [code]true[/code] (vrai) si la chaîne de caractères est vide." +msgstr "" #: doc/classes/Texture.xml msgid "" @@ -72560,9 +75447,8 @@ msgid "Texture is a video surface." msgstr "La texture est une surface vidéo." #: doc/classes/Texture3D.xml -#, fuzzy msgid "Texture with 3 dimensions." -msgstr "Retourne les dimensions de bitmap." +msgstr "" #: doc/classes/Texture3D.xml msgid "" @@ -73146,46 +76032,33 @@ msgid "Clears all values on the theme." msgstr "Efface toutes les valeurs de ce thème." #: doc/classes/Theme.xml -#, fuzzy msgid "" "Clears the [Color] at [code]name[/code] if the theme has [code]node_type[/" "code]." -msgstr "Multiplie le transform [code]a[/code] par le transform [code]b[/code]." +msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Clears the constant at [code]name[/code] if the theme has [code]node_type[/" "code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml -#, fuzzy msgid "" "Clears the [Font] at [code]name[/code] if the theme has [code]node_type[/" "code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml -#, fuzzy msgid "" "Clears the icon at [code]name[/code] if the theme has [code]node_type[/code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml -#, fuzzy msgid "" "Clears [StyleBox] at [code]name[/code] if the theme has [code]node_type[/" "code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml msgid "" @@ -73208,13 +76081,10 @@ msgid "Sets the theme's values to a copy of a given theme." msgstr "Définit les valeurs du thème à partir d'une copie d'un thème donné." #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns the [Color] at [code]name[/code] if the theme has [code]node_type[/" "code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml msgid "" @@ -73229,13 +76099,10 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns the constant at [code]name[/code] if the theme has [code]node_type[/" "code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml msgid "" @@ -73271,13 +76138,10 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns the icon [Texture] at [code]name[/code] if the theme has " "[code]node_type[/code]." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml msgid "" @@ -73354,11 +76218,9 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns a list of all type variations for the given [code]base_type[/code]." msgstr "" -"Retourne l'index de l'élément avec l'identifiant [code]id[/code] spécifié." #: doc/classes/Theme.xml msgid "" @@ -73378,13 +76240,10 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns [code]true[/code] if this theme has a valid [member default_font] " "value." msgstr "" -"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de " -"la chaîne égale à [code]0[/code])." #: doc/classes/Theme.xml msgid "" @@ -73418,13 +76277,10 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "" "Returns [code]true[/code] if [code]theme_type[/code] is marked as a " "variation of [code]base_type[/code]." msgstr "" -"Retourne [code]true[/code] si la piste donnée est importée. Sinon retourne " -"[code]false[/code]." #: doc/classes/Theme.xml msgid "" @@ -73551,9 +76407,8 @@ msgid "" msgstr "" #: doc/classes/Theme.xml -#, fuzzy msgid "Theme's [Color] item type." -msgstr "Le type [Color] du thème." +msgstr "Le type de l'élément [Color] du thème." #: doc/classes/Theme.xml msgid "Theme's constant item type." @@ -73722,13 +76577,10 @@ msgid "" msgstr "" #: doc/classes/TileMap.xml -#, fuzzy msgid "" "Returns an array of all cells with the given tile index specified in " "[code]id[/code]." msgstr "" -"Renvoie la texture de l’atlas de police de caractères à l’index [code]idx[/" -"code]." #: doc/classes/TileMap.xml msgid "Returns a rectangle enclosing the used (non-empty) tiles of the map." @@ -73843,9 +76695,8 @@ msgid "" msgstr "" #: doc/classes/TileMap.xml -#, fuzzy msgid "If [code]true[/code], this TileMap bakes a navigation region." -msgstr "Si [code]true[/code], l'animation nommée existe." +msgstr "" #: doc/classes/TileMap.xml #, fuzzy @@ -73879,11 +76730,10 @@ msgstr "" "valeurs possibles." #: doc/classes/TileMap.xml -#, fuzzy msgid "" "If [code]true[/code], the TileMap's direct children will be drawn in order " "of their Y coordinate." -msgstr "Si [code]true[/code], la frontière de la ligne sera anti-aliasée." +msgstr "" #: doc/classes/TileMap.xml msgid "" @@ -74039,7 +76889,6 @@ msgid "Tile origin at its bottom-left corner." msgstr "Origine de tuile à son coin inférieur gauche." #: doc/classes/TileSet.xml -#, fuzzy msgid "Tile library for tilemaps." msgstr "La bibliothèque des tuiles pour les cartes." @@ -74881,7 +77730,6 @@ msgstr "" "[InputEventAction]." #: doc/classes/TouchScreenButton.xml -#, fuzzy msgid "The button's bitmask." msgstr "Le masque binaire du bouton." @@ -75292,9 +78140,8 @@ msgid "Clears the server from all translations." msgstr "Efface le serveur de toutes les traductions." #: doc/classes/TranslationServer.xml -#, fuzzy msgid "Returns an array of all loaded locales of the project." -msgstr "Renvoie la valeur absolue du paramètre." +msgstr "" #: doc/classes/TranslationServer.xml msgid "" @@ -75537,9 +78384,8 @@ msgid "" msgstr "" #: doc/classes/Tree.xml -#, fuzzy msgid "Causes the [Tree] to jump to the specified [TreeItem]." -msgstr "Définit la position du nÅ“ud spécifié." +msgstr "" #: doc/classes/Tree.xml msgid "" @@ -75977,13 +78823,10 @@ msgstr "" "[code]column[/code]." #: doc/classes/TreeItem.xml -#, fuzzy msgid "" "Returns the [Texture] of the button at index [code]button_idx[/code] in " "column [code]column[/code]." msgstr "" -"Rentourne [code]true[/code] (vrai) si le bouton d'index [code]button[/code] " -"est préssé. Voir [enum JoyButtonList]." #: doc/classes/TreeItem.xml msgid "" @@ -75998,13 +78841,10 @@ msgid "Returns the number of buttons in column [code]column[/code]." msgstr "Retourne le nombre de boutons dans la colonne [code]column[/code]." #: doc/classes/TreeItem.xml -#, fuzzy msgid "" "Returns the id for the button at index [code]button_idx[/code] in column " "[code]column[/code]." msgstr "" -"Rentourne [code]true[/code] (vrai) si le bouton d'index [code]button[/code] " -"est préssé. Voir [enum JoyButtonList]." #: doc/classes/TreeItem.xml msgid "" @@ -76015,9 +78855,8 @@ msgstr "" "[code]button_idx[/code] dans la colonne [code]column[/code]." #: doc/classes/TreeItem.xml -#, fuzzy msgid "Returns the column's cell mode." -msgstr "Retourne le mode de la cellule de la colonne." +msgstr "Retourne le mode des cellules de la colonne." #: doc/classes/TreeItem.xml msgid "" @@ -76039,9 +78878,8 @@ msgid "Returns [code]true[/code] if [code]expand_right[/code] is set." msgstr "Retourne [code]true[/code] si [code]expand_right[/code] est défini." #: doc/classes/TreeItem.xml -#, fuzzy msgid "Returns the given column's icon [Texture]. Error if no icon is set." -msgstr "Retourne l'alignement du texte de la colonne donnée." +msgstr "" #: doc/classes/TreeItem.xml msgid "Returns the column's icon's maximum width." @@ -76063,18 +78901,22 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" +"Retourne le TreeItem suivant dans l'arborescence, ou l'objet null s'il n'y " +"en a pas." #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." msgstr "" -"Retourne le TreeItem suivant visible dans l'arborescence ou null si aucun.\n" +"Retourne le TreeItem voisin suivant visible dans l'arborescence, ou null si " +"aucun.\n" "Si [code]wrap[/code] est activé, la méthode repartira depuis le premier " "élément visible de l'arborescence si elle est appelé sur le dernier élément, " "sinon elle retournera [code]null[/code]." @@ -76085,21 +78927,22 @@ msgstr "Renvoie le TreeItem parent ou un objet nul s’il n’y en a pas." #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" -"Retourne le TreeItem précédent dans l'arbre ou un objet nul s'il n'y en a " -"pas." +"Retourne le TreeItem précédent dans l'arborescence, ou l'objet null s'il n'y " +"en a pas." #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." msgstr "" -"Retourne le TreeItem précédent visible dans l'arborescence ou null si " -"aucun.\n" +"Retourne le TreeItem voisin précédent visible dans l'arborescence, ou null " +"si aucun.\n" "Si [code]wrap[/code] est activé, la méthode repartira depuis le dernier " "élément visible de l'arborescence si elle est appelé sur le premier élément, " "sinon elle retournera [code]null[/code]." @@ -76181,12 +79024,10 @@ msgid "Selects the column [code]column[/code]." msgstr "Sélectionne la colonne [code]column[/code]." #: doc/classes/TreeItem.xml -#, fuzzy msgid "" "Sets the given column's button [Texture] at index [code]button_idx[/code] to " "[code]button[/code]." msgstr "" -"Déplace l’élément de l’index [code]from_idx[/code] à [code]to_idx[/code]." #: doc/classes/TreeItem.xml msgid "" @@ -76486,7 +79327,6 @@ msgid "" msgstr "" #: doc/classes/Tween.xml -#, fuzzy msgid "" "Resets all tweens to their initial values (the ones given, not those before " "the tween)." @@ -77600,9 +80440,8 @@ msgid "Vertical box container." msgstr "Conteneur vertical." #: doc/classes/VBoxContainer.xml -#, fuzzy msgid "Vertical box container. See [BoxContainer]." -msgstr "Conteneur vertical. Voir [BoxContainer]." +msgstr "Conteneur de boites vertical. Voir [BoxContainer]." #: doc/classes/VBoxContainer.xml msgid "The vertical space between the [VBoxContainer]'s elements." @@ -77826,9 +80665,8 @@ msgid "" msgstr "" #: doc/classes/Vector2.xml doc/classes/Vector3.xml -#, fuzzy msgid "Returns this vector projected onto the vector [code]b[/code]." -msgstr "Retourne le vecteur projeté sur le vecteur [code]b[/code]." +msgstr "Retourne ce vecteur projeté sur le vecteur [code]b[/code]." #: doc/classes/Vector2.xml msgid "" @@ -77837,13 +80675,12 @@ msgid "" msgstr "" #: doc/classes/Vector2.xml -#, fuzzy msgid "" "Returns the vector rotated by [code]angle[/code] (in radians). See also " "[method @GDScript.deg2rad]." msgstr "" -"Retourne le vecteur pivoté par [code]phi[/code] en radians. Voir aussi " -"[method @GDScript.deg2rad]." +"Retourne le vecteur pivoté par [code]angle[/code] (en radians). Voir aussi [" +"method @GDScript.deg2rad]." #: doc/classes/Vector2.xml doc/classes/Vector3.xml msgid "" @@ -78161,11 +80998,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -78246,8 +81083,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -78445,7 +81282,6 @@ msgid "" msgstr "" #: modules/gdnative/doc_classes/VideoStreamGDNative.xml -#, fuzzy msgid "[VideoStream] resource for video formats implemented via GDNative." msgstr "" "La ressource [VideoStream] pour les formats vidéo implémentés via GDNative." @@ -78601,12 +81437,10 @@ msgid "Returns the topmost modal in the stack." msgstr "Retourne la vue exclusive la plus en avant dans la pile." #: doc/classes/Viewport.xml -#, fuzzy msgid "" "Returns the mouse's position in this [Viewport] using the coordinate system " "of this [Viewport]." msgstr "" -"Retourne la position de la souris par rapport à la position de cet élément." #: doc/classes/Viewport.xml msgid "Returns information about the viewport from the rendering pipeline." @@ -78617,9 +81451,8 @@ msgid "Returns the [enum ShadowAtlasQuadrantSubdiv] of the specified quadrant." msgstr "" #: doc/classes/Viewport.xml -#, fuzzy msgid "Returns the size override set with [method set_size_override]." -msgstr "Renvoie le mode de remplacement de l’espace pour la zone." +msgstr "" #: doc/classes/Viewport.xml msgid "" @@ -78649,9 +81482,8 @@ msgid "" msgstr "" #: doc/classes/Viewport.xml -#, fuzzy msgid "Returns [code]true[/code] if there are visible modals on-screen." -msgstr "Retourne [code]true[/code] si la colonne donnée est cochée." +msgstr "" #: doc/classes/Viewport.xml msgid "Returns [code]true[/code] if the drag operation is successful." @@ -78714,9 +81546,8 @@ msgid "" msgstr "" #: doc/classes/Viewport.xml -#, fuzzy msgid "If [code]true[/code], the viewport will be used in AR/VR process." -msgstr "Si [code]true[/code], la texture sera centrée." +msgstr "" #: doc/classes/Viewport.xml msgid "If [code]true[/code], the viewport will process 2D audio streams." @@ -78900,10 +81731,8 @@ msgid "" msgstr "" #: doc/classes/Viewport.xml -#, fuzzy msgid "If [code]true[/code], the size override affects stretch as well." msgstr "" -"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité." #: doc/classes/Viewport.xml msgid "" @@ -78934,9 +81763,8 @@ msgid "" msgstr "" #: doc/classes/Viewport.xml -#, fuzzy msgid "The custom [World] which can be used as 3D environment source." -msgstr "Une constante [Transform], qui peut être utilisée comme nÅ“ud d’entrée." +msgstr "" #: doc/classes/Viewport.xml msgid "The custom [World2D] which can be used as 2D environment source." @@ -79037,14 +81865,12 @@ msgid "Amount of surface changes in frame." msgstr "Le nombre de surfaces changées à chaque trame." #: doc/classes/Viewport.xml -#, fuzzy msgid "Amount of draw calls in frame." -msgstr "Le nombre d'appels d'affichage à chaque trame." +msgstr "Le nombre d'appels de dessin à chaque trame." #: doc/classes/Viewport.xml -#, fuzzy msgid "Amount of items or joined items in frame." -msgstr "Quantité d’objets dans le cadre." +msgstr "" #: doc/classes/Viewport.xml msgid "Represents the size of the [enum RenderInfo] enum." @@ -79291,15 +82117,14 @@ msgid "This enabler will stop [Particles2D] nodes." msgstr "Cet activateur arrêtera les nÅ“uds [Particles2D]." #: doc/classes/VisibilityEnabler2D.xml -#, fuzzy msgid "This enabler will stop the parent's [method Node._process] function." -msgstr "Cet activateur arrêtera la fonction _process du parent." +msgstr "Cet activateur arrêtera la fonction [method Node._process] du parent." #: doc/classes/VisibilityEnabler2D.xml -#, fuzzy msgid "" "This enabler will stop the parent's [method Node._physics_process] function." -msgstr "Cet activateur arrêtera la fonction _physics_process du parent." +msgstr "" +"Cet activateur arrêtera la fonction [method Node._physics_process] du parent." #: doc/classes/VisibilityEnabler2D.xml msgid "This enabler will stop [AnimatedSprite] nodes animations." @@ -79353,15 +82178,12 @@ msgid "" msgstr "" #: doc/classes/VisibilityNotifier.xml -#, fuzzy msgid "Emitted when the VisibilityNotifier enters a [Camera]'s view." -msgstr "" -"Émis lorsque le VisibilityNotifier3D entre dans la vue d’un [Camera3D]." +msgstr "Émis lorsque le VisibilityNotifier entre dans la vue d’un [Camera]." #: doc/classes/VisibilityNotifier.xml -#, fuzzy msgid "Emitted when the VisibilityNotifier exits a [Camera]'s view." -msgstr "Émis lorsque le VisibilityNotifier3D quitte la vue d'un [Camera3D]." +msgstr "Émis lorsque le VisibilityNotifier quitte la vue d'un [Camera]." #: doc/classes/VisibilityNotifier.xml msgid "Emitted when the VisibilityNotifier enters the screen." @@ -79394,9 +82216,8 @@ msgid "" msgstr "" #: doc/classes/VisibilityNotifier2D.xml -#, fuzzy msgid "The VisibilityNotifier2D's bounding rectangle." -msgstr "Rectangle englobant de VisibilityNotifier2D." +msgstr "Le rectangle englobant du VisibilityNotifier2D." #: doc/classes/VisibilityNotifier2D.xml msgid "Emitted when the VisibilityNotifier2D enters the screen." @@ -79434,6 +82255,8 @@ msgid "" "Returns the [AABB] (also known as the bounding box) for this " "[VisualInstance]. See also [method get_transformed_aabb]." msgstr "" +"Retourne le [AABB] (\"bounding box\") pour cette [VisualInstance]. Voir " +"aussi [method get_transformed_aaabb]." #: doc/classes/VisualInstance.xml msgid "" @@ -79441,6 +82264,8 @@ msgid "" "example, if the Node is a [MeshInstance], this will return the RID of the " "associated [Mesh]." msgstr "" +"Retourne le RID de la ressource associée à cette [VisualInstance]. Par " +"exemple, si le nÅ“ud est une [MeshInstance], cela retournera le RID du [Mesh]." #: doc/classes/VisualInstance.xml msgid "" @@ -79448,12 +82273,18 @@ msgid "" "by [method VisualServer.instance_create]. This RID is needed if you want to " "call [VisualServer] functions directly on this [VisualInstance]." msgstr "" +"Retourne le RID de cette instance. Ce RID est le même que le RID retourné " +"par [method VisualServer.instance_create]. Ce RID est nécessaire si vous " +"voulez appeler les fonctions [VisualServer] directement sur cette " +"[VisualInstance]." #: doc/classes/VisualInstance.xml msgid "" "Returns [code]true[/code] when the specified layer is enabled in [member " "layers] and [code]false[/code] otherwise." msgstr "" +"Retourne [code]true[/code] si le calque spécifié est actif, ou " +"[code]false[/code] sinon." #: doc/classes/VisualInstance.xml msgid "" @@ -79462,6 +82293,11 @@ msgid "" "Transformed in this case means the [AABB] plus the position, rotation, and " "scale of the [Spatial]'s [Transform]. See also [method get_aabb]." msgstr "" +"Retourne la [AABB] (\"bounding box\") transformée pour cette " +"[VisualInstance].\n" +"Transformé dans ce cas veut dire la [AABB] plus sa position, la rotation et " +"la mise à l'échelle de la [Transform] du [Spatial]. Voir aussi [method " +"get_aabb]." #: doc/classes/VisualInstance.xml msgid "" @@ -79469,6 +82305,9 @@ msgid "" "changes how the engine handles the [VisualInstance] under the hood. " "Equivalent to [method VisualServer.instance_set_base]." msgstr "" +"Définit la ressource qui est instanciée par cette [VisualInstance] qui " +"modifie la façon dont le moteur gère la [VisualInstance] en interne. " +"Équivalent à [method VisualServer.instance_set_base]." #: doc/classes/VisualInstance.xml msgid "Enables a particular layer in [member layers]." @@ -79480,10 +82319,14 @@ msgid "" "This object will only be visible for [Camera]s whose cull mask includes the " "render object this [VisualInstance] is set to." msgstr "" +"Le(s) calque(s) de rendu où cette [VisualInstance] est dessinée.\n" +"Cet objet ne sera visible que pour les [Camera] où le masque de cull inclut " +"l'objet de rendu auquel [VisualInstance] est défini." #: modules/visual_script/doc_classes/VisualScript.xml msgid "A script implemented in the Visual Script programming environment." msgstr "" +"Un script implémenté dans l'environnement de programmation Visual Script." #: modules/visual_script/doc_classes/VisualScript.xml msgid "" @@ -79512,6 +82355,8 @@ msgid "" "Add a variable to the VisualScript, optionally giving it a default value or " "marking it as exported." msgstr "" +"Ajouter une variable au VisualScript, en option lui donnant une valeur par " +"défaut ou la marquant comme exporté." #: modules/visual_script/doc_classes/VisualScript.xml msgid "" @@ -79567,7 +82412,7 @@ msgstr "" #: modules/visual_script/doc_classes/VisualScript.xml msgid "Returns the id of a function's entry point node." -msgstr "" +msgstr "Retourne l'identifiant d'un nÅ“ud de point d'entrée de la fonction." #: modules/visual_script/doc_classes/VisualScript.xml msgid "Returns the position of the center of the screen for a given function." @@ -79594,6 +82439,8 @@ msgid "" "Returns the information for a given variable as a dictionary. The " "information includes its name, type, hint and usage." msgstr "" +"Retourne les informations d'une variable donnée dans un dictionnaire. Les " +"informations comprennent son nom, son type, un indice et son usage." #: modules/visual_script/doc_classes/VisualScript.xml msgid "Returns whether a signal exists with the specified name." @@ -79654,16 +82501,23 @@ msgid "" "Unlike [method data_connect], there isn't a [code]to_port[/code], since the " "target node can have only one sequence port." msgstr "" +"Connecte deux ports d'une séquence. L'exécution passera de " +"[code]from_output[/code] de [code]from_node[/code] vers [code]to_node[/code]." +"\n" +"Contrairement à [method data_connect], il n'y a pas ∂e [code]to_port[/code], " +"puisque le nÅ“ud cible ne peut avoir qu'un seul port dans la séquence." #: modules/visual_script/doc_classes/VisualScript.xml msgid "" "Disconnect two sequence ports previously connected with [method " "sequence_connect]." msgstr "" +"Déconnecte deux ports de séquence précédemment connectés avec [method " +"sequence_connect]." #: modules/visual_script/doc_classes/VisualScript.xml msgid "Position the center of the screen for a function." -msgstr "" +msgstr "Positionne le centre de l'écran sur une fonction." #: modules/visual_script/doc_classes/VisualScript.xml msgid "Set the base type of the script." @@ -79694,13 +82548,15 @@ msgstr "Émis quand les ports d'un nÅ“ud ont changés." #: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml msgid "A Visual Script node representing a constant from the base types." -msgstr "" +msgstr "Un nÅ“ud Visual Script représentant une constante d'un type de base." #: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml msgid "" "A Visual Script node representing a constant from base types, such as " "[constant Vector3.AXIS_X]." msgstr "" +"Un nÅ“ud Visual Script représentant une constante des types de base, comme [" +"constant Vector3.AXIS_X]." #: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml msgid "The type to get the constant from." @@ -79712,7 +82568,7 @@ msgstr "Le nom de la constante à retourner." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "A Visual Script node used to call built-in functions." -msgstr "" +msgstr "Un nÅ“ud Visual Script utilisé pour appeler des fonctions intégrées." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" @@ -79720,6 +82576,9 @@ msgid "" "function or an utility function.\n" "See also [@GDScript], for the same functions in the GDScript language." msgstr "" +"Une fonction intégrée utilisée dans un [VisualScript]. C'est généralement " +"une fonction de mathématiques ou une fonction utilitaire.\n" +"Voir aussi @[GDScript], pour les mêmes fonctions dans le langage GDScript." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "The function to be executed." @@ -79766,6 +82625,8 @@ msgid "" "Return the arc tangent of the input, using the signs of both parameters to " "determine the exact angle." msgstr "" +"Retourner l'arc tangente de l'entrée, en utilisant les signes des deux " +"paramètres pour déterminer l'angle exact." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return the square root of the input." @@ -79784,6 +82645,8 @@ msgid "" "Return the positive remainder of one input divided by the other, using " "floating-point numbers." msgstr "" +"Retourner le reste positif d'une entrée divisée par l'autre, en utilisant " +"des flottants." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return the input rounded down." @@ -79806,6 +82669,8 @@ msgid "" "Return the sign of the input, turning it into 1, -1, or 0. Useful to " "determine if the input is positive or negative." msgstr "" +"Retourner le signe de l'entrée, le transformant en 1, -1, ou 0. Utile pour " +"déterminer si l'entrée est positive ou négative." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return the input raised to a given power." @@ -79816,18 +82681,26 @@ msgid "" "Return the natural logarithm of the input. Note that this is not the typical " "base-10 logarithm function calculators use." msgstr "" +"Retourner le logarithme népérien de l'entrée. Notez que ce n'est pas " +"l'utilisation typique des calculatrices avec la fonction logarithme en " +"base-10." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" "Return the mathematical constant [b]e[/b] raised to the specified power of " "the input. [b]e[/b] has an approximate value of 2.71828." msgstr "" +"Retourner la constante mathématique [b]e[/b] à la puissance spécifiée par " +"l'entrée. [b]e[/b] a une valeur approximativement égal à 2.71828." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" "Return whether the input is NaN (Not a Number) or not. NaN is usually " "produced by dividing 0 by 0, though other ways exist." msgstr "" +"Retourne si l'entrée la valeur spéciale NaN qui signifie que ce n'est pas un " +"nombre (\"Not a Number\") ou non. NaN est généralement produit en divisant 0 " +"par 0, entre autre." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" @@ -79835,6 +82708,8 @@ msgid "" "Infinity is usually produced by dividing a number by 0, though other ways " "exist." msgstr "" +"Retourne si l'entrée est un nombre flottant infini ou non. L'infini est " +"généralement produit en divisant un nombre par 0, entre autre." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" @@ -79847,7 +82722,6 @@ msgstr "" "progressive." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml -#, fuzzy msgid "" "Return the number of digit places after the decimal that the first non-zero " "digit occurs." @@ -79857,13 +82731,16 @@ msgstr "" #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return the input snapped to a given step." -msgstr "" +msgstr "Retourner l'entrée arrondie à l'étape donnée la plus proche." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" "Return a number linearly interpolated between the first two inputs, based on " "the third input. Uses the formula [code]a + (a - b) * t[/code]." msgstr "" +"Retourner un nombre linéairement interpolé entre les deux premières entrées, " +"basé sur la troisième entrée. Utilise la formule [code]a + (a - b) * " +"t[/code]." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Moves the number toward a value, based on the third input." @@ -79890,12 +82767,17 @@ msgid "" "N (where N is smaller than 2^32 - 1), you can use it with the remainder " "function." msgstr "" +"Retourner une entier de 32 bits aléatoire. Pour obtenir une valeur aléatoire " +"entre 0 et N (où N est plus petit que 2^32 - 1), vous pouvez l'utiliser avec " +"la fonction modulo (retournant le reste de la division euclidienne)." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" "Return a random floating-point value between 0 and 1. To obtain a random " "value between 0 to N, you can use it with multiplication." msgstr "" +"Retourner un flottant aléatoire entre 0 et 1. Pour obtenir une valeur " +"aléatoire entre 0 à N, vous pouvez multiplier cette valeur avec N." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return a random floating-point value between the two inputs." @@ -79944,6 +82826,9 @@ msgid "" "never outside it. Equivalent to [code]min(max(input, range_low), range_high)" "[/code]." msgstr "" +"Retourner l'entrée limitée à l'intervalle donné, s'assurant que le résultat " +"n'est jamais en dehors de l'intervalle. Équivalent à [code]min(max(input, " +"minimum), maximum)[/code]." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Return the nearest power of 2 to the input." @@ -79966,6 +82851,8 @@ msgid "" "Return the type of the input as an integer. Check [enum Variant.Type] for " "the integers that might be returned." msgstr "" +"Retourner le type d'entrée en entier. Regardez [enum Variant.Type] pour les " +"valeurs des entiers qui peuvent être retournés." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Checks if a type is registered in the [ClassDB]." @@ -80018,6 +82905,8 @@ msgid "" "Return the [Color] with the given name and alpha ranging from 0 to 1.\n" "[b]Note:[/b] Names are defined in [code]color_names.inc[/code]." msgstr "" +"Retourner la [Color] avec le nom donné et alpha allant de 0 à 1.\n" +"[b]Note :[/b] Les noms sont définis dans [code]color_names.inc[/code]." #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "" @@ -80029,6 +82918,14 @@ msgid "" "return t * t * (3.0 - 2.0 * t)\n" "[/codeblock]" msgstr "" +"Retourner un nombre correctement interpolé entre les deux premières entrées, " +"en fonction de la troisième entrée. Comme [constant MATH_LERP], mais " +"interpole plus rapidement au début et plus lentement à la fin. Utiliser la " +"formule d'interpolation de Hermite:\n" +"[codeblock]\n" +"var t = clamp((weight - from) / (to - from), 0.0, 1.0)\n" +"return t * t * (3.0 - 2.0 * t)\n" +"[/codeblock]" #: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml msgid "Represents the size of the [enum BuiltinFunc] enum." @@ -80143,6 +83040,8 @@ msgid "" "A Visual Script node which calls a base type constructor. It can be used for " "type conversion as well." msgstr "" +"Un nÅ“ud Visual Script qui appelle un constructeur de type de base. Il peut " +"également être utilisé pour la conversion de type." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "A scripted Visual Script node." @@ -80151,6 +83050,8 @@ msgstr "Un nÅ“ud Visual Script scripté." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "A custom Visual Script node which can be scripted in powerful ways." msgstr "" +"Un nÅ“ud Visual Script personnalisé qui peut être scripté de plein de " +"manières." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "Return the node's title." @@ -80204,6 +83105,8 @@ msgid "" "Return the specified output port's hint. See the [enum @GlobalScope." "PropertyHint] hints." msgstr "" +"Retourne l'indice du port de sortie spécifié. Voir les indices dans [enum " +"@GlobalScope.PropertyHint]." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "Return the specified output port's hint string." @@ -80214,10 +83117,11 @@ msgid "Return the specified output port's name." msgstr "Retourne le nom du port de sortie spécifié." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml -#, fuzzy msgid "" "Return the specified output port's type. See the [enum Variant.Type] values." -msgstr "Représente la taille de l'énumération [enum Variant.Type]." +msgstr "" +"Retourne le type du port de sortie spécifié. Voir [enum Variant.Type] " +"valeurs." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" @@ -80225,6 +83129,9 @@ msgid "" "[b]sequence[/b] port (if there is none, on the place that is usually taken " "by it)." msgstr "" +"Retourne le texte du nÅ“ud personnalisé, qui est affiché juste à côté du port " +"d'entrée [b]séquence[/b] (s'il n'y en a aucun, à l'emplacement où " +"habituellement pris par lui)." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" @@ -80257,18 +83164,24 @@ msgstr "" #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "The start mode used the first time when [method _step] is called." msgstr "" +"Le mode de démarrage a utilisé la première fois que [method _step] est " +"appelée." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" "The start mode used when [method _step] is called after coming back from a " "[constant STEP_PUSH_STACK_BIT]." msgstr "" +"Le mode de démarrage utilisé lorsque [method _step] est appelé après être " +"revenu de [constant STEP_PUSH_STACK_BIT]." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" "The start mode used when [method _step] is called after resuming from " "[constant STEP_YIELD_BIT]." msgstr "" +"Le mode de démarrage utilisé lorsque [method _step] est appelé après être " +"revenu de [constant STEP_YIELD_BIT]." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" @@ -80284,6 +83197,9 @@ msgid "" "Hint used by [method _step] to tell that control should return back, either " "hitting a previous [constant STEP_PUSH_STACK_BIT] or exiting the function." msgstr "" +"L'indice utilisé par [method _step] pour dire que la commande doit revenir, " +"soit en atteignant un précédent [constant STEP_PUSH_STACK_BIT] ou en sortant " +"de la fonction." #: modules/visual_script/doc_classes/VisualScriptCustomNode.xml msgid "" @@ -80299,11 +83215,17 @@ msgid "" "Using this requires you to have at least one working memory slot, which is " "used for the [VisualScriptFunctionState]." msgstr "" +"L'indice utilisé par [method _step] pour dire que la fonction doit être " +"attendue.\n" +"En utilisant cela, vous devez avoir au moins un emplacement de mémoire " +"fonctionnel, qui est utilisé pour [VisualScriptFunctionState]." #: modules/visual_script/doc_classes/VisualScriptDeconstruct.xml msgid "" "A Visual Script node which deconstructs a base type instance into its parts." msgstr "" +"Un nÅ“ud Visual Script qui déconstruit une instance de type de base en ses " +"différentes parties." #: modules/visual_script/doc_classes/VisualScriptDeconstruct.xml msgid "The type to deconstruct." @@ -80314,12 +83236,16 @@ msgid "" "Add a custom Visual Script node to the editor. It'll be placed under " "\"Custom Nodes\" with the [code]category[/code] as the parameter." msgstr "" +"Ajoute un nÅ“ud Visual Script personnalisé à l'éditeur. Il sera placé sous " +"\"NÅ“uds personnalisés\" avec la [code]category[/code] en paramètre." #: modules/visual_script/doc_classes/VisualScriptEditor.xml msgid "" "Remove a custom Visual Script node from the editor. Custom nodes already " "placed on scripts won't be removed." msgstr "" +"Retire un nÅ“ud Visual Script personnalisé de l'éditeur. Les nÅ“uds " +"personnalisés déjà placés sur des scripts ne seront pas supprimés." #: modules/visual_script/doc_classes/VisualScriptEditor.xml msgid "Emitted when a custom Visual Script node is added or removed." @@ -80337,6 +83263,11 @@ msgid "" "[b]Output Ports:[/b]\n" "- Sequence" msgstr "" +"Émet un signal spécifié quand il est exécuté.\n" +"[b]Ports d'entrée :[/b]\n" +"- Séquence : [code]emit[/code]\n" +"[b]Ports de sortie :[/b]\n" +"- Séquence" #: modules/visual_script/doc_classes/VisualScriptEmitSignal.xml msgid "The signal to emit." @@ -80344,16 +83275,15 @@ msgstr "Le signal à émettre." #: modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml msgid "A Visual Script node returning a singleton from [@GlobalScope]." -msgstr "" +msgstr "Un nÅ“ud Visual Script retournant un singleton parmi @[GlobalScope]." #: modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml msgid "The singleton's name." msgstr "Le nom du singleton." #: modules/visual_script/doc_classes/VisualScriptExpression.xml -#, fuzzy msgid "A Visual Script node that can execute a custom expression." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script qui peut exécuter une expression personnalisée." #: modules/visual_script/doc_classes/VisualScriptExpression.xml msgid "" @@ -80374,9 +83304,8 @@ msgid "" msgstr "" #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml -#, fuzzy msgid "A Visual Script node for calling a function." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script pour appeler une fonction." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" @@ -80390,6 +83319,8 @@ msgid "" "The script to be used when [member call_mode] is set to [constant " "CALL_MODE_INSTANCE]." msgstr "" +"Le script à utiliser lorsque [member call_mode] est défini à [constant " +"CALL_MODE_INSTANCE]." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml @@ -80397,18 +83328,24 @@ msgid "" "The base type to be used when [member call_mode] is set to [constant " "CALL_MODE_INSTANCE]." msgstr "" +"Le type de base à utiliser lorsque [member call_mode] est défini à [constant " +"CALL_MODE_INSTANCE]." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" "The type to be used when [member call_mode] is set to [constant " "CALL_MODE_BASIC_TYPE]." msgstr "" +"Le type à utiliser lorsque [member call_mode] est défini à [constant " +"CALL_MODE_BASIC_TYPE]." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" "[code]call_mode[/code] determines the target object on which the method will " "be called. See [enum CallMode] for options." msgstr "" +"[code]call_mode[/code] détermine l'objet cible sur lequel la méthode sera " +"appelée. Voir [enum CallMode] pour les options." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "The name of the function to be called." @@ -80420,12 +83357,16 @@ msgid "" "The node path to use when [member call_mode] is set to [constant " "CALL_MODE_NODE_PATH]." msgstr "" +"Le chemin nÅ“ud à utiliser lorsque [member call_mode] est défini à [constant " +"CALL_MODE_NODE_PATH]." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" "The mode for RPC calls. See [method Node.rpc] for more details and [enum " "RPCCallMode] for available options." msgstr "" +"Le mode pour les appels RPC. Voir [method Node.rpc] pour plus de détails et [" +"enum RPCCallMode] pour les options disponibles." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" @@ -80441,12 +83382,17 @@ msgid "" "Can't be higher than the number of available default arguments in the " "method's declaration." msgstr "" +"Le nombre d'arguments par défaut qui seront utilisés lors de l'appel de la " +"fonction. Ne peut être supérieur au nombre d'arguments par défaut " +"disponibles dans la déclaration de la méthode." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" "If [code]false[/code], call errors (e.g. wrong number of arguments) will be " "ignored." msgstr "" +"Si [code]false[/code], les erreurs d'appel (par exemple le nombre erroné " +"d'arguments) seront ignorées." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "The method will be called on this [Object]." @@ -80455,12 +83401,15 @@ msgstr "La méthode sera appelée sur cet [Object]." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "The method will be called on the given [Node] in the scene tree." msgstr "" +"La méthode sera appelée sur le [Node] donné dans l'arborescence de la scène." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "" "The method will be called on an instanced node with the given type and " "script." msgstr "" +"La méthode sera appelée sur un nÅ“ud instancié avec le type et le script " +"donnés." #: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml msgid "The method will be called on a GDScript basic type (e.g. [Vector2])." @@ -80492,6 +83441,8 @@ msgid "" "The method will be called remotely for the given peer, using an unreliable " "protocol." msgstr "" +"La méthode sera appelée à distance pour le pair donné, en utilisant un " +"protocole non fiable." #: modules/visual_script/doc_classes/VisualScriptFunctionState.xml msgid "A Visual Script node representing a function state." @@ -80502,12 +83453,16 @@ msgid "" "[VisualScriptFunctionState] is returned from [VisualScriptYield] and can be " "used to resume a paused function call." msgstr "" +"[VisualScriptFunctionState] est retourné depuis [VisualScriptYield] et peut " +"être utilisé pour reprendre un appel de fonction en pause." #: modules/visual_script/doc_classes/VisualScriptFunctionState.xml msgid "" "Connects this [VisualScriptFunctionState] to a signal in the given object to " "automatically resume when it's emitted." msgstr "" +"Connecte ce [VisualScriptFunctionState] à un signal dans l'objet donné pour " +"reprendre automatiquement lorsqu'il est émis." #: modules/visual_script/doc_classes/VisualScriptFunctionState.xml msgid "Returns whether the function state is valid." @@ -80516,61 +83471,63 @@ msgstr "Retourne si l'état de la fonction est valide." #: modules/visual_script/doc_classes/VisualScriptFunctionState.xml msgid "Resumes the function to run from the point it was yielded." msgstr "" +"Reprend la fonction à exécuter à partir du point où elle a été suspendue." #: modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml -#, fuzzy msgid "A Visual Script node returning a constant from [@GlobalScope]." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script retournant une constante de [@GlobalScope]." #: modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml msgid "The constant to be used." msgstr "La constante à utiliser." #: modules/visual_script/doc_classes/VisualScriptIndexGet.xml -#, fuzzy msgid "A Visual Script node for getting a value from an array or a dictionary." msgstr "" -"NÅ“ud de script visuel utilisé pour créer un tableau à partir d’une liste " -"d’éléments." +"Un nÅ“ud Visual Script pour obtenir une valeur d'un tableau ou d'un " +"dictionnaire." #: modules/visual_script/doc_classes/VisualScriptIndexGet.xml msgid "" "[VisualScriptIndexGet] will return the value stored in an array or a " "dictionary under the given index." msgstr "" +"[VisualScriptIndexGet] retourne la valeur enregistrée dans un tableau ou un " +"dictionnaire à l'index donné." #: modules/visual_script/doc_classes/VisualScriptIndexSet.xml -#, fuzzy msgid "A Visual Script node for setting a value in an array or a dictionary." msgstr "" -"NÅ“ud de script visuel utilisé pour créer un tableau à partir d’une liste " -"d’éléments." +"Un nÅ“ud Visual Script pour définir une valeur dans un tableau ou un " +"dictionnaire." #: modules/visual_script/doc_classes/VisualScriptIndexSet.xml msgid "" "[VisualScriptIndexSet] will set the value stored in an array or a dictionary " "under the given index to the provided new value." msgstr "" +"[VisualScriptIndexSet] définira la valeur enregistrée dans un tableau ou un " +"dictionnaire à l'index donné avec la nouvelle valeur fournie." #: modules/visual_script/doc_classes/VisualScriptInputAction.xml -#, fuzzy msgid "A Visual Script node returning a state of an action." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script retournant l'état de l'action." #: modules/visual_script/doc_classes/VisualScriptInputAction.xml msgid "" "[VisualScriptInputAction] can be used to check if an action is pressed or " "released." msgstr "" +"[VisualScriptInputAction] peut être utilisé pour vérifier si une action est " +"pressée ou relâchée." #: modules/visual_script/doc_classes/VisualScriptInputAction.xml msgid "Name of the action." msgstr "Le nom de l'action." #: modules/visual_script/doc_classes/VisualScriptInputAction.xml -#, fuzzy msgid "State of the action to check. See [enum Mode] for options." -msgstr "La fonction à calculer. Voir [enum Function] pour les options." +msgstr "L'état de l'action à vérifier. Voir [enum Mode] pour les options." #: modules/visual_script/doc_classes/VisualScriptInputAction.xml msgid "[code]True[/code] if action is pressed." @@ -80609,32 +83566,31 @@ msgstr "" #: modules/visual_script/doc_classes/VisualScriptLists.xml msgid "A Visual Script virtual class for in-graph editable nodes." msgstr "" +"Une classe virtuelle Visual Script pour les nÅ“uds modifiables dans le graphe." #: modules/visual_script/doc_classes/VisualScriptLists.xml msgid "" "A Visual Script virtual class that defines the shape and the default " "behavior of the nodes that have to be in-graph editable nodes." msgstr "" +"Une classe virtuelle Visual Script qui définit la forme et le comportement " +"par défaut des nÅ“uds qui doivent être des nÅ“uds modifiables dans le graphe." #: modules/visual_script/doc_classes/VisualScriptLists.xml -#, fuzzy msgid "Adds an input port to the Visual Script node." -msgstr "Un nÅ“ud Visual Script scripté." +msgstr "Ajoute un port d'entrée au nÅ“ud Visual Script." #: modules/visual_script/doc_classes/VisualScriptLists.xml -#, fuzzy msgid "Adds an output port to the Visual Script node." -msgstr "Un nÅ“ud Visual Script scripté." +msgstr "Ajoute un port de sortie au nÅ“ud Visual Script." #: modules/visual_script/doc_classes/VisualScriptLists.xml -#, fuzzy msgid "Removes an input port from the Visual Script node." -msgstr "Supprime un nÅ“ud de la sélection." +msgstr "Supprime un port d'entrée du nÅ“ud Visual Script." #: modules/visual_script/doc_classes/VisualScriptLists.xml -#, fuzzy msgid "Removes an output port from the Visual Script node." -msgstr "Supprime un nÅ“ud de la sélection." +msgstr "Supprime un port de sortie du nÅ“ud Visual Script." #: modules/visual_script/doc_classes/VisualScriptLists.xml msgid "Sets the name of an input port." @@ -80767,13 +83723,15 @@ msgstr "" #: modules/visual_script/doc_classes/VisualScriptNode.xml msgid "Returns the [VisualScript] instance the node is bound to." -msgstr "" +msgstr "Retourne l'instance [VisualScript] liée à ce nÅ“ud." #: modules/visual_script/doc_classes/VisualScriptNode.xml msgid "" "Notify that the node's ports have changed. Usually used in conjunction with " "[VisualScriptCustomNode] ." msgstr "" +"Notifie quand les ports de ce nÅ“ud ont changé. Habituellement utilisé avec " +"[VisualScriptCustomNode] ." #: modules/visual_script/doc_classes/VisualScriptNode.xml msgid "Change the default value of a given port." @@ -80784,11 +83742,8 @@ msgid "Emitted when the available input/output ports are changed." msgstr "Émis quand les ports entrants/sortants sont changés." #: modules/visual_script/doc_classes/VisualScriptOperator.xml -#, fuzzy msgid "A Visual Script node that performs an operation on two values." -msgstr "" -"NÅ“ud de script visuel utilisé pour créer un tableau à partir d’une liste " -"d’éléments." +msgstr "Un nÅ“ud Visual Script qui effectue une opération sur deux valeurs." #: modules/visual_script/doc_classes/VisualScriptOperator.xml msgid "" @@ -80800,21 +83755,18 @@ msgid "" msgstr "" #: modules/visual_script/doc_classes/VisualScriptOperator.xml -#, fuzzy msgid "" "The operation to be performed. See [enum Variant.Operator] for available " "options." msgstr "" -"Type de multiplication à effectuer. Voir [enum Operator] pour les options." +"Le type d'opération à effectuer. Voir [enum Variant.Operator] pour les " +"options disponibles." #: modules/visual_script/doc_classes/VisualScriptOperator.xml -#, fuzzy msgid "" "The type of the values for this operation. See [enum Variant.Type] for " "available options." msgstr "" -"Définit la valeur d’un paramètre de zone. Voir [enum AreaParameter] pour une " -"liste de paramètres disponibles." #: modules/visual_script/doc_classes/VisualScriptPreload.xml msgid "Creates a new [Resource] or loads one from the filesystem." @@ -80835,17 +83787,17 @@ msgid "The [Resource] to load." msgstr "La [Resource] à charger." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml -#, fuzzy msgid "A Visual Script node returning a value of a property from an [Object]." msgstr "" -"NÅ“ud de script visuel utilisé pour créer un tableau à partir d’une liste " -"d’éléments." +"Un nÅ“ud Visual Script retournant une valeur d'une propriété d'un [Object]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" "[VisualScriptPropertyGet] can return a value of any property from the " "current object or other objects." msgstr "" +"[VisualScriptPropertyGet] peut renvoyer une valeur de toute propriété de " +"l'objet courant ou d'autres objets." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -80853,6 +83805,8 @@ msgid "" "The script to be used when [member set_mode] is set to [constant " "CALL_MODE_INSTANCE]." msgstr "" +"Le script à utiliser lorsque [member set_mode] est défini à [constant " +"CALL_MODE_INSTANCE]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -80860,6 +83814,8 @@ msgid "" "The base type to be used when [member set_mode] is set to [constant " "CALL_MODE_INSTANCE]." msgstr "" +"Le type de base à utiliser lorsque [member set_mode] est défini à [constant " +"CALL_MODE_INSTANCE]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -80867,12 +83823,16 @@ msgid "" "The type to be used when [member set_mode] is set to [constant " "CALL_MODE_BASIC_TYPE]." msgstr "" +"Le type à utiliser lorsque [member set_mode] est défini à [constant " +"CALL_MODE_BASIC_TYPE]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" "The indexed name of the property to retrieve. See [method Object." "get_indexed] for details." msgstr "" +"Le nom indexé de la propriété à récupérer. Voir [method Object.get_indexed] " +"pour plus de détails." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -80880,34 +83840,40 @@ msgid "" "The node path to use when [member set_mode] is set to [constant " "CALL_MODE_NODE_PATH]." msgstr "" +"Le chemin du nÅ“ud à utiliser lorsque [member set_mode] est défini à [" +"constant CALL_MODE_NODE_PATH]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" "The name of the property to retrieve. Changing this will clear [member " "index]." msgstr "" +"Le nom de la propriété à récupérer. Changer cela effecera [member index]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" "[code]set_mode[/code] determines the target object from which the property " "will be retrieved. See [enum CallMode] for options." msgstr "" +"[code]set_mode[/code] détermine l'objet cible à partir duquel la propriété " +"sera récupérée. Voir [enum CallMode] pour les options." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "The property will be retrieved from this [Object]." msgstr "La propriété sera récupérée depuis cet [Object]." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml -#, fuzzy msgid "The property will be retrieved from the given [Node] in the scene tree." msgstr "" -"Le propriété est sérialisé et sauvegardé dans le fichier de la scène(défaut)." +"La propriété sera récupérée du [Node] donné dans l'arborescence de la scène." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" "The property will be retrieved from an instanced node with the given type " "and script." msgstr "" +"La propriété sera récupérée à partir d'un nÅ“ud instancié avec le type et le " +"script donnés." #: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml msgid "" @@ -80917,23 +83883,23 @@ msgstr "" "[Vector2])." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml -#, fuzzy msgid "A Visual Script node that sets a property of an [Object]." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud de script visuel qui définit une propriété d'un [Object]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "[VisualScriptPropertySet] can set the value of any property from the current " "object or other objects." msgstr "" +"[VisualScriptPropertySet] peut définir la valeur de toute propriété à partir " +"de l'objet courant ou d'autres objets." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml -#, fuzzy msgid "" "The additional operation to perform when assigning. See [enum AssignOp] for " "options." msgstr "" -"L'opérateur additionelle à effectuer lors de l'assignation. Voir [enum " +"L'opérateur d'addition à effectuer lors de l'assignation. Voir [enum " "AssignOp] pour les options." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -80941,32 +83907,37 @@ msgid "" "The indexed name of the property to set. See [method Object.set_indexed] for " "details." msgstr "" +"Le nom indexé de la propriété à définir. Voir [method Object.set_indexed] " +"pour plus de détails." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "The name of the property to set. Changing this will clear [member index]." -msgstr "" +msgstr "Le nom de la propriété à définir. Changer cela effecera [member index]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "[code]set_mode[/code] determines the target object on which the property " "will be set. See [enum CallMode] for options." msgstr "" +"[code]set_mode[/code] détermine l'objet cible sur lequel la propriété sera " +"définie. Voir [enum CallMode] pour les options." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "The property will be set on this [Object]." msgstr "La propriété sera définie dans cet [Object]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml -#, fuzzy msgid "The property will be set on the given [Node] in the scene tree." msgstr "" -"Le propriété est sérialisé et sauvegardé dans le fichier de la scène(défaut)." +"La propriété sera placée sur le [Node] donné dans l'arborescence de la scène." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "The property will be set on an instanced node with the given type and script." msgstr "" +"La propriété sera définie sur un nÅ“ud instancié avec le type et le script " +"donnés." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "The property will be set on a GDScript basic type (e.g. [Vector2])." @@ -81012,36 +83983,48 @@ msgid "" "A modulo operation will be performed on the property and the value. " "Equivalent of doing [code]%=[/code]." msgstr "" +"Une opération modulo sera effectuée sur la propriété et la valeur. Revient à " +"écrire [code]%=[/code]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "The property will be binarly shifted to the left by the given value. " "Equivalent of doing [code]<<[/code]." msgstr "" +"La propriété sera transférée à gauche par la valeur donnée. Revient de " +"écrire [code]<<[/code]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "The property will be binarly shifted to the right by the given value. " "Equivalent of doing [code]>>[/code]." msgstr "" +"La propriété sera transférée à droite par la valeur donnée. Revient de " +"écrire [code]>>[/code]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "A binary [code]AND[/code] operation will be performed on the property. " "Equivalent of doing [code]&=[/code]." msgstr "" +"Une opération binaire [code]AND[/code] (et) sera effectuée sur la propriété. " +"Revient à écrire [code]&=[/code]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "A binary [code]OR[/code] operation will be performed on the property. " "Equivalent of doing [code]|=[/code]." msgstr "" +"Une opération binaire [code]OR[/code] (ou) sera effectuée sur la propriété. " +"Revient à écrire [code]|=[/code]." #: modules/visual_script/doc_classes/VisualScriptPropertySet.xml msgid "" "A binary [code]XOR[/code] operation will be performed on the property. " "Equivalent of doing [code]^=[/code]." msgstr "" +"Une opération binaire [code]XOR[/code] (ou exclusif) sera effectuée sur la " +"propriété. Revient à écrire [code]^=[/code]." #: modules/visual_script/doc_classes/VisualScriptReturn.xml msgid "Exits a function and returns an optional value." @@ -81176,9 +84159,8 @@ msgid "" msgstr "" #: modules/visual_script/doc_classes/VisualScriptTypeCast.xml -#, fuzzy msgid "A Visual Script node that casts the given value to another type." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "" #: modules/visual_script/doc_classes/VisualScriptTypeCast.xml msgid "" @@ -81246,9 +84228,8 @@ msgid "" msgstr "" #: modules/visual_script/doc_classes/VisualScriptYield.xml -#, fuzzy msgid "A Visual Script node used to pause a function execution." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script pour mettre en pause l'exécution d'une fonction." #: modules/visual_script/doc_classes/VisualScriptYield.xml msgid "" @@ -81257,11 +84238,11 @@ msgid "" msgstr "" #: modules/visual_script/doc_classes/VisualScriptYield.xml -#, fuzzy msgid "" "The mode to use for yielding. See [enum YieldMode] for available options." msgstr "" -"Type de multiplication à effectuer. Voir [enum Operator] pour les options." +"Le mode à utiliser pour suspendre. Voir [enum YieldMode] pour les options " +"disponibles." #: modules/visual_script/doc_classes/VisualScriptYield.xml msgid "The time to wait when [member mode] is set to [constant YIELD_WAIT]." @@ -81280,9 +84261,8 @@ msgid "Yields a function and waits the given time." msgstr "" #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml -#, fuzzy msgid "A Visual Script node yielding for a signal." -msgstr "Un nÅ“ud Visual Script utilisé pour annoter le script." +msgstr "Un nÅ“ud Visual Script pour attendre un signal." #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml msgid "" @@ -81297,6 +84277,8 @@ msgid "" "[code]call_mode[/code] determines the target object to wait for the signal " "emission. See [enum CallMode] for options." msgstr "" +"[code]call_mode[/code] détermine l'objet cible à attendre avant l'émission " +"du signal. Voir [enum CallMode] pour les options." #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml msgid "The signal name to be waited for." @@ -81308,11 +84290,11 @@ msgstr "Un signal depuis cet [Object] sera utilisé." #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml msgid "A signal from the given [Node] in the scene tree will be used." -msgstr "" +msgstr "Un signal du [Node] donné dans l'arborescence de la scène sera utilisé." #: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml msgid "A signal from an instanced node with the given type will be used." -msgstr "" +msgstr "Un signal d'un nÅ“ud instancié avec le type donné sera utilisé." #: doc/classes/VisualServer.xml msgid "Server for anything visible." @@ -81351,12 +84333,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "Sets images to be rendered in the window margin." msgstr "" +"Définit des images dont le rendu sera fait dans les marges de la fenêtre." #: doc/classes/VisualServer.xml msgid "" "Sets margin size, where black bars (or images, if [method " "black_bars_set_images] was used) are rendered." msgstr "" +"Définit la taille de la marge, où des barres noires (ou des images, si [" +"method black_bars_set_images] est utilisé) sont rendues." #: doc/classes/VisualServer.xml msgid "" @@ -81421,6 +84406,10 @@ msgid "" "the vertical aspect ratio which is equivalent to [constant Camera." "KEEP_HEIGHT]." msgstr "" +"Si [code]true[/code], conserve le rapport d'aspect horizontal qui est " +"équivalent à [constant Camera.KEEP_WIDTH]. Si [code]false[/code], conserve " +"le rapport d'aspect vertical qui est équivalent à [constant Camera." +"KEEP_HEIGHT]." #: doc/classes/VisualServer.xml msgid "" @@ -81441,12 +84430,9 @@ msgid "Adds a circle command to the [CanvasItem]'s draw commands." msgstr "Ajouter un cercle aux commandes de dessin du [CanvasItem]." #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If ignore is [code]true[/code], the VisualServer does not perform clipping." msgstr "" -"Si [code]true[/code], le multithreading est utilisé pour améliorer les " -"performances." #: doc/classes/VisualServer.xml msgid "Adds a line command to the [CanvasItem]'s draw commands." @@ -81461,6 +84447,8 @@ msgid "" "Adds a [MultiMesh] to the [CanvasItem]'s draw commands. Only affects its " "aabb at the moment." msgstr "" +"Ajoute un [MultiMesh] aux commandes d'affichage du [CanvasItem]. N'affecte " +"que son aabb pour le moment." #: doc/classes/VisualServer.xml msgid "" @@ -81482,6 +84470,8 @@ msgid "" "Adds a polyline, which is a line from multiple points with a width, to the " "[CanvasItem]'s draw commands." msgstr "" +"Ajoute une suite de lignes, qui est une ligne de plusieurs points avec une " +"largeur, aux commandes d'affichage du [CanvasItem]." #: doc/classes/VisualServer.xml msgid "Adds a primitive to the [CanvasItem]'s draw commands." @@ -81506,6 +84496,8 @@ msgstr "Ajouter un rectangle texturé aux commandes de dessin du [CanvasItem]." msgid "" "Adds a texture rect with region setting to the [CanvasItem]'s draw commands." msgstr "" +"Ajoute un rectangle de texture, avec des réglages de la région à afficher, " +"aux commandes d'affichage du [CanvasItem]." #: doc/classes/VisualServer.xml msgid "Adds a triangle array to the [CanvasItem]'s draw commands." @@ -81514,7 +84506,7 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "Clears the [CanvasItem] and removes all commands in it." -msgstr "" +msgstr "Efface le [CanvasItem] et enlève toutes les commandes." #: doc/classes/VisualServer.xml msgid "" @@ -81531,7 +84523,6 @@ msgstr "" "méthode statique [method free_rid] du VisualServer." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets clipping for the [CanvasItem]." msgstr "Définit la coupure pour le [CanvasItem]." @@ -81577,6 +84568,9 @@ msgid "" "Sets the parent for the [CanvasItem]. The parent can be another canvas item, " "or it can be the root canvas that is attached to the viewport." msgstr "" +"Définit le parent du [CanvasItem]. Le parent peut être un autre élément de " +"toile, ou il peut être la toile racine qui est attachée à la fenêtre " +"d'affichage." #: doc/classes/VisualServer.xml msgid "Sets the color that modulates the [CanvasItem] without children." @@ -81598,9 +84592,8 @@ msgid "Sets if the [CanvasItem] uses its parent's material." msgstr "Définit si le [CanvasItem] utilise le même matériau que son parent." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets if the canvas item (including its children) is visible." -msgstr "Masquer le [CanvasItem] s’il est actuellement visible." +msgstr "Définit si la toile (y compris ses enfants) est visible." #: doc/classes/VisualServer.xml msgid "" @@ -81683,9 +84676,8 @@ msgid "Sets a canvas light's energy." msgstr "Définit l'énergie d'une lumière du canevas." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets a canvas light's height." -msgstr "Définit la hauteur d’une toile." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -81699,19 +84691,23 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "The mode of the light, see [enum CanvasLightMode] constants." -msgstr "" +msgstr "Le mode de la lumière, voir les constantes [enum CanvasLightMode]." #: doc/classes/VisualServer.xml msgid "" "Sets the texture's scale factor of the light. Equivalent to [member Light2D." "texture_scale]." msgstr "" +"Définit le facteur d'échelle de la texture de lumière. Équivalent à [member " +"Light2D.texture_scale]" #: doc/classes/VisualServer.xml msgid "" "Sets the width of the shadow buffer, size gets scaled to the next power of " "two for this." msgstr "" +"Définit la largeur du tampon d'ombre, la taille est arrondie à la puissance " +"de deux suivante pour cela." #: doc/classes/VisualServer.xml msgid "Sets the color of the canvas light's shadow." @@ -81783,11 +84779,11 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "Sets the shape of the occluder polygon." -msgstr "" +msgstr "Définit la forme du polygone occulteur." #: doc/classes/VisualServer.xml msgid "Sets the shape of the occluder polygon as lines." -msgstr "" +msgstr "Définit la forme du polygone occulteur avec des lignes." #: doc/classes/VisualServer.xml msgid "" @@ -81849,6 +84845,8 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "Sets the ambient light parameters. See [Environment] for more details." msgstr "" +"Définit les paramètres de lumière ambiante. Voir [Environnement] pour plus " +"de détails." #: doc/classes/VisualServer.xml msgid "" @@ -81890,18 +84888,24 @@ msgid "" "Sets the variables to be used with the scene fog. See [Environment] for more " "details." msgstr "" +"Définit les variables à utiliser avec le brouillard de scène. Voir " +"[Environnement] pour plus de détails." #: doc/classes/VisualServer.xml msgid "" "Sets the variables to be used with the fog depth effect. See [Environment] " "for more details." msgstr "" +"Définit les variables à utiliser avec l'effet de profondeur du brouillard. " +"Voir [Environnement] pour plus de détails." #: doc/classes/VisualServer.xml msgid "" "Sets the variables to be used with the fog height effect. See [Environment] " "for more details." msgstr "" +"Définit les variables à utiliser avec l'effet de hauteur du brouillard. Voir " +"[Environnement] pour plus de détails." #: doc/classes/VisualServer.xml msgid "" @@ -81920,12 +84924,16 @@ msgid "" "Sets a custom field of view for the background [Sky]. Equivalent to [member " "Environment.background_sky_custom_fov]." msgstr "" +"Définit un angle de vue personnalisé pour le ciel [Sky] en arrière-plan. " +"Équivalent à [member Environnement.background_sky_custom_fov]" #: doc/classes/VisualServer.xml msgid "" "Sets the rotation of the background [Sky] expressed as a [Basis]. Equivalent " "to [member Environment.background_sky_orientation]." msgstr "" +"Définit la rotation du ciel [Sky] en arrière-plan exprimé avec une [Basis]. " +"Équivalent à [member Environnement.background_sky_orientation]" #: doc/classes/VisualServer.xml msgid "" @@ -81969,6 +84977,7 @@ msgstr "Essaye de supprimer un objet dans le VisualServer." #: doc/classes/VisualServer.xml msgid "Returns a certain information, see [enum RenderInfo] for options." msgstr "" +"Retourne une information précise, voir [enum RenderInfo] pour les options." #: doc/classes/VisualServer.xml msgid "Returns the id of the test cube. Creates one if none exists." @@ -81986,6 +84995,10 @@ msgid "" "[b]Note:[/b] When running a headless or server binary, this function returns " "an empty string." msgstr "" +"Retourne le nom de l'adaptateur vidéo (par exemple \"GeForce GTX 1080/PCIe/" +"SSE2\").\n" +"[b]Note :[/b] Lors de l'exécution d'une version sans graphique ou de " +"serveur, cette fonction retourne une chaîne vide." #: doc/classes/VisualServer.xml msgid "" @@ -81993,6 +85006,10 @@ msgid "" "[b]Note:[/b] When running a headless or server binary, this function returns " "an empty string." msgstr "" +"Retourne le vendeur de l'adaptateur vidéo (par exemple \"NVIDIA Corporation\"" +").\n" +"[b]Note :[/b] Lors de l'exécution d'une version sans graphique ou de " +"serveur, cette fonction retourne une chaîne vide." #: doc/classes/VisualServer.xml msgid "Returns the id of a white texture. Creates one if none exists." @@ -82035,21 +85052,24 @@ msgstr "" "Retourne la taille de la cellule définit par [method gi_probe_set_cell_size]." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the data used by the GI probe." -msgstr "Renvoie l’espace affecté à la zone." +msgstr "Retourne les données utilisées par la sonde GI." #: doc/classes/VisualServer.xml msgid "" "Returns the dynamic range set for this GI probe. Equivalent to [member " "GIProbe.dynamic_range]." msgstr "" +"Retourne la gamme dynamique pour cette sonde GI. Équivalent à [member GIProbe" +".dynamic_range]" #: doc/classes/VisualServer.xml msgid "" "Returns the energy multiplier for this GI probe. Equivalent to [member " "GIProbe.energy]." msgstr "" +"Retourne le multiplicateur d'énergie pour cette sonde GI. Équivalent à [" +"member GIProbe.energy]" #: doc/classes/VisualServer.xml msgid "" @@ -82062,6 +85082,8 @@ msgid "" "Returns the propagation value for this GI probe. Equivalent to [member " "GIProbe.propagation]." msgstr "" +"Retourne la valeur de propagation de cette sonde GI. Équivalent à [member " +"GIProbe.propagation]" #: doc/classes/VisualServer.xml msgid "Returns the Transform set by [method gi_probe_set_to_cell_xform]." @@ -82072,15 +85094,14 @@ msgid "" "Returns [code]true[/code] if the GI probe data associated with this GI probe " "is compressed. Equivalent to [member GIProbe.compress]." msgstr "" +"Retourne [code]true[/code] si les données de cette sonde GI sont " +"compressées. Équivalent à [member GIProbe.compress]" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Returns [code]true[/code] if the GI probe is set to interior, meaning it " "does not account for sky light. Equivalent to [member GIProbe.interior]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml msgid "" @@ -82146,9 +85167,8 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets the to cell [Transform] for this GI probe." -msgstr "Retourne la matrice de transformation globale de cet élément." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -82231,9 +85251,8 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets the material to be used to draw the [ImmediateGeometry]." -msgstr "Retourne le matériel affecté à la [ImmediateGeometry3D]." +msgstr "Définit le matériel utilisé pour afficher le [ImmediateGeometry]." #: doc/classes/VisualServer.xml msgid "" @@ -82515,13 +85534,10 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If [code]true[/code], light will subtract light instead of adding light. " "Equivalent to [member Light.light_negative]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml msgid "" @@ -82539,13 +85555,10 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If [code]true[/code], light will cast shadows. Equivalent to [member Light." "shadow_enabled]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml msgid "" @@ -82582,19 +85595,16 @@ msgstr "" "en utilisant la [method instance_set_base] utilisant le RID retourné." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the size of the lightmap capture area." -msgstr "Renvoie le sinus du paramètre." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the energy multiplier used by the lightmap capture." -msgstr "Renvoie le nombre de textures dans l’atlas BitmapFont." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the octree used by the lightmap capture." -msgstr "Renvoie l’espace affecté à la zone." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -82602,9 +85612,8 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the cell transform for this lightmap capture's octree." -msgstr "Retourne la matrice de transformation de la toile de cet objet." +msgstr "" #: doc/classes/VisualServer.xml msgid "Returns [code]true[/code] if capture is in \"interior\" mode." @@ -82672,13 +85681,10 @@ msgid "Returns the value of a certain material's parameter." msgstr "Retourne la valeur du paramètre du matériau." #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Returns the default value for the param if available. Returns [code]null[/" "code] otherwise." msgstr "" -"Retourne la valeur par défaut du paramètre nommé [code]name[/code] du " -"matériau." #: doc/classes/VisualServer.xml msgid "" @@ -82695,9 +85701,8 @@ msgid "Sets an object's next material." msgstr "Définit le prochain matériau d’un objet." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets a material's parameter." -msgstr "Définit le paramètre d’un matériau." +msgstr "Définit le paramètre d'un matériau." #: doc/classes/VisualServer.xml msgid "Sets a material's render priority." @@ -82760,7 +85765,7 @@ msgstr "Supprime la surface d'un maillage." #: doc/classes/VisualServer.xml #, fuzzy msgid "Sets a mesh's blend shape count." -msgstr "Retourne le nombre de formes de mélange d’un maillage." +msgstr "Définit le nombre de formes de mélange d’un maillage." #: doc/classes/VisualServer.xml msgid "Sets a mesh's blend shape mode." @@ -82775,19 +85780,16 @@ msgid "Returns a mesh's surface's aabb." msgstr "Retourne l’aabb de la surface d'un maillage." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a mesh's surface's vertex buffer." -msgstr "Retourne l’aabb personnalisé d’un maillage." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a mesh's surface's amount of indices." -msgstr "Renvoie le nombre de points de la Ligne2D." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a mesh's surface's amount of vertices." -msgstr "Renvoie le nombre de points de la Ligne2D." +msgstr "" #: doc/classes/VisualServer.xml msgid "Returns a mesh's surface's buffer arrays." @@ -82798,32 +85800,28 @@ msgid "Returns a mesh's surface's arrays for blend shapes." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the format of a mesh's surface." -msgstr "Retourne le nom de la méthode d'une piste de méthode." +msgstr "Retourne le format d'une surface d'un maillage." #: doc/classes/VisualServer.xml msgid "Function is unused in Godot 3.x." msgstr "Cette fonction n'est pas utilisée dans Godot 3.x." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a mesh's surface's index buffer." -msgstr "Retourne le mode de forme de mélange d’un maillage." +msgstr "" #: doc/classes/VisualServer.xml msgid "Returns a mesh's surface's material." msgstr "Retourne le matériau de la surface du maillage." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the primitive type of a mesh's surface." -msgstr "Retourne le nom de la méthode d'une piste de méthode." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the aabb of a mesh's surface's skeleton." -msgstr "Retourne la traduction d’un message." +msgstr "" #: doc/classes/VisualServer.xml msgid "Sets a mesh's surface's material." @@ -83097,13 +86095,10 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If [code]true[/code], uses fractional delta which smooths the movement of " "the particles. Equivalent to [member Particles.fract_delta]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml msgid "" @@ -83173,13 +86168,12 @@ msgstr "" "retourné." #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If [code]true[/code], reflections will ignore sky contribution. Equivalent " "to [member ReflectionProbe.interior_enable]." msgstr "" "Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." +"Équivalent à [member ReflectionProbe.interior_enable]." #: doc/classes/VisualServer.xml msgid "" @@ -83215,23 +86209,17 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Sets the ambient light color for this reflection probe when set to interior " "mode. Equivalent to [member ReflectionProbe.interior_ambient_color]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Sets the energy multiplier for this reflection probes ambient light " "contribution when set to interior mode. Equivalent to [member " "ReflectionProbe.interior_ambient_energy]." msgstr "" -"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. " -"Équivalent à [member ReflectionProbe.interior]." #: doc/classes/VisualServer.xml msgid "" @@ -83349,9 +86337,8 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Enables or disables occlusion culling." -msgstr "Active ou désactive une lumière du canevas." +msgstr "Active ou désactive le culling de l'occlusion." #: doc/classes/VisualServer.xml msgid "" @@ -83368,7 +86355,6 @@ msgstr "" "méthode statique [method free_rid] du VisualServer." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a shader's code." msgstr "Retourne le code d'un shader." @@ -83381,7 +86367,6 @@ msgid "Returns the parameters of a shader." msgstr "Retourne les paramètres d'un shader." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Sets a shader's code." msgstr "Définit le code d'un shader." @@ -83466,14 +86451,12 @@ msgstr "" "utilisant la [method instance_set_base] utilisant le RID retourné." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Allocates the GPU memory for the texture." -msgstr "La largeur de la texture." +msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "Binds the texture to a texture slot." -msgstr "Alignez le texte à gauche." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -83496,9 +86479,8 @@ msgstr "" "Crée une texture, alloue l'espace pour une image, et remplit avec l'image." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns a list of all the textures and their information." -msgstr "Retourne le nombre de pistes dans l'animation." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -83517,9 +86499,8 @@ msgid "Returns the flags of a texture." msgstr "Retourne les drapeaux de la texture." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Returns the format of the texture's image." -msgstr "Renvoie le reste de deux vecteurs." +msgstr "" #: doc/classes/VisualServer.xml msgid "Returns the texture's height." @@ -83620,13 +86601,10 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "If [code]true[/code], the image will be stored in the texture's images array " "if overwritten." msgstr "" -"Si [code]true[/code], la [SpinBox] sera modifiable. Sinon, elle sera en " -"lecture seule." #: doc/classes/VisualServer.xml msgid "Sets a viewport's camera." @@ -83637,7 +86615,6 @@ msgid "Sets a viewport's canvas." msgstr "Définit le canevas de la fenêtre d'affichage." #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Copies viewport to a region of the screen specified by [code]rect[/code]. If " "[member Viewport.render_direct_to_screen] is [code]true[/code], then " @@ -83674,7 +86651,7 @@ msgstr "" " $Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))\n" "[/codeblock]\n" "Utiliser cette méthode peut permettre d'améliorer considérablement les " -"performances, surtout sur les appareils peut puissants. Par contre, cela " +"performances, surtout sur les appareils peu puissants. Par contre, cela " "nécessite de gérer manuellement les fenêtres d'affichage. Pour plus " "d'optimisations, voir [method viewport_set_render_direct_to_screen]." @@ -83763,9 +86740,12 @@ msgstr "" "Définit la matrice de transformation globale de la fenêtre d'affichage." #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "Si [code]true[/code], l'interpolation fait une boucle." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -83849,11 +86829,19 @@ msgid "" msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy msgid "" "Sets the viewport's 2D/3D mode. See [enum ViewportUsage] constants for " "options." -msgstr "Convertit le format de l’image. Voir les constantes [enum Format]." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "" @@ -83918,16 +86906,12 @@ msgid "Number of weights/bones per vertex." msgstr "Nombre de poids / os par sommet." #: doc/classes/VisualServer.xml -#, fuzzy msgid "The minimum Z-layer for canvas items." -msgstr "" -"Le niveau minimal du calque de profondeur pour les éléments de canevas." +msgstr "Le niveau minimal du calque de profondeur pour les éléments de canevas." #: doc/classes/VisualServer.xml -#, fuzzy msgid "The maximum Z-layer for canvas items." -msgstr "" -"Le niveau maximal du calque de profondeur pour les éléments de canevas." +msgstr "Le niveau maximal du calque de profondeur pour les éléments de canevas." #: doc/classes/VisualServer.xml msgid "" @@ -83989,7 +86973,6 @@ msgid "A 3-dimensional texture with width, height, and depth." msgstr "Une texture à 3 dimensions, largeur et hauteur, et profondeur." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Repeats the texture (instead of clamp to edge)." msgstr "Répète la texture (plutôt que de s'arrêter aux bordures)." @@ -84383,9 +87366,8 @@ msgid "Number of draw calls during this frame." msgstr "Nombre d'appels d'affichage pour cette trame." #: doc/classes/VisualServer.xml -#, fuzzy msgid "Number of 2d items drawn this frame." -msgstr "Nombre de changements de surface pendant cette image." +msgstr "Le nombre d'éléments 2D affichés dans cette trame." #: doc/classes/VisualServer.xml msgid "Number of 2d draw calls during this frame." @@ -85060,11 +88042,8 @@ msgstr "Sera traduit en [code]uniform bool[/code] dans le code du shader." #: doc/classes/VisualShaderNodeScalarUniform.xml #: doc/classes/VisualShaderNodeTransformUniform.xml #: doc/classes/VisualShaderNodeVec3Uniform.xml -#, fuzzy msgid "A default value to be assigned within the shader." msgstr "" -"Un opérateur scalaire à virgule flottante à utiliser dans le graphique du " -"nuanceur visuel." #: doc/classes/VisualShaderNodeBooleanUniform.xml #: doc/classes/VisualShaderNodeColorUniform.xml @@ -85357,7 +88336,6 @@ msgid "" msgstr "" #: doc/classes/VisualShaderNodeCompare.xml -#, fuzzy msgid "" "The result will be true if all of component in vector satisfy the comparison " "condition." @@ -85366,7 +88344,6 @@ msgstr "" "condition de comparaison." #: doc/classes/VisualShaderNodeCompare.xml -#, fuzzy msgid "" "The result will be true if any of component in vector satisfy the comparison " "condition." @@ -85375,11 +88352,8 @@ msgstr "" "condition de comparaison." #: doc/classes/VisualShaderNodeCubeMap.xml -#, fuzzy msgid "A [CubeMap] sampling node to be used within the visual shader graph." msgstr "" -"Un opérateur scalaire à virgule flottante à utiliser dans le graphique du " -"nuanceur visuel." #: doc/classes/VisualShaderNodeCubeMap.xml msgid "" @@ -85446,11 +88420,8 @@ msgid "" msgstr "" #: doc/classes/VisualShaderNodeCubeMapUniform.xml -#, fuzzy msgid "A [CubeMap] uniform node to be used within the visual shader graph." msgstr "" -"Un tableau uniforme de texture 2D à utiliser dans le graphique de l'ombrage " -"visuel." #: doc/classes/VisualShaderNodeCubeMapUniform.xml msgid "" @@ -86126,13 +89097,12 @@ msgid "Defaults to black color." msgstr "Par défaut à la couleur noire." #: doc/classes/VisualShaderNodeTextureUniformTriplanar.xml -#, fuzzy msgid "" "Performs a uniform texture lookup with triplanar within the visual shader " "graph." msgstr "" -"Effectue une recherche de texture uniforme avec triplanaire dans le " -"graphique de nuanceur visuel." +"Effectue une projection de texture uniforme en triplanaire dans le graphe du " +"Visual Shader." #: doc/classes/VisualShaderNodeTextureUniformTriplanar.xml msgid "" @@ -86141,12 +89111,11 @@ msgid "" msgstr "" #: doc/classes/VisualShaderNodeTransformCompose.xml -#, fuzzy msgid "" "Composes a [Transform] from four [Vector3]s within the visual shader graph." msgstr "" -"Compose un [Transform] à partir de quatre [Vector3] dans le graphique du " -"nuanceur visuel." +"Compose un [Transform] à partir de quatre [Vector3] dans le graphe du Visual " +"Shader." #: doc/classes/VisualShaderNodeTransformCompose.xml msgid "" @@ -86260,11 +89229,10 @@ msgid "Translated to [code]uniform mat4[/code] in the shader language." msgstr "Sera traduit en [code]uniform mat4[/code] dans le code du shader." #: doc/classes/VisualShaderNodeTransformVecMult.xml -#, fuzzy msgid "" "Multiplies a [Transform] and a [Vector3] within the visual shader graph." msgstr "" -"Multiplie un [Transform] et un [Vector3] dans le graphique de shader visuel." +"Multiplie un [Transform] et un [Vector3] dans le graphe du Visual Shader." #: doc/classes/VisualShaderNodeTransformVecMult.xml msgid "" @@ -86307,7 +89275,7 @@ msgstr "" #: doc/classes/VisualShaderNodeUniform.xml #, fuzzy msgid "A base type for the uniforms within the visual shader graph." -msgstr "Type de base pour les uniformes dans le graphique du nuanceur visuel." +msgstr "Le type de base pour les uniformes dans le graphe du Visual Shader." #: doc/classes/VisualShaderNodeUniform.xml msgid "" @@ -86864,10 +89832,9 @@ msgid "Closes this data channel, notifying the other peer." msgstr "Ferme ce canal de données, en notifiant l’autre homologue." #: modules/webrtc/doc_classes/WebRTCDataChannel.xml -#, fuzzy msgid "" "Returns the number of bytes currently queued to be sent over this channel." -msgstr "Retourne le nombre de traqueurs actuellement enregistrés." +msgstr "" #: modules/webrtc/doc_classes/WebRTCDataChannel.xml msgid "" @@ -86958,7 +89925,6 @@ msgid "The channel was created, but it's still trying to connect." msgstr "Le canal a été créé, mais il essaie toujours de se connecter." #: modules/webrtc/doc_classes/WebRTCDataChannel.xml -#, fuzzy msgid "The channel is currently open, and data can flow over it." msgstr "Le canal est actuellement ouvert, et les données peuvent y circuler." @@ -87067,9 +90033,8 @@ msgid "" msgstr "" #: modules/webrtc/doc_classes/WebRTCPeerConnection.xml -#, fuzzy msgid "Interface to a WebRTC peer connection." -msgstr "Interface vers une connexion homologue WebRTC." +msgstr "L'interface de connexion par pair via WebRTC." #: modules/webrtc/doc_classes/WebRTCPeerConnection.xml msgid "" @@ -88123,14 +91088,12 @@ msgid "" msgstr "" #: doc/classes/WindowDialog.xml -#, fuzzy msgid "The vertical offset of the title text." -msgstr "Décalage vertical du texte du titre." +msgstr "Le décalage vertical du texte du titre." #: doc/classes/WindowDialog.xml -#, fuzzy msgid "The font used to draw the title." -msgstr "La police utilisée pour le texte en gras." +msgstr "" #: doc/classes/WindowDialog.xml msgid "The icon for the close button." @@ -88176,10 +91139,9 @@ msgid "" msgstr "" #: doc/classes/World.xml -#, fuzzy msgid "" "The [RID] of this world's navigation map. Used by the [NavigationServer]." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "" #: doc/classes/World.xml msgid "The World's visual scenario." @@ -88214,10 +91176,9 @@ msgid "" msgstr "" #: doc/classes/World2D.xml -#, fuzzy msgid "" "The [RID] of this world's navigation map. Used by the [Navigation2DServer]." -msgstr "Retourne le [RID] de la énième forme d'une zone." +msgstr "" #: doc/classes/World2D.xml msgid "" diff --git a/doc/translations/gl.po b/doc/translations/gl.po index 3273cd8f98..207a818761 100644 --- a/doc/translations/gl.po +++ b/doc/translations/gl.po @@ -848,7 +848,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7685,8 +7692,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9966,7 +9973,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10131,7 +10144,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11742,7 +11761,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20153,7 +20177,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23539,7 +23563,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25370,7 +25394,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28411,13 +28435,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29831,9 +29856,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30407,10 +30432,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30423,6 +30451,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32456,7 +32490,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32472,7 +32506,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32502,7 +32536,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36602,7 +36636,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36863,7 +36897,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36977,6 +37011,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39674,7 +39754,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39686,7 +39772,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45290,6 +45377,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54214,7 +54308,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54254,15 +54349,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55738,11 +55834,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57412,7 +57527,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60303,8 +60418,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63927,13 +64042,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63945,13 +64061,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65759,11 +65876,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65843,8 +65960,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70837,7 +70954,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70922,6 +71043,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/hi.po b/doc/translations/hi.po index 361c131a40..2df4b9bbe4 100644 --- a/doc/translations/hi.po +++ b/doc/translations/hi.po @@ -847,7 +847,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7684,8 +7691,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9965,7 +9972,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10130,7 +10143,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11741,7 +11760,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20152,7 +20176,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23538,7 +23562,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25369,7 +25393,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28410,13 +28434,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29830,9 +29855,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30406,10 +30431,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30422,6 +30450,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32455,7 +32489,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32471,7 +32505,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32501,7 +32535,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36601,7 +36635,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36862,7 +36896,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36976,6 +37010,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39673,7 +39753,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39685,7 +39771,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45289,6 +45376,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54213,7 +54307,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54253,15 +54348,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55737,11 +55833,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57411,7 +57526,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60302,8 +60417,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63926,13 +64041,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63944,13 +64060,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65758,11 +65875,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65842,8 +65959,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70836,7 +70953,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70921,6 +71042,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/hu.po b/doc/translations/hu.po index 2732b7b56a..221206451a 100644 --- a/doc/translations/hu.po +++ b/doc/translations/hu.po @@ -866,7 +866,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7703,8 +7710,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9984,7 +9991,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10149,7 +10162,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11760,7 +11779,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20171,7 +20195,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23557,7 +23581,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25388,7 +25412,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28429,13 +28453,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29849,9 +29874,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30425,10 +30450,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30441,6 +30469,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32474,7 +32508,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32490,7 +32524,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32520,7 +32554,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36620,7 +36654,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36881,7 +36915,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36995,6 +37029,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39692,7 +39772,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39704,7 +39790,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45308,6 +45395,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54232,7 +54326,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54272,15 +54367,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55756,11 +55852,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57430,7 +57545,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60321,8 +60436,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63945,13 +64060,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63963,13 +64079,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65777,11 +65894,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65861,8 +65978,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70855,7 +70972,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70940,6 +71061,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/id.po b/doc/translations/id.po index efc379cffd..39310a6160 100644 --- a/doc/translations/id.po +++ b/doc/translations/id.po @@ -15,12 +15,13 @@ # ProgrammerIndonesia 44 <elo.jhy@gmail.com>, 2022. # Reza Almanda <rezaalmanda27@gmail.com>, 2022. # Tsaqib Fadhlurrahman Soka <sokatsaqib@gmail.com>, 2022. +# yusuf afandi <afandi.yusuf.04@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-05-28 14:11+0000\n" -"Last-Translator: Reza Almanda <rezaalmanda27@gmail.com>\n" +"PO-Revision-Date: 2022-07-09 21:12+0000\n" +"Last-Translator: yusuf afandi <afandi.yusuf.04@gmail.com>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/id/>\n" "Language: id\n" @@ -28,7 +29,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.13-dev\n" +"X-Generator: Weblate 4.13.1-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -122,7 +123,7 @@ msgstr "Metode ini menerima sejumlah argumen setelah yang dijelaskan di sini." #: doc/tools/make_rst.py msgid "This method is used to construct a type." -msgstr "" +msgstr "Metode ini digunakan untuk mengkonstruksi sebuah tipe." #: doc/tools/make_rst.py msgid "" @@ -1198,10 +1199,22 @@ msgstr "" "atau peringatan dicetak." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Seperti [metode cetak], tetapi hanya mencetak saat digunakan dalam mode " -"debug." +"Mencetak trek tumpukan di lokasi kode, hanya berfungsi saat dijalankan " +"dengan debugger dihidupkan.\n" +"Output di konsol akan terlihat seperti ini:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 dalam fungsi '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml #, fuzzy @@ -8096,8 +8109,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10377,7 +10390,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10542,7 +10561,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12153,7 +12178,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20566,7 +20596,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23956,7 +23986,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25793,7 +25823,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28835,13 +28865,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30255,9 +30286,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30831,10 +30862,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30847,6 +30881,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32880,7 +32920,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32896,7 +32936,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32926,7 +32966,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37047,7 +37087,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37308,7 +37348,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37424,6 +37464,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40121,7 +40207,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40133,7 +40225,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45755,6 +45848,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54682,7 +54782,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54722,15 +54823,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56206,11 +56308,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57880,7 +58001,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60777,8 +60898,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64402,13 +64523,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64420,13 +64542,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66234,11 +66357,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66318,8 +66441,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71317,7 +71440,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71402,6 +71529,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/is.po b/doc/translations/is.po index bdd631ef18..e3080abf39 100644 --- a/doc/translations/is.po +++ b/doc/translations/is.po @@ -847,7 +847,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7684,8 +7691,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9965,7 +9972,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10130,7 +10143,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11741,7 +11760,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20152,7 +20176,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23538,7 +23562,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25369,7 +25393,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28410,13 +28434,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29830,9 +29855,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30406,10 +30431,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30422,6 +30450,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32455,7 +32489,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32471,7 +32505,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32501,7 +32535,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36601,7 +36635,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36862,7 +36896,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36976,6 +37010,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39673,7 +39753,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39685,7 +39771,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45289,6 +45376,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54213,7 +54307,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54253,15 +54348,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55737,11 +55833,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57411,7 +57526,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60302,8 +60417,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63926,13 +64041,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63944,13 +64060,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65758,11 +65875,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65842,8 +65959,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70836,7 +70953,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70921,6 +71042,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/it.po b/doc/translations/it.po index 3d9cd62b30..e07c906b29 100644 --- a/doc/translations/it.po +++ b/doc/translations/it.po @@ -25,12 +25,13 @@ # Andrea Leganza <neogene@gmail.com>, 2021. # Federico Caprini <caprinifede@gmail.com>, 2022. # Alessandro Casalino <alessandro.casalino93@gmail.com>, 2022. +# AndreWharn <andrewharnofficial@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-04-25 15:12+0000\n" -"Last-Translator: Micila Micillotto <micillotto@gmail.com>\n" +"PO-Revision-Date: 2022-07-31 16:43+0000\n" +"Last-Translator: Mirko <miknsop@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/it/>\n" "Language: it\n" @@ -38,7 +39,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.12.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -61,6 +62,7 @@ msgid "Theme Properties" msgstr "Proprietà del tema" #: doc/tools/make_rst.py +#, fuzzy msgid "Signals" msgstr "Segnali" @@ -101,18 +103,16 @@ msgid "Default" msgstr "Predefinito" #: doc/tools/make_rst.py -#, fuzzy msgid "Setter" -msgstr "Impostatore" +msgstr "Setter" #: doc/tools/make_rst.py msgid "value" msgstr "valore" #: doc/tools/make_rst.py -#, fuzzy msgid "Getter" -msgstr "Acchiappatore" +msgstr "Getter" #: doc/tools/make_rst.py msgid "" @@ -137,9 +137,8 @@ msgstr "" "qui." #: doc/tools/make_rst.py -#, fuzzy msgid "This method is used to construct a type." -msgstr "Questo metodo viene utilizzato per creare un tipo di variabile." +msgstr "Questo metodo viene utilizzato per creare un tipo." #: doc/tools/make_rst.py msgid "" @@ -1372,10 +1371,22 @@ msgstr "" "messaggi di debug ed errore che vengono mostrati con la stack trace." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Come [method print], ma stampa solo quando viene utilizzato in modalità " -"debug." +"Stampa un stack trace nella posizione del codice, funziona solo quando il " +"debugger è attivato.\n" +"L'output nella console apparirà come:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8702,8 +8713,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10991,7 +11002,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -11156,7 +11173,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12771,7 +12794,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -21291,7 +21319,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24691,7 +24719,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -26531,7 +26559,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -29595,13 +29623,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -31020,9 +31049,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -31597,10 +31626,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31612,6 +31644,13 @@ msgid "Mouse and input coordinates" msgstr "" #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero." + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -33660,7 +33699,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33676,7 +33715,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33709,7 +33748,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37861,7 +37900,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -38125,7 +38164,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -38244,6 +38283,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40949,7 +41034,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40961,7 +41052,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -46611,6 +46703,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -55551,7 +55650,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55591,15 +55691,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56860,7 +56961,7 @@ msgstr "" #: doc/classes/Spatial.xml msgid "Introduction to 3D" -msgstr "" +msgstr "Introduzione al 3D" #: doc/classes/Spatial.xml doc/classes/Vector3.xml msgid "All 3D Demos" @@ -57077,11 +57178,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58756,7 +58876,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61672,8 +61792,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -65336,13 +65456,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -65354,13 +65475,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -67192,11 +67314,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -67276,8 +67398,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -72316,11 +72438,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" -"Se [code] vero [/code], i nodi figli sono ordinati, altrimenti l'ordinamento " -"è disabilitato." #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -72404,6 +72527,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/ja.po b/doc/translations/ja.po index 8ace2ec0c8..fe76c741d0 100644 --- a/doc/translations/ja.po +++ b/doc/translations/ja.po @@ -1333,8 +1333,22 @@ msgstr "" "ãŸã¨ãã«ã‚¹ã‚¿ãƒƒã‚¯ãƒˆãƒ¬ãƒ¼ã‚¹ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "[method print] ã¨åŒæ§˜ã§ã™ãŒã€ã—ã‹ã—デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰æ™‚ã«ã®ã¿è¡¨ç¤ºã—ã¾ã™ã€‚" +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" +"コードä½ç½®ã®ã‚¹ã‚¿ãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚¯ã‚’表示ã—ã¾ã™ã€‚デãƒãƒƒã‚¬ã‚’有効ã«ã—ã¦å®Ÿè¡Œã—ãŸæ™‚ã«ã®" +"ã¿å‹•作ã—ã¾ã™ã€‚\n" +"コンソール内ã§ã®å‡ºåŠ›ã¯ã“ã®ã‚ˆã†ã«ãªã‚Šã¾ã™:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -9918,8 +9932,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -12677,8 +12691,14 @@ msgstr "" "ã¾ã™ã€‚" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." -msgstr "ã“ã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªãŒå†ç”Ÿã•れã¦ã„ã‚‹ãƒã‚¹ã€‚" +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer.xml msgid "" @@ -12860,9 +12880,14 @@ msgstr "" "ã¾ã™ã€‚" #: doc/classes/AudioStreamPlayer3D.xml -#, fuzzy -msgid "The bus on which this audio is playing." -msgstr "ã“ã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªãŒå†ç”Ÿã•れã¦ã„ã‚‹ãƒã‚¹ã€‚" +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -14706,7 +14731,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -23291,7 +23321,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -26714,7 +26744,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -28556,7 +28586,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -31648,13 +31678,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -33082,9 +33113,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -33658,10 +33689,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -33673,6 +33707,14 @@ msgid "Mouse and input coordinates" msgstr "" #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"æ–‡å—列ã®é•·ã•㌠[code]0[/code] ã«ç‰ã—ã‘れ㰠[code]true[/code] ã‚’è¿”ã—ã¾ã™ã€‚" + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -35756,7 +35798,7 @@ msgstr "円柱ã®é«˜ã•。" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -35772,7 +35814,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -35808,7 +35850,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -40005,7 +40047,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -40272,7 +40314,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -40393,6 +40435,53 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +#, fuzzy +msgid "Set the max packet size that this peer can handle." +msgstr "指定ã•れãŸåå‰ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒŽãƒ¼ãƒ‰ã‚’è¿”ã—ã¾ã™ã€‚" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -43101,7 +43190,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -43113,7 +43208,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -48785,6 +48881,14 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +#, fuzzy +msgid "Sorts the elements of the array in ascending order." +msgstr "インデックスã«ã‚ˆã‚Šé…列ã‹ã‚‰è¦ç´ を削除ã—ã¾ã™ã€‚" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -57800,7 +57904,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -57840,15 +57945,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -59334,11 +59440,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -61284,7 +61409,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -64237,8 +64362,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -67931,13 +68056,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -67949,13 +68075,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -69788,11 +69915,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -69872,8 +69999,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -74984,9 +75111,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "[code]true[/code]ã®å ´åˆã€é ‚点色をアルベド色ã¨ã—ã¦ä½¿ç”¨ã—ã¾ã™ã€‚" +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -75070,6 +75200,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/ko.po b/doc/translations/ko.po index bd808074b9..ac9274cee6 100644 --- a/doc/translations/ko.po +++ b/doc/translations/ko.po @@ -1004,7 +1004,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7859,8 +7866,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10141,7 +10148,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10306,7 +10319,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11919,7 +11938,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20440,7 +20464,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23832,7 +23856,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25670,7 +25694,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28713,13 +28737,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30141,9 +30166,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30717,10 +30742,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30733,6 +30761,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32770,7 +32804,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32786,7 +32820,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32816,7 +32850,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36950,7 +36984,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37213,7 +37247,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37331,6 +37365,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40154,7 +40234,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40166,7 +40252,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45796,6 +45883,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54725,7 +54819,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54765,15 +54860,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56249,11 +56345,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57923,7 +58038,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60824,8 +60939,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64457,13 +64572,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64475,13 +64591,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66291,11 +66408,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66375,8 +66492,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71402,7 +71519,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71487,6 +71608,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/lt.po b/doc/translations/lt.po index 2de21d55b3..79790f5e70 100644 --- a/doc/translations/lt.po +++ b/doc/translations/lt.po @@ -857,7 +857,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7694,8 +7701,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9975,7 +9982,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10140,7 +10153,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11751,7 +11770,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20162,7 +20186,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23548,7 +23572,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25379,7 +25403,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28420,13 +28444,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29840,9 +29865,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30416,10 +30441,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30432,6 +30460,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32465,7 +32499,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32481,7 +32515,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32511,7 +32545,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36611,7 +36645,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36872,7 +36906,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36986,6 +37020,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39683,7 +39763,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39695,7 +39781,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45299,6 +45386,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54223,7 +54317,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54263,15 +54358,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55747,11 +55843,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57421,7 +57536,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60312,8 +60427,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63936,13 +64051,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63954,13 +64070,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65768,11 +65885,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65852,8 +65969,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70846,7 +70963,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70931,6 +71052,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/lv.po b/doc/translations/lv.po index 45e3188446..1f63bf69bb 100644 --- a/doc/translations/lv.po +++ b/doc/translations/lv.po @@ -862,7 +862,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7699,8 +7706,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9980,7 +9987,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10145,7 +10158,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11756,7 +11775,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20167,7 +20191,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23556,7 +23580,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25387,7 +25411,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28428,13 +28452,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29848,9 +29873,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30424,10 +30449,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30440,6 +30468,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32473,7 +32507,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32489,7 +32523,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32519,7 +32553,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36619,7 +36653,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36880,7 +36914,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36994,6 +37028,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39691,7 +39771,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39703,7 +39789,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45307,6 +45394,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54231,7 +54325,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54271,15 +54366,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55755,11 +55851,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57429,7 +57544,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60320,8 +60435,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63944,13 +64059,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63962,13 +64078,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65776,11 +65893,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65860,8 +65977,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70854,7 +70971,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70939,6 +71060,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/mr.po b/doc/translations/mr.po index b943c79052..32832a4d8f 100644 --- a/doc/translations/mr.po +++ b/doc/translations/mr.po @@ -845,7 +845,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7682,8 +7689,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9963,7 +9970,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10128,7 +10141,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11739,7 +11758,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20150,7 +20174,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23536,7 +23560,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25367,7 +25391,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28408,13 +28432,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29828,9 +29853,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30404,10 +30429,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30420,6 +30448,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32453,7 +32487,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32469,7 +32503,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32499,7 +32533,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36599,7 +36633,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36860,7 +36894,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36974,6 +37008,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39671,7 +39751,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39683,7 +39769,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45287,6 +45374,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54211,7 +54305,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54251,15 +54346,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55735,11 +55831,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57409,7 +57524,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60300,8 +60415,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63924,13 +64039,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63942,13 +64058,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65756,11 +65873,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65840,8 +65957,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70834,7 +70951,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70919,6 +71040,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/nb.po b/doc/translations/nb.po index 53fca58f26..42dca83c45 100644 --- a/doc/translations/nb.po +++ b/doc/translations/nb.po @@ -857,7 +857,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7694,8 +7701,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9975,7 +9982,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10140,7 +10153,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11751,7 +11770,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20162,7 +20186,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23548,7 +23572,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25379,7 +25403,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28420,13 +28444,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29840,9 +29865,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30416,10 +30441,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30432,6 +30460,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32465,7 +32499,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32481,7 +32515,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32511,7 +32545,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36611,7 +36645,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36872,7 +36906,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36986,6 +37020,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39683,7 +39763,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39695,7 +39781,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45299,6 +45386,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54223,7 +54317,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54263,15 +54358,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55747,11 +55843,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57421,7 +57536,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60312,8 +60427,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63936,13 +64051,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63954,13 +64070,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65768,11 +65885,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65852,8 +65969,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70846,7 +70963,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70931,6 +71052,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/ne.po b/doc/translations/ne.po index 24062d3cff..0ba02ba939 100644 --- a/doc/translations/ne.po +++ b/doc/translations/ne.po @@ -845,7 +845,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7682,8 +7689,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9963,7 +9970,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10128,7 +10141,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11739,7 +11758,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20150,7 +20174,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23536,7 +23560,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25367,7 +25391,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28408,13 +28432,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29828,9 +29853,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30404,10 +30429,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30420,6 +30448,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32453,7 +32487,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32469,7 +32503,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32499,7 +32533,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36599,7 +36633,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36860,7 +36894,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36974,6 +37008,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39671,7 +39751,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39683,7 +39769,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45287,6 +45374,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54211,7 +54305,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54251,15 +54346,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55735,11 +55831,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57409,7 +57524,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60300,8 +60415,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63924,13 +64039,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63942,13 +64058,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65756,11 +65873,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65840,8 +65957,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70834,7 +70951,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70919,6 +71040,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/nl.po b/doc/translations/nl.po index b2066a5491..3053cadb2b 100644 --- a/doc/translations/nl.po +++ b/doc/translations/nl.po @@ -906,7 +906,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7751,8 +7758,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10032,7 +10039,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10197,7 +10210,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11808,7 +11827,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20219,7 +20243,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23608,7 +23632,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25439,7 +25463,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28480,13 +28504,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29900,9 +29925,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30476,10 +30501,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30492,6 +30520,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32525,7 +32559,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32541,7 +32575,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32571,7 +32605,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36671,7 +36705,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36932,7 +36966,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37046,6 +37080,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39743,7 +39823,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39755,7 +39841,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45359,6 +45446,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54284,7 +54378,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54324,15 +54419,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55808,11 +55904,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57482,7 +57597,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60373,8 +60488,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63997,13 +64112,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64015,13 +64131,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65829,11 +65946,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65913,8 +66030,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70907,7 +71024,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70992,6 +71113,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/pl.po b/doc/translations/pl.po index b28e575320..729b6a654c 100644 --- a/doc/translations/pl.po +++ b/doc/translations/pl.po @@ -1279,8 +1279,22 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "Jak [method print], ale wypisuje tylko w trybie debugowania." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" +"Wypisuje zrzut stosu w miejscu kodu, dziaÅ‚a tylko przy uruchamianiu z " +"włączonym debuggerem.\n" +"Wynik w konsoli wyglÄ…dać może tak:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8189,8 +8203,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10471,7 +10485,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10636,7 +10656,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12250,7 +12276,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20691,7 +20722,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24090,7 +24121,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25927,7 +25958,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28986,13 +29017,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30409,9 +30441,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30985,10 +31017,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31001,6 +31036,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -33054,7 +33095,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33070,7 +33111,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33103,7 +33144,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37259,7 +37300,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37523,7 +37564,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37642,6 +37683,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40339,7 +40426,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40351,7 +40444,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -46003,6 +46097,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54943,7 +55044,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54983,15 +55085,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56468,11 +56571,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58145,7 +58267,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61047,8 +61169,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64694,13 +64816,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64712,13 +64835,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66529,11 +66653,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66613,8 +66737,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71646,11 +71770,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" -"JeÅ›li [code]true[/code], potomne wÄ™zÅ‚y sÄ… sortowane. W innym przypadku jest " -"wyłączone." #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -71734,6 +71859,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/pt.po b/doc/translations/pt.po index 99537cdd6b..c99a8e1cd6 100644 --- a/doc/translations/pt.po +++ b/doc/translations/pt.po @@ -1340,9 +1340,22 @@ msgstr "" "rastreamento de pilha quando um erro ou aviso é impresso ." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Igual [method print], mas só imprime quando usado em modo de depuração." +"Imprime a pilha de chamadas no local do código, só funciona com o depurador " +"ativado.\n" +"SaÃda no console vai parecer assim:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8506,8 +8519,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10787,7 +10800,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10952,7 +10971,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12568,7 +12593,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -21026,7 +21056,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24422,7 +24452,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -26259,7 +26289,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -29301,13 +29331,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30721,9 +30752,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -31297,10 +31328,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31313,6 +31347,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -33361,7 +33401,7 @@ msgstr "A altura do cilindro." msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33377,7 +33417,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33408,7 +33448,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37537,7 +37577,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37802,7 +37842,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37920,6 +37960,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40617,7 +40703,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40629,7 +40721,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -46238,6 +46331,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -55231,7 +55331,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55271,15 +55372,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56757,11 +56859,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58449,7 +58570,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61346,8 +61467,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64985,13 +65106,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -65003,13 +65125,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66821,11 +66944,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66905,8 +67028,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71904,7 +72027,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71989,6 +72116,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/pt_BR.po b/doc/translations/pt_BR.po index b432963519..ea624fdf2c 100644 --- a/doc/translations/pt_BR.po +++ b/doc/translations/pt_BR.po @@ -41,12 +41,13 @@ # Fabio Moura de Oliveira <ccmaismais@yahoo.com>, 2022. # Daniel Abrante <danielabrante@protonmail.com>, 2022. # lucas rossy brasil coelho <lucasrossy270@gmail.com>, 2022. +# Felipe Kinoshita <kinofhek@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-06-16 18:58+0000\n" -"Last-Translator: lucas rossy brasil coelho <lucasrossy270@gmail.com>\n" +"PO-Revision-Date: 2022-08-04 06:40+0000\n" +"Last-Translator: Felipe Kinoshita <kinofhek@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot-class-reference/pt_BR/>\n" "Language: pt_BR\n" @@ -54,7 +55,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.13-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -1368,9 +1369,22 @@ msgstr "" "rastreamento de pilha quando um erro ou aviso é impresso ." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"Igual [method print], mas só imprime quando usado em modo de depuração." +"Imprime a pilha de chamadas no local do código, só funciona com o depurador " +"habilitado.\n" +"SaÃda no console vai parecer assim:\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8742,8 +8756,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -11025,7 +11039,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -11190,7 +11210,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12808,7 +12834,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -21320,7 +21351,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24723,7 +24754,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -26562,7 +26593,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -29629,13 +29660,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -31054,9 +31086,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -31630,10 +31662,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31646,6 +31681,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -33698,7 +33739,7 @@ msgstr "A altura do cilindro." msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33714,7 +33755,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33747,7 +33788,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37903,7 +37944,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -38169,7 +38210,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -38288,6 +38329,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40985,7 +41072,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40997,7 +41090,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -46651,6 +46745,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -55595,7 +55696,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55635,15 +55737,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -57123,11 +57226,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58818,7 +58940,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61730,8 +61852,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -65383,13 +65505,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -65401,13 +65524,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -67221,11 +67345,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -67305,8 +67429,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -72339,11 +72463,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" -"Se [code]true[/code], os nós filhos são organizados, do contrário, a " -"organização é desabilitada." #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -72427,6 +72552,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" @@ -76621,6 +76755,13 @@ msgid "" "the same space as the parent YSort, allowing to better organize a scene or " "divide it in multiple ones, yet keep the unique sorting." msgstr "" +"Classifique todos os nós filhos com base em suas posições Y. O nó filho deve " +"herdar de [CanvasItem] para ser classificado. Os nós que têm uma posição Y " +"mais alta serão desenhados mais tarde, então eles aparecerão no topo dos nós " +"que têm uma posição Y mais baixa. O aninhamento de nós YSort é possÃvel. Os " +"nós YSort filhos serão classificados no mesmo espaço que o YSort pai, " +"permitindo organizar melhor uma cena ou dividi-la em várias outras, mas " +"manter a classificação única." #: doc/classes/YSort.xml msgid "" diff --git a/doc/translations/ro.po b/doc/translations/ro.po index 068587e37a..332dbd0801 100644 --- a/doc/translations/ro.po +++ b/doc/translations/ro.po @@ -873,7 +873,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7714,8 +7721,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9995,7 +10002,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10160,7 +10173,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11771,7 +11790,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20182,7 +20206,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23571,7 +23595,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25402,7 +25426,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28443,13 +28467,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29863,9 +29888,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30439,10 +30464,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30455,6 +30483,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32488,7 +32522,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32504,7 +32538,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32534,7 +32568,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36634,7 +36668,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36895,7 +36929,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37010,6 +37044,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39707,7 +39787,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39719,7 +39805,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45323,6 +45410,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54247,7 +54341,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54287,15 +54382,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55771,11 +55867,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57445,7 +57560,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60336,8 +60451,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63960,13 +64075,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63978,13 +64094,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65792,11 +65909,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65876,8 +65993,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70870,7 +70987,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70955,6 +71076,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/ru.po b/doc/translations/ru.po index 6455a611e5..b148868ce6 100644 --- a/doc/translations/ru.po +++ b/doc/translations/ru.po @@ -49,21 +49,22 @@ # FuzzMix <fmwolfiechad@gmail.com>, 2022. # МÐÐ69К <weblate@mah69k.net>, 2022. # Vadim Mitroshkin <Vadim7540@yandex.ru>, 2022. +# SonicStalker Games <dmitriyusolsev1971@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-07-03 00:44+0000\n" -"Last-Translator: Bozhko Artyom Dmitrievich <jek_sun@mail.ru>\n" +"PO-Revision-Date: 2022-08-04 06:40+0000\n" +"Last-Translator: SonicStalker Games <dmitriyusolsev1971@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/ru/>\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\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.13.1-dev\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.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -620,11 +621,11 @@ msgstr "" "[codeblock]\n" "- Меньше -1,0 (не включаÑ): Облегчение вхождениÑ-выхождениÑ\n" "- 1.0: Линейный\n" -"- От -1,0 до 0,0 (не включаÑ): Облегчение в\n" +"- От -1,0 до 0,0 (не включаÑ): Облегчение выхождениÑ-вхождениÑ\n" "- 0.0: ПоÑтоÑнный\n" -"- От 0,0 до 1,0 (не включаÑ): Облегчение\n" +"- От 0,0 до 1,0 (не включаÑ): Облегчение выхождениÑ(только выход)\n" "- 1.0: Линейный\n" -"- Больше 1,0 (не включаÑ): Облегчение\n" +"- Больше 1,0 (не включаÑ): Облегчение вхождениÑ(только вход)\n" "[/codeblock]\n" "[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/" "ease_cheatsheet.png]ease() Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ шпаргалка[/url]\n" @@ -1402,8 +1403,22 @@ msgstr "" "траÑÑировка Ñтека при печати ошибки или предупреждениÑ." #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "Как [method print], но печатает только в режиме отладки." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" +"Как [method print], но включает в ÑÐµÐ±Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¹ кадр Ñтека когда запушен Ñ " +"включенным отладчиком.\n" +"Вывод в конÑоли будет выглÑдеть примерно так:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -1817,19 +1832,30 @@ msgstr "" "Возвращает результат плавной интерполÑции Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ [code]s[/code] между " "[code]0[/code] и [code]1[/code], в завиÑимоÑти от того, где находитÑÑ " "[code]s[/code] отноÑительно [code]from[/code] и [code]to[/code].\n" +"\n" "Возвращаемое значение равно [code]0[/code], еÑли [code]s <= from[/code] и " "[code]1[/code], еÑли[code]s >= to[/code]. ЕÑли [code]s[/code] находитÑÑ " "между [code]from[/code] и [code]to[/code], то возвращаемое значение Ñледует " "S-образной кривой, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑоответÑтвует значению [code]s[/code] между " "[code]0[/code] и [code]1[/code].\n" +"\n" "S-Ð¾Ð±Ñ€Ð°Ð·Ð½Ð°Ñ ÐºÑ€Ð¸Ð²Ð°Ñ ÑвлÑетÑÑ ÐºÑƒÐ±Ð¸Ñ‡ÐµÑким Ñрмитовым Ñплайном, заданным функцией " "[code]f(s) = 3*s^2 - 2*s^3[/code].\n" +"\n" "[codeblock]\n" "smoothstep(0, 2, -5.0) # Returns 0.0\n" "smoothstep(0, 2, 0.5) # Returns 0.15625\n" "smoothstep(0, 2, 1.0) # Returns 0.5\n" "smoothstep(0, 2, 2.0) # Returns 1.0\n" -"[/codeblock]" +"[/codeblock]\n" +"\n" +"Compared to [method ease] with a curve value of [code]-1.6521[/code], [" +"method smoothstep] returns the smoothest possible curve with no sudden " +"changes in the derivative. If you need to perform more advanced transitions, " +"use [Tween] or [AnimationPlayer].\n" +"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/" +"smoothstep_ease_comparison.png]Comparison between smoothstep() and ease(x, -1" +".6521) return values[/url]" #: modules/gdscript/doc_classes/@GDScript.xml #, fuzzy @@ -9352,8 +9378,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -11644,7 +11670,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -11809,7 +11841,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -13435,7 +13473,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -21996,7 +22039,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -25407,7 +25450,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -27247,7 +27290,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -30308,13 +30351,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -31732,9 +31776,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -32308,10 +32352,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -32323,6 +32370,15 @@ msgid "Mouse and input coordinates" msgstr "" #: doc/classes/InputEventMouseMotion.xml +#, fuzzy +msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"Возвращает [code]true[/code] еÑли [code]a[/code] и [code]b[/code] " +"приблизительно равны друг другу." + +#: doc/classes/InputEventMouseMotion.xml msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." @@ -34391,7 +34447,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -34407,7 +34463,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -34440,7 +34496,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -38600,7 +38656,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -38865,7 +38921,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -38997,6 +39053,53 @@ msgstr "" msgid "Control activation of this server." msgstr "Управление активацией данного Ñервера." +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +#, fuzzy +msgid "Set the max packet size that this peer can handle." +msgstr "Возвращает длину вектора." + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml #, fuzzy msgid "" @@ -41769,7 +41872,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -41781,7 +41890,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -47447,6 +47557,14 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +#, fuzzy +msgid "Sorts the elements of the array in ascending order." +msgstr "УдалÑет Ñлемент из маÑÑива по индекÑу." + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -56470,7 +56588,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56510,15 +56629,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -58001,11 +58121,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -59680,7 +59819,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -62621,8 +62760,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -66298,15 +66437,16 @@ msgstr "" #: doc/classes/TreeItem.xml #, fuzzy msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" "Возвращает поÑледний Ñлемент маÑÑива, или[code]null[/code] еÑли маÑÑив " "пуÑтой." #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -66319,15 +66459,16 @@ msgstr "" #: doc/classes/TreeItem.xml #, fuzzy msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" "Возвращает первый Ñлемент в маÑÑиве, или [code]null[/code] еÑли маÑÑив " "пуÑтой." #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -68262,11 +68403,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -68346,8 +68487,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -73399,9 +73540,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "ЕÑли [code]true[/code], текÑтура будет центрирована." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -73485,6 +73629,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/sk.po b/doc/translations/sk.po index 4964bf3ce0..ddcdeb10f1 100644 --- a/doc/translations/sk.po +++ b/doc/translations/sk.po @@ -848,7 +848,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7685,8 +7692,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9966,7 +9973,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10131,7 +10144,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11742,7 +11761,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20153,7 +20177,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23542,7 +23566,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25373,7 +25397,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28414,13 +28438,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29834,9 +29859,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30410,10 +30435,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30426,6 +30454,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32459,7 +32493,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32475,7 +32509,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32505,7 +32539,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36605,7 +36639,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36866,7 +36900,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36980,6 +37014,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39677,7 +39757,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39689,7 +39775,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45293,6 +45380,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54217,7 +54311,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54257,15 +54352,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55741,11 +55837,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57415,7 +57530,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60306,8 +60421,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63930,13 +64045,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63948,13 +64064,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65762,11 +65879,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65846,8 +65963,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70840,7 +70957,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70925,6 +71046,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/sr_Cyrl.po b/doc/translations/sr_Cyrl.po index 89efbf0d11..6a336f195b 100644 --- a/doc/translations/sr_Cyrl.po +++ b/doc/translations/sr_Cyrl.po @@ -859,7 +859,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7696,8 +7703,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9977,7 +9984,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10142,7 +10155,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11753,7 +11772,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20164,7 +20188,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23553,7 +23577,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25384,7 +25408,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28425,13 +28449,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29845,9 +29870,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30421,10 +30446,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30437,6 +30465,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32470,7 +32504,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32486,7 +32520,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32516,7 +32550,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36616,7 +36650,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36877,7 +36911,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36991,6 +37025,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39688,7 +39768,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39700,7 +39786,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45304,6 +45391,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54228,7 +54322,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54268,15 +54363,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55752,11 +55848,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57426,7 +57541,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60317,8 +60432,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63941,13 +64056,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63959,13 +64075,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65773,11 +65890,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65857,8 +65974,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70851,7 +70968,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70936,6 +71057,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/sv.po b/doc/translations/sv.po index e562fe9d6f..b582952401 100644 --- a/doc/translations/sv.po +++ b/doc/translations/sv.po @@ -6,12 +6,13 @@ # Christoffer Sundbom <christoffer_karlsson@live.se>, 2021. # Kent Jofur <kent.jofur@gmail.com>, 2021. # Alex25820 <alexs25820@gmail.com>, 2021. +# Björn Ã…kesson <bjorn.akesson@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2021-12-19 17:31+0000\n" -"Last-Translator: Alex25820 <alexs25820@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:56+0000\n" +"Last-Translator: Björn Ã…kesson <bjorn.akesson@gmail.com>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/sv/>\n" "Language: sv\n" @@ -19,7 +20,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.10\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -92,7 +93,7 @@ msgstr "" #: doc/tools/make_rst.py msgid "Getter" -msgstr "" +msgstr "Getter" #: doc/tools/make_rst.py msgid "" @@ -848,7 +849,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7685,8 +7693,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -9966,7 +9974,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10131,7 +10145,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11742,7 +11762,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20153,7 +20178,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23539,7 +23564,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25370,7 +25395,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28411,13 +28436,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29831,9 +29857,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30407,10 +30433,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30423,6 +30452,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32456,7 +32491,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32472,7 +32507,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32502,7 +32537,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36602,7 +36637,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36863,7 +36898,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -36977,6 +37012,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -37531,7 +37612,7 @@ msgstr "" #: doc/classes/Node.xml msgid "Nodes and Scenes" -msgstr "" +msgstr "Noder och scener" #: doc/classes/Node.xml msgid "All Demos" @@ -39674,7 +39755,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39686,7 +39773,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45290,6 +45378,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54214,7 +54309,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54254,15 +54350,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55738,11 +55835,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57412,7 +57528,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60303,8 +60419,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -63927,13 +64043,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -63945,13 +64062,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65759,11 +65877,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65843,8 +65961,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70837,7 +70955,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -70922,6 +71044,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/th.po b/doc/translations/th.po index 097eae8507..3b8c2afd36 100644 --- a/doc/translations/th.po +++ b/doc/translations/th.po @@ -933,7 +933,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7790,8 +7797,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10072,7 +10079,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10237,7 +10250,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11848,7 +11867,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20263,7 +20287,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23653,7 +23677,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25488,7 +25512,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28530,13 +28554,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29972,9 +29997,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30564,10 +30589,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30580,6 +30608,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32628,7 +32662,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32644,7 +32678,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32674,7 +32708,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36791,7 +36825,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37052,7 +37086,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37169,6 +37203,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39916,7 +39996,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39928,7 +40014,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45541,6 +45628,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54475,7 +54569,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54515,15 +54610,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55999,11 +56095,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57674,7 +57789,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60571,8 +60686,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64196,13 +64311,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64214,13 +64330,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66040,11 +66157,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66124,8 +66241,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71122,7 +71239,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71207,6 +71328,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/tl.po b/doc/translations/tl.po index 7473388512..6fe51a2de6 100644 --- a/doc/translations/tl.po +++ b/doc/translations/tl.po @@ -924,7 +924,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7761,8 +7768,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10046,7 +10053,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10211,7 +10224,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11822,7 +11841,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20236,7 +20260,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23628,7 +23652,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25459,7 +25483,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28500,13 +28524,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29920,9 +29945,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30496,10 +30521,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30512,6 +30540,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32551,7 +32585,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32567,7 +32601,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32600,7 +32634,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36715,7 +36749,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -36976,7 +37010,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37090,6 +37124,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39787,7 +39867,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39799,7 +39885,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45406,6 +45493,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54330,7 +54424,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54370,15 +54465,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55854,11 +55950,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57528,7 +57643,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60419,8 +60534,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64052,13 +64167,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64070,13 +64186,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -65884,11 +66001,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -65968,8 +66085,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -70965,7 +71082,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71050,6 +71171,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/tr.po b/doc/translations/tr.po index 77fbf5f31a..ffa15621df 100644 --- a/doc/translations/tr.po +++ b/doc/translations/tr.po @@ -20,12 +20,13 @@ # Ramazan Aslan <legendraslan@gmail.com>, 2022. # paledega <paledega@yandex.ru>, 2022. # Yekez <yasintonge@gmail.com>, 2022. +# Deleted User <noreply+46858@weblate.org>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-07-03 00:45+0000\n" -"Last-Translator: Yekez <yasintonge@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:56+0000\n" +"Last-Translator: Deleted User <noreply+46858@weblate.org>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot-class-reference/tr/>\n" "Language: tr\n" @@ -33,7 +34,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -96,7 +97,6 @@ msgid "Default" msgstr "Varsayılan" #: doc/tools/make_rst.py -#, fuzzy msgid "Setter" msgstr "Ayarlayıcı" @@ -105,7 +105,6 @@ msgid "value" msgstr "deÄŸer" #: doc/tools/make_rst.py -#, fuzzy msgid "Getter" msgstr "Alıcı" @@ -1315,10 +1314,22 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +#, fuzzy +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" -"[method print] yöntemi gibidir fakat yanlız hata ayıklama (debug) modunda " -"kullanılır." +"Kod içindeki istiflenme konumunu yazdırır ve yanlızca hata ayıklayıcı " +"(debugger) açıkken çalışır.\n" +"Konsoldaki çıktı aÅŸağıdaki gibi bir ÅŸey olacaktır.\n" +"[codeblock]\n" +"Frame 0 - res://test.gd:16 in function '_process'\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8471,8 +8482,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10753,7 +10764,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10918,7 +10935,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12531,7 +12554,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20966,7 +20994,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24362,7 +24390,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -26203,7 +26231,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -29252,13 +29280,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30674,9 +30703,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -31250,10 +31279,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -31266,6 +31298,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -33308,7 +33346,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33324,7 +33362,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33356,7 +33394,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37498,7 +37536,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37762,7 +37800,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37881,6 +37919,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40578,7 +40662,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40590,7 +40680,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -46231,6 +46322,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -55167,7 +55265,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55207,15 +55306,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56691,11 +56791,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58367,7 +58486,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -61268,8 +61387,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64905,13 +65024,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64923,13 +65043,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66739,11 +66860,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66823,8 +66944,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71845,10 +71966,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" -"EÄŸer [code]true[/code] ise düğümler sıraya sokulur, yoksa sıraya sokulmaz." #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -71932,6 +72055,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/uk.po b/doc/translations/uk.po index fe1ac7f153..b1272c6b3e 100644 --- a/doc/translations/uk.po +++ b/doc/translations/uk.po @@ -991,7 +991,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7843,8 +7850,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10125,7 +10132,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10290,7 +10303,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11904,7 +11923,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20332,7 +20356,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23721,7 +23745,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25558,7 +25582,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28608,13 +28632,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30030,9 +30055,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30606,10 +30631,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30622,6 +30650,12 @@ msgstr "Мишка Ñ– координати введеннÑ" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32658,7 +32692,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32674,7 +32708,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32704,7 +32738,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36841,7 +36875,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37104,7 +37138,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37222,6 +37256,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39919,7 +39999,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39931,7 +40017,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45563,6 +45650,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54492,7 +54586,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54532,15 +54627,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56017,11 +56113,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57692,7 +57807,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60594,8 +60709,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64229,13 +64344,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64247,13 +64363,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66064,11 +66181,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66148,8 +66265,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71165,7 +71282,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71250,6 +71371,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/vi.po b/doc/translations/vi.po index 4dbfaf376a..60ab8769ab 100644 --- a/doc/translations/vi.po +++ b/doc/translations/vi.po @@ -1202,8 +1202,15 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "Giống [method print], nhưng chỉ in khi sá» dụng trong chế độ gỡ lá»—i." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -8138,8 +8145,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10420,7 +10427,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10585,7 +10598,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -12199,7 +12218,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20631,7 +20655,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -24023,7 +24047,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25860,7 +25884,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28905,13 +28929,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -30328,9 +30353,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30904,10 +30929,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30920,6 +30948,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32958,7 +32992,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32974,7 +33008,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -33005,7 +33039,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -37143,7 +37177,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37407,7 +37441,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37526,6 +37560,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -40223,7 +40303,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -40235,7 +40321,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45875,6 +45962,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54813,7 +54907,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54853,15 +54948,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -56339,11 +56435,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -58015,7 +58130,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60916,8 +61031,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64553,13 +64668,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64571,13 +64687,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66389,11 +66506,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66473,8 +66590,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71500,9 +71617,12 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -#, fuzzy -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "Nếu [code]true[/code], há»a tiết sẽ được căn ở trung tâm." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -71586,6 +71706,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/doc/translations/zh_CN.po b/doc/translations/zh_CN.po index 2888f15fd1..7647bf0081 100644 --- a/doc/translations/zh_CN.po +++ b/doc/translations/zh_CN.po @@ -62,7 +62,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine class reference\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-07-05 23:52+0000\n" +"PO-Revision-Date: 2022-07-31 16:43+0000\n" "Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot-class-reference/zh_Hans/>\n" @@ -71,7 +71,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: doc/tools/make_rst.py msgid "Description" @@ -507,7 +507,7 @@ msgid "" "a = dectime(60, 10, 0.1)) # a is 59.0\n" "[/codeblock]" msgstr "" -"[b]注æ„:[/b][code]dectime[/code] 已被废弃,将在 Godot 4.0 ä¸åˆ 除,请使用 " +"[b]注æ„:[/b][code]dectime[/code] 已被废弃,将在 Godot 4.0 ä¸ç§»é™¤ï¼Œè¯·ä½¿ç”¨ " "[method move_toward] 代替。\n" "返回 [code]value[/code] å‡åŽ» [code]step[/code] * [code]amount[/code] 的结" "果。\n" @@ -570,7 +570,6 @@ msgstr "" "将(之å‰ä½¿ç”¨ [method inst2dict] 创建的)å—典转æ¢å›žå®žä¾‹ã€‚适用于ååºåˆ—化。" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Returns an \"eased\" value of [code]x[/code] based on an easing function " "defined with [code]curve[/code]. This easing function is based on an " @@ -590,9 +589,9 @@ msgid "" "See also [method smoothstep]. If you need to perform more advanced " "transitions, use [Tween] or [AnimationPlayer]." msgstr "" -"返回 [code]x[/code] “缓动åŽâ€çš„值,结果基于使用 [code]curve[/code] 值定义的缓" -"动函数。该缓动函数是基于指数的。[code]curve[/code] 值å¯ä»¥æ˜¯ä»»æ„浮点数,具体数" -"值会导致以下行为:\n" +"返回 [code]x[/code]“缓动åŽâ€çš„值,结果基于使用 [code]curve[/code] 值定义的缓动" +"函数。该缓动函数是基于指数的。[code]curve[/code] 值å¯ä»¥æ˜¯ä»»æ„浮点数,具体数值" +"会导致以下行为:\n" "[codeblock]\n" "- 低于 -1.0(开区间):缓入缓出\n" "- -1.0:线性\n" @@ -602,9 +601,9 @@ msgstr "" "- 1.0:线性\n" "- 大于 1.0(开区间):缓入\n" "[/codeblock]\n" -"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/" +"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/" "ease_cheatsheet.png]ease() 曲线值速查表[/url]\n" -"请å‚阅 [method smoothstep]ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] 或 " +"å¦è¯·å‚阅 [method smoothstep]ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] 或 " "[AnimationPlayer]。" #: modules/gdscript/doc_classes/@GDScript.xml @@ -646,7 +645,7 @@ msgstr "" "a = floor(2.99) # a = 2.0\n" "a = floor(-2.99) # a = -3.0\n" "[/codeblock]\n" -"请å‚阅 [method ceil]ã€[method round]ã€[method stepify] å’Œ [int]。\n" +"å¦è¯·å‚阅 [method ceil]ã€[method round]ã€[method stepify] å’Œ [int]。\n" "[b]注æ„:[/b]è¯¥æ–¹æ³•è¿”å›žä¸€ä¸ªæµ®ç‚¹æ•°ã€‚å¦‚æžœä½ éœ€è¦æ•´æ•°ï¼Œè€Œ [code]s[/code] 是éžè´Ÿ" "æ•°ï¼Œä½ å¯ä»¥ç›´æŽ¥ä½¿ç”¨ [code]int(s)[/code]。" @@ -1323,8 +1322,21 @@ msgstr "" "在打å°é”™è¯¯æˆ–è¦å‘Šæ—¶è¿˜ä¼šæ˜¾ç¤ºå †æ ˆè·Ÿè¸ªã€‚" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." -msgstr "与 [method print] 类似,但仅在调试模å¼ä¸‹ä½¿ç”¨æ—¶æ‰æ‰“å°ã€‚" +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" +msgstr "" +"与 [method print] 类似,但在打开调试器è¿è¡Œæ—¶è¿˜ä¼šåŒ…å«å½“剿 ˆå¸§ã€‚\n" +"控制å°ä¸çš„è¾“å‡ºåº”è¯¥æ˜¯ç±»ä¼¼è¿™æ ·çš„ï¼š\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml msgid "" @@ -1688,7 +1700,6 @@ msgstr "" "[/codeblock]" #: modules/gdscript/doc_classes/@GDScript.xml -#, fuzzy msgid "" "Returns the result of smoothly interpolating the value of [code]s[/code] " "between [code]0[/code] and [code]1[/code], based on the where [code]s[/code] " @@ -1731,7 +1742,7 @@ msgstr "" "与曲线值为 [code]-1.6521[/code] çš„ [method ease] 相比,[method smoothstep] è¿”" "回最平滑的曲线,导数没有çªç„¶å˜åŒ–ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] " "或 [AnimationPlayer]。\n" -"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/" +"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/" "smoothstep_ease_comparison.png]smoothstep() 与 ease(x, -1.6521) 返回值的比较" "[/url]" @@ -4876,7 +4887,7 @@ msgstr "" "custom_action]ä¿¡å·ã€‚\n" "如果[code]right[/code]为 [code]true[/code],按钮会被放置在所有åŒçº§æŒ‰é’®çš„å³" "边。\n" -"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸åˆ é™¤ä½¿ç”¨æ¤æ–¹æ³•创建的按钮。" +"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸ç§»é™¤ä½¿ç”¨æ¤æ–¹æ³•创建的按钮。" #: doc/classes/AcceptDialog.xml msgid "" @@ -4887,7 +4898,7 @@ msgid "" msgstr "" "å‘å¯¹è¯æ¡†ä¸æ·»åŠ ä¸€ä¸ªæ ‡ç¾ä¸º[code]name[/code]å’Œä¸€ä¸ªå–æ¶ˆåŠ¨ä½œçš„æŒ‰é’®ï¼Œç„¶åŽè¿”回这个新" "创建的按钮。\n" -"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸åˆ é™¤ä½¿ç”¨æ¤æ–¹æ³•创建的按钮。" +"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸ç§»é™¤ä½¿ç”¨æ¤æ–¹æ³•创建的按钮。" #: doc/classes/AcceptDialog.xml msgid "" @@ -4897,7 +4908,7 @@ msgid "" "[member CanvasItem.visible] property." msgstr "" "è¿”å›žå†…ç½®æ–‡æœ¬æ‰€ä½¿ç”¨çš„æ ‡ç¾ã€‚\n" -"[b]è¦å‘Šï¼š[/b]这是个必è¦çš„å†…éƒ¨èŠ‚ç‚¹ï¼Œåˆ é™¤å’Œé‡Šæ”¾å®ƒæœ‰å¯èƒ½é€ æˆå´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éšè—" +"[b]è¦å‘Šï¼š[/b]这是个必è¦çš„内部节点,移除并释放它有å¯èƒ½é€ æˆå´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éšè—" "它或它的任æ„一个å节点,请使用它们的 [member CanvasItem.visible] 属性。" #: doc/classes/AcceptDialog.xml @@ -4908,7 +4919,7 @@ msgid "" "[member CanvasItem.visible] property." msgstr "" "返回确定按钮 [Button] 实例。\n" -"[b]è¦å‘Šï¼š[/b]这是个必è¦çš„å†…éƒ¨èŠ‚ç‚¹ï¼Œåˆ é™¤å’Œé‡Šæ”¾å®ƒæœ‰å¯èƒ½é€ æˆå´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éšè—" +"[b]è¦å‘Šï¼š[/b]这是个必è¦çš„内部节点,移除并释放它有å¯èƒ½é€ æˆå´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éšè—" "它或它的任æ„一个å节点,请使用它们的 [member CanvasItem.visible] 属性。" #: doc/classes/AcceptDialog.xml @@ -5653,7 +5664,7 @@ msgstr "返回给定轨é“ä¸ç»™å®šé”®çš„æ–¹æ³•轨é“上è¦è°ƒç”¨çš„傿•°å€¼ã€‚ #: doc/classes/Animation.xml msgid "Removes a track by specifying the track index." -msgstr "通过指定轨é“索引æ¥åˆ 除一个轨é“。" +msgstr "通过指定轨é“索引æ¥ç§»é™¤ä¸€ä¸ªè½¨é“。" #: doc/classes/Animation.xml msgid "" @@ -5739,11 +5750,11 @@ msgstr "将轨é“上移。" #: doc/classes/Animation.xml msgid "Removes a key by index in a given track." -msgstr "在指定的轨é“ä¸ŠæŒ‰ç´¢å¼•åˆ é™¤ä¸€ä¸ªé”®ã€‚" +msgstr "在指定的轨é“上按索引移除一个键。" #: doc/classes/Animation.xml msgid "Removes a key by position (seconds) in a given track." -msgstr "按ä½ç½®ï¼ˆç§’ï¼‰åˆ é™¤æŒ‡å®šè½¨é“ä¸çš„键。" +msgstr "按ä½ç½®ï¼ˆç§’)移除指定轨é“ä¸çš„键。" #: doc/classes/Animation.xml msgid "Enables/disables the given track. Tracks are enabled by default." @@ -6074,11 +6085,11 @@ msgstr "" #: doc/classes/AnimationNode.xml msgid "Removes an input, call this only when inactive." -msgstr "åˆ é™¤è¾“å…¥ï¼Œä»…åœ¨å¤„äºŽéžæ´»åŠ¨çŠ¶æ€æ—¶è°ƒç”¨æ¤è¾“入。" +msgstr "ç§»é™¤è¾“å…¥ï¼Œä»…åœ¨å¤„äºŽéžæ´»åŠ¨çŠ¶æ€æ—¶è°ƒç”¨æ¤è¾“入。" #: doc/classes/AnimationNode.xml msgid "Adds or removes a path for the filter." -msgstr "æ·»åŠ æˆ–åˆ é™¤ç›é€‰å™¨çš„路径。" +msgstr "æ·»åŠ æˆ–ç§»é™¤ç›é€‰å™¨çš„路径。" #: doc/classes/AnimationNode.xml msgid "" @@ -6094,7 +6105,7 @@ msgstr "如果为 [code]true[/code],则å¯ç”¨ç›é€‰åŠŸèƒ½ã€‚" #: doc/classes/AnimationNode.xml msgid "Emitted when the node was removed from the graph." -msgstr "当该节点从图ä¸åˆ 除时触å‘。" +msgstr "当该节点从图ä¸ç§»é™¤æ—¶è§¦å‘。" #: doc/classes/AnimationNode.xml msgid "" @@ -6317,7 +6328,7 @@ msgstr "返回索引 [code]point[/code] 处的点的ä½ç½®ã€‚" #: doc/classes/AnimationNodeBlendSpace1D.xml msgid "Removes the point at index [code]point[/code] from the blend axis." -msgstr "将索引 [code]point[/code] 处的点从混åˆè½´ä¸Šåˆ 除。" +msgstr "将索引 [code]point[/code] 处的点从混åˆè½´ä¸Šç§»é™¤ã€‚" #: doc/classes/AnimationNodeBlendSpace1D.xml #: doc/classes/AnimationNodeBlendSpace2D.xml @@ -6424,12 +6435,12 @@ msgstr "" #: doc/classes/AnimationNodeBlendSpace2D.xml msgid "Removes the point at index [code]point[/code] from the blend space." -msgstr "从混åˆç©ºé—´ä¸åˆ 除索引 [code]point[/code] 处的点。" +msgstr "从混åˆç©ºé—´ä¸ç§»é™¤ç´¢å¼• [code]point[/code] 处的点。" #: doc/classes/AnimationNodeBlendSpace2D.xml msgid "" "Removes the triangle at index [code]triangle[/code] from the blend space." -msgstr "从混åˆç©ºé—´ä¸åˆ 除索引 [code]triangle[/code] 处的三角形。" +msgstr "从混åˆç©ºé—´ä¸ç§»é™¤ç´¢å¼• [code]triangle[/code] 处的三角形。" #: doc/classes/AnimationNodeBlendSpace2D.xml msgid "" @@ -6475,7 +6486,7 @@ msgstr "æ··åˆç©ºé—´ Y è½´çš„å称。" msgid "" "Emitted every time the blend space's triangles are created, removed, or when " "one of their vertices changes position." -msgstr "æ¯å½“创建ã€åˆ 除混åˆç©ºé—´çš„三角形,或当其ä¸ä¸€ä¸ªé¡¶ç‚¹æ”¹å˜ä½ç½®æ—¶å‘出。" +msgstr "æ¯å½“创建ã€ç§»é™¤æ··åˆç©ºé—´çš„三角形,或当其ä¸ä¸€ä¸ªé¡¶ç‚¹æ”¹å˜ä½ç½®æ—¶å‘出。" #: doc/classes/AnimationNodeBlendSpace2D.xml msgid "The interpolation between animations is linear." @@ -6549,7 +6560,7 @@ msgstr "如果å˜åœ¨å称为 [code]name[/code] çš„å节点,则返回 [code]t #: doc/classes/AnimationNodeBlendTree.xml msgid "Removes a sub-node." -msgstr "åˆ é™¤ä¸€ä¸ªå节点。" +msgstr "移除一个å节点。" #: doc/classes/AnimationNodeBlendTree.xml msgid "Changes the name of a sub-node." @@ -7879,9 +7890,9 @@ msgid "" "list is modified once during the physics step, not immediately after objects " "are moved. Consider using signals instead." msgstr "" -"返回相交的[Area]的列表。é‡å 区域的[member CollisionObject.collision_layer]å¿…" -"须是这个区域[member CollisionObject.collision_mask]çš„ä¸€éƒ¨åˆ†ï¼Œè¿™æ ·æ‰èƒ½è¢«æ£€æµ‹" -"到。\n" +"返回相交的 [Area] 的列表。é‡å 区域的 [member CollisionObject." +"collision_layer] 必须是这个区域 [member CollisionObject.collision_mask] 的一" +"éƒ¨åˆ†ï¼Œè¿™æ ·æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n" "å‡ºäºŽæ€§èƒ½çš„è€ƒè™‘ï¼Œå› ç¢°æ’žéƒ½æ˜¯åŒæ—¶å¤„ç†çš„ï¼Œè¿™ä¸ªåˆ—è¡¨åœ¨ç‰©ç†æ¥éª¤ä¸åªä¿®æ”¹ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯" "在物体被移动åŽç«‹å³ä¿®æ”¹ã€‚è€ƒè™‘ä½¿ç”¨ä¿¡å·æ¥ä»£æ›¿ã€‚" @@ -7894,9 +7905,9 @@ msgid "" "list is modified once during the physics step, not immediately after objects " "are moved. Consider using signals instead." msgstr "" -"返回相交的[PhysicsBody]的列表。é‡å 物体的[member CollisionObject." -"collision_layer]必须是这个区域[member CollisionObject.collision_mask]的一部" -"åˆ†ï¼Œè¿™æ ·æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n" +"返回相交的 [PhysicsBody] 的列表。é‡å 物体的 [member CollisionObject." +"collision_layer] 必须是这个区域 [member CollisionObject.collision_mask] 的一" +"éƒ¨åˆ†ï¼Œè¿™æ ·æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n" "å‡ºäºŽæ€§èƒ½çš„è€ƒè™‘ï¼Œå› ç¢°æ’žéƒ½æ˜¯åŒæ—¶å¤„ç†çš„ï¼Œè¿™ä¸ªåˆ—è¡¨åœ¨ç‰©ç†æ¥éª¤ä¸åªä¿®æ”¹ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯" "在物体被移动åŽç«‹å³ä¿®æ”¹ã€‚è€ƒè™‘ä½¿ç”¨ä¿¡å·æ¥ä»£æ›¿ã€‚" @@ -7975,8 +7986,8 @@ msgid "" "The area's gravity vector (not normalized). If gravity is a point (see " "[member gravity_point]), this will be the point of attraction." msgstr "" -"区域的未归一化的é‡åŠ›å‘é‡ã€‚如果é‡åŠ›ä½œç”¨åœ¨ä¸€ä¸ªç‚¹ä¸Šï¼Œåˆ™å®ƒå°†æ˜¯å¼•åŠ›ç‚¹ã€‚è¯·å‚阅 " -"[member gravity_point]。" +"区域的未归一化的é‡åŠ›å‘é‡ã€‚如果é‡åŠ›ä½œç”¨åœ¨ä¸€ä¸ªç‚¹ä¸Šï¼Œåˆ™å®ƒå°†æ˜¯å¼•åŠ›ç‚¹ï¼ˆè§ [member " +"gravity_point])。" #: doc/classes/Area.xml msgid "" @@ -8882,7 +8893,7 @@ msgid "" "if the array is empty, without printing an error message. See also [method " "pop_front]." msgstr "" -"åˆ é™¤å¹¶è¿”å›žæ•°ç»„ä¸çš„æœ«å°¾å…ƒç´ 。数组为空时,返回 [code]null[/code]。å¦è¯·å‚阅 " +"移除并返回数组ä¸çš„æœ«å°¾å…ƒç´ 。数组为空时,返回 [code]null[/code]。å¦è¯·å‚阅 " "[method pop_front]。" #: doc/classes/Array.xml @@ -9142,11 +9153,11 @@ msgstr "" #: doc/classes/ArrayMesh.xml msgid "Removes all blend shapes from this [ArrayMesh]." -msgstr "åˆ é™¤æ¤[ArrayMesh]的所有混åˆå½¢çŠ¶ã€‚" +msgstr "ç§»é™¤æ¤ [ArrayMesh] 的所有混åˆå½¢çŠ¶ã€‚" #: doc/classes/ArrayMesh.xml msgid "Removes all surfaces from this [ArrayMesh]." -msgstr "åˆ é™¤æ¤[ArrayMesh]的所有表é¢ã€‚" +msgstr "ç§»é™¤æ¤ [ArrayMesh] 的所有表é¢ã€‚" #: doc/classes/ArrayMesh.xml msgid "Returns the number of blend shapes that the [ArrayMesh] holds." @@ -9485,7 +9496,7 @@ msgstr "" "这是链接到控制器跟踪的辅助空间节点。它还为控制器上的按钮ç‰çŠ¶æ€æä¾›äº†å‡ ä¸ªä¾¿æ·" "的通é“。\n" "控制器通过它们的 ID é“¾æŽ¥ã€‚ä½ å¯ä»¥åœ¨æŽ§åˆ¶å™¨å¯ç”¨ä¹‹å‰åˆ›å»ºæŽ§åˆ¶å™¨èŠ‚ç‚¹ã€‚å¦‚æžœä½ çš„æ¸¸æˆ" -"æ€»æ˜¯ä½¿ç”¨ä¸¤ä¸ªæŽ§åˆ¶å™¨ï¼Œå³æ¯åªæ‰‹ä¸€ä¸ªï¼Œä½ å¯ä»¥é¢„先定义 ID 为 1 å’Œ 2 的控制器;一旦" +"总是使用两个控制器(æ¯åªæ‰‹ä¸€ä¸ªï¼‰ï¼Œä½ å¯ä»¥é¢„先定义 ID 为 1 å’Œ 2 的控制器;一旦" "ç¡®å®šäº†æŽ§åˆ¶å™¨ï¼Œå®ƒä»¬å°±ä¼šè¢«æ¿€æ´»ã€‚å¦‚æžœä½ å¸Œæœ›ä½¿ç”¨é¢å¤–的控制器,应该对信å·åР以处" "ç†ï¼Œå¹¶å°† ARVRController èŠ‚ç‚¹æ·»åŠ åˆ°æ‚¨åœºæ™¯ä¸ã€‚\n" "控制器节点的ä½ç½®ç”± [ARVRServer] 自动更新。这使得该节点éžå¸¸é€‚åˆæ·»åŠ å节点以实" @@ -9572,14 +9583,13 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" -"控制器振动的程度。范围从 [code]0.0[/code] 到 [code]1.0[/code],精度 " -"[code].01[/code]。如果更改,会相应地更新 [member ARVRPositionalTracker." -"rumble]。\n" +"控制器振动的程度。范围从 [code]0.0[/code] 到 [code]1.0[/code]。如果更改," +"会相应地更新 [member ARVRPositionalTracker.rumble]。\n" "å¦‚æžœä½ æƒ³è®©æŽ§åˆ¶å™¨åœ¨é™å®šæ—¶é—´å†…振动,这是一个有用的属性,å¯ä»¥å°†å…¶åŠ¨ç”»åŒ–ã€‚" #: doc/classes/ARVRController.xml @@ -9615,8 +9625,8 @@ msgid "" "[ARVRServer]." msgstr "" "需è¦å®žçŽ°è¿™ä¸ªç±»æ‰èƒ½ä½¿ AR 或 VR å¹³å°å¯ä¾› Godot 使用,并且应实现为 C++ æ¨¡å—æˆ– " -"GDNative 模å—,注æ„,对于 GDNative,应使用åç±» ARVRScriptInterface。部分接å£" -"å‘ GDScript å…¬å¼€ï¼Œå› è€Œï¼Œæ‚¨å¯ä»¥æ£€æµ‹ã€å¯ç”¨å’Œé…ç½® AR 或 VR å¹³å°ã€‚\n" +"GDNative 模å—(注æ„,对于 GDNative,应使用åç±» ARVRScriptInterface)。部分接" +"å£å‘ GDScript å…¬å¼€ï¼Œå› è€Œï¼Œæ‚¨å¯ä»¥æ£€æµ‹ã€å¯ç”¨å’Œé…ç½® AR 或 VR å¹³å°ã€‚\n" "接å£åº”ä»¥è¿™æ ·çš„æ–¹å¼ç¼–写,åªéœ€å¯ç”¨å®ƒä»¬å°±å¯ä»¥ä¸ºæˆ‘们æä¾›å·¥ä½œé…置。您å¯ä»¥é€šè¿‡ " "[ARVRServer] 查询å¯ç”¨æŽ¥å£ã€‚" @@ -9637,7 +9647,7 @@ msgstr "返回 [enum Capabilities] æ ‡ç¾çš„组åˆï¼Œæä¾›å…³äºŽè¿™ä¸ªæŽ¥å£åŠŸ #: doc/classes/ARVRInterface.xml msgid "Returns the name of this interface (OpenVR, OpenHMD, ARKit, etc)." -msgstr "返回该接å£çš„å称,如 OpenVRã€OpenHMDã€ARKit ç‰ã€‚" +msgstr "返回该接å£çš„å称(OpenVRã€OpenHMDã€ARKit ç‰ï¼‰ã€‚" #: doc/classes/ARVRInterface.xml msgid "" @@ -9713,7 +9723,7 @@ msgstr "没有 ARVR 功能。" #: doc/classes/ARVRInterface.xml msgid "" "This interface can work with normal rendering output (non-HMD based AR)." -msgstr "æ¤æŽ¥å£å¯ä»¥ä¸Žæ£å¸¸çš„æ¸²æŸ“输出一起工作,éžåŸºäºŽ HMD çš„ AR。" +msgstr "æ¤æŽ¥å£å¯ä»¥ä¸Žæ£å¸¸çš„æ¸²æŸ“输出一起工作(éžåŸºäºŽ HMD çš„ AR)。" #: doc/classes/ARVRInterface.xml msgid "This interface supports stereoscopic rendering." @@ -9721,7 +9731,7 @@ msgstr "è¯¥æŽ¥å£æ”¯æŒç«‹ä½“渲染。" #: doc/classes/ARVRInterface.xml msgid "This interface supports AR (video background and real world tracking)." -msgstr "è¯¥æŽ¥å£æ”¯æŒ AR,视频背景和真实世界跟踪。" +msgstr "è¯¥æŽ¥å£æ”¯æŒ AR(视频背景和真实世界跟踪)。" #: doc/classes/ARVRInterface.xml msgid "" @@ -9764,7 +9774,7 @@ msgstr "追踪行为符åˆé¢„期。" msgid "" "Tracking is hindered by excessive motion (the player is moving faster than " "tracking can keep up)." -msgstr "过度è¿åŠ¨ä¼šé˜»ç¢è¿½è¸ªï¼Œå³çŽ©å®¶çš„ç§»åŠ¨é€Ÿåº¦è¶…è¿‡è¿½è¸ªçš„é€Ÿåº¦ã€‚" +msgstr "过度è¿åŠ¨ä¼šé˜»ç¢è¿½è¸ªï¼ˆçŽ©å®¶çš„ç§»åŠ¨é€Ÿåº¦å¤§äºŽè¿½è¸ªçš„é€Ÿåº¦ï¼‰ã€‚" #: doc/classes/ARVRInterface.xml msgid "" @@ -9782,7 +9792,7 @@ msgstr "我们ä¸çŸ¥é“跟踪的状æ€ï¼Œæˆ–è€…è¿™ä¸ªæŽ¥å£æœªæä¾›å馈。" msgid "" "Tracking is not functional (camera not plugged in or obscured, lighthouses " "turned off, etc.)." -msgstr "追踪功能失效,å³ç›¸æœºæœªæ’ç”µæˆ–è¢«é®æŒ¡ï¼Œç¯å¡”å…³é—,ç‰ç‰ã€‚" +msgstr "追踪功能失效(相机未æ’ç”µæˆ–è¢«é®æŒ¡ã€ç¯å¡”å…³é—,ç‰ç‰ï¼‰ã€‚" #: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml msgid "GDNative wrapper for an ARVR interface." @@ -10097,7 +10107,7 @@ msgstr "æ·»åŠ æ–°æŽ¥å£æ—¶è§¦å‘。" #: doc/classes/ARVRServer.xml msgid "Emitted when an interface is removed." -msgstr "当接å£è¢«åˆ 除时触å‘。" +msgstr "当接å£è¢«ç§»é™¤æ—¶è§¦å‘。" #: doc/classes/ARVRServer.xml msgid "" @@ -10118,9 +10128,9 @@ msgid "" "available (i.e. a new controller is switched on that takes the place of the " "previous one)." msgstr "" -"åˆ é™¤è·Ÿè¸ªå™¨æ—¶è§¦å‘ã€‚å¦‚æžœé€‚å½“ï¼Œæ‚¨åº”è¯¥åˆ é™¤æ‰€æœ‰ [ARVRController] 或 [ARVRAnchor] " -"ç‚¹ã€‚è¿™ä¸æ˜¯å¼ºåˆ¶æ€§çš„ï¼ŒèŠ‚ç‚¹åªæ˜¯å˜ä¸ºä¸æ´»åŠ¨çŠ¶æ€ï¼Œå½“新的跟踪器å¯ç”¨æ—¶å°†å†æ¬¡æ¿€æ´»ï¼Œå³" -"打开一个新的控制器æ¥ä»£æ›¿å‰ä¸€ä¸ªæŽ§åˆ¶å™¨ã€‚" +"移除跟踪器时触å‘ã€‚å¦‚æžœé€‚å½“ï¼Œæ‚¨åº”è¯¥åˆ é™¤æ‰€æœ‰ [ARVRController] 或 [ARVRAnchor] " +"ç‚¹ã€‚è¿™ä¸æ˜¯å¼ºåˆ¶æ€§çš„ï¼ŒèŠ‚ç‚¹åªæ˜¯å˜ä¸ºä¸æ´»åŠ¨çŠ¶æ€ï¼Œå½“新的跟踪器å¯ç”¨æ—¶å°†å†æ¬¡æ¿€æ´»ï¼ˆå³" +"打开一个新的控制器æ¥ä»£æ›¿å‰ä¸€ä¸ªæŽ§åˆ¶å™¨ï¼‰ã€‚" #: doc/classes/ARVRServer.xml msgid "The tracker tracks the location of a controller." @@ -10248,7 +10258,7 @@ msgstr "" #: doc/classes/AspectRatioContainer.xml msgid "" "Aligns child controls with the beginning (left or top) of the container." -msgstr "å°†åæŽ§ä»¶ä¸Žå®¹å™¨çš„开头对é½ï¼Œå·¦ä¾§æˆ–顶部。" +msgstr "å°†åæŽ§ä»¶ä¸Žå®¹å™¨çš„开头对é½ï¼ˆå·¦ä¾§æˆ–顶部)。" #: doc/classes/AspectRatioContainer.xml msgid "Aligns child controls with the center of the container." @@ -10256,7 +10266,7 @@ msgstr "ä½¿åæŽ§ä»¶ä¸Žå®¹å™¨çš„ä¸å¿ƒå¯¹é½ã€‚" #: doc/classes/AspectRatioContainer.xml msgid "Aligns child controls with the end (right or bottom) of the container." -msgstr "å°†åæŽ§ä»¶ä¸Žå®¹å™¨çš„æœ«ç«¯å¯¹é½ï¼Œå³ä¾§æˆ–底部。" +msgstr "å°†åæŽ§ä»¶ä¸Žå®¹å™¨çš„æœ«ç«¯å¯¹é½ï¼ˆå³ä¾§æˆ–底部)。" #: doc/classes/AStar.xml msgid "" @@ -10603,7 +10613,7 @@ msgstr "返回是å¦ç¦ç”¨ç‚¹ä»¥è¿›è¡Œå¯»è·¯ã€‚默认情况下,所有点å‡å¤„ msgid "" "Removes the point associated with the given [code]id[/code] from the points " "pool." -msgstr "ä»Žç‚¹æ± ä¸åˆ 除与给定 [code]id[/code] å…³è”的点。" +msgstr "ä»Žç‚¹æ± ä¸ç§»é™¤ä¸Žç»™å®š [code]id[/code] å…³è”的点。" #: doc/classes/AStar.xml doc/classes/AStar2D.xml msgid "" @@ -11765,7 +11775,7 @@ msgid "" "If [code]true[/code], the sound will be recorded. Note that restarting the " "recording will remove the previously recorded sample." msgstr "" -"如果为 [code]true[/code],将录制声音。请注æ„ï¼Œé‡æ–°å¼€å§‹å½•éŸ³å°†åˆ é™¤å…ˆå‰å½•éŸ³çš„æ ·" +"如果为 [code]true[/code],将录制声音。请注æ„ï¼Œé‡æ–°å¼€å§‹å½•音将移除先å‰å½•éŸ³çš„æ ·" "本。" #: doc/classes/AudioEffectRecord.xml @@ -12058,7 +12068,7 @@ msgid "" "Removes the effect at index [code]effect_idx[/code] from the bus at index " "[code]bus_idx[/code]." msgstr "" -"将索引 [code]effect_idx[/code] 的效果从索引 [code]bus_idx[/code] çš„æ€»çº¿ä¸Šåˆ " +"将索引 [code]effect_idx[/code] 的效果从索引 [code]bus_idx[/code] 的总线上移" "除。" #: doc/classes/AudioServer.xml @@ -12374,8 +12384,18 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "如果为 [code]true[/code]ï¼Œåœ¨æ·»åŠ åˆ°åœºæ™¯æ ‘æ—¶å°†æ’æ”¾éŸ³é¢‘。" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." -msgstr "æ’æ”¾æ¤éŸ³é¢‘的总线。" +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" +"è¿™ä¸ªéŸ³é¢‘åœ¨å“ªä¸ªæ€»çº¿ä¸Šæ’æ”¾ã€‚\n" +"[b]注æ„:[/b]设置这个属性时,请记ä½å®ƒå¹¶ä¸ä¼šå¯¹ç»™å®šçš„å称是å¦ä¸ŽçŽ°æœ‰æ€»çº¿åŒ¹é…进行" +"æ ¡éªŒã€‚è¿™æ˜¯å› ä¸ºéŸ³é¢‘æ€»çº¿å¸ƒå±€å¯ä»¥åœ¨è®¾ç½®è¿™ä¸ªå±žæ€§åŽå†åŠ è½½ã€‚å¦‚æžœè¿™ä¸ªç»™å®šçš„å称在è¿" +"è¡Œæ—¶æ— æ³•è§£æžï¼Œå°±ä¼šå›žé€€åˆ° [code]\"Master\"[/code]。" #: doc/classes/AudioStreamPlayer.xml msgid "" @@ -12568,8 +12588,18 @@ msgstr "" "频。" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." -msgstr "æ’æ”¾æ¤éŸ³é¢‘的总线。" +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." +msgstr "" +"æ’æ”¾éŸ³é¢‘的总线。\n" +"[b]注æ„:[/b]设置这个属性时,请记ä½å®ƒå¹¶ä¸ä¼šå¯¹ç»™å®šçš„å称是å¦ä¸ŽçŽ°æœ‰æ€»çº¿åŒ¹é…进行" +"æ ¡éªŒã€‚è¿™æ˜¯å› ä¸ºéŸ³é¢‘æ€»çº¿å¸ƒå±€å¯ä»¥åœ¨è®¾ç½®è¿™ä¸ªå±žæ€§åŽå†åŠ è½½ã€‚å¦‚æžœè¿™ä¸ªç»™å®šçš„å称在è¿" +"è¡Œæ—¶æ— æ³•è§£æžï¼Œå°±ä¼šå›žé€€åˆ° [code]\"Master\"[/code]。" #: doc/classes/AudioStreamPlayer3D.xml msgid "" @@ -13324,7 +13354,7 @@ msgid "" "will be removed in Godot 4.0. This property no longer has any effect when " "set. Please use [member Control.focus_mode] instead." msgstr "" -"[i]已弃用。[/i]由于冗余,æ¤å±žæ€§å·²å¼ƒç”¨ï¼Œå°†åœ¨ Godot 4.0 ä¸åˆ 除。æ¤å±žæ€§åœ¨è®¾ç½®åŽ" +"[i]已弃用。[/i]由于冗余,æ¤å±žæ€§å·²å¼ƒç”¨ï¼Œå°†åœ¨ Godot 4.0 ä¸ç§»é™¤ã€‚æ¤å±žæ€§åœ¨è®¾ç½®åŽ" "ä¸ä¼šæœ‰ä»»ä½•å½±å“。请改用 [member Control.focus_mode]。" #: doc/classes/BaseButton.xml @@ -13460,7 +13490,7 @@ msgstr "" "用于 3D 旋转和缩放的 3×3 çŸ©é˜µã€‚å‡ ä¹Žæ€»æ˜¯ç”¨ä½œå˜æ¢çš„æ£äº¤åŸºã€‚\n" "åŒ…å« 3 个å‘é‡å—段 Xã€Y å’Œ Z ä½œä¸ºå…¶åˆ—ï¼Œé€šå¸¸è¢«è§£é‡Šä¸ºå˜æ¢çš„局部基å‘é‡ã€‚对于这ç§" "ç”¨é€”ï¼Œå®ƒä¾æ¬¡ç”±ä¸€ä¸ªç¼©æ”¾çŸ©é˜µå’Œä¸€ä¸ªæ—‹è½¬çŸ©é˜µç»„æˆï¼ˆM=R.S)。\n" -"也å¯ä»¥ä½œä¸ºä¸‰ç»´å‘é‡çš„æ•°ç»„æ¥è®¿é—®ã€‚这些å‘é‡é€šå¸¸æ˜¯ç›¸äº’æ£äº¤çš„,但ä¸ä¸€å®šæ˜¯å½’一化的" +"也å¯ä»¥ä½œä¸º 3D å‘é‡çš„æ•°ç»„æ¥è®¿é—®ã€‚这些å‘é‡é€šå¸¸æ˜¯ç›¸äº’æ£äº¤çš„,但ä¸ä¸€å®šæ˜¯å½’一化的" "(由于缩放)。\n" "更多信æ¯è¯·é˜…读文档ä¸çš„ã€ŠçŸ©é˜µå’Œå˜æ¢ã€‹ä¸€æ–‡ã€‚" @@ -14397,9 +14427,9 @@ msgid "" "to the position and orientation of the camera by subclassed cameras such as " "[ClippedCamera], [InterpolatedCamera] and [ARVRCamera]." msgstr "" -"è¿”å›žç›¸æœºçš„å˜æ¢åŠ ä¸Šåž‚ç›´[member v_offset]和水平[member h_offset]çš„åç§»é‡ï¼›ä»¥åŠ" -"ç”±å类相机如[ClippedCamera]ã€[InterpolatedCamera]å’Œ[ARVRCamera]对相机的ä½ç½®å’Œ" -"æ–¹å‘åšå‡ºçš„任何其他调整。" +"è¿”å›žç›¸æœºçš„å˜æ¢åŠ ä¸Šåž‚ç›´ [member v_offset] 和水平 [member h_offset] çš„åç§»é‡ï¼›" +"以åŠç”±å类相机如 [ClippedCamera]ã€[InterpolatedCamera] å’Œ [ARVRCamera] 对相机" +"çš„ä½ç½®å’Œæ–¹å‘åšå‡ºçš„任何其他调整。" #: doc/classes/Camera.xml msgid "" @@ -14510,8 +14540,8 @@ msgid "" "angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip " "planes in world space units." msgstr "" -"å°†æ‘„åƒæœºçš„æŠ•影设置为é€è§†æ¨¡å¼ï¼Œå‚阅[constant PROJECTION_PERSPECTIVE]),指定" -"[code]fov[/code] 视野角度,å•ä½åº¦ï¼Œä»¥åŠä¸–界空间å•ä½çš„[code]z_near[/code]å’Œ" +"å°†æ‘„åƒæœºçš„æŠ•影设置为é€è§†æ¨¡å¼ï¼ˆè§ [constant PROJECTION_PERSPECTIVE]),指定 " +"[code]fov[/code] 视野角度,å•ä½ä¸ºåº¦ï¼Œä»¥åŠä¸–界空间å•ä½çš„[code]z_near[/code]å’Œ" "[code]z_far[/code]è£å‰ªå¹³é¢ã€‚" #: doc/classes/Camera.xml @@ -14550,9 +14580,17 @@ msgstr "æè¿°æ¤ç›¸æœºæ¸²æŸ“哪些 3D 渲染层的剔除掩ç 。" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" -"如果为 [code]true[/code],则说明祖级的 [Viewport] 当剿£åœ¨ä½¿ç”¨è¿™ä¸ªæ‘„åƒå¤´ã€‚" +"如果为 [code]true[/code],则祖级 [Viewport] æ£åœ¨ä½¿ç”¨è¿™ä¸ªç›¸æœºã€‚\n" +"å¦‚æžœåœºæ™¯ä¸æœ‰å¤šä¸ªç›¸æœºï¼Œæ€»ä¼šæœ‰ä¸€ä¸ªè¢«è®¾ä¸ºå½“å‰ç›¸æœºã€‚例如,å‡è®¾åœºæ™¯ä¸å˜åœ¨ä¸¤ä¸ª " +"[Camera] èŠ‚ç‚¹å¹¶ä¸”åªæœ‰ä¸€ä¸ªä¸ºå½“å‰ç›¸æœºï¼Œé‚£ä¹ˆå¦‚果把æŸä¸€ä¸ªç›¸æœºçš„ [member current] " +"设为 [code]false[/code] 就会导致å¦ä¸€ä¸ªç›¸æœºè¢«è®¾ä¸ºå½“å‰ç›¸æœºã€‚" #: doc/classes/Camera.xml msgid "" @@ -14772,7 +14810,7 @@ msgstr "将相机与跟踪的节点对é½ã€‚" msgid "" "Removes any [Camera2D] from the ancestor [Viewport]'s internal currently-" "assigned camera." -msgstr "从父级[Viewport]的内部当å‰åˆ†é…的相机ä¸åˆ 除任何[Camera2D]。" +msgstr "从父级 [Viewport] 的内部当å‰åˆ†é…的相机ä¸ç§»é™¤ä»»ä½• [Camera2D]。" #: doc/classes/Camera2D.xml msgid "Forces the camera to update scroll immediately." @@ -16737,7 +16775,7 @@ msgstr "æ·»åŠ ç¢°æ’žä¾‹å¤–ï¼Œä»¥ä½¿ç›¸æœºä¸ä¼šä¸ŽæŒ‡å®šçš„[RID]碰撞。" #: doc/classes/ClippedCamera.xml msgid "Removes all collision exceptions." -msgstr "åˆ é™¤æ‰€æœ‰ç¢°æ’žä¾‹å¤–ã€‚" +msgstr "移除所有碰撞例外。" #: doc/classes/ClippedCamera.xml msgid "Returns the distance the camera has been offset due to a collision." @@ -16753,11 +16791,11 @@ msgstr "" #: doc/classes/ClippedCamera.xml msgid "Removes a collision exception with the specified node." -msgstr "åˆ é™¤ä¸ŽæŒ‡å®šèŠ‚ç‚¹çš„ç¢°æ’žä¾‹å¤–ã€‚" +msgstr "移除与指定节点的碰撞例外。" #: doc/classes/ClippedCamera.xml msgid "Removes a collision exception with the specified [RID]." -msgstr "åˆ é™¤æŒ‡å®š [RID] 的碰撞例外。" +msgstr "移除指定 [RID] 的碰撞例外。" #: doc/classes/ClippedCamera.xml msgid "" @@ -16924,11 +16962,11 @@ msgstr "返回具有给定形状所有者的给定 id 的形状 [Shape] çš„åç´ #: doc/classes/CollisionObject.xml msgid "Returns the shape owner's [Transform]." -msgstr "返回形状所有者的[Transform]。" +msgstr "返回形状所有者的 [Transform]。" #: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml msgid "Removes a shape from the given shape owner." -msgstr "从给定的形状所有者ä¸åˆ 除一个形状。" +msgstr "从给定的形状所有者ä¸ç§»é™¤ä¸€ä¸ªå½¢çŠ¶ã€‚" #: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml msgid "If [code]true[/code], disables the given shape owner." @@ -16936,7 +16974,7 @@ msgstr "如果为 [code]true[/code],则ç¦ç”¨ç»™å®šçš„形状所有者。" #: doc/classes/CollisionObject.xml msgid "Sets the [Transform] of the given shape owner." -msgstr "设置给定形状所有者的[Transform]。" +msgstr "设置给定形状所有者的 [Transform]。" #: doc/classes/CollisionObject.xml msgid "" @@ -17009,7 +17047,7 @@ msgstr "å½“é¼ æ ‡æŒ‡é’ˆé€€å‡ºæ¤å¯¹è±¡çš„æ‰€æœ‰å½¢çŠ¶æ—¶å‘出。" #: doc/classes/CollisionObject2D.xml msgid "Base node for 2D collision objects." -msgstr "二维碰撞对象的基础节点。" +msgstr "2D 碰撞对象的基础节点。" #: doc/classes/CollisionObject2D.xml msgid "" @@ -17045,7 +17083,7 @@ msgid "" "Returns the [code]one_way_collision_margin[/code] of the shape owner " "identified by given [code]owner_id[/code]." msgstr "" -"返回由给定的[code]owner_id[/code]æ ‡è¯†çš„å½¢çŠ¶æ‰€æœ‰è€…çš„" +"返回由给定的 [code]owner_id[/code] æ ‡è¯†çš„å½¢çŠ¶æ‰€æœ‰è€…çš„ " "[code]one_way_collision_margin[/code]。" #: doc/classes/CollisionObject2D.xml @@ -17054,26 +17092,26 @@ msgid "" "this [CollisionObject2D] will not be reported to collided with " "[CollisionObject2D]s." msgstr "" -"返回 [code]true[/code],如果æºäºŽè¿™ä¸ª[CollisionObject2D]的形状所有者的碰撞ä¸ä¼š" -"被报告给[CollisionObject2D]s。" +"返回 [code]true[/code],如果æºäºŽè¿™ä¸ª [CollisionObject2D] 的形状所有者的碰撞ä¸" +"会被报告给 [CollisionObject2D]。" #: doc/classes/CollisionObject2D.xml msgid "Adds a [Shape2D] to the shape owner." -msgstr "ç»™å½¢çŠ¶æ‰€æœ‰è€…æ·»åŠ ä¸€ä¸ª[Shape2D]。" +msgstr "ç»™å½¢çŠ¶æ‰€æœ‰è€…æ·»åŠ ä¸€ä¸ª [Shape2D]。" #: doc/classes/CollisionObject2D.xml msgid "Returns the [Shape2D] with the given id from the given shape owner." -msgstr "从给定的形状所有者那里返回给定idçš„[Shape2D]。" +msgstr "从给定的形状所有者那里返回给定 id çš„ [Shape2D]。" #: doc/classes/CollisionObject2D.xml msgid "" "Returns the child index of the [Shape2D] with the given id from the given " "shape owner." -msgstr "从给定的形状所有者那里返回给定idçš„[Shape2D]çš„å索引。" +msgstr "从给定的形状所有者那里返回给定 id çš„ [Shape2D] çš„å索引。" #: doc/classes/CollisionObject2D.xml msgid "Returns the shape owner's [Transform2D]." -msgstr "返回形状所有者的[Transform2D]。" +msgstr "返回形状所有者的 [Transform2D]。" #: doc/classes/CollisionObject2D.xml msgid "" @@ -17081,20 +17119,20 @@ msgid "" "originating from this [CollisionObject2D] will not be reported to collided " "with [CollisionObject2D]s." msgstr "" -"如果[code]enable[/code]为 [code]true[/code],则æºè‡ªè¿™ä¸ª[CollisionObject2D]çš„" -"形状所有者的碰撞将ä¸ä¼šè¢«æŠ¥å‘Šç»™[CollisionObject2D]。" +"如果 [code]enable[/code] 为 [code]true[/code],则æºè‡ªè¿™ä¸ª " +"[CollisionObject2D] 的形状所有者的碰撞将ä¸ä¼šè¢«æŠ¥å‘Šç»™ [CollisionObject2D]。" #: doc/classes/CollisionObject2D.xml msgid "" "Sets the [code]one_way_collision_margin[/code] of the shape owner identified " "by given [code]owner_id[/code] to [code]margin[/code] pixels." msgstr "" -"将由给定的[code]owner_id[/code]æ ‡è¯†çš„å½¢çŠ¶æ‰€æœ‰è€…çš„" -"[code]one_way_collision_margin[/code]设置为[code]margin[/code]åƒç´ 。" +"将由给定的 [code]owner_id[/code] æ ‡è¯†çš„å½¢çŠ¶æ‰€æœ‰è€…çš„ " +"[code]one_way_collision_margin[/code] 设置为 [code]margin[/code] åƒç´ 。" #: doc/classes/CollisionObject2D.xml msgid "Sets the [Transform2D] of the given shape owner." -msgstr "设置给定形状所有者的[Transform2D]。" +msgstr "设置给定形状所有者的 [Transform2D]。" #: doc/classes/CollisionObject2D.xml msgid "" @@ -17949,7 +17987,7 @@ msgstr "é“奇è“色。" #: doc/classes/Color.xml msgid "Firebrick color." -msgstr "ç«ç –的颜色。" +msgstr "è€ç«ç –红色。" #: doc/classes/Color.xml msgid "Floral white color." @@ -17961,11 +17999,11 @@ msgstr "森林绿色。" #: doc/classes/Color.xml msgid "Fuchsia color." -msgstr "紫红色的颜色。" +msgstr "洋红色。" #: doc/classes/Color.xml msgid "Gainsboro color." -msgstr "庚斯伯勒颜色。" +msgstr "庚斯伯勒ç°è‰²ã€‚" #: doc/classes/Color.xml msgid "Ghost white color." @@ -17977,7 +18015,7 @@ msgstr "金色。" #: doc/classes/Color.xml msgid "Goldenrod color." -msgstr "金黄的颜色。" +msgstr "金èŠè‰²ã€‚" #: doc/classes/Color.xml msgid "Gray color." @@ -17997,7 +18035,7 @@ msgstr "蜜露色。" #: doc/classes/Color.xml msgid "Hot pink color." -msgstr "ç‚™çƒçš„粉红色。" +msgstr "亮粉色。" #: doc/classes/Color.xml msgid "Indian red color." @@ -18021,7 +18059,7 @@ msgstr "è–°è¡£è‰è‰²ã€‚" #: doc/classes/Color.xml msgid "Lavender blush color." -msgstr "è–°è¡£è‰è…®çº¢çš„颜色。" +msgstr "è–°è¡£è‰ç´«çº¢è‰²ã€‚" #: doc/classes/Color.xml msgid "Lawn green color." @@ -18045,7 +18083,7 @@ msgstr "æ·¡é’色。" #: doc/classes/Color.xml msgid "Light goldenrod color." -msgstr "淡淡的金黄色。" +msgstr "亮金èŠé»„色。" #: doc/classes/Color.xml msgid "Light gray color." @@ -18391,7 +18429,7 @@ msgstr "" #: doc/classes/ColorPicker.xml msgid "" "Removes the given color from the list of color presets of this color picker." -msgstr "从这个å–色器的颜色预设列表ä¸åˆ 除给定的颜色。" +msgstr "从这个å–色器的颜色预设列表ä¸ç§»é™¤ç»™å®šçš„颜色。" #: doc/classes/ColorPicker.xml msgid "Returns the list of colors in the presets of the color picker." @@ -18452,7 +18490,7 @@ msgstr "æ·»åŠ é¢„è®¾æ—¶å‘出。" #: doc/classes/ColorPicker.xml msgid "Emitted when a preset is removed." -msgstr "åˆ é™¤é¢„è®¾æ—¶å‘出。" +msgstr "移除预设时å‘出。" #: doc/classes/ColorPicker.xml msgid "The width of the hue selection slider." @@ -18530,7 +18568,7 @@ msgid "" msgstr "" "返回控件的 [PopupPanel],它å…è®¸ä½ è¿žæŽ¥åˆ°å¼¹å‡ºä¿¡å·ã€‚è¿™å…è®¸ä½ åœ¨æ˜¾ç¤ºæˆ–éšè— " "ColorPicker 时事件处ç†ã€‚\n" -"[b]è¦å‘Šï¼š[/b]è¿™æ˜¯ä¸€ä¸ªå¿…éœ€çš„å†…éƒ¨èŠ‚ç‚¹ï¼Œåˆ é™¤å’Œé‡Šæ”¾å®ƒå¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éš" +"[b]è¦å‘Šï¼š[/b]这是一个必需的内部节点,移除并释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éš" "è—它或其任何å项,请使用其 [member CanvasItem.visible] 属性。" #: doc/classes/ColorPickerButton.xml @@ -18891,7 +18929,7 @@ msgstr "" #: doc/classes/ConfigFile.xml msgid "Removes the entire contents of the config." -msgstr "åˆ é™¤é…置的全部内容。" +msgstr "移除é…置的全部内容。" #: doc/classes/ConfigFile.xml msgid "" @@ -19019,7 +19057,7 @@ msgid "" "if it ends up empty once the key has been removed." msgstr "" "ä¸ºæŒ‡å®šç« èŠ‚çš„æŒ‡å®šé”®èµ‹å€¼ã€‚å¦‚æžœèŠ‚æˆ–é”®ä¸å˜åœ¨ï¼Œåˆ™åˆ›å»ºå®ƒä»¬ã€‚如果指定的键å˜åœ¨ï¼Œä¼ 递 " -"[code]null[/code] å€¼å°±ä¼šåˆ é™¤æŒ‡å®šçš„é”®ï¼Œå¦‚æžœé”®è¢«åˆ é™¤åŽï¼Œé”®æœ€ç»ˆæ˜¯ç©ºçš„ï¼Œå°±ä¼šåˆ é™¤" +"[code]null[/code] 值就会移除指定的键,如果键被移除åŽï¼Œé”®æœ€ç»ˆæ˜¯ç©ºçš„,就会移除" "节。" #: doc/classes/ConfirmationDialog.xml @@ -19051,7 +19089,7 @@ msgid "" "[member CanvasItem.visible] property." msgstr "" "è¿”å›žå–æ¶ˆæŒ‰é’®ã€‚\n" -"[b]è¦å‘Šï¼š[/b]è¿™æ˜¯ä¸€ä¸ªå¿…éœ€çš„å†…éƒ¨èŠ‚ç‚¹ï¼Œåˆ é™¤å’Œé‡Šæ”¾å®ƒå¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éš" +"[b]è¦å‘Šï¼š[/b]这是一个必需的内部节点,移除并释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚å¦‚æžœä½ å¸Œæœ›éš" "è—它或其任何å项,请使用其 [member CanvasItem.visible] 属性。" #: doc/classes/Container.xml @@ -21232,7 +21270,7 @@ msgid "" "points] property using the convex hull algorithm. Removing all unneeded " "points. See [method Geometry.convex_hull_2d] for details." msgstr "" -"基于所æä¾›ç‚¹çš„集åˆï¼Œä½¿ç”¨å‡¸åŒ…ç®—æ³•åˆ›å»ºå’Œåˆ†é… [member points]å±žæ€§ã€‚åˆ é™¤æ‰€æœ‰ä¸éœ€" +"基于所æä¾›ç‚¹çš„集åˆï¼Œä½¿ç”¨å‡¸åŒ…ç®—æ³•åˆ›å»ºå’Œåˆ†é… [member points]属性。移除所有ä¸éœ€" "è¦çš„点。详情请å‚阅 [method Geometry.convex_hull_2d]。" #: doc/classes/ConvexPolygonShape2D.xml @@ -21400,8 +21438,8 @@ msgid "" "Each particle's color will vary along this [GradientTexture] over its " "lifetime (multiplied with [member color])." msgstr "" -"æ¯ä¸ªç²’å的颜色将在其生命周期内éšç€è¿™ä¸ª[GradientTexture]å˜åŒ–,å³ä¸Ž[member " -"color]相乘。" +"æ¯ä¸ªç²’å的颜色将在其生命周期内éšç€è¿™ä¸ª [GradientTexture] å˜åŒ–(与 [member " +"color] 相乘)。" #: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml #: doc/classes/ParticlesMaterial.xml @@ -22468,8 +22506,8 @@ msgid "" "V around the outline of the [member polygon]), the bottom-left quarter to " "the front end face, and the bottom-right quarter to the back end face." msgstr "" -"用于生æˆçš„ç½‘æ ¼çš„æè´¨ã€‚UV å°†æè´¨çš„上åŠéƒ¨åˆ†æ˜ 射到挤出的形状,å³U沿挤出物的长" -"度,V 围绕 [member polygon]çš„è½®å»“ï¼Œå·¦ä¸‹è§’çš„å››åˆ†ä¹‹ä¸€æ˜ å°„åˆ°å‰ç«¯é¢ï¼Œå³ä¸‹è§’的四分" +"用于生æˆçš„ç½‘æ ¼çš„æè´¨ã€‚UV å°†æè´¨çš„上åŠéƒ¨åˆ†æ˜ 射到挤出的形状(U 沿挤出物的长度," +"V 围绕 [member polygon] çš„è½®å»“ï¼‰ï¼Œå·¦ä¸‹è§’çš„å››åˆ†ä¹‹ä¸€æ˜ å°„åˆ°å‰ç«¯é¢ï¼Œå³ä¸‹è§’的四分" "ä¹‹ä¸€æ˜ å°„åˆ°åŽç«¯é¢ã€‚" #: modules/csg/doc_classes/CSGPolygon.xml @@ -22792,11 +22830,11 @@ msgstr "" #: modules/csg/doc_classes/CSGShape.xml msgid "" "Geometry of both primitives is merged, intersecting geometry is removed." -msgstr "åˆå¹¶ä¸¤ä¸ªå›¾å…ƒçš„å‡ ä½•ä½“ï¼Œåˆ é™¤ç›¸äº¤çš„å‡ ä½•ä½“ã€‚" +msgstr "åˆå¹¶ä¸¤ä¸ªå›¾å…ƒçš„å‡ ä½•ä½“ï¼Œç§»é™¤ç›¸äº¤çš„å‡ ä½•ä½“ã€‚" #: modules/csg/doc_classes/CSGShape.xml msgid "Only intersecting geometry remains, the rest is removed." -msgstr "ä»…ä¿ç•™ç›¸äº¤çš„å‡ ä½•ï¼Œå…¶ä½™çš„å°†è¢«åˆ é™¤ã€‚" +msgstr "ä»…ä¿ç•™ç›¸äº¤çš„å‡ ä½•ï¼Œå…¶ä½™çš„å°†è¢«ç§»é™¤ã€‚" #: modules/csg/doc_classes/CSGShape.xml msgid "" @@ -22899,7 +22937,7 @@ msgstr "" msgid "" "A script implemented in the C# programming language (Mono-enabled builds " "only)." -msgstr "用C#编程è¯è¨€å®žçŽ°çš„è„šæœ¬ï¼ˆä»…å¯ç”¨Mono的版本)。" +msgstr "用 C# 编程è¯è¨€å®žçŽ°çš„è„šæœ¬ï¼ˆä»… Mono 版本ä¸å˜åœ¨ï¼‰ã€‚" #: modules/mono/doc_classes/CSharpScript.xml msgid "" @@ -22907,14 +22945,14 @@ msgid "" "class and is only available in Mono-enabled Godot builds.\n" "See also [GodotSharp]." msgstr "" -"æ¤ç±»è¡¨ç¤ºC#脚本。它与[GDScript]类的Cï¼ƒç‰æ•ˆï¼Œå¹¶ä¸”仅在å¯ç”¨äº†Monoçš„Godot版本ä¸å¯" -"用。\n" -"å¦è¯·å‚阅[GodotSharp]。" +"这个类表示 C# 脚本,是 [GDScript] 类在 C# ä¸çš„对ç‰ä½“,仅在å¯ç”¨äº† Mono çš„ " +"Godot 版本ä¸å¯ç”¨ã€‚\n" +"å¦è¯·å‚阅 [GodotSharp]。" #: modules/mono/doc_classes/CSharpScript.xml #: modules/gdnative/doc_classes/PluginScript.xml msgid "Returns a new instance of the script." -msgstr "返回脚本的新实例。" +msgstr "返回该脚本的新实例。" #: doc/classes/CubeMap.xml msgid "A CubeMap is a 6-sided 3D texture." @@ -23231,11 +23269,11 @@ msgstr "釿–°è®¡ç®—曲线的烘焙点缓å˜ã€‚" msgid "" "Removes points that are closer than [code]CMP_EPSILON[/code] (0.00001) units " "to their neighbor on the curve." -msgstr "åˆ é™¤æ¯”æ›²çº¿ä¸Šçš„ç›¸é‚»ç‚¹è¿‘[code]CMP_EPSILON[/code](0.00001)个å•ä½çš„点。" +msgstr "移除比曲线上的相邻点近 [code]CMP_EPSILON[/code](0.00001)个å•ä½çš„点。" #: doc/classes/Curve.xml doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "Removes all points from the curve." -msgstr "从曲线ä¸åˆ 除所有点。" +msgstr "从曲线ä¸ç§»é™¤æ‰€æœ‰ç‚¹ã€‚" #: doc/classes/Curve.xml doc/classes/Curve2D.xml doc/classes/Curve3D.xml msgid "Returns the number of points describing the curve." @@ -23284,7 +23322,7 @@ msgstr "" #: doc/classes/Curve.xml msgid "Removes the point at [code]index[/code] from the curve." -msgstr "从曲线ä¸åˆ 除 [code]index[/code] 处的点。" +msgstr "从曲线ä¸ç§»é™¤ [code]index[/code] 处的点。" #: doc/classes/Curve.xml msgid "" @@ -23426,9 +23464,9 @@ msgid "" "the index is out of bounds, the function sends an error to the console, and " "returns [code](0, 0)[/code]." msgstr "" -"返回指å‘顶点[code]idx[/code]的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹[code]idx[/" -"code]çš„ã€‚å¦‚æžœç´¢å¼•è¶…å‡ºäº†èŒƒå›´ï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€ä¸€æ¡é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, 0)" -"[/code]。" +"返回指å‘顶点 [code]idx[/code] 的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ " +"[code]idx[/code] çš„ã€‚å¦‚æžœç´¢å¼•è¶…å‡ºäº†èŒƒå›´ï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€ä¸€æ¡é”™è¯¯ï¼Œå¹¶è¿”回 " +"[code](0, 0)[/code]。" #: doc/classes/Curve2D.xml msgid "" @@ -23437,9 +23475,9 @@ msgid "" "code]. If the index is out of bounds, the function sends an error to the " "console, and returns [code](0, 0)[/code]." msgstr "" -"返回从顶点[code]idx[/code]引出的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ " -"[code]idx[/code]ã€‚å¦‚æžœç´¢å¼•è¶Šç•Œï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, 0)[/" -"code]。" +"返回从顶点 [code]idx[/code] 引出的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ " +"[code]idx[/code]ã€‚å¦‚æžœç´¢å¼•è¶Šç•Œï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, " +"0)[/code]。" #: doc/classes/Curve2D.xml msgid "" @@ -23569,7 +23607,7 @@ msgstr "" #: doc/classes/Curve3D.xml msgid "Describes a Bézier curve in 3D space." -msgstr "æè¿°äºŒç»´ç©ºé—´çš„è´å…¹å°”曲线。" +msgstr "æè¿° 3D 空间的è´å…¹å°”曲线。" #: doc/classes/Curve3D.xml msgid "" @@ -24099,7 +24137,7 @@ msgstr "GDScript 基础:å—å…¸" #: doc/classes/Dictionary.xml msgid "Clear the dictionary, removing all key/value pairs." -msgstr "清除å—å…¸ï¼Œåˆ é™¤æ‰€æœ‰é”®/值对。" +msgstr "清除å—典,移除所有键/值对。" #: doc/classes/Dictionary.xml msgid "" @@ -24232,7 +24270,6 @@ msgstr "" "æ¢çš„ä¸–ç•Œç©ºé—´åæ ‡ï¼ˆåŽŸç‚¹ï¼‰ä¼šè¢«å¿½ç•¥ã€‚åªä¼šç”¨åŸºæ¥ç¡®å®šå…‰çº¿çš„æ–¹å‘。" #: doc/classes/DirectionalLight.xml -#, fuzzy msgid "" "Amount of extra bias for shadow splits that are far away. If self-shadowing " "occurs only on the splits far away, increasing this value can fix them. This " @@ -24240,7 +24277,8 @@ msgid "" "SHADOW_ORTHOGONAL]." msgstr "" "远处阴影分裂的é¢å¤–åç½®é‡ã€‚如果自身阴影åªäº§ç”Ÿè¿œå¤„çš„åˆ†è£‚ï¼Œå¢žåŠ è¿™ä¸ªå€¼å¯ä»¥ä¿®å¤å®ƒ" -"们。" +"们。当 [member directional_shadow_mode] 为 [constant SHADOW_ORTHOGONAL] 时会" +"被忽略。" #: doc/classes/DirectionalLight.xml msgid "" @@ -24249,6 +24287,9 @@ msgid "" "moderate performance cost. This is ignored when [member " "directional_shadow_mode] is [constant SHADOW_ORTHOGONAL]." msgstr "" +"如果为 [code]true[/code],会牺牲阴影的细节,æ¢å–分割区域之间更平滑的过渡。å¯" +"用阴影混åˆåˆ†å‰²åŒæ—¶ä¹Ÿä¼šå¸¦æ¥ä¸€äº›æ€§èƒ½æ¶ˆè€—。当 [member directional_shadow_mode] " +"为 [constant SHADOW_ORTHOGONAL] 时会被忽略。" #: doc/classes/DirectionalLight.xml msgid "" @@ -24263,6 +24304,8 @@ msgid "" "shadow detail and performance (since more objects need to be included in the " "directional shadow rendering)." msgstr "" +"阴影分割的最大è·ç¦»ã€‚将这个值增大会让方å‘阴影在更远处å¯è§ï¼Œä»£ä»·æ˜¯æ•´ä½“的阴影细" +"节é™ä½Žå’Œæ€§èƒ½ï¼ˆå› 为渲染方å‘阴影时需è¦åŒ…嫿›´å¤šçš„对象)。" #: doc/classes/DirectionalLight.xml msgid "The light's shadow rendering algorithm. See [enum ShadowMode]." @@ -24275,39 +24318,36 @@ msgid "" msgstr "当物体垂直于光线时,å¯ç”¨äºŽä¿®å¤è‡ªèº«é˜´å½±çš„特殊情况。" #: doc/classes/DirectionalLight.xml -#, fuzzy msgid "" "The distance from camera to shadow split 1. Relative to [member " "directional_shadow_max_distance]. Only used when [member " "directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant " "SHADOW_PARALLEL_4_SPLITS]." msgstr "" -"相机到影å分割1çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]ã€‚åªæœ‰å½“" -"[member directional_shadow_mode]是[code]SHADOW_PARALLEL_2_SPLITS[/code]或" -"[code]SHADOW_PARALLEL_4_SPLITS[/code]æ—¶æ‰ä½¿ç”¨ã€‚" +"相机到阴影分割 1 çš„è·ç¦»ã€‚相对于 [member directional_shadow_max_distance]。åª" +"有当 [member directional_shadow_mode] 为 [constant SHADOW_PARALLEL_2_SPLITS] " +"或 [constant SHADOW_PARALLEL_4_SPLITS] æ—¶æ‰ä½¿ç”¨ã€‚" #: doc/classes/DirectionalLight.xml -#, fuzzy msgid "" "The distance from shadow split 1 to split 2. Relative to [member " "directional_shadow_max_distance]. Only used when [member " "directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant " "SHADOW_PARALLEL_4_SPLITS]." msgstr "" -"阴影分割1到分割2çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。仅在" -"[member directional_shadow_mode]为[code]SHADOW_PARALLEL_2_SPLITS[/code]或" -"[code]SHADOW_PARALLEL_4_SPLITS[/code]时使用。" +"阴影分割 1 到分割 2 çš„è·ç¦»ã€‚相对于 [member directional_shadow_max_distance]。" +"仅在 [member directional_shadow_mode] 为 [constant SHADOW_PARALLEL_2_SPLITS] " +"或 [constant SHADOW_PARALLEL_4_SPLITS] 时使用。" #: doc/classes/DirectionalLight.xml -#, fuzzy msgid "" "The distance from shadow split 2 to split 3. Relative to [member " "directional_shadow_max_distance]. Only used when [member " "directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]." msgstr "" -"从影å分割2到分割3çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。åª" -"有当[member directional_shadow_mode]为[code]SHADOW_PARALLEL_4_SPLITS[/code]æ—¶" -"æ‰ä½¿ç”¨ã€‚" +"从阴影分割 2 到分割 3 çš„è·ç¦»ã€‚相对于 [member " +"directional_shadow_max_distance]ã€‚åªæœ‰å½“ [member directional_shadow_mode] 为 " +"[constant SHADOW_PARALLEL_4_SPLITS] æ—¶æ‰ä½¿ç”¨ã€‚" #: doc/classes/DirectionalLight.xml msgid "" @@ -24547,8 +24587,8 @@ msgid "" "Closes the current stream opened with [method list_dir_begin] (whether it " "has been fully processed with [method get_next] does not matter)." msgstr "" -"å…³é—用 [method list_dir_begin] æ‰“å¼€çš„å½“å‰æµï¼Œå¹¶ä¸å…³æ³¨æ˜¯å¦å·²ç»ç”¨ [method " -"get_next] 完æˆå¤„ç†ã€‚" +"å…³é—用 [method list_dir_begin] æ‰“å¼€çš„å½“å‰æµï¼ˆå¹¶ä¸å…³æ³¨æ˜¯å¦å·²ç»ç”¨ [method " +"get_next] 完æˆå¤„ç†ï¼‰ã€‚" #: doc/classes/Directory.xml msgid "" @@ -24762,8 +24802,8 @@ msgid "" "[constant PacketPeerDTLS.STATUS_HANDSHAKING], as it is normal that 50% of " "the new connections will be invalid due to cookie exchange." msgstr "" -"å°è¯•与给定的 [code]udp_peer[/code] å¯åЍ DTLS æ¡æ‰‹ï¼Œè¯¥ peer 必须已ç»è¿žæŽ¥ï¼Œè¯·å‚" -"阅 [method PacketPeerUDP.connect_to_host]。\n" +"å°è¯•与给定的 [code]udp_peer[/code] å¯åЍ DTLS æ¡æ‰‹ï¼Œè¯¥ peer 必须已ç»è¿žæŽ¥ï¼ˆè§ " +"[method PacketPeerUDP.connect_to_host])。\n" "[b]注æ„:[/b]ä½ å¿…é¡»æ£€æŸ¥è¿”å›ž PacketPeerUDP çš„çŠ¶æ€æ˜¯å¦ä¸º [constant " "PacketPeerDTLS.STATUS_HANDSHAKING]ï¼Œå› ä¸ºæ£å¸¸æƒ…况下,50% çš„æ–°è¿žæŽ¥ä¼šå› ä¸º " "cookie 交æ¢è€Œæ— 效。" @@ -25196,9 +25236,9 @@ msgid "" "appear in the inspector when selecting a node that extends the class " "specified by [code]class_name[/code]." msgstr "" -"如果[code]class_name[/code]指定的类ä¸çš„[code]property[/code]被ç¦ç”¨ï¼Œåˆ™è¿”回 " -"[code]true[/code]。当属性被ç¦ç”¨æ—¶ï¼Œå½“[code]class_name[/code]类被指定为类的(ç»§" -"承)父节点时,它将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸ã€‚" +"如果 [code]class_name[/code] 指定的类ä¸çš„ [code]property[/code] 属性被ç¦ç”¨ï¼Œ" +"则返回 [code]true[/code]。ç¦ç”¨æŸä¸€å±žæ€§åŽï¼Œå½“选ä¸ç»§æ‰¿è‡ª " +"[code]class_name[/code] 类的节点时,该属性将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸ã€‚" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25214,17 +25254,19 @@ msgid "" "format obtained by using the feature profile manager's [b]Export[/b] button " "or the [method save_to_file] method." msgstr "" -"从文件ä¸åŠ è½½ä¸€ä¸ªç¼–è¾‘å™¨åŠŸèƒ½é…置文件。该文件必须éµå¾ªJSONæ ¼å¼ï¼Œé€šè¿‡ä½¿ç”¨åŠŸèƒ½é…ç½®" -"文件管ç†å™¨çš„[b]Export[/b]按钮或[method save_to_file]方法获得。" +"从文件ä¸åŠ è½½ä¸€ä¸ªç¼–è¾‘å™¨åŠŸèƒ½é…置文件。该文件必须éµå¾ª JSON " +"æ ¼å¼ï¼Œé€šè¿‡ä½¿ç”¨åŠŸèƒ½é…置文件管ç†å™¨çš„[b]导出[/b]按钮或 [method save_to_file] " +"方法获得。" #: doc/classes/EditorFeatureProfile.xml msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" -"将编辑器的功能é…ç½®ä¿å˜åˆ°JSONæ ¼å¼çš„æ–‡ä»¶ä¸ã€‚ç„¶åŽå¯ä»¥ä½¿ç”¨ç‰¹å¾é…置文件管ç†å™¨çš„[b]" -"导入[/b]按钮或[method load_from_file]按钮导入它。" +"将编辑器的功能é…ç½®ä¿å˜åˆ° JSON " +"æ ¼å¼çš„æ–‡ä»¶ä¸ã€‚ç„¶åŽå¯ä»¥ä½¿ç”¨åŠŸèƒ½é…置文件管ç†å™¨çš„[b]导入[/b]按钮或 [method " +"load_from_file] 方法导入它。" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25232,8 +25274,9 @@ msgid "" "by [code]class_name[/code]. When disabled, the class won't appear in the " "Create New Node dialog." msgstr "" -"如果 [code]disable[/code] 是 [code]true[/code],则ç¦ç”¨ [code]class_name[/" -"code] 指定的类。被ç¦ç”¨æ—¶ï¼Œè¯¥ç±»ä¸ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° Nodeâ€å¯¹è¯æ¡†ä¸ã€‚" +"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ " +"[code]class_name[/code] 指定的类。ç¦ç”¨åŽï¼Œè¯¥ç±»ä¸ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° " +"Nodeâ€å¯¹è¯æ¡†ä¸ã€‚" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25242,9 +25285,9 @@ msgid "" "appear in the Create New Node dialog but the inspector will be read-only " "when selecting a node that extends the class." msgstr "" -"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ [code]class_name[/" -"code] 指定的类的编辑。ç¦ç”¨æ—¶ï¼Œç±»ä»ç„¶ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° Nodeâ€å¯¹è¯æ¡†ä¸ï¼Œä½†åœ¨é€‰æ‹©ç»§" -"承的节点时,检查器将åªè¯»ã€‚" +"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ " +"[code]class_name[/code] 指定的类的编辑。ç¦ç”¨åŽï¼Œè¯¥ç±»ä»ç„¶ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° " +"Nodeâ€å¯¹è¯æ¡†ä¸ï¼Œä½†åœ¨é€‰ä¸ç»§æ‰¿çš„节点时,检查器将åªè¯»ã€‚" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25253,9 +25296,10 @@ msgid "" "When a property is disabled, it won't appear in the inspector when selecting " "a node that extends the class specified by [code]class_name[/code]." msgstr "" -"如果 [code]disable[/code] 是 [code]true[/code],则ç¦ç”¨ [code]class_name[/" -"code] 指定的类ä¸çš„ [code]property[/code] 的编辑。当属性被ç¦ç”¨æ—¶ï¼Œå½“选择继承 " -"[code]class_name[/code] 指定的类的节点时,它将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸ã€‚" +"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ " +"[code]class_name[/code] 指定的类ä¸çš„ [code]property[/code] " +"属性的编辑。ç¦ç”¨æŸä¸€å±žæ€§åŽï¼Œé€‰ä¸ç»§æ‰¿è‡ª [code]class_name[/code] " +"指定的类的节点时,这个属性将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸ã€‚" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25286,7 +25330,7 @@ msgstr "" msgid "" "The AssetLib tab. If this feature is disabled, the AssetLib tab won't " "display." -msgstr "AssetLib选项å¡ã€‚如果ç¦ç”¨æ¤åŠŸèƒ½ï¼Œåˆ™ä¸ä¼šæ˜¾ç¤ºAssetLib选项å¡ã€‚" +msgstr "AssetLib 选项å¡ã€‚如果ç¦ç”¨æ¤åŠŸèƒ½ï¼Œåˆ™ä¸ä¼šæ˜¾ç¤º AssetLib 选项å¡ã€‚" #: doc/classes/EditorFeatureProfile.xml msgid "" @@ -25334,7 +25378,7 @@ msgstr "" #: doc/classes/EditorFileDialog.xml msgid "Removes all filters except for \"All Files (*)\"." -msgstr "åˆ é™¤é™¤â€œAll Files(*)â€ç›é€‰å™¨ä¹‹å¤–的所有ç›é€‰å™¨ã€‚" +msgstr "移除“All Files(*)â€ç›é€‰å™¨ä¹‹å¤–的所有ç›é€‰å™¨ã€‚" #: doc/classes/EditorFileDialog.xml msgid "" @@ -25948,7 +25992,7 @@ msgstr "" msgid "" "Emitted when the Edit button of an [Object] has been pressed in the " "inspector. This is mainly used in the remote scene tree inspector." -msgstr "åœ¨æ£€æŸ¥å™¨ä¸æŒ‰ä¸‹[Object]的编辑按钮时触å‘。主è¦ç”¨äºŽè¿œç¨‹åœºæ™¯æ ‘检查器ä¸ã€‚" +msgstr "åœ¨æ£€æŸ¥å™¨ä¸æŒ‰ä¸‹ [Object] 的编辑按钮时触å‘。主è¦ç”¨äºŽè¿œç¨‹åœºæ™¯æ ‘检查器ä¸ã€‚" #: doc/classes/EditorInspector.xml msgid "Emitted when a property is edited in the inspector." @@ -25960,8 +26004,8 @@ msgid "" "by clicking the \"key\" icon next to a property when the Animation panel is " "toggled." msgstr "" -"当属性在检查器ä¸è¢«é”®å…¥æ—¶è§¦å‘。当切æ¢åŠ¨ç”»é¢æ¿æ—¶ï¼Œå¯é€šè¿‡ç‚¹å‡»å±žæ€§æ—边的 \"é”® " -"\"å›¾æ ‡å¯¹å±žæ€§è¿›è¡Œé”®æŽ§ã€‚" +"当属性在检查器ä¸è¢«é”®å…¥æ—¶è§¦å‘ã€‚å½“åŠ¨ç”»é¢æ¿æ‰“开时,å¯é€šè¿‡ç‚¹å‡»å±žæ€§æ—边的“钥匙â€å›¾" +"æ ‡ä¸ºå±žæ€§æ·»åŠ å…³é”®å¸§ã€‚" #: doc/classes/EditorInspector.xml msgid "Emitted when a property is selected in the inspector." @@ -26069,7 +26113,7 @@ msgid "" "built-in editor for this property, otherwise allows to insert a custom " "editor before the built-in one." msgstr "" -"å…è®¸è¢«è°ƒç”¨åœ¨æ£€æŸ¥å™¨ä¸æ·»åŠ ç‰¹å®šå±žæ€§çš„ç¼–è¾‘å™¨ã€‚é€šå¸¸è¿™äº›ç¼–è¾‘å™¨ç»§æ‰¿" +"å…è®¸è¢«è°ƒç”¨åœ¨æ£€æŸ¥å™¨ä¸æ·»åŠ ç‰¹å®šå±žæ€§çš„ç¼–è¾‘å™¨ã€‚é€šå¸¸è¿™äº›ç¼–è¾‘å™¨ç»§æ‰¿ " "[EditorProperty]。返回 [code]true[/code]åˆ é™¤è¯¥å±žæ€§çš„å†…ç½®ç¼–è¾‘å™¨ï¼Œå¦åˆ™å…许在内" "ç½®ç¼–è¾‘å™¨ä¹‹å‰æ’入一个自定义编辑器。" @@ -26147,8 +26191,8 @@ msgid "" "code] and [code]interface/editor/custom_display_scale[/code] editor " "settings. Editor must be restarted for changes to be properly applied." msgstr "" -"返回编辑器用户 UI 的实际比例,[code]1.0[/code] 比例为 100%。这å¯ä»¥ç”¨æ¥è°ƒæ•´ç”±" -"æ’ä»¶æ·»åŠ çš„ç”¨æˆ· UI çš„ä½ç½®å’Œå°ºå¯¸ã€‚\n" +"返回编辑器用户 UI 的实际比例([code]1.0[/code] 表示比例为 100%)。这å¯ä»¥ç”¨æ¥" +"调整由æ’ä»¶æ·»åŠ çš„ç”¨æˆ· UI çš„ä½ç½®å’Œå°ºå¯¸ã€‚\n" "[b]注æ„:[/b]这个值是通过 [code]interface/editor/display_scale[/code] å’Œ " "[code]interface/editor/custom_display_scale[/code] 编辑器设置项æ¥è®¾ç½®ã€‚编辑器" "å¿…é¡»é‡æ–°å¯åЍæ‰èƒ½æ£ç¡®åº”用这些å˜åŒ–。" @@ -29114,7 +29158,7 @@ msgid "" "The global color saturation value of the rendered scene (default value is " "1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code]." msgstr "" -"渲染场景的全局色彩饱和度值,默认值为1ã€‚åªæœ‰åœ¨ [code]adjustment_enabled[/" +"渲染场景的全局色彩饱和度值(默认值为 1ï¼‰ã€‚åªæœ‰åœ¨ [code]adjustment_enabled[/" "code] 为 [code]true[/code] æ—¶æ‰æœ‰æ•ˆã€‚" #: doc/classes/Environment.xml @@ -29557,7 +29601,7 @@ msgid "" "The screen-space ambient occlusion bias. This should be kept high enough to " "prevent \"smooth\" curves from being affected by ambient occlusion." msgstr "" -"å±å¹•空间环境光é®è”½åå·®ã€‚è¯¥å€¼åº”ä¿æŒåœ¨è¶³å¤Ÿé«˜çš„æ°´å¹³ï¼Œä»¥é˜²æ¢â€œå¹³æ»‘â€æ›²çº¿å—到环境光" +"å±å¹•空间环境光é®è”½åç½®ã€‚è¯¥å€¼åº”ä¿æŒåœ¨è¶³å¤Ÿé«˜çš„æ°´å¹³ï¼Œä»¥é˜²æ¢â€œå¹³æ»‘â€æ›²çº¿å—到环境光" "é®è”½çš„å½±å“。" #: doc/classes/Environment.xml @@ -29593,13 +29637,13 @@ msgstr "" msgid "" "The primary screen-space ambient occlusion intensity. See also [member " "ssao_radius]." -msgstr "主è¦çš„å±å¹•空间环境光é®è”½å¼ºåº¦ã€‚å‚阅[member ssao_radius]。" +msgstr "主å±å¹•的空间环境光é®è”½å¼ºåº¦ã€‚å¦è¯·å‚阅 [member ssao_radius]。" #: doc/classes/Environment.xml msgid "" "The secondary screen-space ambient occlusion intensity. See also [member " "ssao_radius2]." -msgstr "主è¦çš„å±å¹•空间环境光é®è”½å¼ºåº¦ã€‚å‚阅 [member ssao_radius]。" +msgstr "次å±å¹•的空间环境光é®è”½å¼ºåº¦ã€‚å¦è¯·å‚阅 [member ssao_radius2]。" #: doc/classes/Environment.xml msgid "" @@ -29641,11 +29685,11 @@ msgstr "ç”¨äºŽè‰²è°ƒæ˜ å°„çš„é»˜è®¤æ›å…‰ã€‚" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" -"è¦ä½¿ç”¨çš„è‰²è°ƒæ˜ å°„æ¨¡å¼ã€‚è‰²è°ƒæ˜ å°„æ˜¯â€œè½¬æ¢â€HDR 值以适åˆåœ¨ LDR 显示器上呈现的过程。" -"(Godot å°šä¸æ”¯æŒåœ¨ HDR 显示器上进行渲染。)" +"è¦ä½¿ç”¨çš„è‰²è°ƒæ˜ å°„æ¨¡å¼ã€‚è‰²è°ƒæ˜ å°„æ˜¯å°† HDR 值“转æ¢â€ä¸ºé€‚åˆåœ¨ SDR " +"显示器上呈现的值过程。(Godot å°šä¸æ”¯æŒåœ¨ HDR 显示器上进行渲染。)" #: doc/classes/Environment.xml msgid "" @@ -31817,9 +31861,9 @@ msgid "" "inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. " "somewhere on the line extending from the segment." msgstr "" -"返回由([code]s1[/code], [code]s2[/code])定义的二维线上最接近[code]point[/" -"code]的二维点。返回的点å¯ä»¥åœ¨çº¿æ®µï¼ˆ[code]s1[/code], [code]s2[/code])内,也å¯" -"以在线段外,å³åœ¨ä»Žçº¿æ®µå»¶ä¼¸å‡ºæ¥çš„æŸå¤„ã€‚" +"返回由 ([code]s1[/code], [code]s2[/code]) 定义的 2D 线上最接近 [code]point[/" +"code] çš„ 2D 点。返回的点å¯ä»¥åœ¨çº¿æ®µ ([code]s1[/code], [code]s2[/code]) 内,也" +"å¯ä»¥åœ¨çº¿æ®µå¤–,å³åœ¨ä»Žçº¿æ®µå»¶ä¼¸å‡ºæ¥çš„æŸå¤„ã€‚" #: doc/classes/Geometry.xml msgid "" @@ -31920,13 +31964,14 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" -"给定表示图å—çš„[Vector2]数组,构建一个地图集。返回的å—典有两个键:" -"[code]points[/code]是[Vector2]çš„å‘é‡ï¼Œç”¨äºŽæŒ‡å®šæ¯ä¸ªå›¾å—çš„ä½ç½®ï¼Œ[code]size[/" -"code]åŒ…å«æ•´ä¸ªå›¾é›†çš„æ•´ä½“大å°ï¼Œä½œä¸º[Vector2]。" +"给定表示图å—çš„ [Vector2] " +"数组,构建一个地图集。返回的å—典有两个键:[code]points[/code] 是 [Vector2] " +"的数组,用于指定æ¯ä¸ªå›¾å—çš„ä½ç½®ï¼Œ[code]size[/code] åŒ…å«æ•´ä¸ªå›¾é›†çš„æ•´ä½“大å°ï¼Œ" +"是一个 [Vector2]。" #: doc/classes/Geometry.xml msgid "" @@ -33206,9 +33251,7 @@ msgstr "å°å›¾çŸ©å½¢çš„大å°ã€‚åœ°å›¾è‡ªèº«åŸºäºŽç½‘æ ¼åŒºåŸŸçš„å¤§å°ï¼Œå¹¶è¢« msgid "" "If [code]true[/code], enables disconnection of existing connections in the " "GraphEdit by dragging the right end." -msgstr "" -"如果为 [code]true[/code],通过拖动å³ç«¯ï¼Œå¯ä»¥æ–开图形编辑GraphEditä¸çŽ°æœ‰çš„è¿ž" -"接。" +msgstr "如果为 [code]true[/code],通过拖动å³ç«¯ï¼Œå¯ä»¥æ–å¼€ GraphEdit ä¸çŽ°æœ‰çš„è¿žæŽ¥ã€‚" #: doc/classes/GraphEdit.xml msgid "The scroll offset." @@ -33265,9 +33308,9 @@ msgid "" "code] slot of the [code]from[/code] GraphNode and the [code]to_slot[/code] " "slot of the [code]to[/code] GraphNode is attempted to be created." msgstr "" -"当试图创建[code]æ¥è‡ªfrom[/code]图形节点GraphNode1çš„[code]from_slot[/code]槽和" -"[code]to[/code]图形节点GraphNode2çš„[code]to_slot[/code]槽之间的连接时,会å‘图" -"形编辑GraphEditå‘出。" +"å°è¯•创建从 [code]from[/code] GraphNode çš„ [code]from_slot[/code] 槽到 " +"[code]to[/code] GraphNode çš„ [code]to_slot[/code] 槽之间的连接时,会å‘该 " +"GraphEdit å‘出。" #: doc/classes/GraphEdit.xml msgid "" @@ -33294,9 +33337,9 @@ msgid "" "slot of [code]from[/code] GraphNode and [code]to_slot[/code] slot of " "[code]to[/code] GraphNode is attempted to be removed." msgstr "" -"当试图移除 [code]from[/code] 图形节点GraphNode1çš„ [code]from_slot[/code]槽和" -"[code]to[/code] 图形节点GraphNode çš„[code]to_slot[/code] 槽之间的连接时,会å‘" -"é€åˆ°å›¾å½¢ç¼–辑GraphEdit。" +"å°è¯•移除从 [code]from[/code] GraphNode çš„ [code]from_slot[/code] 槽到 " +"[code]to[/code] GraphNode çš„ [code]to_slot[/code] 槽之间的连接时,会å‘该 " +"GraphEdit å‘出。" #: doc/classes/GraphEdit.xml msgid "" @@ -33520,9 +33563,8 @@ msgstr "" msgid "" "Sets the [Color] of the right (output) side of the slot [code]idx[/code] to " "[code]color_right[/code]." -msgstr "" -"å°†æ’æ§½[code]idx[/code]çš„å³ä¾§ï¼ˆè¾“出)的颜色[Color]设置为[code]color_right[/" -"code]。" +msgstr "å°†æ’æ§½ [code]idx[/code] çš„å³ä¾§ï¼ˆè¾“出)的颜色 [Color] 设置为 " +"[code]color_right[/code]。" #: doc/classes/GraphNode.xml msgid "" @@ -33558,7 +33600,7 @@ msgstr "" #: doc/classes/GraphNode.xml msgid "If [code]true[/code], the GraphNode is a comment node." -msgstr "如果为 [code]true[/code],则 GraphNode 是注释节点。" +msgstr "如果为 [code]true[/code],则该 GraphNode 是注释节点。" #: doc/classes/GraphNode.xml msgid "" @@ -33586,7 +33628,7 @@ msgstr "" #: doc/classes/GraphNode.xml msgid "If [code]true[/code], the GraphNode is selected." -msgstr "如果为 [code]true[/code],图形节点GraphNode被选ä¸ã€‚" +msgstr "如果为 [code]true[/code],则该 GraphNode 被选ä¸ã€‚" #: doc/classes/GraphNode.xml msgid "" @@ -35506,7 +35548,6 @@ msgid "A node with the ability to send HTTP(S) requests." msgstr "具有å‘é€ HTTP(S) 请求能力的节点。" #: doc/classes/HTTPRequest.xml -#, fuzzy msgid "" "A node with the ability to send HTTP requests. Uses [HTTPClient] " "internally.\n" @@ -35601,7 +35642,7 @@ msgstr "" " # 执行 POST 请求。截æ¢åˆ°æ–‡æ¡£ç¼–写时,下é¢çš„ URL 会返回 JSON。\n" " # 注æ„:请勿使用å•个 HTTPRequest 节点进行连ç»è¯·æ±‚。\n" " # 下é¢çš„ä»£ç æ®µä»…ä¾›å‚考。\n" -" var body = {\"name\": \"Godette\"}\n" +" var body = to_json({\"name\": \"Godette\"})\n" " error = http_request.request(\"https://httpbin.org/post\", [], true, " "HTTPClient.METHOD_POST, body)\n" " if error != OK:\n" @@ -35774,19 +35815,20 @@ msgstr "å…许的最大é‡å®šå‘æ•°ã€‚ç”¨äºŽé˜²æ¢æ— é™é‡å®šå‘循环。" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." -msgstr "" -"如果设为大于 [code]0.0[/code] 的值,在ç»è¿‡ [code]timeout[/code] ç§’ä»æœª[i]完æˆ" -"[/i]请求时,该 HTTP 请求就会超时。对于 REST API ç‰è¾ƒå°çš„ HTTP 请求,将 " -"[member timeout] 设为大于 [code]0.0[/code] 的值å¯ä»¥å®šæ—¶é˜²æ¢åº”用程åºåœ¨å¤±è´¥æ—¶é™·" -"å…¥é•¿æ—¶é—´çš„æ— å“应状æ€ã€‚ä¸‹è½½æ–‡ä»¶æ—¶è¯·ä¿æŒ [code]0.0[/code],防æ¢åœ¨éœ€è¦èŠ±è´¹è¾ƒé•¿æ—¶" -"间下载时导致下载失败。" +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." +msgstr "" +"如果在请求开始å‰è®¾ä¸ºå¤§äºŽ [code]0.0[/code] 的值,在ç»è¿‡ [code]timeout[/code] " +"ç§’ä»æœª[i]完æˆ[/i]请求时,该 HTTP 请求就会超时。对于 REST API ç‰è¾ƒå°çš„ HTTP 请" +"求,将 [member timeout] 设为 [code]10.0[/code] 到 [code]30.0[/code] 之间的值" +"å¯ä»¥å®šæ—¶é˜²æ¢åº”用程åºåœ¨å¤±è´¥æ—¶é™·å…¥é•¿æ—¶é—´çš„æ— å“应状æ€ã€‚ä¸‹è½½æ–‡ä»¶æ—¶è¯·ä¿æŒ " +"[code]0.0[/code],防æ¢åœ¨éœ€è¦èŠ±è´¹è¾ƒé•¿æ—¶é—´ä¸‹è½½æ—¶å¯¼è‡´ä¸‹è½½å¤±è´¥ã€‚" #: doc/classes/HTTPRequest.xml msgid "If [code]true[/code], multithreading is used to improve performance." @@ -36013,7 +36055,7 @@ msgstr "" msgid "" "Stretches the image and enlarges it by a factor of 2. No interpolation is " "done." -msgstr "拉伸图åƒå¹¶å°†å…¶æ”¾å¤§2å€ï¼Œä¸è¿›è¡Œæ’值。" +msgstr "拉伸图åƒå¹¶å°†å…¶æ”¾å¤§ 2 å€ï¼Œä¸è¿›è¡Œæ’值。" #: doc/classes/Image.xml msgid "Fills the image with [code]color[/code]." @@ -36053,7 +36095,7 @@ msgstr "" "错误。\n" "[b]注æ„:[/b]多级æ¸è¿œçº¹ç†çš„ç”Ÿæˆæ˜¯åœ¨ CPU 上完æˆçš„,是å•线程的,并且[i]总是[/i]" "在主线程上完æˆã€‚è¿™æ„味ç€åœ¨æ¸¸æˆè¿‡ç¨‹ä¸ç”Ÿæˆå¤šçº§æ¸è¿œçº¹ç†ä¼šå¯¼è‡´æ˜Žæ˜¾çš„å¡é¡¿ï¼Œå³ä½¿ä»Ž " -"[Thread] 调用[method generate_mipmaps]。" +"[Thread] 调用 [method generate_mipmaps]。" #: doc/classes/Image.xml msgid "Returns a copy of the image's raw data." @@ -36303,7 +36345,7 @@ msgstr "" #: doc/classes/Image.xml msgid "Shrinks the image by a factor of 2." -msgstr "将图åƒç¼©å°2å€ã€‚" +msgstr "将图åƒç¼©å° 2 å€ã€‚" #: doc/classes/Image.xml msgid "Converts the raw data from the sRGB colorspace to a linear scale." @@ -36329,7 +36371,7 @@ msgstr "[Image] 资æºå…许的最大高度。" #: doc/classes/Image.xml msgid "Texture format with a single 8-bit depth representing luminance." -msgstr "çº¹ç†æ ¼å¼ï¼Œå…·æœ‰ä»£è¡¨äº®åº¦çš„å•一8使·±åº¦ã€‚" +msgstr "çº¹ç†æ ¼å¼ï¼Œå…·æœ‰ä»£è¡¨äº®åº¦çš„å•一 8 使·±åº¦ã€‚" #: doc/classes/Image.xml msgid "" @@ -36407,16 +36449,16 @@ msgid "" "OpenGL texture format [code]GL_RGB32F[/code] where there are three " "components, each a 32-bit floating-point values." msgstr "" -"OpenGLçº¹ç†æ ¼å¼[code]GL_RGB32F[/code]ï¼Œå…¶ä¸æœ‰ä¸‰ä¸ªéƒ¨åˆ†ï¼Œæ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯32使µ®ç‚¹" -"值。" +"OpenGL çº¹ç†æ ¼å¼ [code]GL_RGB32F[/code]ï¼Œå…¶ä¸æœ‰ä¸‰ä¸ªéƒ¨åˆ†ï¼Œæ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯ 32 使µ®" +"点值。" #: doc/classes/Image.xml msgid "" "OpenGL texture format [code]GL_RGBA32F[/code] where there are four " "components, each a 32-bit floating-point values." msgstr "" -"OpenGLçº¹ç†æ ¼å¼[code]GL_RGBA32F[/code]ï¼Œå…¶ä¸æœ‰å››ä¸ªéƒ¨åˆ†ï¼Œæ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯32使µ®ç‚¹" -"值。" +"OpenGL çº¹ç†æ ¼å¼ [code]GL_RGBA32F[/code]ï¼Œå…¶ä¸æœ‰å››ä¸ªéƒ¨åˆ†ï¼Œæ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯ 32 使µ®" +"点值。" #: doc/classes/Image.xml msgid "" @@ -36704,7 +36746,7 @@ msgstr "表示 [enum Format] 枚举的大å°ã€‚" msgid "" "Performs nearest-neighbor interpolation. If the image is resized, it will be " "pixelated." -msgstr "执行最近邻æ’值.如果调整图åƒå¤§å°,它将被åƒç´ 化." +msgstr "执行最近邻æ’值。如果调整图åƒå¤§å°ï¼Œå®ƒå°†è¢«åƒç´ 化。" #: doc/classes/Image.xml msgid "" @@ -36721,8 +36763,8 @@ msgid "" "This mode often gives better results compared to [constant " "INTERPOLATE_BILINEAR], at the cost of being slower." msgstr "" -"执行三次æ’值.如果调整图åƒå¤§å°,则图åƒå°†æ¨¡ç³Š.与[constant INTERPOLATE_BILINEAR]" -"相比,æ¤æ¨¡å¼é€šå¸¸ä¼šäº§ç”Ÿæ›´å¥½çš„结果,但代价是速度较慢." +"执行三次æ’值。如果调整图åƒå¤§å°ï¼Œåˆ™å›¾åƒå°†æ¨¡ç³Šã€‚与 [constant " +"INTERPOLATE_BILINEAR] ç›¸æ¯”ï¼Œæ¤æ¨¡å¼é€šå¸¸ä¼šäº§ç”Ÿæ›´å¥½çš„结果,但代价是速度较慢。" #: doc/classes/Image.xml msgid "" @@ -36754,36 +36796,36 @@ msgid "" "Performs Lanczos interpolation. This is the slowest image resizing mode, but " "it typically gives the best results, especially when downscalng images." msgstr "" -"执行Lanczosæ’值.这是最慢的图åƒè°ƒæ•´å¤§å°æ¨¡å¼,但通常å¯ä»¥æä¾›æœ€ä½³æ•ˆæžœ,尤其是在缩" -"å°å›¾åƒæ—¶." +"执行 Lanczos æ’值。这是最慢的图åƒè°ƒæ•´å¤§å°æ¨¡å¼ï¼Œä½†é€šå¸¸å¯ä»¥æä¾›æœ€ä½³æ•ˆæžœï¼Œå°¤å…¶æ˜¯" +"在缩å°å›¾åƒæ—¶ã€‚" #: doc/classes/Image.xml msgid "Image does not have alpha." -msgstr "图片没有Alpha通é“." +msgstr "图片没有 Alpha 通é“。" #: doc/classes/Image.xml msgid "Image stores alpha in a single bit." -msgstr "图åƒå°†Alphaå˜å‚¨åœ¨å•个bitä¸." +msgstr "图åƒå°† Alpha å˜å‚¨åœ¨å•个 bit ä¸ã€‚" #: doc/classes/Image.xml msgid "Image uses alpha." -msgstr "图åƒä½¿ç”¨é˜¿å°”法。" +msgstr "图åƒä½¿ç”¨ Alpha。" #: doc/classes/Image.xml msgid "Use S3TC compression." -msgstr "使用S3TC压缩。" +msgstr "使用 S3TC 压缩。" #: doc/classes/Image.xml msgid "Use PVRTC2 compression." -msgstr "使用PVRTC2压缩。" +msgstr "使用 PVRTC2 压缩。" #: doc/classes/Image.xml msgid "Use PVRTC4 compression." -msgstr "使用PVRTC4压缩。" +msgstr "使用 PVRTC4 压缩。" #: doc/classes/Image.xml msgid "Use ETC compression." -msgstr "使用ETC压缩。" +msgstr "使用 ETC 压缩。" #: doc/classes/Image.xml msgid "Use ETC2 compression." @@ -37002,7 +37044,7 @@ msgstr "" #: doc/classes/ImmediateGeometry.xml msgid "" "Simple helper to draw an UV sphere with given latitude, longitude and radius." -msgstr "用于绘制给定ç»çº¬åº¦å’ŒåŠå¾„çš„UVçƒä½“的简å•辅助工具。" +msgstr "用于绘制给定ç»çº¬åº¦å’ŒåŠå¾„çš„ UV çƒä½“的简å•辅助工具。" #: doc/classes/ImmediateGeometry.xml msgid "" @@ -37022,11 +37064,11 @@ msgstr "" #: doc/classes/ImmediateGeometry.xml msgid "Clears everything that was drawn using begin/end." -msgstr "清除使用begin/end绘制的一切内容。" +msgstr "清除使用 begin/end 绘制的一切内容。" #: doc/classes/ImmediateGeometry.xml msgid "Ends a drawing context and displays the results." -msgstr "ç»“æŸæ£åœ¨ç»˜åˆ¶çš„context并显示其结果。" +msgstr "ç»“æŸæ£åœ¨ç»˜åˆ¶çš„上下文并显示其结果。" #: doc/classes/ImmediateGeometry.xml msgid "The current drawing color." @@ -37078,10 +37120,10 @@ msgid "" "[method parse_input_event] instead." msgstr "" "这将模拟按下指定的按键动作。\n" -"强度å¯ä»¥ç”¨äºŽéžå¸ƒå°”è¿ç®—的动作,它的范围在0 到 1之间,代表给定动作的力度。\n" -"[b]注æ„:[/b]这个方法ä¸ä¼šå¼•起任何[method Node._input]调用。它旨在与[method " -"is_action_pressed]å’Œ[method is_action_just_pressed]ä¸€èµ·ä½¿ç”¨ã€‚å¦‚æžœä½ æƒ³æ¨¡æ‹Ÿ" -"[code]_input[/code],请使用[method parse_input_event]代替。" +"强度å¯ä»¥ç”¨äºŽéžå¸ƒå°”è¿ç®—的动作,它的范围在 0 到 1 之间,代表给定动作的力度。\n" +"[b]注æ„:[/b]这个方法ä¸ä¼šå¼•起任何 [method Node._input] 调用。它旨在与 " +"[method is_action_pressed] å’Œ [method is_action_just_pressed] 一起使用。如果" +"ä½ æƒ³æ¨¡æ‹Ÿ [code]_input[/code],请使用 [method parse_input_event] 代替。" #: doc/classes/Input.xml msgid "If the specified action is already pressed, this will release it." @@ -37170,8 +37212,8 @@ msgid "" "get_action_strength(\"negative_action\")[/code]." msgstr "" "通过指定两个动作æ¥èŽ·å–轴的输入,一个是负的,一个是æ£çš„。\n" -"这是写[code]Input.get_action_strength(\"positive_action\")-Input." -"get_action_strength(\"negative_action\")[/code]的简写。" +"这是 [code]Input.get_action_strength(\"positive_action\")-Input." +"get_action_strength(\"negative_action\")[/code] 的简写。" #: doc/classes/Input.xml msgid "" @@ -37181,7 +37223,7 @@ msgstr "返回一个 [Array],包å«å½“剿‰€æœ‰è¿žæŽ¥æ‰‹æŸ„的设备 ID。" #: doc/classes/Input.xml msgid "Returns the currently assigned cursor shape (see [enum CursorShape])." -msgstr "è¿”å›žå½“å‰æŒ‡å®šçš„å…‰æ ‡å½¢çŠ¶ï¼ˆå‚阅 [enum CursorShape])。" +msgstr "è¿”å›žå½“å‰æŒ‡å®šçš„å…‰æ ‡å½¢çŠ¶ï¼ˆè§ [enum CursorShape])。" #: doc/classes/Input.xml msgid "" @@ -37192,11 +37234,11 @@ msgid "" "measurement for each axis is m/s² while on iOS it's a multiple of the " "Earth's gravitational acceleration [code]g[/code] (~9.81 m/s²)." msgstr "" -"å¦‚æžœè®¾å¤‡æœ‰åŠ é€Ÿåº¦ä¼ æ„Ÿå™¨ï¼Œåˆ™è¿”å›žè®¾å¤‡çš„é‡åŠ›ã€‚å¦åˆ™ï¼Œè¯¥æ–¹æ³•返回[constant Vector3." +"å¦‚æžœè®¾å¤‡æœ‰åŠ é€Ÿåº¦ä¼ æ„Ÿå™¨ï¼Œåˆ™è¿”å›žè®¾å¤‡çš„é‡åŠ›ã€‚å¦åˆ™ï¼Œè¯¥æ–¹æ³•返回 [constant Vector3." "ZERO]。\n" -"[b]注æ„:[/b]这个方法åªåœ¨Androidå’ŒiOS上工作。在其他平å°ä¸Šï¼Œå®ƒæ€»æ˜¯è¿”回" -"[constant Vector3.ZERO]。在Android上,æ¯ä¸ªè½´çš„æµ‹é‡å•使˜¯m/s²,而在iOS上,它是" -"地çƒé‡åŠ›åŠ é€Ÿåº¦çš„å€æ•°[code]g[/code](~9.81 m/s²)。" +"[b]注æ„:[/b]这个方法åªåœ¨ Android å’Œ iOS 上工作。在其他平å°ä¸Šï¼Œå®ƒæ€»æ˜¯è¿”回 " +"[constant Vector3.ZERO]。在 Android 上,æ¯ä¸ªè½´çš„æµ‹é‡å•使˜¯ m/s²,而在 iOS " +"上,它是地çƒé‡åŠ›åŠ é€Ÿåº¦çš„å€æ•° [code]g[/code](~9.81 m/s²)。" #: doc/classes/Input.xml msgid "" @@ -37206,16 +37248,16 @@ msgid "" "[b]Note:[/b] This method only works on Android and iOS. On other platforms, " "it always returns [constant Vector3.ZERO]." msgstr "" -"å¦‚æžœè®¾å¤‡æœ‰é™€èžºä»ªä¼ æ„Ÿå™¨ï¼Œåˆ™è¿”å›žå›´ç»•è®¾å¤‡Xã€Yã€Z轴的旋转速率,å•ä½ä¸ºrad/s。å¦" -"则,该方法返回[constant Vector3.ZERO]。\n" -"[b]注æ„:[/b]这个方法åªåœ¨Androidå’ŒiOS上工作。在其他平å°ä¸Šï¼Œæ€»æ˜¯è¿”回[constant " -"Vector3.ZERO]。" +"å¦‚æžœè®¾å¤‡æœ‰é™€èžºä»ªä¼ æ„Ÿå™¨ï¼Œåˆ™è¿”å›žå›´ç»•è®¾å¤‡ Xã€Yã€Z 轴的旋转速率,å•ä½ä¸º rad/s。å¦" +"则,该方法返回 [constant Vector3.ZERO]。\n" +"[b]注æ„:[/b]这个方法åªåœ¨ Android å’Œ iOS 上工作。在其他平å°ä¸Šï¼Œæ€»æ˜¯è¿”回 " +"[constant Vector3.ZERO]。" #: doc/classes/Input.xml msgid "" "Returns the current value of the joypad axis at given index (see [enum " "JoystickList])." -msgstr "è¿”å›žç»™å®šç´¢å¼•çš„æ¸¸æˆæ‰‹æŸ„轴的当å‰å€¼ï¼Œå‚阅[enum JoystickList]。" +msgstr "è¿”å›žç»™å®šç´¢å¼•çš„æ¸¸æˆæ‰‹æŸ„轴的当å‰å€¼ï¼ˆè§ [enum JoystickList])。" #: doc/classes/Input.xml msgid "Returns the index of the provided axis name." @@ -37236,15 +37278,16 @@ msgid "" "Receives a gamepad button from [enum JoystickList] and returns its " "equivalent name as a string." msgstr "" -"从[enum JoystickList]ä¸æŽ¥æ”¶æ¸¸æˆæ‰‹æŸ„按钮,并将其对应的å称作为一个å—符串返回。" +"从 [enum JoystickList] ä¸æŽ¥æ”¶æ¸¸æˆæ‰‹æŸ„按钮,并将其对应的å称作为一个å—符串返" +"回。" #: doc/classes/Input.xml msgid "" "Returns a SDL2-compatible device GUID on platforms that use gamepad " "remapping. Returns [code]\"Default Gamepad\"[/code] otherwise." msgstr "" -"åœ¨ä½¿ç”¨æ¸¸æˆæ‰‹æŸ„釿˜ 射的平å°ä¸Šè¿”回一个SDL2兼容的设备GUID。å¦åˆ™è¿”回 " -"[code]\"Default Gamepad\"[/code]é»˜è®¤æ¸¸æˆæ‰‹æŸ„。" +"åœ¨ä½¿ç”¨æ¸¸æˆæ‰‹æŸ„釿˜ 射的平å°ä¸Šè¿”回一个 SDL2 兼容的设备 GUID。å¦åˆ™è¿”回 " +"[code]\"Default Gamepad\"[/code] é»˜è®¤æ¸¸æˆæ‰‹æŸ„。" #: doc/classes/Input.xml msgid "Returns the name of the joypad at the specified device index." @@ -37485,7 +37528,7 @@ msgstr "" #: doc/classes/Input.xml msgid "" "Removes all mappings from the internal database that match the given GUID." -msgstr "从内部数æ®åº“ä¸åˆ 除与给定GUID匹é…çš„æ‰€æœ‰æ˜ å°„." +msgstr "从内部数æ®åº“ä¸åˆ 除与给定 GUID 匹é…çš„æ‰€æœ‰æ˜ å°„ã€‚" #: doc/classes/Input.xml msgid "" @@ -37495,9 +37538,9 @@ msgid "" "[b]Note:[/b] This value can be immediately overwritten by the hardware " "sensor value on Android and iOS." msgstr "" -"è®¾ç½®åŠ é€Ÿåº¦ä¼ æ„Ÿå™¨çš„åŠ é€Ÿåº¦å€¼ã€‚å¯ä»¥ç”¨äºŽåœ¨æ²¡æœ‰ç¡¬ä»¶ä¼ 感器的设备上进行调试,例如在" -"PC上的编辑器ä¸ã€‚\n" -"[b]注æ„:[/b]这个值在Androidå’ŒiOS上å¯ç«‹å³è¢«ç¡¬ä»¶ä¼ 感器的值所覆盖。" +"è®¾ç½®åŠ é€Ÿåº¦ä¼ æ„Ÿå™¨çš„åŠ é€Ÿåº¦å€¼ã€‚å¯ä»¥ç”¨äºŽåœ¨æ²¡æœ‰ç¡¬ä»¶ä¼ 感器的设备上进行调试,例如在 " +"PC 上的编辑器ä¸ã€‚\n" +"[b]注æ„:[/b]这个值在 Android å’Œ iOS 上å¯ç«‹å³è¢«ç¡¬ä»¶ä¼ 感器的值所覆盖。" #: doc/classes/Input.xml msgid "" @@ -37532,7 +37575,7 @@ msgid "" "[b]Note:[/b] This method generates an [InputEventMouseMotion] to update " "cursor immediately." msgstr "" -"设置视窗ä¸ä½¿ç”¨çš„é»˜è®¤å…‰æ ‡å½¢çŠ¶ï¼Œè€Œä¸æ˜¯ [constant CURSOR_ARROW]。\n" +"设置该视区ä¸ä½¿ç”¨çš„é»˜è®¤å…‰æ ‡å½¢çŠ¶ï¼Œè€Œä¸æ˜¯ [constant CURSOR_ARROW]。\n" "[b]注æ„:[/b]å¦‚æžœè¦æ›´æ”¹ [Control] èŠ‚ç‚¹çš„é»˜è®¤å…‰æ ‡å½¢çŠ¶ï¼Œè¯·æ”¹ç”¨ [member Control." "mouse_default_cursor_shape]。\n" "[b]注æ„:[/b]这个方法会生æˆä¸€ä¸ª [InputEventMouseMotion] ä»¥ç«‹å³æ›´æ–°å…‰æ ‡ã€‚" @@ -37627,7 +37670,6 @@ msgid "Controls the mouse mode. See [enum MouseMode] for more information." msgstr "æŽ§åˆ¶é¼ æ ‡æ¨¡å¼ã€‚详情请å‚阅 [enum MouseMode]。" #: doc/classes/Input.xml -#, fuzzy msgid "" "If [code]true[/code], similar input events sent by the operating system are " "accumulated. When input accumulation is enabled, all input events generated " @@ -37639,16 +37681,18 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" "如果为 [code]true[/code],会对æ“作系统å‘é€çš„类似输入事件进行累积。当å¯ç”¨è¾“å…¥" "累积时,在一帧ä¸äº§ç”Ÿçš„æ‰€æœ‰è¾“入事件将被åˆå¹¶ï¼Œå¹¶åœ¨è¯¥å¸§å®Œæˆæ¸²æŸ“æ—¶å‘å‡ºã€‚å› æ¤ï¼Œè¿™" "é™åˆ¶äº†æ¯ç§’的输入方法调用次数,使之与渲染FPS相一致。\n" -"è¾“å…¥ç´¯åŠ åœ¨é»˜è®¤æƒ…å†µä¸‹æ˜¯å¯ç”¨çš„。它å¯ä»¥è¢«ç¦ç”¨ï¼Œå°†ä»¥å¢žåŠ CPU使用率为代价,获得ç¨å¾®" +"输入累积在默认情况下是å¯ç”¨çš„。它å¯ä»¥è¢«ç¦ç”¨ï¼Œå°†ä»¥å¢žåŠ CPU使用率为代价,获得ç¨å¾®" "æ›´ç²¾ç¡®åŠæ›´çµæ•的输入。在需è¦è‡ªç”±ç»˜åˆ¶çº¿æ¡çš„应用ä¸ï¼Œä¸€èˆ¬åº”ç”¨åœ¨ç”¨æˆ·ç»˜åˆ¶çº¿æ¡æ—¶ç¦" -"ç”¨è¾“å…¥ç´¯åŠ ï¼Œä»¥èŽ·å¾—ç´§è·Ÿå®žé™…è¾“å…¥çš„ç»“æžœã€‚" +"ç”¨è¾“å…¥ç´¯åŠ ï¼Œä»¥èŽ·å¾—ç´§è·Ÿå®žé™…è¾“å…¥çš„ç»“æžœã€‚\n" +"[b]注æ„:[/b]输入累积是默认[i]å¯ç”¨[/i]的。推è那些ä¸éœ€è¦éžå¸¸æ´»è·ƒè¾“入的游æˆä¿" +"æŒå¯ç”¨ï¼Œèƒ½å¤Ÿé™ä½Ž CPU å 用。" #: doc/classes/Input.xml msgid "Emitted when a joypad device has been connected or disconnected." @@ -38056,7 +38100,8 @@ msgstr "" msgid "" "Stores information about joystick motions. One [InputEventJoypadMotion] " "represents one axis at a time." -msgstr "å˜å‚¨å…³äºŽæ“纵æ†è¿åŠ¨çš„ä¿¡æ¯ã€‚一个[InputEventJoypadMotion]一次代表一个轴。" +msgstr "" +"å˜å‚¨å…³äºŽæ“纵æ†è¿åŠ¨çš„ä¿¡æ¯ã€‚一个 [InputEventJoypadMotion] 一次代表一个轴。" #: doc/classes/InputEventJoypadMotion.xml msgid "Axis identifier. Use one of the [enum JoystickList] axis constants." @@ -38373,26 +38418,31 @@ msgid "Input event type for mouse motion events." msgstr "é¼ æ ‡ç§»åŠ¨äº‹ä»¶çš„è¾“å…¥äº‹ä»¶ç±»åž‹ã€‚" #: doc/classes/InputEventMouseMotion.xml -#, fuzzy msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " "avoid visible gaps in lines if the user is moving the mouse quickly." msgstr "" "包å«é¼ æ ‡å’Œç¬”çš„è¿åŠ¨ä¿¡æ¯ã€‚支æŒç›¸å¯¹ã€ç»å¯¹ä½ç½®å’Œé€Ÿåº¦ã€‚è§ [method Node._input]。\n" -"[b]注æ„:[/b]默认情况下,这个事件最多åªèƒ½åœ¨æ¯ä¸€å¸§æ¸²æŸ“ä¸å‘å‡ºä¸€æ¬¡ã€‚å¦‚æžœä½ éœ€è¦æ›´" -"精确的输入报告,请将 [member Input.use_accumulated_input] 设为 [code]false[/" -"code],让事件尽å¯èƒ½é¢‘ç¹åœ°å‘å°„ã€‚å¦‚æžœä½ ä½¿ç”¨ InputEventMouseMotion æ¥ç”»çº¿ï¼Œè¯·è€ƒ" -"è™‘åŒæ—¶å®žçް [url=https://en.wikipedia.org/wiki/" -"Bresenham%27s_line_algorithm]Bresenham 的线æ¡ç®—法[/url],以é¿å…在用户快速移动" -"é¼ æ ‡æ—¶å‡ºçŽ°å¯è§çš„线æ¡ç©ºéš™ã€‚" +"[b]注æ„:[/b]è¿™ä¸ªäº‹ä»¶çš„è¡Œä¸ºå— [member Input.use_accumulated_input] å–值的影" +"å“。设为 [code]true[/code] 时(默认),从æ“作系统获å–åˆ°çš„é¼ æ ‡/笔的移动事件会" +"被åˆå¹¶ï¼Œæ¯ä¸ªæ¸²æŸ“帧最多åªä¼šå‘出一个累积事件。设为 [code]false[/code] 时,收到" +"å‡ ä¸ªäº‹ä»¶å°±ä¼šå‘å‡ºå‡ ä¸ªäº‹ä»¶ï¼Œå³æ¯ä¸ªæ¸²æŸ“帧å¯èƒ½å‘出多次,能够精确地汇报输入,但代" +"价是å 用 CPU。\n" +"[b]注æ„:[/b]å¦‚æžœä½ ä½¿ç”¨ InputEventMouseMotion æ¥ç”»çº¿ï¼Œè¯·è€ƒè™‘åŒæ—¶å®žçް" +"[url=https://zh.wikipedia.org/zh-cn/" +"%E5%B8%83%E9%9B%B7%E6%A3%AE%E6%BC%A2%E5%A7%86%E7%9B%B4%E7%B7%9A%E6%BC%94%E7%AE%97%E6%B3%95]" +"布雷森汉姆直线算法[/url],以é¿å…åœ¨ç”¨æˆ·å¿«é€Ÿç§»åŠ¨é¼ æ ‡æ—¶å‡ºçŽ°å¯è§çš„线æ¡ç©ºéš™ã€‚" #: doc/classes/InputEventMouseMotion.xml msgid "Mouse and input coordinates" @@ -38400,6 +38450,14 @@ msgstr "é¼ æ ‡å’Œè¾“å…¥åæ ‡" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" +"使用手写笔的橡皮端时,返回 [code]true[/code]。\n" +"[b]注æ„:[/b]这个属性在 Linuxã€macOS å’Œ Windows 上实现。" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "è¡¨ç¤ºç”¨æˆ·å¯¹ç¬”æ–½åŠ çš„åŽ‹åŠ›ã€‚èŒƒå›´ä»Ž [code]0.0[/code] 到 [code]1.0[/code] 。" @@ -38540,15 +38598,15 @@ msgstr "" #: doc/classes/InputMap.xml msgid "" "Adds an [InputEvent] to an action. This [InputEvent] will trigger the action." -msgstr "ç»™ä¸€ä¸ªåŠ¨ä½œæ·»åŠ ä¸€ä¸ª[InputEvent]。这个[InputEvent]将触å‘这个动作。" +msgstr "ç»™æŸä¸ªåŠ¨ä½œæ·»åŠ ä¸€ä¸ª [InputEvent]。这个 [InputEvent] 将触å‘这个动作。" #: doc/classes/InputMap.xml msgid "Removes an [InputEvent] from an action." -msgstr "从一个动作ä¸åˆ 除一个[InputEvent]。" +msgstr "从æŸä¸ªåŠ¨ä½œä¸åˆ 除一个 [InputEvent]。" #: doc/classes/InputMap.xml msgid "Removes all events from an action." -msgstr "从动作ä¸åˆ 除所有事件。" +msgstr "从æŸä¸ªåŠ¨ä½œä¸åˆ 除所有事件。" #: doc/classes/InputMap.xml msgid "Returns a deadzone value for the action." @@ -38558,7 +38616,7 @@ msgstr "返回该æ“作的æ»åŒºå€¼ã€‚" msgid "" "Returns [code]true[/code] if the action has the given [InputEvent] " "associated with it." -msgstr "如果该动作有给定的[InputEvent]与之相关,则返回 [code]true[/code]。" +msgstr "如果该动作有给定的 [InputEvent] 与之相关,则返回 [code]true[/code]。" #: doc/classes/InputMap.xml msgid "Sets a deadzone value for the action." @@ -38571,12 +38629,13 @@ msgid "" "An [InputEvent] can then be added to this action with [method " "action_add_event]." msgstr "" -"在[InputMap]ä¸Šæ·»åŠ ä¸€ä¸ªç©ºçš„åŠ¨ä½œï¼Œæœ‰ä¸€ä¸ªå¯é…置的æ»åŒº[code]deadzone[/code]。\n" -"ç„¶åŽå¯ä»¥ç”¨[method action_add_event]ç»™è¿™ä¸ªåŠ¨ä½œæ·»åŠ ä¸€ä¸ª[InputEvent]。" +"在 [InputMap] ä¸Šæ·»åŠ ä¸€ä¸ªç©ºçš„åŠ¨ä½œï¼Œæœ‰ä¸€ä¸ªå¯é…置的æ»åŒº [code]deadzone[/" +"code]。\n" +"ç„¶åŽå¯ä»¥ç”¨ [method action_add_event] ç»™è¿™ä¸ªåŠ¨ä½œæ·»åŠ ä¸€ä¸ª [InputEvent]。" #: doc/classes/InputMap.xml msgid "Removes an action from the [InputMap]." -msgstr "从[InputMap]ä¸åˆ 除一个动作。" +msgstr "从 [InputMap] ä¸åˆ 除一个动作。" #: doc/classes/InputMap.xml msgid "" @@ -38610,21 +38669,21 @@ msgstr "" #: doc/classes/InputMap.xml msgid "Returns an array of all actions in the [InputMap]." -msgstr "返回[InputMap]䏿‰€æœ‰åŠ¨ä½œçš„æ•°ç»„ã€‚" +msgstr "返回 [InputMap] 䏿‰€æœ‰åŠ¨ä½œçš„æ•°ç»„ã€‚" #: doc/classes/InputMap.xml msgid "" "Returns [code]true[/code] if the [InputMap] has a registered action with the " "given name." -msgstr "如果[InputMap]有一个给定å称的注册动作,返回 [code]true[/code]。" +msgstr "如果 [InputMap] 有一个给定å称的注册动作,返回 [code]true[/code]。" #: doc/classes/InputMap.xml msgid "" "Clears all [InputEventAction] in the [InputMap] and load it anew from " "[ProjectSettings]." msgstr "" -"清除[InputMap]ä¸çš„æ‰€æœ‰[InputEventAction],并从[ProjectSettings]项目设置ä¸é‡æ–°" -"åŠ è½½å®ƒã€‚" +"清除 [InputMap] ä¸çš„æ‰€æœ‰ [InputEventAction],并从 [ProjectSettings] 项目设置" +"ä¸é‡æ–°åŠ è½½å®ƒã€‚" #: doc/classes/InstancePlaceholder.xml msgid "Placeholder for the root [Node] of a [PackedScene]." @@ -38663,7 +38722,7 @@ msgid "" "Object.call_deferred] if calling from a thread." msgstr "" "获å–调用 [method replace_by_instance] æ—¶é»˜è®¤åŠ è½½çš„ [PackedScene] èµ„æºæ–‡ä»¶çš„è·¯" -"å¾„ã€‚ä¸æ˜¯çº¿ç¨‹å®‰å…¨çš„。如果从线程调用,请使用[method Object.call_deferred]。" +"å¾„ã€‚ä¸æ˜¯çº¿ç¨‹å®‰å…¨çš„。如果从线程调用,请使用 [method Object.call_deferred]。" #: doc/classes/InstancePlaceholder.xml msgid "" @@ -38757,7 +38816,7 @@ msgstr "" #: doc/classes/InterpolatedCamera.xml msgid "[i]Deprecated.[/i] Camera which moves toward another node." -msgstr "[i] 已弃用。[/i] å‘å¦ä¸€ä¸ªèŠ‚ç‚¹ç§»åŠ¨çš„ç›¸æœºã€‚" +msgstr "[i] 已弃用。[/i]å‘å¦ä¸€ä¸ªèŠ‚ç‚¹ç§»åŠ¨çš„ç›¸æœºã€‚" #: doc/classes/InterpolatedCamera.xml msgid "" @@ -38767,10 +38826,10 @@ msgid "" "If it is not [member enabled] or does not have a valid target set, " "InterpolatedCamera acts like a normal Camera." msgstr "" -"[i]å·²ç»å¼ƒç”¨ï¼ˆå°†åœ¨Godot 4.0 ä¸åˆ 除)。[/i]æ’值相机是一ç§[Camera],å¯ä»¥å¹³ç¨³åœ°ç§»" +"[i]已弃用(将在Godot 4.0 ä¸åˆ 除)。[/i]æ’å€¼ç›¸æœºæ˜¯ä¸€ç§ [Camera],å¯ä»¥å¹³ç¨³åœ°ç§»" "动,以匹é…ç›®æ ‡èŠ‚ç‚¹çš„ä½ç½®å’Œæ—‹è½¬ã€‚\n" -"å¦‚æžœå®ƒä¸æ˜¯[member enabled]æˆ–æ²¡æœ‰æœ‰æ•ˆçš„ç›®æ ‡é›†ï¼ŒInterpolatedCamera 的行为就åƒä¸€" -"个æ£å¸¸çš„相机。" +"å¦‚æžœå®ƒä¸æ˜¯ [member enabled] æˆ–æ²¡æœ‰æœ‰æ•ˆçš„ç›®æ ‡é›†ï¼ŒInterpolatedCamera 的行为就åƒ" +"一个æ£å¸¸çš„相机。" #: doc/classes/InterpolatedCamera.xml msgid "Sets the node to move toward and orient with." @@ -38783,10 +38842,9 @@ msgid "" msgstr "如果为 [code]true[/code]ï¼Œå¹¶ä¸”è®¾ç½®äº†ç›®æ ‡ï¼Œç›¸æœºå°†è‡ªåŠ¨ç§»åŠ¨ã€‚" #: doc/classes/InterpolatedCamera.xml -#, fuzzy msgid "" "The camera's process callback. See [enum InterpolatedCameraProcessMode]." -msgstr "相机的过程回调。请å‚阅[enum Camera2DProcessMode]。" +msgstr "该相机的处ç†å›žè°ƒã€‚è§ [enum InterpolatedCameraProcessMode]。" #: doc/classes/InterpolatedCamera.xml msgid "" @@ -38796,7 +38854,7 @@ msgstr "相机å‘å…¶ç›®æ ‡ç§»åŠ¨çš„é€Ÿåº¦ã€‚è¾ƒé«˜çš„å€¼å°†å¯¼è‡´ç›¸æœºçš„è¿åЍ #: doc/classes/InterpolatedCamera.xml msgid "The target's [NodePath]." -msgstr "ç›®æ ‡çš„[NodePath]。" +msgstr "ç›®æ ‡çš„ [NodePath]。" #: doc/classes/IntervalTweener.xml msgid "Creates an idle interval in a [SceneTreeTween] animation." @@ -38847,7 +38905,7 @@ msgstr "" #: doc/classes/IP.xml msgid "Returns all the user's current IPv4 and IPv6 addresses as an array." -msgstr "以数组形å¼è¿”回所有用户的当å‰IPv4å’ŒIPv6地å€ã€‚" +msgstr "以数组形å¼è¿”å›žæ‰€æœ‰ç”¨æˆ·çš„å½“å‰ IPv4 å’Œ IPv6 地å€ã€‚" #: doc/classes/IP.xml msgid "" @@ -38905,8 +38963,8 @@ msgid "" "method). The address type returned depends on the [enum Type] constant given " "as [code]ip_type[/code]." msgstr "" -"åœ¨è§£æžæ—¶è¿”回一个给定的主机åçš„IPv4或IPv6地å€ï¼ˆé˜»å¡žç±»åž‹æ–¹æ³•)。返回的地å€ç±»åž‹" -"å–决于作为[code]ip_type[/code]çš„[enum Type]常é‡ã€‚" +"åœ¨è§£æžæ—¶è¿”回一个给定的主机åçš„ IPv4 或 IPv6 地å€ï¼ˆé˜»å¡žç±»åž‹æ–¹æ³•)。返回的地å€" +"类型å–决于作为 [code]ip_type[/code] çš„ [enum Type] 常é‡ã€‚" #: doc/classes/IP.xml msgid "" @@ -38947,7 +39005,7 @@ msgid "" "Maximum number of concurrent DNS resolver queries allowed, [constant " "RESOLVER_INVALID_ID] is returned if exceeded." msgstr "" -"å…许的最大并å‘DNSè§£æžå™¨æŸ¥è¯¢æ•°é‡ï¼Œå¦‚果超过,则返回[constant " +"å…è®¸çš„æœ€å¤§å¹¶å‘ DNS è§£æžå™¨æŸ¥è¯¢æ•°é‡ï¼Œå¦‚果超过,则返回 [constant " "RESOLVER_INVALID_ID]。" #: doc/classes/IP.xml @@ -38978,7 +39036,6 @@ msgid "" msgstr "æä¾›å¯é€‰ä¸é¡¹ç›®ï¼ˆå’Œ/æˆ–å›¾æ ‡ï¼‰åˆ—è¡¨çš„æŽ§ä»¶ï¼Œæ—¢å¯ä»¥æ˜¯å•列,也å¯ä»¥æ˜¯å¤šåˆ—。" #: doc/classes/ItemList.xml -#, fuzzy msgid "" "This control provides a selectable list of items that may be in a single (or " "multiple columns) with option of text, icons, or both text and icon. " @@ -39008,12 +39065,19 @@ msgstr "" "本ã€å›¾æ ‡æˆ–åŒæ—¶é€‰æ‹©æ–‡æœ¬å’Œå›¾æ ‡ã€‚支æŒå·¥å…·æç¤ºï¼Œåˆ—表ä¸çš„æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æ˜¯ä¸åŒ" "的。\n" "列表ä¸å¯é€‰æ‹©çš„项目å¯ä»¥è¢«é€‰æ‹©æˆ–å–æ¶ˆé€‰æ‹©ï¼Œå¹¶ä¸”å¯ä»¥å¯ç”¨å¤šé‡é€‰æ‹©ã€‚ç”¨é¼ æ ‡å³é”®é€‰æ‹©" -"也å¯ä»¥è¢«å¯ç”¨ï¼Œä»¥å…许使用弹出å¼ä¸Šä¸‹æ–‡èœå•。项目也å¯ä»¥é€šè¿‡åŒå‡»å®ƒä»¬æˆ–按Enter回车" -"é”®æ¥ \"激活\"。\n" -"é¡¹ç›®æ–‡æœ¬åªæ”¯æŒå•行å—符串,å—符串ä¸çš„æ¢è¡Œå—符(例如[code]\\n[/code])ä¸ä¼šäº§ç”Ÿ" -"æ¢è¡Œã€‚在[constant ICON_MODE_TOP]模å¼ä¸‹ï¼Œæ–‡æœ¬è‡ªé€‚应(warp)是å¯ç”¨çš„,但默认情况" -"下会调整列的宽度以完全适åˆå…¶å†…å®¹ã€‚ä½ éœ€è¦è®¾ç½®[member fixed_column_width]大于0" -"æ¥åŒ…使–‡æœ¬ã€‚" +"也å¯ä»¥è¢«å¯ç”¨ï¼Œä»¥å…许使用弹出å¼ä¸Šä¸‹æ–‡èœå•。项目也å¯ä»¥é€šè¿‡åŒå‡»å®ƒä»¬æˆ–按回车键" +"æ¥â€œæ¿€æ´»â€ã€‚\n" +"é¡¹ç›®æ–‡æœ¬åªæ”¯æŒå•行å—符串,å—符串ä¸çš„æ¢è¡Œå—符(例如 [code]\\n[/code])ä¸ä¼šäº§ç”Ÿ" +"æ¢è¡Œã€‚文本æ¢è¡Œä¼šåœ¨ [constant ICON_MODE_TOP] 模å¼ä¸‹å¯ç”¨ï¼Œä½†é»˜è®¤æƒ…况下会调整列" +"的宽度以完全适åˆå…¶å†…å®¹ã€‚ä½ éœ€è¦å°† [member fixed_column_width] 设为大于 0 的值" +"æ‰èƒ½è®©æ–‡æœ¬æ¢è¡Œã€‚\n" +"[b]å¢žé‡æœç´¢ï¼š[/b]与 [PopupMenu] å’Œ [Tree] 类似,[ItemList] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶" +"在列表ä¸è¿›è¡Œæœç´¢ã€‚按下与æŸä¸ªæ¡ç›®åç§°é¦–å—æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„" +"第一个æ¡ç›®ã€‚在æ¤ä¹‹åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰" +"键,选ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å—æ¯å¯¹åº”的按键,直接匹é…" +"并选䏿‰€éœ€çš„æ¡ç›®ã€‚è¿™ä¸¤ä¸ªåŠ¨ä½œéƒ½ä¼šåœ¨æœ€åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—è¡¨é¡¶ç«¯ã€‚ä½ å¯ä»¥é€š" +"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] " +"修改超时时长。" #: doc/classes/ItemList.xml msgid "Adds an item to the item list with no text, only an icon." @@ -39026,9 +39090,9 @@ msgid "" "with no icon.\n" "If selectable is [code]true[/code], the list item will be selectable." msgstr "" -"å°†ä¸€ä¸ªé¡¹ç›®æ·»åŠ åˆ°é¡¹ç›®åˆ—è¡¨ä¸ï¼Œå¹¶æŒ‡å®šæ–‡æœ¬ã€‚æŒ‡å®šä¸€ä¸ªå›¾æ ‡[code]icon[/code],或者图" -"æ ‡[code]icon[/code]使用空[code]null[/code]ä½œä¸ºæ²¡æœ‰å›¾æ ‡çš„åˆ—è¡¨é¡¹ã€‚\n" -"如果å¯é€‰æ‹©å¡«[code]true[/code],列表项将是å¯é€‰æ‹©çš„。" +"å°†ä¸€ä¸ªé¡¹ç›®æ·»åŠ åˆ°é¡¹ç›®åˆ—è¡¨ä¸ï¼Œå¹¶æŒ‡å®šæ–‡æœ¬ã€‚æŒ‡å®šä¸€ä¸ªå›¾æ ‡ [code]icon[/code],或者" +"å›¾æ ‡ [code]icon[/code] 使用空 [code]null[/code] ä½œä¸ºæ²¡æœ‰å›¾æ ‡çš„åˆ—è¡¨é¡¹ã€‚\n" +"如果å¯é€‰æ‹©å¡« [code]true[/code],列表项将是å¯é€‰æ‹©çš„。" #: doc/classes/ItemList.xml msgid "Removes all items from the list." @@ -39059,13 +39123,13 @@ msgstr "返回当å‰åˆ—表ä¸çš„项目数。" msgid "" "Returns the custom background color of the item specified by [code]idx[/" "code] index." -msgstr "返回由[code]idx[/code]索引指定的项目的自定义背景颜色。" +msgstr "返回由 [code]idx[/code] 索引指定的项目的自定义背景颜色。" #: doc/classes/ItemList.xml msgid "" "Returns the custom foreground color of the item specified by [code]idx[/" "code] index." -msgstr "返回由[code]idx[/code]ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„è‡ªå®šä¹‰å‰æ™¯é¢œè‰²ã€‚" +msgstr "返回由 [code]idx[/code] ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„è‡ªå®šä¹‰å‰æ™¯é¢œè‰²ã€‚" #: doc/classes/ItemList.xml msgid "Returns the icon associated with the specified index." @@ -39073,13 +39137,13 @@ msgstr "è¿”å›žä¸ŽæŒ‡å®šç´¢å¼•ç›¸å…³çš„å›¾æ ‡ã€‚" #: doc/classes/ItemList.xml msgid "Returns a [Color] modulating item's icon at the specified index." -msgstr "返回指定索引处的[Color]颜色调制(modulating) é¡¹çš„å›¾æ ‡ã€‚" +msgstr "返回指定索引处的 [Color] é¢œè‰²è°ƒåˆ¶é¡¹çš„å›¾æ ‡ã€‚" #: doc/classes/ItemList.xml msgid "" "Returns the region of item's icon used. The whole icon will be used if the " "region has no area." -msgstr "è¿”å›žé¡¹ç›®å›¾æ ‡çš„ä½¿ç”¨åŒºåŸŸã€‚å¦‚æžœè¯¥åŒºåŸŸå¤§å°ä¸º0ï¼Œæ•´ä¸ªå›¾æ ‡å°†è¢«ä½¿ç”¨ã€‚" +msgstr "è¿”å›žé¡¹ç›®å›¾æ ‡çš„ä½¿ç”¨åŒºåŸŸã€‚å¦‚æžœè¯¥åŒºåŸŸå¤§å°ä¸º 0ï¼Œæ•´ä¸ªå›¾æ ‡å°†è¢«ä½¿ç”¨ã€‚" #: doc/classes/ItemList.xml msgid "Returns the metadata value of the specified index." @@ -39159,13 +39223,13 @@ msgstr "" msgid "" "Sets the background color of the item specified by [code]idx[/code] index to " "the specified [Color]." -msgstr "å°†[code]idx[/code]索引指定的项目的背景色设置为指定的颜色[Color]。" +msgstr "å°† [code]idx[/code] 索引指定的项目的背景色设置为指定的颜色 [Color]。" #: doc/classes/ItemList.xml msgid "" "Sets the foreground color of the item specified by [code]idx[/code] index to " "the specified [Color]." -msgstr "å°†[code]idx[/code]ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„å‰æ™¯é¢œè‰²è®¾ç½®ä¸ºæŒ‡å®šçš„颜色[Color]。" +msgstr "å°† [code]idx[/code] ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„å‰æ™¯é¢œè‰²è®¾ç½®ä¸ºæŒ‡å®šçš„颜色 [Color]。" #: doc/classes/ItemList.xml msgid "" @@ -39174,17 +39238,17 @@ msgid "" "(when double-clicking or pressing Enter)." msgstr "" "ç¦ç”¨ï¼ˆæˆ–å¯ç”¨ï¼‰æŒ‡å®šç´¢å¼•上的项目。\n" -"ç¦ç”¨çš„项目ä¸èƒ½è¢«é€‰ä¸ï¼Œä¹Ÿä¸ä¼šè§¦å‘激活信å·ï¼ˆå½“åŒå‡»æˆ–按Enter回车键)。" +"ç¦ç”¨çš„项目ä¸èƒ½è¢«é€‰ä¸ï¼Œä¹Ÿä¸ä¼šè§¦å‘激活信å·ï¼ˆå½“åŒå‡»æˆ–按回车键)。" #: doc/classes/ItemList.xml msgid "" "Sets (or replaces) the icon's [Texture] associated with the specified index." -msgstr "设置(或替æ¢ï¼‰ä¸ŽæŒ‡å®šç´¢å¼•ç›¸å…³çš„å›¾æ ‡çš„çº¹ç†[Texture]。" +msgstr "设置(或替æ¢ï¼‰ä¸ŽæŒ‡å®šç´¢å¼•ç›¸å…³çš„å›¾æ ‡çš„çº¹ç† [Texture]。" #: doc/classes/ItemList.xml msgid "" "Sets a modulating [Color] of the item associated with the specified index." -msgstr "设置与指定索引相关的项目的调制颜色[Color]。" +msgstr "设置与指定索引相关的项目的调制颜色 [Color]。" #: doc/classes/ItemList.xml msgid "" @@ -39263,19 +39327,20 @@ msgid "" "affected." msgstr "" "æ‰€æœ‰å›¾æ ‡å°†è¢«è°ƒæ•´åˆ°çš„å°ºå¯¸ã€‚\n" -"如果X或Y分é‡ä¸å¤§äºŽ0ï¼Œå›¾æ ‡çš„å¤§å°å°†ä¸ä¼šå—到影å“。" +"如果 X 或 Y 分é‡ä¸å¤§äºŽ 0ï¼Œå›¾æ ‡çš„å¤§å°å°†ä¸ä¼šå—到影å“。" #: doc/classes/ItemList.xml msgid "" "The icon position, whether above or to the left of the text. See the [enum " "IconMode] constants." -msgstr "å›¾æ ‡çš„ä½ç½®ï¼Œæ˜¯åœ¨æ–‡æœ¬çš„上方还是在文本的左边。å‚阅[enum IconMode]常é‡ã€‚" +msgstr "" +"å›¾æ ‡çš„ä½ç½®ï¼Œæ˜¯åœ¨æ–‡æœ¬çš„上方还是在文本的左边。å‚阅 [enum IconMode] 常é‡ã€‚" #: doc/classes/ItemList.xml msgid "" "The scale of icon applied after [member fixed_icon_size] and transposing " "takes effect." -msgstr "在[member fixed_icon_size]和转置生效åŽåº”ç”¨çš„å›¾æ ‡æ¯”ä¾‹ã€‚" +msgstr "在 [member fixed_icon_size] 和转置生效åŽåº”ç”¨çš„å›¾æ ‡æ¯”ä¾‹ã€‚" #: doc/classes/ItemList.xml msgid "" @@ -39320,7 +39385,7 @@ msgstr "å…许å•选或多选。å‚阅[enum SelectMode]常é‡ã€‚" msgid "" "Triggered when specified list item is activated via double-clicking or by " "pressing Enter." -msgstr "当指定的列表项目通过åŒå‡»æˆ–按Enter激活时触å‘。" +msgstr "当指定的列表项目通过åŒå‡»æˆ–按回车键激活时触å‘。" #: doc/classes/ItemList.xml msgid "" @@ -39352,7 +39417,7 @@ msgstr "在å…许多选的列表上更改多选时触å‘。" msgid "" "Triggered when a left mouse click is issued within the rect of the list but " "on empty space." -msgstr "å½“é¼ æ ‡å·¦é”®åœ¨åˆ—è¡¨çš„çŸ©å½¢(rect)范围内但在空白处å•击时,会被触å‘。" +msgstr "å½“é¼ æ ‡å·¦é”®åœ¨åˆ—è¡¨çš„çŸ©å½¢èŒƒå›´å†…ä½†åœ¨ç©ºç™½å¤„å•击时,会被触å‘。" #: doc/classes/ItemList.xml msgid "" @@ -39360,8 +39425,8 @@ msgid "" "on empty space.\n" "[member allow_rmb_select] must be enabled." msgstr "" -"当在列表的矩形(rect)范围内但在空白处å•å‡»é¼ æ ‡å³é”®æ—¶è¢«è§¦å‘。\n" -"[member allow_rmb_select]必须被å¯ç”¨ã€‚" +"当在列表的矩形范围内但在空白处å•å‡»é¼ æ ‡å³é”®æ—¶è¢«è§¦å‘。\n" +"[member allow_rmb_select] 必须被å¯ç”¨ã€‚" #: doc/classes/ItemList.xml msgid "Icon is drawn above the text." @@ -39377,7 +39442,7 @@ msgstr "ä»…å…许选择å•个项目。" #: doc/classes/ItemList.xml msgid "Allows selecting multiple items by holding Ctrl or Shift." -msgstr "å…许通过按ä½Ctrl或Shift选择多个项目。" +msgstr "å…è®¸é€šè¿‡æŒ‰ä½ Ctrl 或 Shift 选择多个项目。" #: doc/classes/ItemList.xml doc/classes/Tree.xml msgid "Default text [Color] of the item." @@ -39385,7 +39450,7 @@ msgstr "项目的默认文本颜色 [Color]。" #: doc/classes/ItemList.xml doc/classes/Tree.xml msgid "Text [Color] used when the item is selected." -msgstr "选择项目时使用的文本颜色[Color]。" +msgstr "选择项目时使用的文本颜色 [Color]。" #: doc/classes/ItemList.xml msgid "" @@ -39421,27 +39486,27 @@ msgstr "[ItemList] çš„é»˜è®¤æ ·å¼ç›’ [StyleBox],å³åœ¨æŽ§ä»¶æœªèŽ·å¾—ç„¦ç‚¹æ— #: doc/classes/ItemList.xml msgid "[StyleBox] used when the [ItemList] is being focused." -msgstr "当[ItemList]被èšç„¦æ—¶ä½¿ç”¨çš„æ ·å¼ç›’[StyleBox]。" +msgstr "当 [ItemList] 被èšç„¦æ—¶ä½¿ç”¨çš„æ ·å¼ç›’ [StyleBox]。" #: doc/classes/ItemList.xml msgid "[StyleBox] used for the cursor, when the [ItemList] is being focused." -msgstr "当[ItemList]被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’[StyleBox]。" +msgstr "当 [ItemList] 被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’ [StyleBox]。" #: doc/classes/ItemList.xml msgid "" "[StyleBox] used for the cursor, when the [ItemList] is not being focused." -msgstr "当[ItemList]没有被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’[StyleBox]。" +msgstr "当 [ItemList] 没有被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’ [StyleBox]。" #: doc/classes/ItemList.xml msgid "" "[StyleBox] for the selected items, used when the [ItemList] is not being " "focused." -msgstr "æ‰€é€‰é¡¹çš„æ ·å¼ç›’[StyleBox],当[ItemList]没有获得焦点时使用。" +msgstr "æ‰€é€‰é¡¹çš„æ ·å¼ç›’ [StyleBox],当 [ItemList] 没有获得焦点时使用。" #: doc/classes/ItemList.xml msgid "" "[StyleBox] for the selected items, used when the [ItemList] is being focused." -msgstr "æ‰€é€‰é¡¹çš„æ ·å¼ç›’[StyleBox],当[ItemList]没有获得焦点时使用。" +msgstr "æ‰€é€‰é¡¹çš„æ ·å¼ç›’ [StyleBox],当 [ItemList] 没有获得焦点时使用。" #: doc/classes/JavaScript.xml msgid "" @@ -39670,7 +39735,7 @@ msgstr "创建 Android æ’ä»¶" #: doc/classes/Joint.xml msgid "Base class for all 3D joints." -msgstr "所有3D关节的基类。" +msgstr "所有 3D 关节的基类。" #: doc/classes/Joint.xml msgid "" @@ -39694,11 +39759,11 @@ msgstr "如果为 [code]true[/code]ï¼Œåˆ™èŠ‚ç‚¹çš„ä¸¤ä¸ªä¸»ä½“æ— æ³•ç›¸äº’ç¢°æ’ž #: doc/classes/Joint.xml msgid "The node attached to the first side (A) of the joint." -msgstr "连接到关节第一侧(A)的节点。" +msgstr "连接到关节第一侧(A)的节点。" #: doc/classes/Joint.xml msgid "The node attached to the second side (B) of the joint." -msgstr "连接到关节第二侧(B)的节点。" +msgstr "连接到关节第二侧(B)的节点。" #: doc/classes/Joint.xml msgid "" @@ -39957,9 +40022,9 @@ msgid "" "- [code]params[/code]: An array or dictionary of parameters being passed to " "the method." msgstr "" -"返回JSON-RPC通知形å¼çš„å—典。通知是一次性的信æ¯ï¼Œä¸éœ€è¦æœ‰å“应。\n" -"- [code]method[/code]:被调用的方法的å称。\n" -"- [code]params[/code]:ä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或å—典。" +"返回 JSON-RPC 通知形å¼çš„å—典。通知是一次性的信æ¯ï¼Œä¸éœ€è¦æœ‰å“应。\n" +"- [code]method[/code]:被调用的方法的å称。\n" +"- [code]params[/code]ï¼šä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或å—典。" #: doc/classes/JSONRPC.xml msgid "" @@ -39972,11 +40037,11 @@ msgid "" "- [code]id[/code]: Uniquely identifies this request. The server is expected " "to send a response with the same ID." msgstr "" -"以JSON-RPC请求的形å¼è¿”回å—典。请求被å‘é€åˆ°æœåŠ¡å™¨ï¼Œå¹¶æœŸæœ›å¾—åˆ°å“应。ID å—æ®µç”¨äºŽ" -"æœåŠ¡å™¨æŒ‡å®šå®ƒæ£åœ¨å“应的确切请求。\n" -"- [code]method[/code]:被调用的方法的å称。\n" -"- [code]params[/code]:ä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或å—典。\n" -"- [code]id[/code]:å”¯ä¸€æ ‡è¯†æ¤è¯·æ±‚。æœåŠ¡å™¨åº”å‘é€å…·æœ‰ç›¸åŒ ID çš„å“应。" +"以 JSON-RPC 请求的形å¼è¿”回å—典。请求被å‘é€åˆ°æœåŠ¡å™¨ï¼Œå¹¶æœŸæœ›å¾—åˆ°å“应。ID å—æ®µç”¨" +"于æœåŠ¡å™¨æŒ‡å®šå®ƒæ£åœ¨å“应的确切请求。\n" +"- [code]method[/code]:被调用的方法的å称。\n" +"- [code]params[/code]ï¼šä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或å—典。\n" +"- [code]id[/code]ï¼šå”¯ä¸€æ ‡è¯†æ¤è¯·æ±‚。æœåŠ¡å™¨åº”å‘é€å…·æœ‰ç›¸åŒ ID çš„å“应。" #: doc/classes/JSONRPC.xml msgid "" @@ -40016,9 +40081,8 @@ msgid "" "[code]action[/code]: The action to be run, as a Dictionary in the form of a " "JSON-RPC request or notification." msgstr "" -"给定采用 JSON-RPC 请求形å¼çš„å—典:解压请求并è¿è¡Œå®ƒã€‚通过查看å为 \"method\" " -"çš„å—æ®µå¹¶åœ¨ JSONRPC å¯¹è±¡ä¸æŸ¥æ‰¾ç‰æ•ˆå‘½å的函数æ¥è§£æžæ–¹æ³•。如果找到,则调用该方" -"法。\n" +"给定采用 JSON-RPC 请求形å¼çš„å—典:解压请求并è¿è¡Œå®ƒã€‚通过查看å为“methodâ€çš„å—" +"段并在 JSONRPC å¯¹è±¡ä¸æŸ¥æ‰¾ç‰æ•ˆå‘½å的函数æ¥è§£æžæ–¹æ³•。如果找到,则调用该方法。\n" "è¦æ·»åŠ æ–°çš„å—æ”¯æŒæ–¹æ³•,请扩展 JSONRPC ç±»å¹¶åœ¨ä½ çš„å类上调用 [method " "process_action]。\n" "[code]action[/code]:è¦è¿è¡Œçš„动作,作为 JSON-RPC 请求或通知形å¼çš„å—典。" @@ -40217,8 +40281,8 @@ msgid "" "platform's motion, it will always be first in the slide collisions." msgstr "" "沿ç€å‘é‡ç§»åŠ¨ç‰©ä½“ã€‚å¦‚æžœè¿™ä¸ªç‰©ä½“ä¸Žå¦ä¸€ä¸ªç‰©ä½“相撞,它将沿ç€å¦ä¸€ä¸ªç‰©ä½“滑动,而ä¸" -"是立å³åœæ¢ã€‚如果å¦ä¸€ä¸ªç‰©ä½“是[KinematicBody]或[RigidBody],它也会被å¦ä¸€ä¸ªç‰©ä½“" -"çš„è¿åŠ¨æ‰€å½±å“ã€‚ä½ å¯ä»¥ç”¨å®ƒæ¥åˆ¶ä½œç§»åŠ¨å’Œæ—‹è½¬çš„å¹³å°ï¼Œæˆ–者让节点推动其他节点。\n" +"是立å³åœæ¢ã€‚如果å¦ä¸€ä¸ªç‰©ä½“是 [KinematicBody] 或 [RigidBody],它也会被å¦ä¸€ä¸ªç‰©" +"体的è¿åŠ¨æ‰€å½±å“ã€‚ä½ å¯ä»¥ç”¨å®ƒæ¥åˆ¶ä½œç§»åŠ¨å’Œæ—‹è½¬çš„å¹³å°ï¼Œæˆ–者让节点推动其他节点。\n" "这个方法应该在 [method Node._physics_process] ä¸ä½¿ç”¨ï¼Œæˆ–者在被 [method Node." "_physics_process] 调用的方法ä¸ä½¿ç”¨ï¼Œå› ä¸ºå®ƒåœ¨è®¡ç®—æ—¶ï¼Œè‡ªåŠ¨ä½¿ç”¨ç‰©ç†æ¥éª¤çš„ " "[code]delta[/code] 值。å¦åˆ™ï¼Œæ¨¡æ‹Ÿå°†ä»¥ä¸æ£ç¡®çš„速度è¿è¡Œã€‚\n" @@ -40411,7 +40475,7 @@ msgid "" "value is always positive and only valid after calling [method " "move_and_slide] and when [method is_on_floor] returns [code]true[/code]." msgstr "" -"æ ¹æ®[code]up_direction[/code]返回最åŽä¸€ä¸ªç¢°æ’žç‚¹çš„地æ¿ç¢°æ’žè§’度,默认为" +"æ ¹æ® [code]up_direction[/code] 返回最åŽä¸€ä¸ªç¢°æ’žç‚¹çš„地æ¿ç¢°æ’žè§’度,默认为 " "[code]Vector2.UP[/code]。æ¤å€¼å§‹ç»ˆä¸ºæ£å€¼ï¼Œå¹¶ä¸”仅在调用 [method " "move_and_slide] åŽä¸”当 [method is_on_floor] 返回 [code]true[/code] 时有效。" @@ -40421,8 +40485,8 @@ msgid "" "latest collision that occurred during the last call to [method " "move_and_slide]." msgstr "" -"返回[KinematicCollision2D],它包å«åœ¨æœ€åŽä¸€æ¬¡è°ƒç”¨[method move_and_slide]æ—¶å‘生" -"的最新碰撞信æ¯ã€‚" +"返回 [KinematicCollision2D],它包å«åœ¨æœ€åŽä¸€æ¬¡è°ƒç”¨ [method move_and_slide] æ—¶" +"å‘生的最新碰撞信æ¯ã€‚" #: doc/classes/KinematicBody2D.xml msgid "" @@ -40570,9 +40634,9 @@ msgid "" "colliding object, the remaining motion, and the collision position. This " "information can be used to calculate a collision response." msgstr "" -"包å«[KinematicBody]碰撞的碰撞数æ®ã€‚当[KinematicBody]使用[method " -"KinematicBody.move_and_collide]移动时,如果它检测到与å¦ä¸€ä¸ªç‰©ä½“的碰撞就会åœ" -"æ¢ã€‚如果检测到碰撞,将返回一个KinematicCollision对象。\n" +"åŒ…å« [KinematicBody] 碰撞的碰撞数æ®ã€‚当 [KinematicBody] 使用 [method " +"KinematicBody.move_and_collide] 移动时,如果它检测到与å¦ä¸€ä¸ªç‰©ä½“的碰撞就会åœ" +"æ¢ã€‚如果检测到碰撞,将返回一个 KinematicCollision 对象。\n" "这个对象包å«å…³äºŽç¢°æ’žçš„ä¿¡æ¯ï¼ŒåŒ…括碰撞的物体ã€å‰©ä½™çš„è¿åŠ¨å’Œç¢°æ’žçš„ä½ç½®ã€‚这些信æ¯" "å¯ä»¥ç”¨æ¥è®¡ç®—碰撞å“应。" @@ -40581,8 +40645,8 @@ msgid "" "The collision angle according to [code]up_direction[/code], which is " "[code]Vector3.UP[/code] by default. This value is always positive." msgstr "" -"æ ¹æ®[code]up_direction[/code]的碰撞角度,默认为[code]Vector3.UP[/code]。这个" -"值总是为æ£ã€‚" +"æ ¹æ® [code]up_direction[/code] 的碰撞角度,默认为 [code]Vector3.UP[/code]。这" +"个值总是为æ£ã€‚" #: doc/classes/KinematicCollision.xml doc/classes/KinematicCollision2D.xml msgid "The colliding body." @@ -40819,19 +40883,19 @@ msgstr "通过展开行æ¥å¯¹é½æ•´ä¸ªæ–‡æœ¬ã€‚" #: doc/classes/Label.xml msgid "Default text [Color] of the [Label]." -msgstr "[Label]æ ‡ç¾çš„默认文本颜色[Color]。" +msgstr "[Label] æ ‡ç¾çš„默认文本颜色 [Color]。" #: doc/classes/Label.xml msgid "[Color] of the text's shadow effect." -msgstr "文本阴影效果的颜色[Color]。" +msgstr "文本阴影效果的颜色 [Color]。" #: doc/classes/Label.xml msgid "The tint of [Font]'s outline. See [member DynamicFont.outline_color]." -msgstr "[Font]轮廓的色调。å‚阅[member DynamicFont.outline_color]。" +msgstr "[Font] è½®å»“çš„è‰²è°ƒã€‚è§ [member DynamicFont.outline_color]。" #: doc/classes/Label.xml msgid "Vertical space between lines in multiline [Label]." -msgstr "多行[Label]ä¸å„行之间的垂直空间。" +msgstr "多行 [Label] ä¸å„行之间的垂直空间。" #: doc/classes/Label.xml msgid "" @@ -40956,7 +41020,7 @@ msgstr "对 [Font] 轮廓的染色。" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -40964,8 +41028,8 @@ msgid "" "sorted from back to front (subject to priority)." msgstr "" "设置文本轮廓的渲染优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n" -"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认" -"值)时适用。\n" +"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant " +"ALPHA_CUT_DISABLED](默认值)时适用。\n" "[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº" "æ–¹å¼ã€‚è¿™æ˜¯å› ä¸ºä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。" @@ -40977,7 +41041,7 @@ msgstr "æ ‡ç¾ä¸Šä¸€ä¸ªåƒç´ 宽度的大å°ï¼Œä»¥ 3D 缩放。" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -40985,8 +41049,8 @@ msgid "" "sorted from back to front (subject to priority)." msgstr "" "设置文本的渲染优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n" -"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认" -"值)时适用。\n" +"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant " +"ALPHA_CUT_DISABLED](默认值)时适用。\n" "[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº" "æ–¹å¼ã€‚è¿™æ˜¯å› ä¸ºä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。" @@ -41013,9 +41077,9 @@ msgstr "如果打开,环境ä¸çš„ç¯å…‰ä¼šå½±å“è¯¥æ ‡ç¾ã€‚" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." -msgstr "如果打开,从åŽé¢ä¹Ÿå¯ä»¥çœ‹åˆ°æ–‡æœ¬ï¼Œå¦‚æžœä¸æ‰“开,从åŽé¢çœ‹å®ƒæ˜¯ä¸å¯è§çš„。" +msgstr "如果打开,从åŽé¢ä¹Ÿå¯ä»¥çœ‹åˆ°æ–‡æœ¬ã€‚å¦‚æžœä¸æ‰“开,从åŽé¢çœ‹è¯¥æ–‡æœ¬æ˜¯ä¸å¯è§çš„。" #: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml #: doc/classes/SpriteBase3D.xml @@ -41169,7 +41233,7 @@ msgstr "如果为 [code]true[/code],ç¯å…‰åªåœ¨ç¼–辑器ä¸å‡ºçŽ°ï¼Œåœ¨è¿è¡Œ #: doc/classes/Light.xml msgid "The light's bake mode. See [enum BakeMode]." -msgstr "ç¯å…‰çš„烘焙模å¼ã€‚å‚阅[enum BakeMode]。" +msgstr "ç¯å…‰çš„烘焙模å¼ã€‚è§ [enum BakeMode]。" #: doc/classes/Light.xml msgid "" @@ -43605,11 +43669,14 @@ msgid "" "[method Mesh.surface_get_material] to get materials associated with the " "[Mesh] resource." msgstr "" +"返回该 [Mesh] 资æºä¸ŠæŸä¸ªè¡¨é¢çš„ [Material] 覆盖项。\n" +"[b]注æ„:[/b]这个函数åªä¼šè¿”回与这个 [MeshInstance] 相关è”çš„[i]覆盖[/i]æè´¨ã€‚" +"è¦èŽ·å–与该 [Mesh] 相关è”çš„æè´¨ï¼Œè¯·è€ƒè™‘使用 [method get_active_material] 或 " +"[method Mesh.surface_get_material]。" #: doc/classes/MeshInstance.xml -#, fuzzy msgid "Returns the number of surface override materials." -msgstr "è¿”å›žè¡¨é¢æè´¨çš„æ•°é‡ã€‚" +msgstr "è¿”å›žè¡¨é¢æè´¨è¦†ç›–é¡¹çš„æ•°é‡ã€‚" #: doc/classes/MeshInstance.xml msgid "" @@ -43664,6 +43731,8 @@ msgid "" "resource. This material is associated with this [MeshInstance] rather than " "with the [Mesh] resource." msgstr "" +"设置该 [Mesh] 资æºçš„æŒ‡å®šè¡¨é¢çš„ [Material] 覆盖项。这个æè´¨ä¼šä¸Žè¿™ä¸ª " +"[MeshInstance] å…³è”ï¼Œè€Œä¸æ˜¯ä¸Ž [Mesh] 资æºå…³è”。" #: doc/classes/MeshInstance.xml msgid "The [Mesh] resource for the instance." @@ -44658,7 +44727,6 @@ msgid "Mesh-based navigation and pathfinding node." msgstr "åŸºäºŽç½‘æ ¼çš„å¯¼èˆªå’Œå¯»è·¯èŠ‚ç‚¹ã€‚" #: doc/classes/Navigation.xml -#, fuzzy msgid "" "[i]Deprecated.[/i] [Navigation] node and [method get_simple_path] are " "deprecated and will be removed in a future version. Use [method " @@ -44669,6 +44737,8 @@ msgid "" "class also assists with aligning navigation agents with the meshes they are " "navigating on." msgstr "" +"[i]已弃用。[/i][Navigation] 节点和 [method get_simple_path] 已弃用,会在将æ¥" +"的版本ä¸ç§»é™¤ã€‚请用 [method NavigationServer.map_get_path] 替代。\n" "在 [NavigationMesh] 的集åˆä¸æä¾›å¯¼èˆªå’Œå¯»è·¯åŠŸèƒ½ã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œè¿™äº›å°†è‡ªåŠ¨ä»Žå " "[NavigationMeshInstance] èŠ‚ç‚¹ä¸æ”¶é›†ã€‚除了基本的寻路之外,这个类还能帮助导航代" "ç†ä¸Žå…¶æ‰€å¯¼èˆªçš„ç½‘æ ¼å¯¹é½ã€‚" @@ -44716,7 +44786,6 @@ msgid "Returns the [RID] of the navigation map on the [NavigationServer]." msgstr "返回这个导航地图在 [NavigationServer] 上的 [RID]。" #: doc/classes/Navigation.xml -#, fuzzy msgid "" "[i]Deprecated.[/i] [Navigation] node and [method get_simple_path] are " "deprecated and will be removed in a future version. Use [method " @@ -44726,6 +44795,8 @@ msgid "" "agent properties associated with each [NavigationMesh] (radius, height, " "etc.) are considered in the path calculation, otherwise they are ignored." msgstr "" +"[i]已弃用。[/i][Navigation] 节点和 [method get_simple_path] 已弃用,会在将æ¥" +"的版本ä¸ç§»é™¤ã€‚请用 [method NavigationServer.map_get_path] 替代。\n" "è¿”å›žä¸¤ä¸ªç»™å®šç‚¹ä¹‹é—´çš„è·¯å¾„ã€‚ç‚¹éƒ½æ˜¯åœ¨å±€éƒ¨åæ ‡ç©ºé—´ä¸çš„。如果 [code]optimize[/" "code] 为 [code]true[/code](默认),则计算路径时会考虑æ¯ä¸ª [NavigationMesh] " "所关è”的代ç†çš„属性(åŠå¾„ã€é«˜åº¦ç‰ï¼‰ï¼Œå¦åˆ™ä¼šè¢«å¿½ç•¥ã€‚" @@ -44770,7 +44841,6 @@ msgid "2D navigation and pathfinding node." msgstr "2D 导航和寻路节点。" #: doc/classes/Navigation2D.xml -#, fuzzy msgid "" "[i]Deprecated.[/i] [Navigation2D] node and [method get_simple_path] are " "deprecated and will be removed in a future version. Use [method " @@ -44779,6 +44849,8 @@ msgid "" "as a collection of [NavigationPolygon] resources. By default, these are " "automatically collected from child [NavigationPolygonInstance] nodes." msgstr "" +"[i]已弃用。[/i][Navigation2D] 节点和 [method get_simple_path] 已弃用,会在将" +"æ¥çš„版本ä¸ç§»é™¤ã€‚请用 [method Navigation2DServer.map_get_path] 替代。\n" "Navigation2D 在 2D 区域内æä¾›å¯¼èˆªå’Œå¯»è·¯ï¼Œè¯¥åŒºåŸŸä»¥ [NavigationPolygon] 资æºåˆ" "é›†çš„å½¢å¼æŒ‡å®šã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œè¿™äº›èµ„æºæ˜¯è‡ªåŠ¨ä»Žå项 [NavigationPolygonInstance] 节" "ç‚¹ä¸æ”¶é›†çš„。" @@ -44798,7 +44870,6 @@ msgstr "" "[NavigationPolygonInstance]。" #: doc/classes/Navigation2D.xml -#, fuzzy msgid "" "[i]Deprecated.[/i] [Navigation2D] node and [method get_simple_path] are " "deprecated and will be removed in a future version. Use [method " @@ -44807,6 +44878,8 @@ msgid "" "space. If [code]optimize[/code] is [code]true[/code] (the default), the path " "is smoothed by merging path segments where possible." msgstr "" +"[i]已弃用。[/i][Navigation2D] 节点和 [method get_simple_path] 已弃用,会在将" +"æ¥çš„版本ä¸ç§»é™¤ã€‚请用 [method Navigation2DServer.map_get_path] 替代。\n" "è¿”å›žä¸¤ä¸ªç»™å®šç‚¹ä¹‹é—´çš„è·¯å¾„ã€‚ç‚¹æ˜¯åœ¨å±€éƒ¨åæ ‡ç©ºé—´ä¸çš„。如果 [code]optimize[/code] " "为 [code]true[/code](默认值),路径将尽å¯èƒ½åœ°åˆå¹¶è·¯å¾„段,从而平滑。" @@ -44973,6 +45046,8 @@ msgid "" "returns both 2D and 3D created navigation maps as there is technically no " "distinction between them." msgstr "" +"返回该 NavigationServer 上所有已创建的导航地图的 [RID]ã€‚ä¼šåŒæ—¶è¿”回已创建的 " +"2D å’Œ 3D å¯¼èˆªåœ°å›¾ï¼Œå› ä¸ºç†è®ºä¸Šå®ƒä»¬ä¹‹é—´æ˜¯æ²¡æœ‰åŒºåˆ«çš„。" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Create a new map." @@ -45006,6 +45081,21 @@ msgid "" "but it can also introduce bugs if used inappropriately without much " "foresight." msgstr "" +"这个函数会立å³å¼ºåˆ¶è¿›è¡ŒæŒ‡å®šå¯¼èˆªåœ°å›¾çš„åŒæ¥ï¼Œå‚æ•° [code]map[/code] 为 [RID] ç±»" +"型。默认情况下,导航地图仅会在æ¯ä¸ªç‰©ç†å¸§çš„æœ«å°¾è¿›è¡ŒåŒæ¥ã€‚这个函数å¯ç”¨äºŽç«‹å³" +"ï¼ˆé‡æ–°ï¼‰è®¡ç®—è¯¥å¯¼èˆªåœ°å›¾çš„æ‰€æœ‰å¯¼èˆªç½‘æ ¼å’Œåœ°åŒºè¿žæŽ¥ã€‚è¿™æ ·å°±èƒ½å¤Ÿåœ¨ä¿®æ”¹åœ°å›¾åŽï¼Œåœ¨åŒ" +"一帧ä¸ç«‹å³å¯¹å¯¼èˆªè·¯å¾„è¿›è¡ŒæŸ¥è¯¢ï¼ˆéœ€è¦æ—¶å¯ä»¥è¿›è¡Œå¤šæ¬¡åŒæ¥ï¼‰ã€‚\n" +"由于技术上的é™åˆ¶ï¼Œå½“å‰çš„ NavigationServer 命令队列会被清空。这æ„å‘³ç€æ‰€æœ‰å·²åœ¨" +"当å‰ç‰©ç†å¸§ä¸å…¥é˜Ÿçš„命令都会被执行,å³ä¾¿è¿™äº›å‘½ä»¤ä¸ŽæŒ‡å®šçš„åœ°å›¾æ— å…³ï¼Œé’ˆå¯¹çš„æ˜¯å…¶ä»–" +"地图ã€åœ°åŒºã€ä»£ç†ã€‚æ¶ˆè€—è¾ƒå¤§çš„å¯¼èˆªç½‘æ ¼ä»¥åŠåœ°åŒºè¿žæŽ¥çš„计算åªä¼šå¯¹æŒ‡å®šçš„地图进行。" +"其他地图会在该物ç†å¸§çš„æœ«å°¾è¿›è¡Œå¸¸è§„çš„åŒæ¥ã€‚如果指定的地图在进行强制更新åŽåˆæ”¶" +"到了修改,那么它也会在其他地图更新时å—到更新。\n" +"这个函数ä¸ä¼šè§¦åŠé¿éšœå¤„ç†ä»¥åŠ [code]safe_velocity[/code] ä¿¡å·çš„分å‘,这些还是" +"会在该物ç†å¸§çš„æœ«å°¾é’ˆå¯¹æ‰€æœ‰åœ°å›¾çš„代ç†è¿›è¡Œå¤„ç†ã€‚\n" +"[b]注æ„:[/b]èƒ½åŠ›è¶Šå¤§ï¼Œè´£ä»»è¶Šå¤§ã€‚åªæœ‰çœŸæ£æ˜Žç™½è‡ªå·±åœ¨å¹²ä»€ä¹ˆçš„用户æ‰åº”è¯¥åœ¨çœŸæ£æœ‰" +"éœ€è¦æ—¶ä½¿ç”¨è¿™ä¸ªå‡½æ•°ã€‚å¼ºåˆ¶è¿›è¡Œå¯¼èˆªåœ°å›¾çš„ç«‹å³æ›´æ–°éœ€è¦å¯¹ NavigationServer åŠ é”å¹¶" +"清空整个 NavigationServer çš„å‘½ä»¤é˜Ÿåˆ—ã€‚è¿™æ ·åšä¸ä»…ä¼šå¤§å¹…å½±å“æ¸¸æˆçš„æ€§èƒ½ï¼Œå¦‚果使" +"用ä¸å½“ã€ç¼ºä¹è¿œè§ï¼Œè¿˜å¯èƒ½å¼•å…¥ bug。" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "" @@ -45139,6 +45229,15 @@ msgid "" "(which should be avoided in general) the result might not be what is " "expected." msgstr "" +"å¦‚æžœç»™å‡ºçš„ä¸–ç•Œç©ºé—´åæ ‡ç‚¹ [code]point[/code] ç›®å‰ç”±ç»™å‡ºçš„导航地区 " +"[code]region[/code] 拥有,则返回 [code]true[/code]ã€‚è¿™é‡Œçš„â€œæ‹¥æœ‰â€æŒ‡çš„æ˜¯è¯¥åœ°åŒº" +"çš„å¯¼èˆªç½‘æ ¼å¤šè¾¹å½¢é¢ä¸åŒ…å«è¿™ä¸ªå¯èƒ½çš„ä½ç½®ï¼Œå¹¶ä¸”与给出的地区的导航地区上所有其他" +"å¯¼èˆªåœ°åŒºçš„å¯¼èˆªç½‘æ ¼ç›¸æ¯”ï¼Œå®ƒä¸Žè¿™ä¸ªç‚¹çš„è·ç¦»æ˜¯æœ€è¿‘的。\n" +"å¦‚æžœæœ‰å¤šä¸ªå¯¼èˆªç½‘æ ¼åŒ…å«è¿™ä¸ªç‚¹å¹¶ä¸”è·ç¦»ç›¸ç‰ï¼Œå“ªä¸ªå¯¼èˆªåœ°åŒºçš„多边形先被处ç†ï¼Œé‚£ä¸ª" +"å¯¼èˆªåœ°åŒºå°±èŽ·å–æ‰€æœ‰æƒã€‚多边形的处ç†é¡ºåºä¸Žå¯¼èˆªåœ°åŒºåœ¨ NavigationServer 上的注册" +"顺åºä¸€è‡´ã€‚\n" +"[b]注æ„:[/b]如果ä¸åŒå¯¼èˆªåœ°åŒºçš„å¯¼èˆªç½‘æ ¼å˜åœ¨é‡å (通常应当é¿å…),å¯èƒ½å¾—到预料" +"之外的结果。" #: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml msgid "Sets the [code]enter_cost[/code] for this [code]region[/code]." @@ -45405,6 +45504,10 @@ msgid "" "it will constantly overshoot or undershoot the distance to the next point on " "each physics frame update." msgstr "" +"è·ç¦»é˜ˆå€¼ï¼Œç”¨äºŽç¡®å®šæ˜¯å¦å·²åˆ°è¾¾æŸä¸ªè·¯å¾„点。使用这个值,代ç†å°±ä¸å¿…精确地到达æŸä¸ª" +"路径点,到达æŸä¸ªåŒºåŸŸå†…å³å¯ã€‚如果这个值设得太大,该 NavigationAgent 将跳过路径" +"上的点,å¯èƒ½å¯¼è‡´å…¶ç¦»å¼€è¯¥å¯¼èˆªç½‘æ ¼ã€‚å¦‚æžœè¿™ä¸ªå€¼è®¾å¾—å¤ªå°ï¼Œè¯¥ NavigationAgent 将陷" +"入釿–°å¯»è·¯çš„æ»å¾ªçŽ¯ï¼Œå› ä¸ºå®ƒåœ¨æ¯æ¬¡ç‰©ç†å¸§æ›´æ–°åŽéƒ½ä¼šè¶…过或者到ä¸äº†ä¸‹ä¸€ä¸ªç‚¹ã€‚" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45424,6 +45527,11 @@ msgid "" "bake [NavigationMesh] resources with a different [member NavigationMesh." "agent_radius] property and use different navigation maps for each actor size." msgstr "" +"该é¿éšœä»£ç†çš„åŠå¾„。这是该é¿éšœä»£ç†çš„“身体â€ï¼Œä¸æ˜¯é¿éšœæœºåˆ¶çš„èµ·å§‹åŠå¾„(由 [member " +"neighbor_dist] 控制)。\n" +"ä¸ä¼šå½±å“æ£å¸¸çš„寻路。è¦ä¿®æ”¹è§’色的寻路åŠå¾„,请在烘焙 [NavigationMesh] èµ„æºæ—¶ä½¿" +"用ä¸åŒçš„ [member NavigationMesh.agent_radius] 属性,针对ä¸åŒçš„角色大å°ä½¿ç”¨ä¸" +"åŒçš„导航地图。" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45434,6 +45542,9 @@ msgid "" "overshoot or undershoot the distance to the final target point on each " "physics frame update." msgstr "" +"è·ç¦»é˜ˆå€¼ï¼Œç”¨äºŽç¡®å®šæ˜¯å¦å·²åˆ°è¾¾æœ€ç»ˆçš„ç›®æ ‡ç‚¹ã€‚ä½¿ç”¨è¿™ä¸ªå€¼ï¼Œä»£ç†å°±ä¸å¿…精确地到达最" +"ç»ˆçš„ç›®æ ‡ï¼Œåˆ°è¾¾è¯¥åŒºåŸŸå†…å³å¯ã€‚如果这个值设得太å°ï¼Œè¯¥ NavigationAgent 将陷入釿–°" +"寻路的æ»å¾ªçŽ¯ï¼Œå› ä¸ºå®ƒåœ¨æ¯æ¬¡ç‰©ç†å¸§æ›´æ–°åŽéƒ½ä¼šè¶…过或者到ä¸äº†æœ€ç»ˆçš„ç›®æ ‡ç‚¹ã€‚" #: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml msgid "" @@ -45555,6 +45666,9 @@ msgid "" "[member neighbor_dist]).\n" "Does not affect normal pathfinding." msgstr "" +"该é¿éšœä»£ç†çš„åŠå¾„。这是该é¿éšœä»£ç†çš„“身体â€ï¼Œä¸æ˜¯é¿éšœæœºåˆ¶çš„èµ·å§‹åŠå¾„(由 [member " +"neighbor_dist] 控制)。\n" +"ä¸ä¼šå½±å“æ£å¸¸çš„寻路。" #: doc/classes/NavigationMesh.xml msgid "A mesh to approximate the walkable areas and obstacles." @@ -45694,11 +45808,11 @@ msgstr "" msgid "" "If the baking [AABB] has a volume the navigation mesh baking will be " "restricted to its enclosing area." -msgstr "" +msgstr "如果烘焙 [AABB] å˜åœ¨ä½“ç§¯ï¼Œå¯¹è¯¥å¯¼èˆªç½‘æ ¼çš„çƒ˜ç„™ä¼šè¢«é™åˆ¶åœ¨å…¶å†…部区域ä¸ã€‚" #: doc/classes/NavigationMesh.xml msgid "The position offset applied to the [member filter_baking_aabb] [AABB]." -msgstr "" +msgstr "应用于 [member filter_baking_aabb] [AABB] çš„ä½ç½®åç§»é‡ã€‚" #: doc/classes/NavigationMesh.xml msgid "If [code]true[/code], marks spans that are ledges as non-walkable." @@ -45871,7 +45985,6 @@ msgid "Helper class for creating and clearing navigation meshes." msgstr "å¯¹å¯¼èˆªç½‘æ ¼è¿›è¡Œåˆ›å»ºå’Œæ¸…ç†çš„辅助类。" #: doc/classes/NavigationMeshGenerator.xml -#, fuzzy msgid "" "This class is responsible for creating and clearing 3D navigation meshes " "used as [NavigationMesh] resources inside [NavigationMeshInstance]. The " @@ -45931,7 +46044,11 @@ msgstr "" "è±¡ï¼Œé€šè¿‡åœ¨ç½‘æ ¼çš„åŒ…å›´åŒºåŸŸå‘¨è¾¹åˆ›å»ºä½“ç´ ä¸–ç•Œï¼Œæ¥æ£€æŸ¥åŽŸå§‹å‡ ä½•ä½“ä¸é€‚åˆ " "[NavigationMesh] 代ç†è¡Œèµ°çš„地形。\n" "ç„¶åŽå°±ä¼šè¿”å›žæœ€ç»ˆçš„å¯¼èˆªç½‘æ ¼ï¼Œä¿å˜åœ¨ [NavigationMesh] ä¸ï¼Œå³å¯äº¤ä»˜ " -"[NavigationMeshInstance] 使用。" +"[NavigationMeshInstance] 使用。\n" +"[b]注æ„:[/b]ä½¿ç”¨ç½‘æ ¼æ¥å®šä¹‰å¯è¡Œèµ°åŒºåŸŸå¹¶é®æŒ¡å¯¼èˆªçƒ˜ç„™å¹¶ä¸æ€»èƒ½æˆåŠŸã€‚çƒ˜ç„™å¯¼èˆªå¤„ç†" +"ç½‘æ ¼åŽŸå§‹å‡ ä½•ä½“æ—¶ï¼Œå¹¶æ²¡æœ‰å‡ ä½•ä½“â€œä½äºŽå†…部â€çš„æ¦‚念,这是有æ„è€Œä¸ºä¹‹çš„ã€‚æ ¹æ®å½“å‰çƒ˜" +"ç„™å‚æ•°çš„ä¸åŒï¼Œåªè¦é®æŒ¡ç½‘æ ¼è¶³å¤Ÿå¤§ï¼Œå¤§åˆ°èƒ½å¤Ÿå°†å¯¼èˆªç½‘æ ¼åŒºåŸŸåŒ…å«åœ¨å…¶å†…部,烘焙时" +"就会生æˆä¸€ä¸ªå¯¼èˆªç½‘æ ¼åŒºåŸŸï¼Œä½äºŽé®æŒ¡çš„åŽŸå§‹å‡ ä½•ä½“ç½‘æ ¼å†…éƒ¨ã€‚" #: doc/classes/NavigationMeshGenerator.xml msgid "" @@ -45971,18 +46088,18 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." msgstr "" -"[NavigationMesh] 的实例。[Navigation] èŠ‚ç‚¹æ ¹æ®å®ƒçš„ [NavigationMesh] èµ„æºæ¥ç¡®" -"定哪些å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n" +"[NavigationMesh] 的实例。[Navigation] èŠ‚ç‚¹æ ¹æ®å®ƒçš„ [NavigationMesh] " +"èµ„æºæ¥ç¡®å®šå“ªäº›å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n" "默认情况下,这个节点会在默认的 [World] 导航地图ä¸è¿›è¡Œæ³¨å†Œã€‚如果这个节点是 " "[Navigation] 节点的å项,就会在该导航节点的导航地图ä¸è¿›è¡Œæ³¨å†Œã€‚\n" "如果两个地图共享类似的边界,就å¯ä»¥ç›¸äº’è¿žæŽ¥ã€‚ä½ å¯ä»¥é€šè¿‡ [method " -"NavigationServer.map_set_edge_connection_margin] 设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€" -"的最å°è·ç¦»ã€‚\n" +"NavigationServer.map_set_edge_connection_margin] " +"设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€çš„æœ€å°è·ç¦»ã€‚\n" "[b]注æ„:[/b]å°†ä¸¤ä¸ªåœ°åŒºçš„å¯¼èˆªç½‘æ ¼ç›¸äº’é‡å å¹¶ä¸è¶³ä»¥å°†å…¶ç›¸è¿žã€‚它们必须共享类似的" "边界。\n" "从å¦ä¸€ä¸ªåœ°åŒºè¿›å…¥è¿™ä¸ªåœ°å›¾çš„æ¶ˆè€—å¯ä»¥é€šè¿‡ [member enter_cost] 进行控制。\n" @@ -46308,18 +46425,18 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." msgstr "" -"导航地图上的地区。[Navigation2DServer] æ ¹æ®å®ƒçš„ [NavigationPolygon] èµ„æºæ¥ç¡®" -"定哪些å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n" +"导航地图上的地区。[Navigation2DServer] æ ¹æ®å®ƒçš„ [NavigationPolygon] " +"èµ„æºæ¥ç¡®å®šå“ªäº›å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n" "默认情况下,这个节点会在默认的 [World2D] 导航地图ä¸è¿›è¡Œæ³¨å†Œã€‚如果这个节点是 " "[Navigation2D] 节点的å项,就会在该导航节点的导航地图ä¸è¿›è¡Œæ³¨å†Œã€‚\n" "如果两个地图共享类似的边界,就å¯ä»¥ç›¸äº’è¿žæŽ¥ã€‚ä½ å¯ä»¥é€šè¿‡ [method " -"Navigation2DServer.map_set_edge_connection_margin] 设置两个顶点连接两æ¡è¾¹ç•Œæ‰€" -"需的最å°è·ç¦»ã€‚\n" +"Navigation2DServer.map_set_edge_connection_margin] " +"设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€çš„æœ€å°è·ç¦»ã€‚\n" "[b]注æ„:[/b]å°†ä¸¤ä¸ªåœ°åŒºçš„å¯¼èˆªç½‘æ ¼ç›¸äº’é‡å å¹¶ä¸è¶³ä»¥å°†å…¶ç›¸è¿žã€‚它们必须共享类似的" "边界。\n" "从å¦ä¸€ä¸ªåœ°åŒºè¿›å…¥è¿™ä¸ªåœ°å›¾çš„寻路消耗å¯ä»¥é€šè¿‡ [member enter_cost] 进行控制。\n" @@ -46462,6 +46579,62 @@ msgstr "" msgid "Control activation of this server." msgstr "控制这个æœåŠ¡å™¨æ˜¯å¦æ¿€æ´»ã€‚" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "对 [NetworkedMultiplayerPeer] 的一ç§å®žçŽ°ï¼Œèƒ½å¤Ÿé€šè¿‡è„šæœ¬æŽ§åˆ¶ã€‚" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" +"对 [NetworkedMultiplayerPeer] 的一ç§å®žçŽ°ï¼Œèƒ½å¤Ÿä½œä¸º [member MultiplayerAPI." +"network_peer] 使用并且通过脚本控制。\n" +"其目的是为高级多人 API æ·»åŠ æ–°çš„åŽç«¯ï¼Œä¸å¿…使用 GDNative。" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" +"呿œ¬åœ° [MultiplayerAPI] ä¼ é€’æ•°æ®åŒ…。\n" +"å½“ä½ çš„è„šæœ¬é€šè¿‡ç½‘ç»œæ”¶åˆ°å…¶ä»–å¯¹ç‰ä½“的数æ®åŒ…时(å‘逿–¹å‘出 [signal " +"packet_generated] ä¿¡å·ï¼‰ï¼Œå°†å…¶ä¼ é€’ç»™è¿™ä¸ªæ–¹æ³•ä¼šåœ¨æœ¬åœ°è¿›è¡Œä¼ é€’ã€‚" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "使用给定的 [code]peer_id[/code] åˆå§‹åŒ–该对ç‰ä½“(必须在 1 å’Œ 2147483647 " +"之间)。" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "设置连接的状æ€ã€‚è§ [enum NetworkedMultiplayerPeer.ConnectionStatus]。" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "设置这个对ç‰ä½“所能够处ç†çš„æœ€å¤§æ•°æ®åŒ…大å°ã€‚" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" +"当本地 [MultiplayerAPI] ç”Ÿæˆæ•°æ®åŒ…时触å‘。\n" +"ä½ çš„è„šæœ¬åº”å½“èŽ·å–这个数æ®åŒ…并将其通过网络å‘é€ç»™è¯·æ±‚的对ç‰ä½“(" +"å¯¹æ–¹æ”¶åˆ°è¯¥æ•°æ®æ—¶åº”当调用 [method deliver_packet])。" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -48495,7 +48668,6 @@ msgstr "" "称设置为唯一å称。" #: doc/classes/Node.xml -#, fuzzy msgid "" "Emitted when a child node enters the scene tree, either because it entered " "on its own or because this node entered with it.\n" @@ -48503,7 +48675,9 @@ msgid "" "NOTIFICATION_ENTER_TREE] and [signal tree_entered]." msgstr "" "在åèŠ‚ç‚¹è¿›å…¥åœºæ™¯æ ‘æ—¶è§¦å‘,å¯ä»¥æ˜¯å› 为该å节点自行进入,也å¯ä»¥æ˜¯å› 为本节点带ç€" -"该å节点一起进入。" +"该å节点一起进入。\n" +"这个信å·ä¼šåœ¨è¯¥å节点自身的 [constant NOTIFICATION_ENTER_TREE] å’Œ [signal " +"tree_entered] [i]之åŽ[/i]触å‘。" #: doc/classes/Node.xml msgid "" @@ -48514,14 +48688,19 @@ msgid "" "tree and valid. This signal is emitted [i]after[/i] the child node's own " "[signal tree_exiting] and [constant NOTIFICATION_EXIT_TREE]." msgstr "" +"在å节点å³å°†é€€å‡ºåœºæ™¯æ ‘时触å‘,å¯ä»¥æ˜¯å› 为该å节点自行退出,也å¯ä»¥æ˜¯å› 为本节点" +"带ç€è¯¥å节点一起退出。\n" +"æ”¶åˆ°è¿™ä¸ªä¿¡å·æ—¶ï¼Œè¯¥å节 [code]node[/code] ä»åœ¨æ ‘ä¸å¹¶ä¸”有效。这个信å·ä¼šåœ¨è¯¥å节" +"点自身的 [signal tree_exiting] å’Œ [constant NOTIFICATION_EXIT_TREE] [i]之åŽ[/" +"i]触å‘。" #: doc/classes/Node.xml msgid "Emitted when the node is ready." -msgstr "当节点准备好时触å‘。" +msgstr "当该节点准备好时触å‘。" #: doc/classes/Node.xml msgid "Emitted when the node is renamed." -msgstr "在é‡å‘½å节点时触å‘。" +msgstr "当该节点被é‡å‘½å时触å‘。" #: doc/classes/Node.xml msgid "" @@ -48529,34 +48708,39 @@ msgid "" "This signal is emitted [i]after[/i] the related [constant " "NOTIFICATION_ENTER_TREE] notification." msgstr "" +"å½“è¯¥èŠ‚ç‚¹è¿›å…¥æ ‘æ—¶è§¦å‘。\n" +"这个信å·ä¼šåœ¨ç›¸å…³çš„ [constant NOTIFICATION_ENTER_TREE] 通知[i]之åŽ[/i]触å‘。" #: doc/classes/Node.xml msgid "Emitted after the node exits the tree and is no longer active." -msgstr "åœ¨èŠ‚ç‚¹é€€å‡ºæ ‘ä¹‹åŽè§¦å‘,并且ä¸å†å¤„于活动状æ€ã€‚" +msgstr "å½“è¯¥èŠ‚ç‚¹é€€å‡ºæ ‘ä¹‹åŽè§¦å‘,并且ä¸å†å¤„于活动状æ€ã€‚" #: doc/classes/Node.xml -#, fuzzy msgid "" "Emitted when the node is still active but about to exit the tree. This is " "the right place for de-initialization (or a \"destructor\", if you will).\n" "This signal is emitted [i]before[/i] the related [constant " "NOTIFICATION_EXIT_TREE] notification." msgstr "" -"当节点ä»å¤„于活动状æ€ä½†å³å°†é€€å‡ºæ ‘æ—¶å‘出。这是ååˆå§‹åŒ–çš„æ£ç¡®ä½ç½®ï¼ˆå¦‚果愿æ„,也" -"å¯ä»¥ç§°ä¹‹ä¸ºâ€œæžæž„函数â€ï¼‰ã€‚" +"当该节点ä»å¤„于活动状æ€ä½†å³å°†é€€å‡ºæ ‘æ—¶å‘出。这是ååˆå§‹åŒ–çš„æ£ç¡®ä½ç½®ï¼ˆå¦‚果愿æ„," +"也å¯ä»¥ç§°ä¹‹ä¸ºâ€œæžæž„函数â€ï¼‰ã€‚\n" +"这个信å·ä¼šåœ¨ç›¸å…³çš„ [constant NOTIFICATION_EXIT_TREE] 通知[i]之å‰[/i]触å‘。" #: doc/classes/Node.xml msgid "" "Notification received when the node enters a [SceneTree].\n" "This notification is emitted [i]before[/i] the related [signal tree_entered]." msgstr "" +"当该节点进入 [SceneTree] 时收到的通知。\n" +"这个通知会在相关的 [signal tree_entered] [i]之å‰[/i]å‘出。" #: doc/classes/Node.xml -#, fuzzy msgid "" "Notification received when the node is about to exit a [SceneTree].\n" "This notification is emitted [i]after[/i] the related [signal tree_exiting]." -msgstr "当该节点å³å°†é€€å‡º [SceneTree] 时收到的通知。" +msgstr "" +"当该节点å³å°†é€€å‡º [SceneTree] 时收到的通知。\n" +"这个通知会在相关的 [signal tree_exiting] [i]之åŽ[/i]å‘出。" #: doc/classes/Node.xml msgid "Notification received when the node is moved in the parent." @@ -50148,8 +50332,18 @@ msgid "See [enum ShadowDetail]." msgstr "è§ [enum ShadowDetail]。" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." -msgstr "è§ [enum ShadowMode]。" +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." +msgstr "" +"为这个 [OmniLight] 使用的阴影渲染模å¼ã€‚è§ [enum ShadowMode]。\n" +"[b]注æ„:[/b]在 GLES2 ä¸ï¼Œåªæœ‰æ”¯æŒæ·±åº¦ç«‹æ–¹ä½“贴图功能的 GPU æ‰æ”¯æŒ [constant " +"SHADOW_CUBE]。Radeon HD 4000 系列ç‰è¾ƒè€çš„ GPU " +"䏿”¯æŒç«‹æ–¹ä½“è´´å›¾é˜´å½±ï¼Œå› æ¤ä¼šå›žé€€åˆ°ä½¿ç”¨åŒæŠ›ç‰©é¢é˜´å½±ã€‚" #: doc/classes/OmniLight.xml msgid "" @@ -50161,10 +50355,11 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" -"阴影被渲染æˆä¸€ä¸ªç«‹æ–¹ä½“贴图。比 [constant SHADOW_DUAL_PARABOLOID] æ…¢ï¼Œä½†è´¨é‡æ›´" -"高。" +"阴影被渲染至一个立方体贴图。比 [constant SHADOW_DUAL_PARABOLOID] " +"æ…¢ï¼Œä½†è´¨é‡æ›´é«˜ã€‚ä»…åœ¨æ”¯æŒæ·±åº¦ç«‹æ–¹ä½“贴图功能的 GPU 上支æŒã€‚" #: doc/classes/OmniLight.xml msgid "Use more detail vertically when computing the shadow." @@ -50236,7 +50431,7 @@ msgid "" "code] with fixed y-coordinate value 0.0." msgstr "" "返回给定 x åæ ‡å¤„çš„ 1D 噪声值 [code][-1,1][/code]。\n" -"[b]注æ„:[/b]这个方法实际上返回的是固定 Y åæ ‡å€¼ä¸º 0.0 的二维噪声值 [code]" +"[b]注æ„:[/b]这个方法实际上返回的是固定 Y åæ ‡å€¼ä¸º 0.0 çš„ 2D 噪声值 [code]" "[-1,1][/code]。" #: modules/opensimplex/doc_classes/OpenSimplexNoise.xml @@ -50802,7 +50997,6 @@ msgstr "" "径。" #: doc/classes/OS.xml -#, fuzzy msgid "" "Returns the command-line arguments passed to the engine.\n" "Command-line arguments can be written in any form, including both [code]--" @@ -50842,6 +51036,10 @@ msgstr "" " if argument.find(\"=\") > -1:\n" " var key_value = argument.split(\"=\")\n" " arguments[key_value[0].lstrip(\"--\")] = key_value[1]\n" +" else:\n" +" # å°†ä¸å¸¦å‚æ•°çš„é€‰é¡¹åŠ å…¥è¯¥å—典,\n" +" # å–值为空å—符串。\n" +" arguments[argument.lstrip(\"--\")] = \"\"\n" "[/codeblock]" #: doc/classes/OS.xml @@ -54032,11 +54230,11 @@ msgid "" "[b]Note:[/b] Many of these monitors are not updated in real-time, so there " "may be a short delay between changes." msgstr "" -"这个类æä¾›äº†å¯¹ä¸€äº›ä¸Žæ€§èƒ½æœ‰å…³çš„ä¸åŒç›‘控的访问,比如内å˜ä½¿ç”¨é‡ã€ç»˜åˆ¶è°ƒç”¨å’ŒFPS。" -"这些与编辑器的[b]Monitor[/b]æ ‡ç¾ä¸çš„[b]Debugger[/b]颿¿æ‰€æ˜¾ç¤ºçš„æ•°å€¼ç›¸åŒã€‚通过" -"使用这个类的[method get_monitor]方法,å¯ä»¥ä»Žä½ 的代ç ä¸è®¿é—®è¿™äº›æ•°æ®ã€‚\n" +"这个类æä¾›äº†å¯¹ä¸€äº›ä¸Žæ€§èƒ½æœ‰å…³çš„ä¸åŒç›‘控的访问,比如内å˜ä½¿ç”¨é‡ã€ç»˜åˆ¶è°ƒç”¨å’Œ " +"FPS。这些与编辑器[b]调试器[/b]颿¿çš„[b]监视[/b]æ ‡ç¾ä¸çš„æ‰€æ˜¾ç¤ºçš„æ•°å€¼ç›¸åŒã€‚通过" +"使用这个类的 [method get_monitor] 方法,å¯ä»¥ä»Žä½ 的代ç ä¸è®¿é—®è¿™äº›æ•°æ®ã€‚\n" "[b]注æ„:[/b]è¿™äº›ç›‘è§†å™¨ä¸æœ‰å‡ 个åªåœ¨è°ƒè¯•模å¼ä¸‹å¯ç”¨ï¼Œå½“在å‘布版构建ä¸ä½¿ç”¨æ—¶ï¼Œå°†" -"总是返回0。\n" +"总是返回 0。\n" "[b]注æ„:[/b]这些监控器ä¸çš„è®¸å¤šä¸æ˜¯å®žæ—¶æ›´æ–°çš„,所以在å˜åŒ–之间å¯èƒ½ä¼šæœ‰çŸæš‚的延" "迟。" @@ -54114,7 +54312,7 @@ msgstr "å¤å„¿èŠ‚ç‚¹çš„æ•°é‡ï¼Œå¤å„¿èŠ‚ç‚¹å³æ— æ³•è¢«æŒ‰çˆ¶çº§è¿½æº¯åˆ°æ ¹èŠ‚ #: doc/classes/Performance.xml msgid "3D objects drawn per frame." -msgstr "æ¯å¸§ç»˜åˆ¶3D对象的数é‡ã€‚" +msgstr "æ¯å¸§ç»˜åˆ¶ 3D 对象的数é‡ã€‚" #: doc/classes/Performance.xml msgid "Vertices drawn per frame. 3D only." @@ -54270,30 +54468,30 @@ msgstr "å¯¹ç‰©ä½“æ–½åŠ æ—‹è½¬å†²é‡ã€‚" #: doc/classes/Physics2DDirectBodyState.xml #: doc/classes/PhysicsDirectBodyState.xml msgid "Returns the collider's [RID]." -msgstr "返回碰撞体的[RID]。" +msgstr "返回该碰撞体的 [RID]。" #: doc/classes/Physics2DDirectBodyState.xml #: doc/classes/PhysicsDirectBodyState.xml msgid "Returns the collider's object id." -msgstr "返回碰撞体的对象 id。" +msgstr "返回该碰撞体的对象 id。" #: doc/classes/Physics2DDirectBodyState.xml msgid "" "Returns the collider object. This depends on how it was created (will return " "a scene node if such was used to create it)." msgstr "" -"返回碰撞体对象。这å–决于它是如何创建的(如果是被作为场景节点创建的,那么将返" -"回场景节点)。" +"返回该碰撞体对象。这å–决于它是如何创建的(如果是被作为场景节点创建的,那么将" +"返回场景节点)。" #: doc/classes/Physics2DDirectBodyState.xml #: doc/classes/PhysicsDirectBodyState.xml msgid "Returns the contact position in the collider." -msgstr "返回碰撞体ä¸çš„æŽ¥è§¦ä½ç½®ã€‚" +msgstr "返回该碰撞体ä¸çš„æŽ¥è§¦ä½ç½®ã€‚" #: doc/classes/Physics2DDirectBodyState.xml #: doc/classes/PhysicsDirectBodyState.xml msgid "Returns the collider's shape index." -msgstr "返回碰撞体的形状索引。" +msgstr "返回该碰撞体的形状索引。" #: doc/classes/Physics2DDirectBodyState.xml msgid "" @@ -54301,13 +54499,13 @@ msgid "" "[method Object.get_meta], and is set with [method Physics2DServer." "shape_set_data]." msgstr "" -"返回碰撞形状的元数æ®ã€‚这个元数æ®ä¸åŒäºŽ [method Object.get_meta],是用 " +"返回该碰撞形状的元数æ®ã€‚这个元数æ®ä¸åŒäºŽ [method Object.get_meta],是用 " "[method Physics2DServer.shape_set_data] 设置的。" #: doc/classes/Physics2DDirectBodyState.xml #: doc/classes/PhysicsDirectBodyState.xml msgid "Returns the linear velocity vector at the collider's contact point." -msgstr "返回碰撞体接触点处的线速度å‘é‡ã€‚" +msgstr "返回该碰撞体接触点处的线速度å‘é‡ã€‚" #: doc/classes/Physics2DDirectBodyState.xml msgid "" @@ -54315,8 +54513,8 @@ msgid "" "[b]Note:[/b] By default, this returns 0 unless bodies are configured to " "monitor contacts. See [member RigidBody2D.contact_monitor]." msgstr "" -"返回æ¤ç‰©ä½“与其他物体的接触次数。\n" -"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回0。å‚阅 [member " +"返回这个物体与其他物体的接触次数。\n" +"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回 0ã€‚è§ [member " "RigidBody2D.contact_monitor]。" #: doc/classes/Physics2DDirectBodyState.xml @@ -54616,7 +54814,7 @@ msgstr "" "通过 [Physics2DShapeQueryParameters] 对象检查给出的形状与空间的交点。返回的相" "交形状是一个å—典数组,包å«ä»¥ä¸‹å—段:\n" "[code]collider[/code]:碰撞的对象。\n" -"[code]collider_id[/code]:碰撞对象的ID。\n" +"[code]collider_id[/code]:碰撞对象的 ID。\n" "[code]metadata[/code]:相交形状的元数æ®ã€‚这个元数æ®ä¸Ž [method Object." "get_meta] ä¸åŒï¼Œæ˜¯ç”¨ [method Physics2DServer.shape_set_data] 设置的。\n" "[code]rid[/code]:相交对象的 [RID]。\n" @@ -54725,13 +54923,13 @@ msgid "" "5: The shape index of the area where the object entered/exited." msgstr "" "设置当任何主体/区域进入或退出该区域时调用的函数。这个回调函数将被任何与区域交" -"互的对象调用,并接å—5ä¸ªå‚æ•°:\n" -"1: [constant AREA_BODY_ADDED]或[constant AREA_BODY_REMOVED],å–决于对象是å¦è¿›" -"入或退出该区域。\n" -"2:进入/退出该区域对象的[RID]。\n" -"3:进入/退出该区域对象的实例ID。\n" -"4:进入/离开该区域的物体的形状指数。\n" -"5:物体进入/离开区域的形状指数。" +"äº’çš„å¯¹è±¡è°ƒç”¨ï¼Œå¹¶æŽ¥å— 5 ä¸ªå‚æ•°ï¼š\n" +"1:[constant AREA_BODY_ADDED] 或 [constant AREA_BODY_REMOVED],å–决于对象是å¦" +"进入或退出该区域。\n" +"2:进入/退出该区域对象的 [RID]。\n" +"3:进入/退出该区域对象的实例 ID。\n" +"4:进入/离开该区域的物体的形状指数。\n" +"5:物体进入/离开区域的形状指数。" #: doc/classes/Physics2DServer.xml msgid "" @@ -54847,7 +55045,7 @@ msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。请å‚阅 [enum BodyParameter] 获å–å¯ç”¨å #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "Returns the [RID] of the nth shape of a body." -msgstr "返回 body 的第 n 个碰撞形状的 [RID]。" +msgstr "返回物体的第 n 个碰撞形状的 [RID]。" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "Returns the number of shapes assigned to a body." @@ -54874,7 +55072,7 @@ msgid "" "Returns whether a body uses a callback function to calculate its own physics " "(see [method body_set_force_integration_callback])." msgstr "" -"返回一个 body 是å¦ä½¿ç”¨å›žè°ƒå‡½æ•°æ¥è®¡ç®—它自己的物ç†å€¼ï¼ˆè§ [method " +"返回一个物体是å¦ä½¿ç”¨å›žè°ƒå‡½æ•°æ¥è®¡ç®—它自己的物ç†å€¼ï¼ˆè§ [method " "body_set_force_integration_callback])。" #: doc/classes/Physics2DServer.xml @@ -55059,7 +55257,7 @@ msgstr "è¿”å›žä¸€ä¸ªå…³èŠ‚çš„ç±»åž‹ï¼ˆè§ [enum JointType])。" msgid "" "Sets a joint parameter. See [enum JointParam] for a list of available " "parameters." -msgstr "è®¾ç½®å…³èŠ‚å‚æ•°ã€‚有关å¯ç”¨å‚数的列表,请å‚阅[enum JointParam]。" +msgstr "è®¾ç½®å…³èŠ‚å‚æ•°ã€‚有关å¯ç”¨å‚数的列表,请å‚阅 [enum JointParam]。" #: doc/classes/Physics2DServer.xml msgid "" @@ -55188,8 +55386,8 @@ msgid "" "violating a constraint, to avoid leaving them in that state because of " "numerical imprecision." msgstr "" -"常é‡ï¼Œç”¨äºŽè®¾ç½®/èŽ·å–æ‰€æœ‰ç‰©ç†çº¦æŸçš„默认求解器å置。解算器å差是一个控制两个物体" -"在è¿å约æŸåŽ \"åå¼¹ \"ç¨‹åº¦çš„å› ç´ ï¼Œä»¥é¿å…由于数值ä¸ç²¾ç¡®è€Œä½¿å®ƒä»¬å¤„于这ç§çжæ€ã€‚" +"常é‡ï¼Œç”¨äºŽè®¾ç½®/èŽ·å–æ‰€æœ‰ç‰©ç†çº¦æŸçš„默认求解器å置。解算器å置是一个控制两个物体" +"在è¿å约æŸåŽâ€œåå¼¹â€ç¨‹åº¦çš„å› ç´ ï¼Œä»¥é¿å…由于数值ä¸ç²¾ç¡®è€Œä½¿å®ƒä»¬å¤„于这ç§çжæ€ã€‚" #: doc/classes/Physics2DServer.xml msgid "" @@ -55241,8 +55439,8 @@ msgid "" "supplied form is a convex polygon." msgstr "" "这是用于创建凸多边形的常é‡ã€‚一个多边形是由一个点的列表定义的。它å¯ä»¥ç”¨äºŽäº¤ç‚¹" -"和内/外侧检查。与[member CollisionPolygon2D.polygon]属性ä¸åŒï¼Œç”¨[method " -"shape_set_data]修改的多边形并ä¸éªŒè¯æ‰€æä¾›çš„ç‚¹çš„å½¢å¼æ˜¯ä¸€ä¸ªå‡¸å½¢å¤šè¾¹å½¢ã€‚" +"和内/外侧检查。与 [member CollisionPolygon2D.polygon] 属性ä¸åŒï¼Œç”¨ [method " +"shape_set_data] 修改的多边形并ä¸éªŒè¯æ‰€æä¾›çš„ç‚¹çš„å½¢å¼æ˜¯ä¸€ä¸ªå‡¸å½¢å¤šè¾¹å½¢ã€‚" #: doc/classes/Physics2DServer.xml msgid "" @@ -55344,15 +55542,15 @@ msgstr "" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "Constant for static bodies." -msgstr "StaticBody 的常é‡ã€‚" +msgstr "陿€ç‰©ä½“的常é‡ã€‚" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "Constant for kinematic bodies." -msgstr "KinematicBody 的常é‡ã€‚" +msgstr "è¿åЍå¦ç‰©ä½“的常é‡ã€‚" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "Constant for rigid bodies." -msgstr "RigidBody 的常é‡ã€‚" +msgstr "刚体的常é‡ã€‚" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "" @@ -55444,8 +55642,8 @@ msgid "" "undamped spring, while 1 causes the system to reach equilibrium as fast as " "possible (critical damping)." msgstr "" -"设置弹簧接头的阻尼比率。值为0è¡¨ç¤ºæ— é˜»å°¼å¼¹ç°§ï¼Œè€Œ1导致系统尽å¯èƒ½å¿«åœ°è¾¾åˆ°å¹³è¡¡" -"(临界阻尼)。" +"设置弹簧接头的阻尼比率。值为 0 è¡¨ç¤ºæ— é˜»å°¼å¼¹ç°§ï¼Œè€Œ 1 导致系统尽å¯èƒ½å¿«åœ°è¾¾åˆ°å¹³" +"衡(临界阻尼)。" #: doc/classes/Physics2DServer.xml msgid "" @@ -55459,13 +55657,13 @@ msgstr "" msgid "" "Enables continuous collision detection by raycasting. It is faster than " "shapecasting, but less precise." -msgstr "通过射线投射实现连ç»çš„碰撞检测。它比 shapecasting 更快,但ä¸å¤Ÿç²¾ç¡®ã€‚" +msgstr "通过射线投射实现连ç»çš„碰撞检测。它比形状投射更快,但ä¸å¤Ÿç²¾ç¡®ã€‚" #: doc/classes/Physics2DServer.xml msgid "" "Enables continuous collision detection by shapecasting. It is the slowest " "CCD method, and the most precise." -msgstr "通过形å˜å®žçŽ°è¿žç»çš„碰撞检测。它是最慢的CCD方法,也是最精确的。" +msgstr "通过形å˜å®žçŽ°è¿žç»çš„碰撞检测。它是最慢的 CCD 方法,也是最精确的。" #: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml msgid "" @@ -55665,7 +55863,7 @@ msgid "" "monitor contacts. See [member RigidBody.contact_monitor]." msgstr "" "返回æ¤ç‰©ä½“与其他物体的接触次数。\n" -"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回0。å‚阅 [member " +"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回 0ã€‚è§ [member " "RigidBody2D.contact_monitor]。" #: doc/classes/PhysicsDirectBodyState.xml @@ -55745,15 +55943,15 @@ msgid "" "If the shape did not intersect anything, then an empty dictionary is " "returned instead." msgstr "" -"检查通过[PhysicsShapeQueryParameters]对象给出的形状与空间的交点。如果它与一个" -"以上的形状å‘生碰撞,则选择最近的。返回的对象是包å«ä»¥ä¸‹å—段的å—å…¸:\n" -"[code]collider_id[/code]:碰撞对象的ID。\n" -"[code]linear_velocity[/code]:碰撞对象的速度[Vector3]。如果对象是一个[Area]," -"结果是[code](0, 0, 0)[/code]。\n" -"[code]normal[/code]:ç‰©ä½“åœ¨äº¤ç‚¹å¤„çš„è¡¨é¢æ³•线。\n" -"[code]点[/code]:相交点。\n" -"[code]rid[/code]:相交物体的[RID]。\n" -"[code]shape[/code]:碰撞形状的形状索引。\n" +"检查通过 [PhysicsShapeQueryParameters] 对象给出的形状与空间的交点。如果它与一" +"个以上的形状å‘生碰撞,则选择最近的。返回的对象是包å«ä»¥ä¸‹å—段的å—典:\n" +"[code]collider_id[/code]:碰撞对象的 ID。\n" +"[code]linear_velocity[/code]:碰撞对象的速度 [Vector3]。如果对象是一个 " +"[Area],结果是 [code](0, 0, 0)[/code]。\n" +"[code]normal[/code]ï¼šç‰©ä½“åœ¨äº¤ç‚¹å¤„çš„è¡¨é¢æ³•线。\n" +"[code]point[/code]:相交点。\n" +"[code]rid[/code]:相交物体的 [RID]。\n" +"[code]shape[/code]:碰撞形状的形状索引。\n" "如果该形状没有与任何物体相交,那么将返回空的å—典。" #: doc/classes/PhysicsDirectSpaceState.xml @@ -55802,17 +56000,17 @@ msgid "" "determine if the ray should collide with [PhysicsBody]s or [Area]s, " "respectively." msgstr "" -"在给定的空间ä¸ä¸Žä¸€æ¡å°„çº¿ç›¸äº¤ã€‚è¿”å›žçš„å¯¹è±¡æ˜¯å…·æœ‰ä¸‹åˆ—å—æ®µçš„å—å…¸:\n" -"[code]collider[/code]:碰撞的对象。\n" -"[code]collider_id[/code]:碰撞对象的ID。\n" -"[code]normal[/code]:ç‰©ä½“åœ¨ç›¸äº¤ç‚¹çš„è¡¨é¢æ³•线。\n" -"[code]position[/code]:交å‰ç‚¹ã€‚\n" -"[code]rid[/code]:相交物体的[RID]。\n" -"[code]形状[/code]:碰撞形状的形状索引。\n" +"在给定的空间ä¸ä¸Žä¸€æ¡å°„çº¿ç›¸äº¤ã€‚è¿”å›žçš„å¯¹è±¡æ˜¯å…·æœ‰ä¸‹åˆ—å—æ®µçš„å—典:\n" +"[code]collider[/code]:碰撞的对象。\n" +"[code]collider_id[/code]:碰撞对象的 ID。\n" +"[code]normal[/code]ï¼šç‰©ä½“åœ¨ç›¸äº¤ç‚¹çš„è¡¨é¢æ³•线。\n" +"[code]position[/code]:交å‰ç‚¹ã€‚\n" +"[code]rid[/code]:相交物体的 [RID]。\n" +"[code]shape[/code]:碰撞形状的形状索引。\n" "如果射线没有与任何物体相交,那么将返回空的å—典。\n" -"æ¤å¤–,该方法å¯ä»¥æŽ¥å—一个[code]exclude[/code]对象或[RID]数组,该数组将被排除在" -"碰撞之外,[code]collision_mask[/code]使ީç è¡¨ç¤ºè¦æ£€æŸ¥çš„物ç†å±‚,或者布尔值æ¥ç¡®" -"定射线是å¦åº”该分别与[PhysicsBody]或[Area]å‘生碰撞。" +"æ¤å¤–,该方法å¯ä»¥æŽ¥å—一个 [code]exclude[/code] 对象或 [RID] 数组,该数组将被排" +"除在碰撞之外,[code]collision_mask[/code] 使ީç è¡¨ç¤ºè¦æ£€æŸ¥çš„物ç†å±‚,或者布尔" +"值æ¥ç¡®å®šå°„线是å¦åº”该分别与 [PhysicsBody] 或 [Area] å‘生碰撞。" #: doc/classes/PhysicsDirectSpaceState.xml msgid "" @@ -55827,13 +56025,13 @@ msgid "" "The number of intersections can be limited with the [code]max_results[/code] " "parameter, to reduce the processing time." msgstr "" -"通过[PhysicsShapeQueryParameters]对象给出的形状与空间检查交点。相交的形状会以" -"数组的形å¼è¿”å›žï¼Œè¯¥æ•°ç»„åŒ…å«æœ‰ä»¥ä¸‹å—段的å—å…¸:\n" -"[code]collider[/code]:碰撞的对象。\n" -"[code]collider_id[/code]:碰撞对象的ID。\n" -"[code]rid[/code]:相交物体的[RID]。\n" -"[code]shape[/code]:碰撞形状的形状索引。\n" -"å¯ä»¥ç”¨[code]max_results[/code]傿•°é™åˆ¶ç›¸äº¤çš„æ•°é‡ï¼Œä»¥å‡å°‘å¤„ç†æ—¶é—´ã€‚" +"通过 [PhysicsShapeQueryParameters] 对象给出的形状与空间检查交点。相交的形状会" +"以数组的形å¼è¿”å›žï¼Œè¯¥æ•°ç»„åŒ…å«æœ‰ä»¥ä¸‹å—段的å—典:\n" +"[code]collider[/code]:碰撞的对象。\n" +"[code]collider_id[/code]:碰撞对象的 ID。\n" +"[code]rid[/code]:相交物体的 [RID]。\n" +"[code]shape[/code]:碰撞形状的形状索引。\n" +"å¯ä»¥ç”¨ [code]max_results[/code] 傿•°é™åˆ¶ç›¸äº¤çš„æ•°é‡ï¼Œä»¥å‡å°‘å¤„ç†æ—¶é—´ã€‚" #: doc/classes/PhysicsMaterial.xml msgid "A material for physics properties." @@ -55842,7 +56040,7 @@ msgstr "具有物ç†å±žæ€§çš„æè´¨ã€‚" #: doc/classes/PhysicsMaterial.xml msgid "" "Provides a means of modifying the collision properties of a [PhysicsBody]." -msgstr "æä¾›äº†ä¸€ç§ä¿®æ”¹[PhysicsBody]的碰撞属性的方法。" +msgstr "æä¾›äº†ä¸€ç§ä¿®æ”¹ [PhysicsBody] 的碰撞属性的方法。" #: doc/classes/PhysicsMaterial.xml msgid "" @@ -55856,14 +56054,16 @@ msgid "" "The body's bounciness. Values range from [code]0[/code] (no bounce) to " "[code]1[/code] (full bounciness)." msgstr "" -"实体的弹性。值的范围从[code]0[/code]ï¼ˆæ— å弹)到[code]1[/code](完全å弹)。" +"实体的弹性。值的范围从 [code]0[/code]ï¼ˆæ— å弹)到 [code]1[/code](完全å" +"弹)。" #: doc/classes/PhysicsMaterial.xml msgid "" "The body's friction. Values range from [code]0[/code] (frictionless) to " "[code]1[/code] (maximum friction)." msgstr "" -"物体的摩擦。å–值范围从[code]0[/code]ï¼ˆæ— æ‘©æ“¦ï¼‰åˆ°[code]1[/code](最大摩擦)。" +"物体的摩擦。å–值范围从 [code]0[/code]ï¼ˆæ— æ‘©æ“¦ï¼‰åˆ° [code]1[/code](最大摩" +"擦)。" #: doc/classes/PhysicsMaterial.xml msgid "" @@ -55891,7 +56091,7 @@ msgstr "" #: doc/classes/PhysicsServer.xml msgid "Creates an [Area]." -msgstr "创建一个[Area]区域。" +msgstr "创建一个 [Area] 区域。" #: doc/classes/PhysicsServer.xml msgid "" @@ -55936,7 +56136,7 @@ msgid "" "BodyMode] constants, for the type of body created. Additionally, the body " "can be created in sleeping state to save processing time." msgstr "" -"创建物ç†ä½“ã€‚å¯¹äºŽåˆ›å»ºçš„ç‰©ä½“ç±»åž‹ï¼Œç¬¬ä¸€ä¸ªå‚æ•°å¯ä»¥æ˜¯[enum BodyMode]常é‡ä¸çš„任何" +"创建物ç†ä½“ã€‚å¯¹äºŽåˆ›å»ºçš„ç‰©ä½“ç±»åž‹ï¼Œç¬¬ä¸€ä¸ªå‚æ•°å¯ä»¥æ˜¯ [enum BodyMode] 常é‡ä¸çš„任何" "值。æ¤å¤–,物体å¯ä»¥åœ¨ä¼‘çœ çŠ¶æ€ä¸‹åˆ›å»ºï¼Œä»¥èŠ‚çœå¤„ç†æ—¶é—´ã€‚" #: doc/classes/PhysicsServer.xml @@ -55951,7 +56151,7 @@ msgstr "" msgid "" "Returns the value of a body parameter. A list of available parameters is on " "the [enum BodyParameter] constants." -msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ[enum BodyParameter]常é‡ä¸Šã€‚" +msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ [enum BodyParameter] 常é‡ä¸Šã€‚" #: doc/classes/PhysicsServer.xml msgid "" @@ -55982,7 +56182,7 @@ msgstr "" #: doc/classes/PhysicsServer.xml msgid "Sets the body mode, from one of the [enum BodyMode] constants." -msgstr "从[enum BodyMode]常é‡ä¹‹ä¸€è®¾ç½®ä¸»ä½“模å¼ã€‚" +msgstr "从 [enum BodyMode] 常é‡ä¹‹ä¸€è®¾ç½®ä¸»ä½“模å¼ã€‚" #: doc/classes/PhysicsServer.xml msgid "" @@ -55992,7 +56192,7 @@ msgstr "è®¾ç½®ç‰©ä½“å‚æ•°ã€‚å¯ç”¨å‚数列表ä½äºŽ [enum BodyParameter] å¸¸é‡ #: doc/classes/PhysicsServer.xml msgid "Sets the body pickable with rays if [code]enabled[/code] is set." -msgstr "如果设置了[code]enabled[/code],则设置å¯ä½¿ç”¨å…‰çº¿æ‹¾å–的物体。" +msgstr "如果设置了 [code]enabled[/code],则设置å¯ä½¿ç”¨å…‰çº¿æ‹¾å–的物体。" #: doc/classes/PhysicsServer.xml msgid "Sets a body state (see [enum BodyState] constants)." @@ -56108,12 +56308,12 @@ msgstr "设置关节的优先级值。" #: doc/classes/PhysicsServer.xml msgid "" "Returns position of the joint in the local space of body a of the joint." -msgstr "返回关节在关节物体A的局部空间ä¸çš„ä½ç½®ã€‚" +msgstr "返回关节在关节物体 A 的局部空间ä¸çš„ä½ç½®ã€‚" #: doc/classes/PhysicsServer.xml msgid "" "Returns position of the joint in the local space of body b of the joint." -msgstr "返回关节在关节物体B的局部空间ä¸çš„ä½ç½®ã€‚" +msgstr "返回关节在关节物体 B 的局部空间ä¸çš„ä½ç½®ã€‚" #: doc/classes/PhysicsServer.xml msgid "Gets a pin_joint parameter (see [enum PinJointParam] constants)." @@ -56121,11 +56321,11 @@ msgstr "èŽ·å– pin_joint 傿•°ï¼ˆè§ [enum PinJointParam] 常é‡ï¼‰ã€‚" #: doc/classes/PhysicsServer.xml msgid "Sets position of the joint in the local space of body a of the joint." -msgstr "设置关节在关节物体A的局部空间ä¸çš„ä½ç½®ã€‚" +msgstr "设置关节在关节物体 A 的局部空间ä¸çš„ä½ç½®ã€‚" #: doc/classes/PhysicsServer.xml msgid "Sets position of the joint in the local space of body b of the joint." -msgstr "设置关节在关节物体B的局部空间ä¸çš„ä½ç½®ã€‚" +msgstr "设置关节在关节物体 B 的局部空间ä¸çš„ä½ç½®ã€‚" #: doc/classes/PhysicsServer.xml msgid "Sets a pin_joint parameter (see [enum PinJointParam] constants)." @@ -56133,7 +56333,7 @@ msgstr "设置 pin_joint 傿•°ï¼ˆè§ [enum PinJointParam] 常é‡ï¼‰ã€‚" #: doc/classes/PhysicsServer.xml msgid "Activates or deactivates the 3D physics engine." -msgstr "激活或åœç”¨3D物ç†å¼•擎。" +msgstr "激活或åœç”¨ 3D 物ç†å¼•擎。" #: doc/classes/PhysicsServer.xml msgid "" @@ -56155,8 +56355,8 @@ msgid "" "body or an area. To do so, you must use [method area_set_shape] or [method " "body_set_shape]." msgstr "" -"创建一个[enum ShapeType]ç±»åž‹çš„å½¢çŠ¶ã€‚ä¸æŠŠå®ƒåˆ†é…给一个体或一个区域。è¦åšåˆ°è¿™ä¸€" -"ç‚¹ï¼Œä½ å¿…é¡»ä½¿ç”¨[method area_set_shape]或[method body_set_shape]。" +"创建一个 [enum ShapeType] ç±»åž‹çš„å½¢çŠ¶ã€‚ä¸æŠŠå®ƒåˆ†é…给一个体或一个区域。è¦åšåˆ°è¿™" +"ä¸€ç‚¹ï¼Œä½ å¿…é¡»ä½¿ç”¨ [method area_set_shape] 或 [method body_set_shape]。" #: doc/classes/PhysicsServer.xml msgid "Returns the type of shape (see [enum ShapeType] constants)." @@ -56177,7 +56377,7 @@ msgstr "" msgid "" "Sets the value for a space parameter. A list of available parameters is on " "the [enum SpaceParameter] constants." -msgstr "è®¾ç½®ç©ºé—´å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ[enum SpaceParameter]常é‡ä¸Šã€‚" +msgstr "è®¾ç½®ç©ºé—´å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ [enum SpaceParameter] 常é‡ä¸Šã€‚" #: doc/classes/PhysicsServer.xml msgid "The [Joint] is a [PinJoint]." @@ -56221,7 +56421,7 @@ msgstr "" msgid "" "If above 0, this value is the maximum value for an impulse that this Joint " "puts on its ends." -msgstr "如果大于0ï¼Œè¿™ä¸ªå€¼å°±æ˜¯è¿™ä¸ªå…³èŠ‚å¯¹å…¶ä¸¤ç«¯æ–½åŠ çš„å†²é‡çš„æœ€å¤§å€¼ã€‚" +msgstr "如果大于 0ï¼Œè¿™ä¸ªå€¼å°±æ˜¯è¿™ä¸ªå…³èŠ‚å¯¹å…¶ä¸¤ç«¯æ–½åŠ çš„å†²é‡çš„æœ€å¤§å€¼ã€‚" #: doc/classes/PhysicsServer.xml msgid "The maximum rotation across the Hinge." @@ -56474,7 +56674,7 @@ msgid "" "Pin joint for 3D rigid bodies. It pins 2 bodies (rigid or static) together. " "See also [Generic6DOFJoint]." msgstr "" -"3Dåˆšä½“çš„é’‰å…³èŠ‚ã€‚å®ƒå°†ä¸¤ä¸ªç‰©ä½“ï¼ˆåˆšä½“æˆ–é™æ€ä½“)钉在一起。å‚阅" +"3D åˆšä½“çš„é’‰å…³èŠ‚ã€‚å®ƒå°†ä¸¤ä¸ªç‰©ä½“ï¼ˆåˆšä½“æˆ–é™æ€ä½“)钉在一起。å¦è¯·å‚阅 " "[Generic6DOFJoint]。" #: doc/classes/PinJoint.xml @@ -56493,7 +56693,7 @@ msgstr "è¢«é’‰åœ¨ä¸€èµ·çš„ç‰©ä½“ä¹‹é—´ä¿æŒå…±é€Ÿçš„力。越高,力越大。 msgid "" "If above 0, this value is the maximum value for an impulse that this Joint " "produces." -msgstr "如果大于0,这个值就是æ¤å…³èŠ‚äº§ç”Ÿçš„å†²é‡çš„æœ€å¤§å€¼ã€‚" +msgstr "如果大于 0,这个值就是æ¤å…³èŠ‚äº§ç”Ÿçš„å†²é‡çš„æœ€å¤§å€¼ã€‚" #: doc/classes/PinJoint2D.xml msgid "Pin Joint for 2D shapes." @@ -56551,7 +56751,7 @@ msgstr "返回平é¢çš„ä¸å¿ƒã€‚" msgid "" "Returns the shortest distance from the plane to the position [code]point[/" "code]." -msgstr "返回从平é¢åˆ°ä½ç½®[code]point[/code]的最çŸè·ç¦»ã€‚" +msgstr "返回从平é¢åˆ°ä½ç½® [code]point[/code] 的最çŸè·ç¦»ã€‚" #: doc/classes/Plane.xml msgid "" @@ -56608,7 +56808,7 @@ msgstr "" #: doc/classes/Plane.xml msgid "" "Returns [code]true[/code] if [code]point[/code] is located above the plane." -msgstr "如果[code]point[/code]ä½äºŽå¹³é¢ä¸Šæ–¹ï¼Œåˆ™è¿”回 [code]true[/code]。" +msgstr "如果 [code]point[/code] ä½äºŽå¹³é¢ä¸Šæ–¹ï¼Œåˆ™è¿”回 [code]true[/code]。" #: doc/classes/Plane.xml msgid "Returns a copy of the plane, normalized." @@ -56618,7 +56818,7 @@ msgstr "返回平é¢çš„ä¸€ä¸ªæ ‡å‡†åŒ–å‰¯æœ¬ã€‚" msgid "" "Returns the orthogonal projection of [code]point[/code] into a point in the " "plane." -msgstr "返回 [code]点[/code]在平é¢ä¸Šçš„æ£äº¤æŠ•å½±ã€‚" +msgstr "返回 [code]point[/code] 在平é¢ä¸Šçš„æ£äº¤æŠ•å½±ã€‚" #: doc/classes/Plane.xml msgid "" @@ -56628,9 +56828,9 @@ msgid "" "[code]d[/code], while the [code](a, b, c)[/code] coordinates are represented " "by the [member normal] property." msgstr "" -"从原点到平é¢çš„è·ç¦»ï¼Œæ²¿[member normal]æ–¹å‘。这个值通常是éžè´Ÿçš„。\n" -"在平é¢[code]ax + by + cz = d[/code]çš„æ ‡é‡æ–¹ç¨‹ä¸ï¼Œè¿™æ˜¯[code]d[/code],而[code]" -"(a, b, c)[/code]åæ ‡ç”±[member normal]属性表示。" +"从原点到平é¢çš„è·ç¦»ï¼Œæ²¿ [member normal] æ–¹å‘。这个值通常是éžè´Ÿçš„。\n" +"åœ¨å¹³é¢ [code]ax + by + cz = d[/code] çš„æ ‡é‡æ–¹ç¨‹ä¸ï¼Œè¿™æ˜¯ [code]d[/code],而 " +"[code](a, b, c)[/code] åæ ‡ç”± [member normal] 属性表示。" #: doc/classes/Plane.xml msgid "" @@ -56640,8 +56840,8 @@ msgid "" "property." msgstr "" "å¹³é¢çš„æ³•线,必须归一化。\n" -"在平é¢[code]ax + by + cz = d[/code]çš„æ ‡é‡æ–¹ç¨‹ä¸ï¼Œè¿™æ˜¯å‘é‡[code](a, b, c)[/" -"code],其ä¸[code]d[/code]是[member d]属性。" +"åœ¨å¹³é¢ [code]ax + by + cz = d[/code] çš„æ ‡é‡æ–¹ç¨‹ä¸ï¼Œè¿™æ˜¯å‘é‡ [code](a, b, c)[/" +"code]ï¼Œå…¶ä¸ [code]d[/code] 是 [member d] 属性。" #: doc/classes/Plane.xml msgid "The X component of the plane's [member normal] vector." @@ -56850,12 +57050,12 @@ msgid "" "If [code]true[/code], polygon will be inverted, containing the area outside " "the defined points and extending to the [code]invert_border[/code]." msgstr "" -"如果为 [code]true[/code],则多边形将å转,包å«å®šä¹‰ç‚¹ä¹‹å¤–的区域,并扩展到" -"[code]invert_border[/code](å转边界)." +"如果为 [code]true[/code],则多边形将å转,包å«å®šä¹‰ç‚¹ä¹‹å¤–的区域,并扩展到 " +"[code]invert_border[/code](å转边界)。" #: doc/classes/Polygon2D.xml msgid "The offset applied to each vertex." -msgstr "应用于æ¯ä¸ªé¡¶ç‚¹çš„ä½ç½®åç§»é‡." +msgstr "应用于æ¯ä¸ªé¡¶ç‚¹çš„ä½ç½®åç§»é‡ã€‚" #: doc/classes/Polygon2D.xml msgid "" @@ -56965,11 +57165,12 @@ msgstr "" msgid "" "Constructs a new [PoolByteArray]. Optionally, you can pass in a generic " "[Array] that will be converted." -msgstr "构建新的[PoolByteArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +msgstr "" +"构建新的 [PoolByteArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolByteArray.xml msgid "Appends a [PoolByteArray] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolByteArray]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolByteArray]。" #: doc/classes/PoolByteArray.xml msgid "" @@ -57114,6 +57315,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "改å˜ç»™å®šç´¢å¼•处的å—节。" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "将该数组ä¸çš„å…ƒç´ æŒ‰å‡åºæŽ’列。" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -57176,11 +57384,11 @@ msgid "" "Constructs a new [PoolColorArray]. Optionally, you can pass in a generic " "[Array] that will be converted." msgstr "" -"构建新的[PoolColorArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +"构建新的 [PoolColorArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolColorArray.xml msgid "Appends a [PoolColorArray] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ ä¸€ä¸ª[PoolColorArray]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ ä¸€ä¸ª [PoolColorArray]。" #: doc/classes/PoolColorArray.xml doc/classes/PoolIntArray.xml msgid "Appends a value to the array." @@ -57260,18 +57468,19 @@ msgstr "" msgid "" "Constructs a new [PoolIntArray]. Optionally, you can pass in a generic " "[Array] that will be converted." -msgstr "构建新的[PoolIntArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +msgstr "" +"构建新的 [PoolIntArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolIntArray.xml msgid "Appends a [PoolIntArray] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolIntArray]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolIntArray]。" #: doc/classes/PoolIntArray.xml msgid "" "Inserts a new int at a given position in the array. The position must be " "valid, or at the end of the array ([code]idx == size()[/code])." msgstr "" -"在数组ä¸çš„æŒ‡å®šä½ç½®æ’入一个新的int。这个ä½ç½®å¿…须是有效的,或者在数组的末端" +"在数组ä¸çš„æŒ‡å®šä½ç½®æ’入一个新的 int。这个ä½ç½®å¿…须是有效的,或者在数组的末端" "([code]idx == size()[/code])。" #: doc/classes/PoolIntArray.xml @@ -57402,11 +57611,11 @@ msgid "" "Constructs a new [PoolStringArray]. Optionally, you can pass in a generic " "[Array] that will be converted." msgstr "" -"构建新的[PoolStringArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +"构建新的 [PoolStringArray]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolStringArray.xml msgid "Appends a [PoolStringArray] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolStringArray]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolStringArray]。" #: doc/classes/PoolStringArray.xml msgid "" @@ -57481,15 +57690,15 @@ msgid "" "Constructs a new [PoolVector2Array]. Optionally, you can pass in a generic " "[Array] that will be converted." msgstr "" -"构建新的[PoolVector2Array]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +"构建新的 [PoolVector2Array]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolVector2Array.xml msgid "Appends a [PoolVector2Array] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector2Array]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector2Array]。" #: doc/classes/PoolVector2Array.xml msgid "Inserts a [Vector2] at the end." -msgstr "在末尾æ’å…¥[Vector2]。" +msgstr "在末尾æ’入一个 [Vector2]。" #: doc/classes/PoolVector2Array.xml msgid "Changes the [Vector2] at the given index." @@ -57548,15 +57757,15 @@ msgid "" "Constructs a new [PoolVector3Array]. Optionally, you can pass in a generic " "[Array] that will be converted." msgstr "" -"构建新的[PoolVector3Array]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的[Array],它将被转æ¢ã€‚" +"构建新的 [PoolVector3Array]ã€‚ä½ å¯ä»¥é€‰æ‹©ä¼ 入一个通用的 [Array],它将被转æ¢ã€‚" #: doc/classes/PoolVector3Array.xml msgid "Appends a [PoolVector3Array] at the end of this array." -msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector3Array]。" +msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector3Array]。" #: doc/classes/PoolVector3Array.xml msgid "Inserts a [Vector3] at the end." -msgstr "在末尾æ’å…¥[Vector3]。" +msgstr "在末尾æ’入一个 [Vector3]。" #: doc/classes/PoolVector3Array.xml msgid "Changes the [Vector3] at the given index." @@ -57670,11 +57879,11 @@ msgstr "PopupDialog æ˜¯å¼¹å‡ºå¯¹è¯æ¡†çš„基类,与 [WindowDialog] 一起。" #: doc/classes/PopupDialog.xml msgid "Sets a custom [StyleBox] for the panel of the [PopupDialog]." -msgstr "为[PopupDialog]çš„é¢æ¿è®¾ç½®è‡ªå®šä¹‰çš„[StyleBox]。" +msgstr "为 [PopupDialog] çš„é¢æ¿è®¾ç½®è‡ªå®šä¹‰çš„ [StyleBox]。" #: doc/classes/PopupMenu.xml msgid "PopupMenu displays a list of options." -msgstr "PopupMenu(弹出èœå•)显示选项列表." +msgstr "PopupMenu 会显示一个选项列表。" #: doc/classes/PopupMenu.xml msgid "" @@ -57692,6 +57901,14 @@ msgid "" "keystroke was registered. You can adjust the timeout duration by changing " "[member ProjectSettings.gui/timers/incremental_search_max_interval_msec]." msgstr "" +"[PopupMenu] 是会显示一个选项列表的 [Control]。常è§äºŽå·¥å…·æ 和上下文èœå•ä¸ã€‚\n" +"[b]å¢žé‡æœç´¢ï¼š[/b]与 [ItemList] å’Œ [Tree] 类似,[PopupMenu] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶" +"在列表ä¸è¿›è¡Œæœç´¢ã€‚按下与æŸä¸ªæ¡ç›®åç§°é¦–å—æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„" +"第一个æ¡ç›®ã€‚在æ¤ä¹‹åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰" +"键,选ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å—æ¯å¯¹åº”的按键,直接匹é…" +"并选䏿‰€éœ€çš„æ¡ç›®ã€‚è¿™ä¸¤ä¸ªåŠ¨ä½œéƒ½ä¼šåœ¨æœ€åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—è¡¨é¡¶ç«¯ã€‚ä½ å¯ä»¥é€š" +"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] " +"修改超时时长。" #: doc/classes/PopupMenu.xml msgid "" @@ -57724,12 +57941,13 @@ msgid "" "built-in checking behavior and must be checked/unchecked manually. See " "[method set_item_checked] for more info on how to control it." msgstr "" -"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®,并将指定的[ShortCut]分é…给它.å°†å¤é€‰æ¡†çš„æ ‡ç¾è®¾ç½®ä¸º" -"ShortCutçš„åç§°.\n" -"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code].如果没有æä¾›[code]id[/code],将从索引ä¸åˆ›å»ºä¸€" -"个.\n" -"[b]注æ„:[/b]坿£€æŸ¥é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªæ£€æŸ¥æ ‡è®°,但没有任何内置的检查行为,必须手动" -"æ£€æŸ¥æˆ–å–æ¶ˆæ£€æŸ¥. å‚阅 [method set_item_checked]了解更多关于如何控制它的信æ¯." +"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®,并将指定的 [ShortCut] 分é…给它。将å¤é€‰æ¡†çš„æ ‡ç¾è®¾ç½®ä¸º " +"ShortCut çš„å称。\n" +"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引ä¸åˆ›" +"建一个。\n" +"[b]注æ„:[/b]坿£€æŸ¥é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªæ£€æŸ¥æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手" +"åŠ¨æ£€æŸ¥æˆ–å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] 了解更多关于如何控制它的信" +"æ¯ã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -57744,14 +57962,14 @@ msgid "" "built-in checking behavior and must be checked/unchecked manually. See " "[method set_item_checked] for more info on how to control it." msgstr "" -"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®ï¼Œå¸¦æœ‰æ–‡æœ¬[code]label[/code]å’Œå›¾æ ‡[code]texture[/" +"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®ï¼Œå¸¦æœ‰æ–‡æœ¬ [code]label[/code] å’Œå›¾æ ‡ [code]texture[/" "code]。\n" -"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code],以åŠä¸€ä¸ªåŠ é€Ÿå™¨ï¼ˆ[code]accel[/code])。如果没" -"有æä¾›[code]id[/code],将从索引ä¸åˆ›å»ºä¸€ä¸ªã€‚如果没有æä¾›[code]accel[/code],那" -"么默认的[code]0[/code]将被分é…给它。å‚阅[method get_item_accelerator]èŽ·å–æ›´å¤š" -"å…³äºŽåŠ é€Ÿå™¨çš„ä¿¡æ¯ã€‚\n" +"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code],以åŠä¸€ä¸ªåŠ é€Ÿå™¨ï¼ˆ[code]accel[/code])。如果" +"没有æä¾› [code]id[/code],将从索引ä¸åˆ›å»ºä¸€ä¸ªã€‚如果没有æä¾› [code]accel[/" +"code],那么默认的 [code]0[/code] 将被分é…给它。å‚阅 [method " +"get_item_accelerator] èŽ·å–æ›´å¤šå…³äºŽåŠ é€Ÿå™¨çš„ä¿¡æ¯ã€‚\n" "[b]注æ„:[/b]å¯é€‰é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªå¤é€‰æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手动" -"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅[method set_item_checked]èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚" +"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -57764,12 +57982,12 @@ msgid "" "built-in checking behavior and must be checked/unchecked manually. See " "[method set_item_checked] for more info on how to control it." msgstr "" -"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯é€‰é¡¹ç›®ï¼Œå¹¶ä¸ºå…¶åˆ†é…指定的[ShortCut]å’Œå›¾æ ‡[code]texture[/code]。" -"å°†å¤é€‰æ¡†çš„æ ‡ç¾è®¾ç½®ä¸º[ShortCut]çš„å称。\n" -"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引ä¸åˆ›å»º" -"一个。\n" +"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯é€‰é¡¹ç›®ï¼Œå¹¶ä¸ºå…¶åˆ†é…指定的 [ShortCut] å’Œå›¾æ ‡ [code]texture[/" +"code]。将å¤é€‰æ¡†çš„æ ‡ç¾è®¾ç½®ä¸º [ShortCut] çš„å称。\n" +"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引ä¸åˆ›" +"建一个。\n" "[b]注æ„:[/b]å¯é€‰é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªå¤é€‰æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手动" -"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅[method set_item_checked]èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚" +"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -57788,12 +58006,12 @@ msgstr "" #: doc/classes/PopupMenu.xml msgid "Same as [method add_icon_check_item], but uses a radio check button." -msgstr "与[method add_icon_check_item]相åŒï¼Œä½†ä½¿ç”¨å•选按钮。" +msgstr "与 [method add_icon_check_item] 相åŒï¼Œä½†ä½¿ç”¨å•选按钮。" #: doc/classes/PopupMenu.xml msgid "" "Same as [method add_icon_check_shortcut], but uses a radio check button." -msgstr "与[method add_icon_check_shortcut]相åŒï¼Œä½†ä½¿ç”¨ä¸€ä¸ªå•选按钮。" +msgstr "与 [method add_icon_check_shortcut] 相åŒï¼Œä½†ä½¿ç”¨ä¸€ä¸ªå•选按钮。" #: doc/classes/PopupMenu.xml msgid "" @@ -57802,9 +58020,9 @@ msgid "" "An [code]id[/code] can optionally be provided. If no [code]id[/code] is " "provided, one will be created from the index." msgstr "" -"æ·»åŠ ä¸€ä¸ªæ–°é¡¹ï¼Œå¹¶åˆ†é…æŒ‡å®šçš„[ShortCut]å’Œå›¾æ ‡[code]texture[/code]给它。将å¤é€‰æ¡†" -"çš„æ ‡ç¾è®¾ç½®ä¸º[ShortCut]çš„å称。\n" -"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引ä¸åˆ›å»ºä¸€" +"æ·»åŠ ä¸€ä¸ªæ–°é¡¹ï¼Œå¹¶åˆ†é…æŒ‡å®šçš„ [ShortCut] å’Œå›¾æ ‡ [code]texture[/code] 给它。将å¤" +"é€‰æ¡†çš„æ ‡ç¾è®¾ç½®ä¸º [ShortCut] çš„å称。\n" +"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引ä¸åˆ›å»ºä¸€" "个。" #: doc/classes/PopupMenu.xml @@ -57889,9 +58107,9 @@ msgid "" "A [code]label[/code] can optionally be provided, which will appear at the " "center of the separator." msgstr "" -"åœ¨é¡¹ç›®ä¹‹é—´æ·»åŠ ä¸€ä¸ªåˆ†éš”ç¬¦ã€‚åˆ†éš”ç¬¦ä¹Ÿå ç”¨ä¸€ä¸ªç´¢å¼•ï¼Œä½ å¯ä»¥é€šè¿‡ä½¿ç”¨[code]id[/code]" -"傿•°æ¥è®¾ç½®ã€‚\n" -"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ªæ ‡ç¾[code]label[/code],它将出现在分隔符的ä¸å¿ƒã€‚" +"åœ¨é¡¹ç›®ä¹‹é—´æ·»åŠ ä¸€ä¸ªåˆ†éš”ç¬¦ã€‚åˆ†éš”ç¬¦ä¹Ÿå ç”¨ä¸€ä¸ªç´¢å¼•ï¼Œä½ å¯ä»¥é€šè¿‡ä½¿ç”¨ [code]id[/" +"code] 傿•°æ¥è®¾ç½®ã€‚\n" +"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ªæ ‡ç¾ [code]label[/code],它将出现在分隔符的ä¸å¿ƒã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -57899,8 +58117,8 @@ msgid "" "An [code]id[/code] can optionally be provided. If no [code]id[/code] is " "provided, one will be created from the index." msgstr "" -"æ·»åŠ ä¸€ä¸ª[ShortCut]。\n" -"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引ä¸åˆ›å»ºä¸€" +"æ·»åŠ ä¸€ä¸ª [ShortCut]。\n" +"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引ä¸åˆ›å»ºä¸€" "个。" #: doc/classes/PopupMenu.xml @@ -57911,14 +58129,14 @@ msgid "" "An [code]id[/code] can optionally be provided. If no [code]id[/code] is " "provided, one will be created from the index." msgstr "" -"æ·»åŠ ä¸€ä¸ªé¡¹ç›®ï¼Œå½“å•击父[PopupMenu]节点时,它将作为åèœå•。[code]submenu[/code]" -"傿•°æ˜¯å节点[PopupMenu]çš„å称,当点击项目时显示该å节点。\n" -"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引ä¸åˆ›å»ºä¸€" +"æ·»åŠ ä¸€ä¸ªé¡¹ç›®ï¼Œå½“å•击父 [PopupMenu] 节点时,它将作为åèœå•。[code]submenu[/" +"code] 傿•°æ˜¯å节点 [PopupMenu] çš„å称,当点击项目时显示该å节点。\n" +"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引ä¸åˆ›å»ºä¸€" "个。" #: doc/classes/PopupMenu.xml msgid "Removes all items from the [PopupMenu]." -msgstr "从[PopupMenu]ä¸ç§»é™¤æ‰€æœ‰é¡¹ç›®ã€‚" +msgstr "从该 [PopupMenu] ä¸ç§»é™¤æ‰€æœ‰é¡¹ç›®ã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -57932,19 +58150,20 @@ msgid "" "are special combinations of keys that activate the item, no matter which " "control is focused." msgstr "" -"返回索引[code]idx[/code]å¤„é¡¹ç›®çš„åŠ é€Ÿé¡¹ã€‚åŠ é€Ÿå™¨æ˜¯ä¸€ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»" -"物å“ï¼Œæ— è®ºå“ªä¸ªæŽ§åˆ¶é”®å¤„äºŽç„¦ç‚¹çŠ¶æ€ã€‚" +"返回索引 [code]idx[/code] å¤„é¡¹ç›®çš„åŠ é€Ÿé¡¹ã€‚åŠ é€Ÿå™¨æ˜¯ä¸€ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€" +"活物å“ï¼Œæ— è®ºå“ªä¸ªæŽ§åˆ¶é”®å¤„äºŽç„¦ç‚¹çŠ¶æ€ã€‚" #: doc/classes/PopupMenu.xml msgid "Returns the number of items in the [PopupMenu]." -msgstr "返回[PopupMenu]ä¸çš„项目数。" +msgstr "返回该 [PopupMenu] ä¸çš„项目数。" #: doc/classes/PopupMenu.xml msgid "" "Returns the id of the item at index [code]idx[/code]. [code]id[/code] can be " "manually assigned, while index can not." msgstr "" -"返回索引[code]idx[/code]处项目的id。[code]id[/code]å¯ä»¥æ‰‹åŠ¨åˆ†é…,而索引ä¸èƒ½ã€‚" +"返回索引 [code]idx[/code] 处项目的 id。[code]id[/code] å¯ä»¥æ‰‹åŠ¨åˆ†é…,而索引ä¸" +"能。" #: doc/classes/PopupMenu.xml msgid "" @@ -57952,8 +58171,8 @@ msgid "" "Index is automatically assigned to each item by the engine. Index can not be " "set manually." msgstr "" -"è¿”å›žåŒ…å«æŒ‡å®šçš„[code]id[/code]的项的索引。索引由引擎自动分é…ç»™æ¯ä¸ªé¡¹ç›®ã€‚ä¸èƒ½æ‰‹" -"动设置索引。" +"è¿”å›žåŒ…å«æŒ‡å®šçš„ [code]id[/code] 的项的索引。索引由引擎自动分é…ç»™æ¯ä¸ªé¡¹ç›®ã€‚ä¸èƒ½" +"手动设置索引。" #: doc/classes/PopupMenu.xml msgid "" @@ -57961,26 +58180,26 @@ msgid "" "can set it with [method set_item_metadata], which provides a simple way of " "assigning context data to items." msgstr "" -"返回指定项的元数æ®ï¼Œè¯¥é¡¹å¯ä»¥æ˜¯ä»»ä½•类型。您å¯ä»¥ä½¿ç”¨[method set_item_metadata]" -"æ¥è®¾ç½®å®ƒï¼Œå®ƒæä¾›äº†ä¸€ç§å°†ä¸Šä¸‹æ–‡æ•°æ®åˆ†é…ç»™é¡¹çš„ç®€å•æ–¹æ³•。" +"返回指定项的元数æ®ï¼Œè¯¥é¡¹å¯ä»¥æ˜¯ä»»ä½•类型。您å¯ä»¥ä½¿ç”¨ [method " +"set_item_metadata] æ¥è®¾ç½®å®ƒï¼Œå®ƒæä¾›äº†ä¸€ç§å°†ä¸Šä¸‹æ–‡æ•°æ®åˆ†é…ç»™é¡¹çš„ç®€å•æ–¹æ³•。" #: doc/classes/PopupMenu.xml msgid "" "Returns the [ShortCut] associated with the specified [code]idx[/code] item." -msgstr "返回与指定的[code]idx[/code]项关è”çš„[ShortCut]。" +msgstr "返回与指定的 [code]idx[/code] 项关è”çš„ [ShortCut]。" #: doc/classes/PopupMenu.xml msgid "" "Returns the submenu name of the item at index [code]idx[/code]. See [method " "add_submenu_item] for more info on how to add a submenu." msgstr "" -"返回在索引[code]idx[/code]处的项目的åèœå•åã€‚æ›´å¤šå…³äºŽå¦‚ä½•æ·»åŠ åèœå•的信æ¯ï¼Œ" -"请å‚阅[method add_submenu_item]。" +"返回在索引 [code]idx[/code] 处的项目的åèœå•åã€‚æ›´å¤šå…³äºŽå¦‚ä½•æ·»åŠ åèœå•的信" +"æ¯ï¼Œè¯·å‚阅 [method add_submenu_item]。" #: doc/classes/PopupMenu.xml msgid "" "Returns the tooltip associated with the specified index [code]idx[/code]." -msgstr "返回与指定索引 [code]idx[/code]å…³è”的工具æç¤ºã€‚" +msgstr "返回与指定索引 [code]idx[/code] å…³è”的工具æç¤ºã€‚" #: doc/classes/PopupMenu.xml msgid "" @@ -58056,7 +58275,7 @@ msgstr "将当å‰èšç„¦é¡¹ç›®è®¾ç½®ä¸ºç»™å®šçš„索引 [code]index[/code]。" #: doc/classes/PopupMenu.xml msgid "Hides the [PopupMenu] when the window loses focus." -msgstr "当窗å£å¤±åŽ»ç„¦ç‚¹æ—¶éšè—[PopupMenu]。" +msgstr "当窗å£å¤±åŽ»ç„¦ç‚¹æ—¶éšè— [PopupMenu]。" #: doc/classes/PopupMenu.xml msgid "" @@ -58064,7 +58283,7 @@ msgid "" "special combinations of keys that activate the item, no matter which control " "is focused." msgstr "" -"设置索引[code]idx[/code]é¡¹çš„åŠ é€Ÿé”®ã€‚åŠ é€Ÿå™¨æ˜¯ä¸€ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»ç‰©" +"设置索引 [code]idx[/code] é¡¹çš„åŠ é€Ÿé”®ã€‚åŠ é€Ÿå™¨æ˜¯ä¸€ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»ç‰©" "å“ï¼Œæ— è®ºå“ªä¸ªæŽ§åˆ¶é”®å¤„äºŽç„¦ç‚¹çŠ¶æ€ã€‚" #: doc/classes/PopupMenu.xml @@ -58098,15 +58317,15 @@ msgstr "" #: doc/classes/PopupMenu.xml msgid "Sets the checkstate status of the item at index [code]idx[/code]." -msgstr "设置项目在index [code]idx[/code]处的checkstate状æ€ã€‚" +msgstr "è®¾ç½®åœ¨ç´¢å¼•å· [code]idx[/code] 处的项目的勾选状æ€ã€‚" #: doc/classes/PopupMenu.xml msgid "" "Enables/disables the item at index [code]idx[/code]. When it is disabled, it " "can't be selected and its action can't be invoked." msgstr "" -"å¯ç”¨/ç¦ç”¨ç´¢å¼•[code]idx[/code]项。当它被ç¦ç”¨æ—¶ï¼Œå°±æ— æ³•é€‰æ‹©å®ƒï¼Œä¹Ÿæ— æ³•è°ƒç”¨å®ƒçš„æ“" -"作。" +"å¯ç”¨/ç¦ç”¨ç´¢å¼• [code]idx[/code] 项。当它被ç¦ç”¨æ—¶ï¼Œå°±æ— æ³•é€‰æ‹©å®ƒï¼Œä¹Ÿæ— æ³•è°ƒç”¨å®ƒçš„" +"æ“作。" #: doc/classes/PopupMenu.xml msgid "Replaces the [Texture] icon of the specified [code]idx[/code]." @@ -62092,7 +62311,6 @@ msgstr "" "义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "This is the maximum number of shaders that can be compiled (or reconstructed " "from cache) at the same time.\n" @@ -62118,12 +62336,10 @@ msgstr "" "能多的异æ¥ç¼–è¯‘çš„åŒæ—¶ï¼Œä¸å¯¹æ¸¸æˆçš„å“åº”æ€§é€ æˆå½±å“,å¦åˆ™å°±ä¼šè¾œè´Ÿå¼‚æ¥ç¼–译所带æ¥çš„" "好处。æ¢å¥è¯è¯´ï¼Œä½ å¯èƒ½ä¼šç‰ºç‰²ä¸€ç‚¹ç‚¹çš„ FPSï¼Œæ€»æ¯”åŒæ¥ç¼–译让整个游æˆåœæ»žè¦å¥½ã€‚\n" "默认值比较ä¿å®ˆï¼Œæ‰€ä»¥å»ºè®®ä½ æ ¹æ®è‡ªå·±çš„ç›®æ ‡ç¡¬ä»¶ä½œå‡ºè°ƒæ•´ã€‚\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„" -"义。" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "The default is a very conservative override for [member rendering/gles3/" "shaders/max_simultaneous_compiles].\n" @@ -62132,15 +62348,13 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]." msgstr "" -"默认是针对 [code]rendering/gles3/shaders/max_concurrent_compiles[/code] 的覆" +"默认是针对 [member rendering/gles3/shaders/max_simultaneous_compiles] 的覆" "盖,å–值éžå¸¸ä¿å®ˆã€‚\n" "æ ¹æ®ä½ æ‰€è®¾å®šä¸ºç›®æ ‡çš„ç‰¹å®šè®¾å¤‡ï¼Œä½ å¯èƒ½ä¼šæƒ³è¦æé«˜è¿™ä¸ªå€¼ã€‚\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„" -"义。" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "The default is a very conservative override for [member rendering/gles3/" "shaders/max_simultaneous_compiles].\n" @@ -62149,15 +62363,13 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]." msgstr "" -"默认是针对 [code]rendering/gles3/shaders/max_concurrent_compiles[/code] 的覆" +"默认是针对 [member rendering/gles3/shaders/max_simultaneous_compiles] 的覆" "盖,å–值éžå¸¸ä¿å®ˆã€‚\n" "æ ¹æ®ä½ æ‰€è®¾å®šä¸ºç›®æ ‡çš„ç‰¹å®šè®¾å¤‡ï¼Œä½ å¯èƒ½ä¼šæƒ³è¦æé«˜è¿™ä¸ªå€¼ã€‚\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„" -"义。" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "The maximum size, in megabytes, that the ubershader cache can grow up to. On " "startup, the least recently used entries will be deleted until the total " @@ -62167,12 +62379,10 @@ msgid "" msgstr "" "超级ç€è‰²å™¨ç¼“å˜æ‰€èƒ½å¢žé•¿åˆ°çš„æœ€å¤§å¤§å°ï¼Œå•ä½ä¸ºå…†å—节。在å¯åŠ¨æ—¶ï¼Œä¼šåˆ é™¤æœ€ä¹…æœªç”¨çš„" "æ¡ç›®ï¼Œç›´åˆ°æ€»å¤§å°åˆ°è¾¾èŒƒå›´å†…。\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„" -"义。" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "An override for [member rendering/gles3/shaders/shader_cache_size_mb], so a " "smaller maximum size can be configured for mobile platforms, where storage " @@ -62180,14 +62390,12 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]." msgstr "" -"[code]rendering/gles3/shaders/ubershader_cache_size_mb[/code] 的覆盖项,为针" -"对移动平å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„å˜å‚¨ç©ºé—´æ›´æœ‰é™ã€‚\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„" -"义。" +"[member rendering/gles3/shaders/shader_cache_size_mb] 的覆盖项,为针对移动平" +"å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„å˜å‚¨ç©ºé—´æ›´æœ‰é™ã€‚\n" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "An override for [member rendering/gles3/shaders/shader_cache_size_mb], so a " "smaller maximum size can be configured for web platforms, where storage " @@ -62197,11 +62405,11 @@ msgid "" "[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/" "shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]." msgstr "" -"[code]rendering/gles3/shaders/ubershader_cache_size_mb[/code] 的覆盖项,为针" -"对移动平å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„å˜å‚¨ç©ºé—´æ›´æœ‰é™ã€‚\n" -"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/" -"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„" -"义。" +"[member rendering/gles3/shaders/shader_cache_size_mb] 的覆盖项,为针对移动平" +"å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„å˜å‚¨ç©ºé—´æ›´æœ‰é™ã€‚\n" +"[b]注æ„:[/b]ç›®å‰ Web å¹³å°å°šä¸æ”¯æŒç€è‰²å™¨ç¼“å˜ã€‚\n" +"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/" +"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。" #: doc/classes/ProjectSettings.xml msgid "" @@ -62247,28 +62455,26 @@ msgstr "" "ç€è‰²å™¨ä¹Ÿä¸ä¼šä½¿ç”¨å¼‚æ¥ç¼–译。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "An override for [member rendering/gles3/shaders/shader_compilation_mode], so " "asynchronous compilation can be disabled on mobile platforms.\n" "You may want to do that since mobile GPUs generally won't support " "ubershaders due to their complexity." msgstr "" -"[code]rendering/gles3/shaders/shader_compilation_mode[/code] 的覆盖项,用于为" -"移动设备ç¦ç”¨å¼‚æ¥ç¼–译。\n" +"[member rendering/gles3/shaders/shader_compilation_mode] 的覆盖项,用于为移动" +"设备ç¦ç”¨å¼‚æ¥ç¼–译。\n" "移动 GPU 通常ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "An override for [member rendering/gles3/shaders/shader_compilation_mode], so " "asynchronous compilation can be disabled on web platforms.\n" "You may want to do that since certain browsers (especially on mobile " "platforms) generally won't support ubershaders due to their complexity." msgstr "" -"[code]rendering/gles3/shaders/shader_compilation_mode[/code] 的覆盖项,用于为" -"移动设备ç¦ç”¨å¼‚æ¥ç¼–译。\n" -"移动 GPU 通常ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。" +"[member rendering/gles3/shaders/shader_compilation_mode] 的覆盖项,用于为 " +"Web å¹³å°ç¦ç”¨å¼‚æ¥ç¼–译。\n" +"æŸäº›æµè§ˆå™¨ï¼ˆå°¤å…¶åœ¨ç§»åЍ平å°ä¸Šï¼‰é€šå¸¸ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。" #: doc/classes/ProjectSettings.xml msgid "" @@ -62887,13 +63093,12 @@ msgid "" msgstr "阴影贴图的细分象é™å¤§å°ã€‚请å‚é˜…é˜´å½±æ˜ å°„æ–‡æ¡£ã€‚" #: doc/classes/ProjectSettings.xml -#, fuzzy msgid "" "Size for shadow atlas (used for OmniLights and SpotLights). The value will " "be rounded up to the nearest power of 2. See shadow mapping documentation." msgstr "" "设置阴影图集的图åƒå¤§å°ï¼ˆç”¨äºŽå…¨å‘光和èšå…‰ï¼‰ã€‚该值将被四èˆäº”入到最接近的 2 çš„" -"幂。" +"幂。è§é˜´å½±è´´å›¾æ–‡æ¡£ã€‚" #: doc/classes/ProjectSettings.xml msgid "" @@ -63678,14 +63883,14 @@ msgid "" "Generates a pseudo-random float between [code]0.0[/code] and [code]1.0[/" "code] (inclusive)." msgstr "" -"产生一个[code]0.0[/code]å’Œ[code]1.0[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚" +"生æˆä¸€ä¸ª[code]0.0[/code]å’Œ[code]1.0[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚" #: doc/classes/RandomNumberGenerator.xml msgid "" "Generates a pseudo-random float between [code]from[/code] and [code]to[/" "code] (inclusive)." msgstr "" -"产生一个[code]from[/code]å’Œ[code]to[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚" +"生æˆä¸€ä¸ª[code]from[/code]å’Œ[code]to[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚" #: doc/classes/RandomNumberGenerator.xml msgid "" @@ -63694,8 +63899,8 @@ msgid "" "specified [code]mean[/code] and a standard [code]deviation[/code]. This is " "also called Gaussian distribution." msgstr "" -"产生一个[url=https://en.wikipedia.org/wiki/Normal_distribution]æ£æ€åˆ†å¸ƒ[/url]" -"çš„ä¼ªéšæœºæ•°ï¼Œä½¿ç”¨Box-Mullerå˜æ¢ï¼Œå…·æœ‰æŒ‡å®šçš„[code]mean[/code]å’Œæ ‡å‡†" +"生æˆä¸€ä¸ª[url=https://en.wikipedia.org/wiki/Normal_distribution]æ£æ€åˆ†å¸ƒ[/url]" +"çš„ä¼ªéšæœºæ•°ï¼Œä½¿ç”¨ Box-Muller å˜æ¢ï¼Œå…·æœ‰æŒ‡å®šçš„ [code]mean[/code] å’Œæ ‡å‡† " "[code]deviation[/code]。这也被称为高斯分布。" #: doc/classes/RandomNumberGenerator.xml @@ -63703,16 +63908,16 @@ msgid "" "Generates a pseudo-random 32-bit unsigned integer between [code]0[/code] and " "[code]4294967295[/code] (inclusive)." msgstr "" -"产生一个[code]0[/code]å’Œ[code]4294967295[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº32使— 符" -"å·æ•´æ•°ã€‚" +"生æˆä¸€ä¸ª [code]0[/code] å’Œ [code]4294967295[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº 32 " +"使— ç¬¦å·æ•´æ•°ã€‚" #: doc/classes/RandomNumberGenerator.xml msgid "" "Generates a pseudo-random 32-bit signed integer between [code]from[/code] " "and [code]to[/code] (inclusive)." msgstr "" -"产生一个[code]to[/code]å’Œ[code]from[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº32使œ‰ç¬¦å·æ•´" -"数。" +"生æˆä¸€ä¸ª [code]to[/code] å’Œ [code]from[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº 32 使œ‰ç¬¦" +"å·æ•´æ•°ã€‚" #: doc/classes/RandomNumberGenerator.xml msgid "Setups a time-based seed to generator." @@ -63815,20 +64020,20 @@ msgstr "使该 [Range] åœæ¢ä¸Žä»»ä½•å…¶ä»– Range 共享其æˆå‘˜å˜é‡ã€‚" #: doc/classes/Range.xml msgid "" "If [code]true[/code], [member value] may be greater than [member max_value]." -msgstr "如果为 [code]true[/code],[member value]å¯èƒ½å¤§äºŽ[member max_value]。" +msgstr "如果为 [code]true[/code],[member value] å¯èƒ½å¤§äºŽ [member max_value]。" #: doc/classes/Range.xml msgid "" "If [code]true[/code], [member value] may be less than [member min_value]." -msgstr "如果为 [code]true[/code],[member value]å¯èƒ½å°äºŽ[member min_value]。" +msgstr "如果为 [code]true[/code],[member value] å¯èƒ½å°äºŽ [member min_value]。" #: doc/classes/Range.xml msgid "" "If [code]true[/code], and [code]min_value[/code] is greater than 0, " "[code]value[/code] will be represented exponentially rather than linearly." msgstr "" -"如果为 [code]true[/code],并且[code]min_value[/code]大于0,[code]value[/code]" -"将以指数方å¼è€Œä¸æ˜¯çº¿æ€§æ–¹å¼è¡¨ç¤ºã€‚" +"如果为 [code]true[/code],并且 [code]min_value[/code] 大于 0,[code]value[/" +"code] 将以指数方å¼è€Œä¸æ˜¯çº¿æ€§æ–¹å¼è¡¨ç¤ºã€‚" #: doc/classes/Range.xml msgid "" @@ -63850,12 +64055,12 @@ msgid "" "multiplied by [code]page[/code] over the difference between [code]min_value[/" "code] and [code]max_value[/code]." msgstr "" -"页é¢å¤§å°ã€‚主è¦ç”¨äºŽ[ScrollBar]。ScrollBar的长度是它的尺寸乘以[code]page[/code]" -"超过[code]min_value[/code]å’Œ[code]max_value[/code]之间的差值。" +"页é¢å¤§å°ã€‚主è¦ç”¨äºŽ [ScrollBar]。ScrollBar 的长度是它的尺寸乘以 [code]page[/" +"code] 超过 [code]min_value[/code] å’Œ [code]max_value[/code] 之间的差值。" #: doc/classes/Range.xml msgid "The value mapped between 0 and 1." -msgstr "该值在0å’Œ1ä¹‹é—´è¿›è¡Œæ˜ å°„ã€‚" +msgstr "该值在 0 å’Œ 1 ä¹‹é—´è¿›è¡Œæ˜ å°„ã€‚" #: doc/classes/Range.xml msgid "" @@ -63871,9 +64076,9 @@ msgid "" "[code]value[/code] will first be rounded to a multiple of [code]step[/code] " "then rounded to the nearest integer." msgstr "" -"如果大于0,[code]value[/code]将总是被四èˆäº”入为[code]step[/code]çš„å€æ•°ã€‚如果" -"[code]rounded[/code]也是[code]true[/code],[code]value[/code]将首先被四èˆäº”å…¥" -"为[code]step[/code]çš„å€æ•°ï¼Œç„¶åŽèˆå…¥ä¸ºæœ€è¿‘的整数。" +"如果大于 0,[code]value[/code] 将总是被四èˆäº”入为 [code]step[/code] çš„å€æ•°ã€‚" +"如果 [code]rounded[/code] 也是 [code]true[/code],[code]value[/code] 将首先被" +"å››èˆäº”入为 [code]step[/code] çš„å€æ•°ï¼Œç„¶åŽèˆå…¥ä¸ºæœ€è¿‘的整数。" #: doc/classes/Range.xml msgid "Range's current value." @@ -63884,8 +64089,8 @@ msgid "" "Emitted when [member min_value], [member max_value], [member page], or " "[member step] change." msgstr "" -"在 [member min_value], [member max_value], [member page], 或 [member step] 改" -"å˜æ—¶é‡Šæ”¾ä¿¡å·ã€‚" +"在 [member min_value]ã€[member max_value]ã€[member page]ã€[member step] 改å˜" +"时释放信å·ã€‚" #: doc/classes/Range.xml msgid "" @@ -63928,12 +64133,12 @@ msgstr "" "以便找到沿光线路径最近的对象。\n" "RayCast å¯ä»¥å¿½ç•¥æŸäº›å¯¹è±¡ï¼Œæ–¹æ³•是通过 [code]add_exception[/code] å°†å®ƒä»¬æ·»åŠ åˆ°" "例外列表ä¸ï¼Œæˆ–者通过使用碰撞层和掩ç 设置,进行适当的过滤。\n" -"RayCast å¯ä»¥é…置为报告与 [Area]([member collide_with_areas]) å’Œ/或 " -"[PhysicsBody]([member collide_with_bodies]) 的碰撞。\n" +"RayCast å¯ä»¥é…置为报告与 [Area]([member collide_with_areas])和/或 " +"[PhysicsBody]([member collide_with_bodies])的碰撞。\n" "åªæœ‰å¯ç”¨çš„光线投射æ‰èƒ½æ£€æµ‹ç©ºé—´å¹¶æŠ¥å‘Šç¢°æ’žã€‚\n" -"RayCast 计算æ¯ä¸ªç‰©ç†å¸§çš„交集(å‚阅 [Node]),并将结果缓å˜èµ·æ¥ï¼Œä»¥ä¾¿ç¨åŽä½¿ç”¨ï¼Œ" -"直到下一帧。如果物ç†å¸§ä¹‹é—´ï¼ˆæˆ–åŒä¸€å¸§æœŸé—´ï¼‰éœ€è¦å¤šæ¬¡æ£€æµ‹ï¼Œè¯·åœ¨è°ƒæ•´å…‰çº¿æŠ•å°„åŽä½¿" -"用[method force_raycast_update]。" +"RayCast 计算æ¯ä¸ªç‰©ç†å¸§çš„äº¤é›†ï¼ˆè§ [Node]),并将结果缓å˜èµ·æ¥ï¼Œä»¥ä¾¿ç¨åŽä½¿ç”¨ï¼Œç›´" +"到下一帧。如果物ç†å¸§ä¹‹é—´ï¼ˆæˆ–åŒä¸€å¸§æœŸé—´ï¼‰éœ€è¦å¤šæ¬¡æ£€æµ‹ï¼Œè¯·åœ¨è°ƒæ•´å…‰çº¿æŠ•å°„åŽä½¿ç”¨ " +"[method force_raycast_update]。" #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -63961,7 +64166,7 @@ msgid "" msgstr "" "更新射线的碰撞信æ¯ã€‚ä½¿ç”¨æ¤æ–¹æ³•ç«‹å³æ›´æ–°ç¢°æ’žä¿¡æ¯ï¼Œè€Œä¸æ˜¯ç‰å¾…下一次 " "[code]_physics_process[/code] 调用,例如,如果光线或其父级已更改状æ€ã€‚\n" -"[b]注æ„:[/b][code]enabled[/code]ä¸éœ€è¦æ¤åŠŸèƒ½ã€‚" +"[b]注æ„:[/b][code]enabled[/code] ä¸éœ€è¦æ¤åŠŸèƒ½ã€‚" #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -63987,7 +64192,7 @@ msgid "" "[b]Note:[/b] Bit indices range from 0-19." msgstr "" "如果通过的ä½ç´¢å¼•被打开,则返回 [code]true[/code]。\n" -"[b]注æ„:[/b]使Œ‡æ•°èŒƒå›´ä¸º0-19。" +"[b]注æ„:[/b]使Œ‡æ•°èŒƒå›´ä¸º 0-19。" #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -64025,8 +64230,8 @@ msgid "" "Sets the bit index passed to the [code]value[/code] passed.\n" "[b]Note:[/b] Bit indexes range from 0-19." msgstr "" -"å°†ä¼ é€’çš„ä½ç´¢å¼•è®¾ç½®ä¸ºä¼ é€’çš„[code]值[/code]。\n" -"[b]注æ„:[/b]ä½ç´¢å¼•的范围是0-19。" +"å°†ä¼ é€’çš„ä½ç´¢å¼•è®¾ç½®ä¸ºä¼ é€’çš„ [code]value[/code]。\n" +"[b]注æ„:[/b]ä½ç´¢å¼•的范围是 0-19。" #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "" @@ -64061,9 +64266,9 @@ msgid "" "If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in " "[member ProjectSettings.debug/shapes/collision/shape_color] is used." msgstr "" -"如果在 [b]Debug[/b] èœå•ä¸å¯ç”¨äº†å¯è§ç¢°æ’žå½¢çж [b]Visible Collision Shapes[/" -"b],则å¯ç”¨äºŽåœ¨ç¼–辑器ä¸å’Œè¿è¡Œæ—¶ç»˜åˆ¶å½¢çŠ¶çš„è‡ªå®šä¹‰é¢œè‰²ã€‚å¦‚æžœ [RayCast] 与æŸç‰©ä½“å‘" -"生碰撞,æ¤é¢œè‰²å°†åœ¨è¿è¡Œæ—¶çªå‡ºæ˜¾ç¤ºã€‚\n" +"如果在[b]调试[/b]èœå•ä¸å¯ç”¨äº†[b]显示碰撞区域[/b],则å¯ç”¨äºŽåœ¨ç¼–辑器ä¸å’Œè¿è¡Œæ—¶" +"绘制形状的自定义颜色。如果 [RayCast] 与æŸç‰©ä½“å‘生碰撞,æ¤é¢œè‰²å°†åœ¨è¿è¡Œæ—¶çªå‡ºæ˜¾" +"示。\n" "如果设置为 [code]Color(0.0, 0.0, 0.0)[/code](默认),则使用 [member " "ProjectSettings.debug/shapes/collision/shape_color] ä¸è®¾ç½®çš„颜色。" @@ -64075,8 +64280,8 @@ msgid "" "shape to be visible at run-time." msgstr "" "如果设置为 [code]1[/code],则将一æ¡çº¿ç”¨ä½œè°ƒè¯•形状。å¦åˆ™ï¼Œå°†ç»˜åˆ¶ä¸€ä¸ªæˆªæ–的金å—" -"å¡”æ¥è¡¨ç¤º [RayCast]。需è¦åœ¨ [b]调试[/b] èœå•ä¸å¯ç”¨å¯è§ç¢°æ’žå½¢çж [b]Visible " -"Collision Shapes[/b],以便调试形状在è¿è¡Œæ—¶å¯è§ã€‚" +"å¡”æ¥è¡¨ç¤º [RayCast]。需è¦åœ¨[b]调试[/b]èœå•ä¸å¯ç”¨[b]显示碰撞区域[/b],以便调试" +"形状在è¿è¡Œæ—¶å¯è§ã€‚" #: doc/classes/RayCast.xml doc/classes/RayCast2D.xml msgid "If [code]true[/code], collisions will be reported." @@ -64148,9 +64353,9 @@ msgid "" "itself from whatever is touching its far endpoint. It's often useful for " "characters." msgstr "" -"用于3D碰撞的射线形状,它å¯ä»¥è¢«è®¾ç½®æˆä¸€ä¸ª[PhysicsBody]或[Area]。一æ¡å°„çº¿å¹¶ä¸æ˜¯" -"真æ£çš„碰撞体;然而,它试图将自己与其远端点接触的东西分开。这通常对角色很有" -"用。" +"用于 3D 碰撞的射线形状,它å¯ä»¥è¢«è®¾ç½®æˆä¸€ä¸ª [PhysicsBody] 或 [Area]。一æ¡å°„线" +"并䏿˜¯çœŸæ£çš„碰撞体;然而,它试图将自己与其远端点接触的东西分开。这通常对角色" +"很有用。" #: doc/classes/RayShape.xml doc/classes/RayShape2D.xml msgid "The ray's length." @@ -64170,8 +64375,8 @@ msgid "" "it tries to separate itself from whatever is touching its far endpoint. It's " "often useful for characters." msgstr "" -"äºŒç»´ç¢°æ’žçš„å°„çº¿å½¢çŠ¶ã€‚å°„çº¿å¹¶ä¸æ˜¯çœŸæ£çš„碰撞体;相å,它试图将自己与接触其远端的" -"任何东西分开。它通常对角色很有用。" +"2D ç¢°æ’žçš„å°„çº¿å½¢çŠ¶ã€‚å°„çº¿å¹¶ä¸æ˜¯çœŸæ£çš„碰撞体;相å,它试图将自己与接触其远端的任" +"何东西分开。它通常对角色很有用。" #: doc/classes/Rect2.xml msgid "2D axis-aligned bounding box." @@ -64190,11 +64395,11 @@ msgstr "" #: doc/classes/Rect2.xml msgid "Constructs a [Rect2] by position and size." -msgstr "按ä½ç½®å’Œå¤§å°æž„é€ ä¸€ä¸ª[Rect2]。" +msgstr "按ä½ç½®å’Œå¤§å°æž„é€ ä¸€ä¸ª [Rect2]。" #: doc/classes/Rect2.xml msgid "Constructs a [Rect2] by x, y, width, and height." -msgstr "通过xã€yã€å®½åº¦å’Œé«˜åº¦æž„é€ ä¸€ä¸ª[Rect2]。" +msgstr "通过 xã€yã€å®½åº¦å’Œé«˜åº¦æž„é€ ä¸€ä¸ª [Rect2]。" #: doc/classes/Rect2.xml msgid "" @@ -64315,13 +64520,13 @@ msgstr "返回一个更大的 [Rect2],其ä¸åŒ…å«è¿™ä¸ª [Rect2] å’Œ [code]b[/ #: doc/classes/RectangleShape2D.xml msgid "Rectangle shape for 2D collisions." -msgstr "二维碰撞的矩形。" +msgstr "2D 碰撞的矩形。" #: doc/classes/RectangleShape2D.xml msgid "" "Rectangle shape for 2D collisions. This shape is useful for modeling box-" "like 2D objects." -msgstr "二维碰撞的矩形。这个形状对于建模盒状2D对象很有用。" +msgstr "2D 碰撞的矩形。这个形状对于建模盒状 2D 对象很有用。" #: doc/classes/RectangleShape2D.xml msgid "" @@ -66279,8 +66484,8 @@ msgid "" "for a body." msgstr "" "在物ç†å¤„ç†è¿‡ç¨‹ä¸è¢«è°ƒç”¨ï¼Œå…è®¸ä½ è¯»å–并安全地修改对象的模拟状æ€ã€‚默认情况下,它" -"是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是[member custom_integrator]属性å…è®¸ä½ ç¦ç”¨é»˜" -"è®¤è¡Œä¸ºï¼Œä¸ºä¸€ä¸ªç‰©ä½“æ–½åŠ å®Œå…¨è‡ªå®šä¹‰çš„åˆåŠ›ã€‚" +"会和通常的物ç†è¡Œä¸ºä¸€èµ·ç”Ÿæ•ˆï¼Œä½†æ˜¯ä½ å¯ä»¥é€šè¿‡ [member custom_integrator] 属性ç¦" +"ç”¨é»˜è®¤è¡Œä¸ºï¼Œä¸ºç‰©ä½“æ–½åŠ å®Œå…¨è‡ªå®šä¹‰çš„åˆåŠ›ã€‚" #: doc/classes/RigidBody.xml msgid "" @@ -66321,7 +66526,7 @@ msgid "" "position uses the rotation of the global coordinate system, but is centered " "at the object's origin." msgstr "" -"å¯¹ç‰©ä½“æ–½åŠ ä¸€ä¸ªæœ‰å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— 关的! 在æ¯ä¸€å¸§ä¸æ–½åŠ ä¸€ä¸ªå†²é‡å°†äº§ç”Ÿä¸€" +"å¯¹ç‰©ä½“æ–½åŠ ä¸€ä¸ªæœ‰å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— 关的ï¼åœ¨æ¯ä¸€å¸§ä¸æ–½åŠ ä¸€ä¸ªå†²é‡å°†äº§ç”Ÿä¸€" "ä¸ªä¸Žå¸§çŽ‡ç›¸å…³çš„åŠ›ã€‚å‡ºäºŽè¿™ä¸ªåŽŸå› ï¼Œå®ƒåº”è¯¥åªåœ¨æ¨¡æ‹Ÿä¸€æ¬¡æ€§å½±å“时使用。该ä½ç½®ä½¿ç”¨å…¨" "å±€åæ ‡ç³»çš„æ—‹è½¬ï¼Œä½†ä»¥ç‰©ä½“的原点为ä¸å¿ƒã€‚" @@ -66564,12 +66769,12 @@ msgid "" "[code]body[/code] the [Node], if it exists in the tree, of the other " "[PhysicsBody] or [GridMap]." msgstr "" -"当与å¦ä¸€ä¸ª[PhysicsBody]或[GridMap]å‘生碰撞时触å‘。需è¦å°†[member " -"contact_monitor]设置为 [code]true[/code],并且将[member contacts_reported]设" -"置得足够高以检测所有的碰撞。如果[MeshLibrary]有碰撞[Shape],[GridMap]就会被检" -"测到。\n" -"[code]body[/code]çš„[Node],如果它å˜åœ¨äºŽæ ‘ä¸ï¼Œåˆ™æ˜¯å…¶ä»–[PhysicsBody]或[GridMap]" -"的节点。" +"当与å¦ä¸€ä¸ª [PhysicsBody] 或 [GridMap] å‘生碰撞时触å‘。需è¦å°† [member " +"contact_monitor] 设置为 [code]true[/code],并且将 [member contacts_reported] " +"设置得足够高以检测所有的碰撞。如果 [MeshLibrary] 有碰撞 [Shape],[GridMap] å°±" +"会被检测到。\n" +"[code]body[/code] çš„ [Node],如果它å˜åœ¨äºŽæ ‘ä¸ï¼Œåˆ™æ˜¯å…¶ä»– [PhysicsBody] 或 " +"[GridMap] 的节点。" #: doc/classes/RigidBody.xml msgid "" @@ -66580,12 +66785,12 @@ msgid "" "[code]body[/code] the [Node], if it exists in the tree, of the other " "[PhysicsBody] or [GridMap]." msgstr "" -"当与å¦ä¸€ä¸ª[PhysicsBody]或[GridMap]çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘。需è¦å°†[member " -"contact_monitor]设置为 [code]true[/code],并且将[member contacts_reported]设" -"置得足够高以检测到所有的碰撞。如果[MeshLibrary]有碰撞[Shape],[GridMap]就会被" -"检测到。\n" -"[code]body[/code]çš„[Node],如果它å˜åœ¨äºŽæ ‘ä¸ï¼Œåˆ™æ˜¯å…¶ä»–[PhysicsBody]或[GridMap]" -"的节点。" +"当与å¦ä¸€ä¸ª [PhysicsBody]或 [GridMap] çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘。需è¦å°† [member " +"contact_monitor] 设置为 [code]true[/code],并且将 [member contacts_reported] " +"设置得足够高以检测到所有的碰撞。如果 [MeshLibrary] 有碰撞 [Shape],[GridMap] " +"就会被检测到。\n" +"[code]body[/code]çš„[Node],如果它å˜åœ¨äºŽæ ‘ä¸ï¼Œåˆ™æ˜¯å…¶ä»– [PhysicsBody] 或 " +"[GridMap] 的节点。" #: doc/classes/RigidBody.xml msgid "" @@ -66678,35 +66883,34 @@ msgid "" "engine or [code]emit_signal(\"sleeping_state_changed\")[/code] is used." msgstr "" "当物ç†å¼•擎改å˜ç‰©ä½“çš„ç¡çœ çŠ¶æ€æ—¶å‘出。\n" -"[b]注æ„:[/b]改å˜[member sleeping]的值ä¸ä¼šè§¦å‘这个信å·ã€‚åªæœ‰å½“物ç†å¼•擎改å˜äº†" -"ç¡çœ çŠ¶æ€æˆ–者使用了[code]emit_signal(\"sleeping_state_changed\")[/code]时,它" -"æ‰ä¼šè¢«å‘出。" +"[b]注æ„:[/b]æ”¹å˜ [member sleeping] 的值ä¸ä¼šè§¦å‘这个信å·ã€‚åªæœ‰å½“物ç†å¼•擎改å˜" +"了ç¡çœ çŠ¶æ€æˆ–者使用了 [code]emit_signal(\"sleeping_state_changed\")[/code] " +"时,它æ‰ä¼šè¢«å‘出。" #: doc/classes/RigidBody.xml msgid "" "Rigid body mode. This is the \"natural\" state of a rigid body. It is " "affected by forces, and can move, rotate, and be affected by user code." msgstr "" -"刚体模å¼ã€‚这是一个刚体的 \"自然 \"状æ€ã€‚它å—到力的影å“,å¯ä»¥ç§»åŠ¨ã€æ—‹è½¬ï¼Œå¹¶å—" -"到用户代ç 的影å“。" +"刚体模å¼ã€‚这是一个刚体的“自然â€çжæ€ã€‚它å—到力的影å“,å¯ä»¥ç§»åŠ¨ã€æ—‹è½¬ï¼Œå¹¶å—到用" +"户代ç 的影å“。" #: doc/classes/RigidBody.xml msgid "" "Static mode. The body behaves like a [StaticBody], and can only move by user " "code." -msgstr "陿¢æ¨¡å¼ã€‚实体的行为就åƒä¸€ä¸ª[StaticBody],åªèƒ½é€šè¿‡ç”¨æˆ·ä»£ç 移动。" +msgstr "陿¢æ¨¡å¼ã€‚该实体的行为与 [StaticBody] 类似,åªèƒ½è¢«ç”¨æˆ·ä»£ç 移动。" #: doc/classes/RigidBody.xml msgid "" "Character body mode. This behaves like a rigid body, but can not rotate." -msgstr "角色模å¼ã€‚这与刚体的行为类似,但ä¸èƒ½æ—‹è½¬ã€‚" +msgstr "角色模å¼ã€‚与刚体的行为类似,但ä¸èƒ½æ—‹è½¬ã€‚" #: doc/classes/RigidBody.xml msgid "" "Kinematic body mode. The body behaves like a [KinematicBody], and can only " "move by user code." -msgstr "" -"è¿åŠ¨ä½“æ¨¡å¼ã€‚这个实体的行为就åƒä¸€ä¸ª[KinematicBody],åªèƒ½é€šè¿‡ç”¨æˆ·ä»£ç æ¥ç§»åŠ¨ã€‚" +msgstr "è¿åŠ¨ä½“æ¨¡å¼ã€‚该实体的行为与 [KinematicBody] 类似,åªèƒ½è¢«ç”¨æˆ·ä»£ç 移动。" #: doc/classes/RigidBody2D.xml msgid "A body that is controlled by the 2D physics engine." @@ -66744,7 +66948,7 @@ msgstr "" "è¦è®°ä½ï¼Œç‰©ç†ç‰©ä½“在自己管ç†å˜æ¢ï¼Œå®ƒä¼šè¦†ç›–ä½ çš„å˜æ¢è®¾ç½®ã€‚所以任何直接或间接的å˜" "æ¢ï¼ˆåŒ…括节点或其父级的缩放)将åªåœ¨ç¼–辑器ä¸å¯è§ï¼Œå¹¶åœ¨è¿è¡Œæ—¶ç«‹å³é‡ç½®ã€‚\n" "å¦‚æžœä½ éœ€è¦è¦†ç›–默认的物ç†è¡Œä¸ºæˆ–者在è¿è¡Œæ—¶æ·»åŠ å˜æ¢ï¼Œä½ å¯ä»¥å†™ä¸€ä¸ªè‡ªå®šä¹‰çš„åˆåŠ›ã€‚" -"å‚阅 [member custom_integrator]。\n" +"è§ [member custom_integrator]。\n" "è´¨é‡ä¸å¿ƒæ€»æ˜¯ä½äºŽèŠ‚ç‚¹çš„åŽŸç‚¹ï¼Œè€Œä¸è€ƒè™‘ [CollisionShape2D] ä¸å¿ƒç‚¹çš„å移。" #: doc/classes/RigidBody2D.xml @@ -66764,10 +66968,10 @@ msgid "" "custom_integrator] allows you to disable the default behavior and write " "custom force integration for a body." msgstr "" -"å…è®¸ä½ è¯»å–并安全地修改对象的模拟状æ€ã€‚å¦‚æžœä½ éœ€è¦ç›´æŽ¥æ”¹å˜ç‰©ä½“çš„" -"[code]position[/code]或其他物ç†å±žæ€§ï¼Œè¯·ä½¿ç”¨å®ƒä»£æ›¿[method Node." -"_physics_process]。默认情况下,它是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是[member " -"custom_integrator]å…è®¸ä½ ç¦ç”¨é»˜è®¤è¡Œä¸ºå¹¶ä¸ºä¸€ä¸ªç‰©ä½“编写自定义的åˆåŠ›ã€‚" +"å…è®¸ä½ è¯»å–并安全地修改对象的模拟状æ€ã€‚å¦‚æžœä½ éœ€è¦ç›´æŽ¥æ”¹å˜ç‰©ä½“çš„ " +"[code]position[/code] 或其他物ç†å±žæ€§ï¼Œè¯·ä½¿ç”¨å®ƒä»£æ›¿ [method Node." +"_physics_process]。默认情况下,它是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是 [member " +"custom_integrator] å…è®¸ä½ ç¦ç”¨é»˜è®¤è¡Œä¸ºå¹¶ä¸ºä¸€ä¸ªç‰©ä½“编写自定义的åˆåŠ›ã€‚" #: doc/classes/RigidBody2D.xml msgid "" @@ -66778,8 +66982,8 @@ msgid "" "global coordinate system, but is centered at the object's origin." msgstr "" "å¯¹ç‰©ä½“æ–½åŠ ä¸€ä¸ªæœ‰å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— 关的。æ¯ä¸€å¸§åº”用一个冲é‡ä¼šæœ‰ä¸€ä¸ªä¸Žå¸§" -"ç›¸å…³çš„åŠ›ã€‚ç”±äºŽè¿™ä¸ªåŽŸå› ï¼Œå®ƒåªåº”该在模拟一次性冲击时使用(å¦åˆ™å°±ä½¿ç”¨\"_force " -"\"函数)。ä½ç½®ä½¿ç”¨å…¨å±€åæ ‡ç³»çš„æ—‹è½¬ï¼Œä½†ä»¥ç‰©ä½“çš„åŽŸç‚¹ä¸ºä¸å¿ƒã€‚" +"ç›¸å…³çš„åŠ›ã€‚ç”±äºŽè¿™ä¸ªåŽŸå› ï¼Œå®ƒåªåº”该在模拟一次性冲击时使用(å¦åˆ™å°±ä½¿ç”¨â€œ_forceâ€å‡½" +"数)。ä½ç½®ä½¿ç”¨å…¨å±€åæ ‡ç³»çš„æ—‹è½¬ï¼Œä½†ä»¥ç‰©ä½“çš„åŽŸç‚¹ä¸ºä¸å¿ƒã€‚" #: doc/classes/RigidBody2D.xml msgid "" @@ -66845,8 +67049,8 @@ msgid "" "If [code]true[/code], the body will emit signals when it collides with " "another RigidBody2D. See also [member contacts_reported]." msgstr "" -"如果为 [code]true[/code],则物体在与å¦ä¸€ä¸ªRigidBody2D碰撞时会å‘出信å·ã€‚å‚阅" -"[member contacts_reported]。" +"如果为 [code]true[/code],则物体在与å¦ä¸€ä¸ª RigidBody2D 碰撞时会å‘出信å·ã€‚å¦è¯·" +"å‚阅 [member contacts_reported]。" #: doc/classes/RigidBody2D.xml msgid "" @@ -66902,7 +67106,7 @@ msgid "" "from the [b]Default Gravity[/b] value in [b]Project > Project Settings > " "Physics > 2d[/b] and/or any additional gravity vector applied by [Area2D]s." msgstr "" -"ä¹˜ä»¥æ–½åŠ åœ¨ç‰©ä½“ä¸Šçš„é‡åŠ›ã€‚ç‰©ä½“çš„é‡åŠ›æ˜¯ç”±[b]项目 > 项目设置 > ç‰©ç† > 2D[/b]ä¸çš„" +"ä¹˜ä»¥æ–½åŠ åœ¨ç‰©ä½“ä¸Šçš„é‡åŠ›ã€‚ç‰©ä½“çš„é‡åŠ›æ˜¯ç”±[b]项目 > 项目设置 > ç‰©ç† > 2D[/b] ä¸çš„" "[b]默认é‡åŠ›[/b]值和/或任何由 [Area2D] 应用的é¢å¤–é‡åŠ›å‘é‡è®¡ç®—出æ¥çš„。" #: doc/classes/RigidBody2D.xml @@ -66939,7 +67143,7 @@ msgid "" "thread and runs at a different granularity. Use [method _integrate_forces] " "as your process loop for precise control of the body state." msgstr "" -"该实体的线速度,å•ä½ä¸ºåƒç´ æ¯ç§’。å¯ä»¥å¶å°”使用,但是[b]ä¸è¦æ¯ä¸€å¸§éƒ½è®¾ç½®å®ƒ[/b]," +"该实体的线速度,å•ä½ä¸ºåƒç´ æ¯ç§’。å¯ä»¥å¶å°”使用,但是[b]ä¸è¦æ¯ä¸€å¸§éƒ½åŽ»è®¾ç½®[/b]," "å› ä¸ºç‰©ç†å¯èƒ½åœ¨å¦ä¸€ä¸ªçº¿ç¨‹ä¸è¿è¡Œï¼Œå¹¶ä¸”以ä¸åŒçš„间隔。使用 [method " "_integrate_forces] ä½œä¸ºä½ çš„è¿›ç¨‹å¾ªçŽ¯ï¼Œä»¥ç²¾ç¡®æŽ§åˆ¶ç‰©ä½“çŠ¶æ€ã€‚" @@ -67067,20 +67271,20 @@ msgstr "" #: doc/classes/RigidBody2D.xml msgid "Static mode. The body behaves like a [StaticBody2D] and does not move." -msgstr "陿€æ¨¡å¼ã€‚物体的行为就åƒä¸€ä¸ª[StaticBody2D],ä¸ä¼šç§»åŠ¨ã€‚" +msgstr "陿€æ¨¡å¼ã€‚该物体的行为与 [StaticBody2D] 类似,ä¸ä¼šç§»åŠ¨ã€‚" #: doc/classes/RigidBody2D.xml msgid "" "Character mode. Similar to [constant MODE_RIGID], but the body can not " "rotate." -msgstr "角色模å¼ã€‚与 [constant MODE_RIGID] 类似,但主体ä¸èƒ½æ—‹è½¬ã€‚" +msgstr "角色模å¼ã€‚与 [constant MODE_RIGID] 类似,但该实体ä¸èƒ½æ—‹è½¬ã€‚" #: doc/classes/RigidBody2D.xml msgid "" "Kinematic mode. The body behaves like a [KinematicBody2D], and must be moved " "by code." msgstr "" -"è¿åЍ妿¨¡å¼ã€‚这个物体的行为就åƒä¸€ä¸ª [KinematicBody2D]ï¼Œå¿…é¡»é€šè¿‡ä»£ç æ¥ç§»åŠ¨ã€‚" +"è¿åЍ妿¨¡å¼ã€‚该物体的行为就åƒä¸Ž [KinematicBody2D] ç±»ä¼¼ï¼Œå¿…é¡»é€šè¿‡ä»£ç æ¥ç§»åŠ¨ã€‚" #: doc/classes/RigidBody2D.xml msgid "" @@ -67104,7 +67308,7 @@ msgstr "使用形状投射å¯ç”¨è¿žç»ç¢°æ’žæ£€æµ‹ã€‚这是最慢的 CCD 方法ï #: doc/classes/Room.xml msgid "Room node, used to group objects together locally for [Portal] culling." -msgstr "Room 节点,用于在本地将对象组åˆåœ¨ä¸€èµ·ä»¥è¿›è¡Œ [Portal] 剔除。" +msgstr "房间节点,用于在本地将对象组åˆåœ¨ä¸€èµ·ä»¥è¿›è¡Œ [Portal] 剔除。" #: doc/classes/Room.xml msgid "" @@ -67245,7 +67449,7 @@ msgid "" "before unloading a level, when transitioning from level to level, or " "returning to a main menu." msgstr "" -"该方法会从 [b]portal graph[/b] æ¸…é™¤æ‰€æœ‰è½¬æ¢æ•°æ®ã€‚在å¸è½½å…³å¡ã€ä»Žå…³å¡è½¬æ¢åˆ°å…³å¡" +"该方法会清除 [b]room graph[/b] 䏿‰€æœ‰çš„è½¬æ¢æ•°æ®ã€‚在å¸è½½å…³å¡ã€ä»Žå…³å¡è½¬æ¢åˆ°å…³å¡" "或返回主èœå•时使用æ¤é€‰é¡¹ã€‚" #: doc/classes/RoomManager.xml @@ -67345,7 +67549,7 @@ msgstr "" "å»ºè®®æ‚¨ä»…å°†å¯¹è±¡æ”¾ç½®åœ¨å¸Œæœ›ç•™åœ¨è¿™äº›ç©ºé—´å†…çš„ç©ºé—´ä¸ - å³ [code]portal mode[/code]" "是 [code]STATIC[/code] 或 [code]DYNAMIC[/code](ä¸ç©¿è¶Š Portal)。" "[code]GLOBAL[/code] å’Œ [code]ROAMING[/code] å¯¹è±¡æœ€å¥½æ”¾ç½®åœ¨åœºæ™¯æ ‘çš„å¦ä¸€éƒ¨åˆ†ï¼Œ" -"以é¿å…混淆。有关portal模å¼çš„完整说明,请å‚阅 [CullInstance]。" +"以é¿å…混淆。有关 portal 模å¼çš„完整说明,请å‚阅 [CullInstance]。" #: doc/classes/RoomManager.xml msgid "" @@ -68461,7 +68665,6 @@ msgid "" msgstr "通过脚本进行通用动画的轻é‡çº§å¯¹è±¡ï¼Œä½¿ç”¨ [Tweener]。" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "[SceneTreeTween] is a tween managed by the scene tree. As opposed to " "[Tween], it does not require the instantiation of a node.\n" @@ -68543,21 +68746,21 @@ msgstr "" "建 [SceneTreeTween]。手动创建的 [SceneTreeTween](å³ä½¿ç”¨ [code]Tween.new()[/" "code]ï¼‰æ˜¯æ— æ•ˆçš„ï¼Œä¸èƒ½ç”¨äºŽå¯¹å€¼è¿›è¡Œè¡¥é—´ï¼Œä½†ä½ å¯ä»¥ç”¨ [method interpolate_value] " "æ¥æ‰‹åЍæ’值。\n" -"[SceneTreeTween] 动画是由 [Tweener] åºåˆ—æž„æˆçš„,默认串行执行。å‘该 " -"[SceneTreeTween] è¿½åŠ [Tweener] å³å¯åˆ›å»ºåºåˆ—。使用 [Tweener] æ¥åšåŠ¨ç”»å°±å«åšè¡¥" -"间(Tweening)。示例补间åºåˆ—æ˜¯ç±»ä¼¼è¿™æ ·çš„ï¼š\n" +"è¡¥é—´åŠ¨ç”»æ˜¯é€šè¿‡å‘ [SceneTreeTween] å¯¹è±¡ä¸æ·»åŠ [Tweener] åˆ›å»ºçš„ï¼Œæ·»åŠ çš„æ–¹æ³•æœ‰ " +"[method tween_property]ã€[method tween_interval]ã€[method tween_callback]ã€" +"[method tween_method]:\n" "[codeblock]\n" "var tween = get_tree().create_tween()\n" "tween.tween_property($Sprite, \"modulate\", Color.red, 1)\n" "tween.tween_property($Sprite, \"scale\", Vector2(), 1)\n" "tween.tween_callback($Sprite, \"queue_free\")\n" "[/codeblock]\n" -"这个åºåˆ—会让 [code]$Sprite[/code] å˜çº¢ï¼Œç„¶åŽç¼©å°ï¼Œæœ€åŽè°ƒç”¨ [method Node." -"queue_free] æ¥ç§»é™¤ç²¾çµã€‚更多用法信æ¯è¯·å‚阅 [method tween_property]ã€[method " -"tween_interval]ã€[method tween_callback]ã€[method tween_method] 方法。\n" +"这个åºåˆ—会让 [code]$Sprite[/code] å˜çº¢ï¼Œç„¶åŽç¼©å°ï¼Œæœ€åŽå†è°ƒç”¨ [method Node." +"queue_free] æ¥é‡Šæ”¾è¯¥ç²¾çµã€‚[Tweener] 默认是一个接一个执行的。这个行为å¯ä»¥é€šè¿‡ " +"[method parallel] å’Œ [method set_parallel] 更改。\n" "使用 [code]tween_*[/code] 方法创建 [Tweener] åŽï¼Œå¯ä»¥ä½¿ç”¨é“¾å¼æ–¹æ³•调用æ¥è°ƒæ•´" "该 [Tweener] çš„å±žæ€§ã€‚ä¾‹å¦‚ï¼Œå¦‚æžœä½ æƒ³è¦åœ¨ä¸Šé¢çš„例åä¸è®¾ç½®ä¸åŒçš„è¿‡æ¸¡ç±»åž‹ï¼Œé‚£ä¹ˆä½ " -"å¯ä»¥ï¼š\n" +"å¯ä»¥ä½¿ç”¨ [method set_trans]:\n" "[codeblock]\n" "var tween = get_tree().create_tween()\n" "tween.tween_property($Sprite, \"modulate\", Color.red, 1).set_trans(Tween." @@ -68566,8 +68769,9 @@ msgstr "" "TRANS_BOUNCE)\n" "tween.tween_callback($Sprite, \"queue_free\")\n" "[/codeblock]\n" -"[SceneTreeTween] 的大部分方法都å¯ä»¥ç”¨è¿™ç§æ–¹æ³•进行链å¼è°ƒç”¨ã€‚在这个示例ä¸ï¼Œæˆ‘们" -"对该 [SceneTreeTween] 进行了绑定,并设置了默认的过渡:\n" +"[SceneTreeTween] 的大部分方法都å¯ä»¥ç”¨è¿™ç§æ–¹æ³•进行链å¼è°ƒç”¨ã€‚在下é¢çš„示例ä¸ï¼Œæˆ‘" +"们将该 [SceneTreeTween] 绑定到了执行脚本的节点,并为其 [Tweener] 设置了默认的" +"过渡:\n" "[codeblock]\n" "var tween = get_tree().create_tween().bind_node(self).set_trans(Tween." "TRANS_ELASTIC)\n" @@ -68579,7 +68783,7 @@ msgstr "" "[codeblock]\n" "var tween = create_tween()\n" "for sprite in get_children():\n" -" tween.tween_property(sprite, \"position\", Vector2(), 1)\n" +" tween.tween_property(sprite, \"position\", Vector2(0, 0), 1)\n" "[/codeblock]\n" "上é¢çš„示例ä¸ï¼Œè¯¥èŠ‚ç‚¹çš„æ‰€æœ‰åèŠ‚ç‚¹éƒ½ä¼šä¾æ¬¡è¢«ç§»åŠ¨åˆ° (0, 0)。\n" "一些 [Tweener] 会用到过渡和缓动。å‰è€…æŽ¥å— [enum Tween.TransitionType] 常é‡ï¼Œ" @@ -68633,7 +68837,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Processes the [SceneTreeTween] by the given [code]delta[/code] value, in " "seconds. This is mostly useful for manual control when the [SceneTreeTween] " @@ -68648,14 +68851,14 @@ msgid "" msgstr "" "使用给定的增é‡ç§’æ•° [code]delta[/code] 处ç†è¯¥ [SceneTreeTween]。最常è§çš„用法是" "在该 [SceneTreeTween] æš‚åœæ—¶å¯¹å…¶è¿›è¡Œæ‰‹åŠ¨æŽ§åˆ¶ã€‚ä¹Ÿå¯ç”¨äºŽç«‹å³åœæ¢è¯¥ " -"[SceneTreeTween] 的动画,使用比完整长度更大的 [code]delta[/code] å³å¯ã€‚\n" +"[SceneTreeTween] 的动画,将 [code]delta[/code] 设得比完整长度更大å³å¯ã€‚\n" "如果该 [SceneTreeTween] ä»ç„¶æœ‰æœªå®Œæˆçš„ [Tweener],则返回 [code]true[/" "code]。\n" -"[b]注æ„:[/b]该 [SceneTreeTween] 在完æˆåŽä¼šå¤±æ•ˆï¼Œä½†ä½ å¯ä»¥åœ¨ step åŽè°ƒç”¨ " -"[method stop] 将其ä¿ç•™å¹¶é‡ç½®ã€‚" +"[b]注æ„:[/b]该 [SceneTreeTween] 完æˆåŠ¨ç”»åŽï¼Œä¼šåœ¨ä¸‹ä¸€ä¸ªå¤„ç†å¸§ä¸å¤±æ•ˆã€‚ä½ å¯ä»¥åœ¨" +"执行 [method custom_step] åŽè°ƒç”¨ [method stop] 将该 [SceneTreeTween] ä¿ç•™å¹¶é‡" +"置。" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Returns the total time in seconds the [SceneTreeTween] has been animating (i." "e. the time since it started, not counting pauses etc.). The time is " @@ -68709,20 +68912,20 @@ msgid "" msgstr "返回该 [SceneTreeTween] ç›®å‰æ˜¯å¦æ£åœ¨æ‰§è¡Œï¼Œå³æœªæš‚åœä¸”未完æˆã€‚" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Returns whether the [SceneTreeTween] is valid. A valid [SceneTreeTween] is a " "[SceneTreeTween] contained by the scene tree (i.e. the array from [method " "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" "返回该 [SceneTreeTween] æ˜¯å¦æœ‰æ•ˆã€‚有效的 [SceneTreeTween] æ˜¯ç”±åœºæ™¯æ ‘åŒ…å«çš„ " "[SceneTreeTween]ï¼ˆå³ [method SceneTree.get_processed_tweens] 返回的数组ä¸åŒ…å«" "这个 [SceneTreeTween])。[SceneTreeTween] 失效的情况有:补间完æˆã€è¢«é”€æ¯ã€ä½¿" -"用 [code]Tween.new()[/code] åˆ›å»ºã€‚æ— æ•ˆçš„ [SceneTreeTween] ä¸èƒ½è¿½åŠ " -"[Tweener]ï¼Œå› ä¸ºæ— æ³•è¿›è¡ŒåŠ¨ç”»ã€‚ä¸è¿‡ [method interpolate_value] 还是å¯ä»¥ä½¿ç”¨çš„。" +"用 [code]SceneTreeTween.new()[/code] åˆ›å»ºã€‚æ— æ•ˆçš„ [SceneTreeTween] ä¸èƒ½è¿½åŠ " +"[Tweener]ã€‚ä½†ä½ ä»ç„¶èƒ½å¤Ÿä½¿ç”¨ [method interpolate_value]。" #: doc/classes/SceneTreeTween.xml msgid "Aborts all tweening operations and invalidates the [SceneTreeTween]." @@ -68769,28 +68972,28 @@ msgstr "" "的默认缓动类型。" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" "è¿™åªè¯¥è¡¥é—´åºåˆ—çš„é‡å¤æ¬¡æ•°ï¼Œå³ [code]set_loops(2)[/code] 会让动画执行两次。\n" "调用这个方法时如果ä¸å¸¦å‚数,那么该 [SceneTreeTween] ä¼šæ— é™æ‰§è¡Œï¼Œç›´åˆ°è¢« " -"[method kill] 销æ¯ã€ç»‘å®šèŠ‚ç‚¹è¢«é‡Šæ”¾ã€æˆ–è€…æ‰€æœ‰è¿›è¡ŒåŠ¨ç”»çš„å¯¹è±¡éƒ½è¢«é‡Šæ”¾ï¼ˆæ— æ³•å†è¿›" -"行任何动画)。\n" -"[b]è¦å‘Šï¼š[/b]ä½¿ç”¨æ— é™å¾ªçŽ¯æ—¶è¯·ä¸€å®šè¦åŠ å…¥ä¸€äº›æ—¶é•¿/延迟。0 时长的循环动画(例如" -"å•个ä¸å¸¦å»¶è¿Ÿçš„ [CallbackTweener] æˆ–è€…èŠ‚ç‚¹æ— æ•ˆçš„ [PropertyTweener]ï¼‰å’Œæ— é™ " -"[code]while[/code] å¾ªçŽ¯æ˜¯ä¸€æ ·çš„ï¼Œä¼šå¯¼è‡´æ¸¸æˆå†»ç»“。如果 [SceneTreeTween] 的生命" -"期ä¾èµ–于æŸä¸ªèŠ‚ç‚¹ï¼Œè¯·ä¸€å®šä½¿ç”¨ [method bind_node]。" +"[method kill] 销æ¯ã€è¯¥ [SceneTreeTween] ç»‘å®šçš„èŠ‚ç‚¹è¢«é‡Šæ”¾ã€æˆ–者所有进行动画的" +"å¯¹è±¡éƒ½è¢«é‡Šæ”¾ï¼ˆæ— æ³•å†è¿›è¡Œä»»ä½•动画)。\n" +"[b]è¦å‘Šï¼š[/b]ä½¿ç”¨æ— é™å¾ªçŽ¯æ—¶è¯·ä¸€å®šè¦åŠ å…¥ä¸€äº›æ—¶é•¿/å»¶è¿Ÿã€‚ä¸ºäº†é˜²æ¢æ¸¸æˆå†»ç»“,0 æ—¶" +"长的循环动画(例如å•个ä¸å¸¦å»¶è¿Ÿçš„ [CallbackTweener])会在循环若干次åŽåœæ¢ï¼Œé€ " +"æˆå‡ºä¹Žé¢„料的结果。如果 [SceneTreeTween] 的生命期ä¾èµ–于æŸä¸ªèŠ‚ç‚¹ï¼Œè¯·ä¸€å®šä½¿ç”¨ " +"[method bind_node]。" #: doc/classes/SceneTreeTween.xml msgid "" @@ -68874,7 +69077,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Creates and appends an [IntervalTweener]. This method can be used to create " "delays in the tween animation, as an alternative to using the delay in other " @@ -68971,7 +69173,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Creates and appends a [PropertyTweener]. This method tweens a " "[code]property[/code] of an [code]object[/code] between an initial value and " @@ -69005,7 +69206,7 @@ msgstr "" "åˆ›å»ºå¹¶è¿½åŠ ä¸€ä¸ª [PropertyTweener]。这个方法会将 [code]object[/code] 对象的 " "[code]property[/code] 属性在åˆå§‹å€¼å’Œæœ€ç»ˆå€¼ [code]final_val[/code] 之间进行补" "间,æŒç»æ—¶é—´ä¸º [code]duration[/code] 秒。åˆå§‹å€¼é»˜è®¤ä¸ºè¯¥ [PropertyTweener] å¯" -"动时的值。例如:\n" +"动时该属性的值。例如:\n" "[codeblock]\n" "var tween = create_tween()\n" "tween.tween_property($Sprite, \"position\", Vector2(100, 200), 1)\n" @@ -69027,7 +69228,6 @@ msgstr "" "[/codeblock]" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Emitted when the [SceneTreeTween] has finished all tweening. Never emitted " "when the [SceneTreeTween] is set to infinite looping (see [method " @@ -69038,12 +69238,11 @@ msgid "" msgstr "" "在该 [SceneTreeTween] å®Œæˆæ‰€æœ‰è¡¥é—´æ—¶è§¦å‘。该 [SceneTreeTween] è¢«è®¾ä¸ºæ— é™å¾ªçޝ" "æ—¶ä¸ä¼šè§¦å‘ï¼ˆè§ [method set_loops])。\n" -"[b]注æ„:[/b]触å‘这个信å·åŽï¼Œè¯¥ [SceneTreeTween] ä¼šè¢«ç§»é™¤ï¼ˆç½®ä¸ºæ— æ•ˆï¼‰ï¼Œä½†ä¸æ˜¯" -"ç«‹å³å‘生的,而是在下一个处ç†å¸§ä¸å‘生。在该信å·çš„回调ä¸è°ƒç”¨ [method stop] 会ä¿" -"留该 [SceneTreeTween]。" +"[b]注æ„:[/b]触å‘这个信å·åŽï¼Œè¯¥ [SceneTreeTween] 会在下一个处ç†å¸§ä¸è¢«ç§»é™¤ï¼ˆç½®" +"ä¸ºæ— æ•ˆï¼‰ã€‚åœ¨è¯¥ä¿¡å·çš„回调ä¸è°ƒç”¨ [method stop] å¯ä»¥é˜²æ¢è¯¥ [SceneTreeTween] 被移" +"除。" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Emitted when a full loop is complete (see [method set_loops]), providing the " "loop index. This signal is not emitted after the final loop, use [signal " @@ -69053,7 +69252,6 @@ msgstr "" "会在最åŽä¸€æ¬¡å¾ªçޝåŽè§¦å‘ï¼Œè¿™ç§æƒ…况请使用 [signal finished] 代替。" #: doc/classes/SceneTreeTween.xml -#, fuzzy msgid "" "Emitted when one step of the [SceneTreeTween] is complete, providing the " "step index. One step is either a single [Tweener] or a group of [Tweener]s " @@ -69733,7 +69931,7 @@ msgstr "" #: doc/classes/Shape2D.xml msgid "The shape's custom solver bias." -msgstr "形状的自定义求解器å差。" +msgstr "形状的自定义求解器å置。" #: doc/classes/ShortCut.xml msgid "A shortcut for binding input." @@ -70632,13 +70830,13 @@ msgstr "å¯ç”¨æ¤èŠ‚ç‚¹çš„å‘ˆçŽ°ã€‚å°† [member visible] 更改为 [code]true[/co msgid "" "Transforms [code]local_point[/code] from this node's local space to world " "space." -msgstr "å°† [code]local_point[/code] 从该节点的本地空间转æ¢ä¸ºä¸–界空间。" +msgstr "å°† [code]local_point[/code] 从这个节点的局部空间转æ¢ä¸ºä¸–界空间。" #: doc/classes/Spatial.xml msgid "" "Transforms [code]global_point[/code] from world space to this node's local " "space." -msgstr "å°† [code]global_point[/code] 从世界空间转æ¢åˆ°è¿™ä¸ªèŠ‚ç‚¹çš„æœ¬åœ°ç©ºé—´ã€‚" +msgstr "å°† [code]global_point[/code] 从世界空间转æ¢åˆ°è¿™ä¸ªèŠ‚ç‚¹çš„å±€éƒ¨ç©ºé—´ã€‚" #: doc/classes/Spatial.xml msgid "" @@ -70648,7 +70846,7 @@ msgid "" "offset of [code](2, 0, 0)[/code] would actually add 20 ([code]2 * 10[/code]) " "to the X coordinate." msgstr "" -"通过给定的åç§»é‡ [Vector3] 改å˜èŠ‚ç‚¹çš„ä½ç½®ã€‚\n" +"通过给定的åç§»é‡ [Vector3] 改å˜è¯¥èŠ‚ç‚¹çš„ä½ç½®ã€‚\n" "注æ„,平移 [code]offset[/code] å—节点缩放的影å“,所以如果按例如 [code]" "(10,1,1)[/code] 进行缩放,平移 [code](2,0,0)[/code] 实际上会在 X åæ ‡ä¸Šå¢žåŠ " "20 ([code]2 * 10[/code])。" @@ -70656,23 +70854,48 @@ msgstr "" #: doc/classes/Spatial.xml msgid "" "Changes the node's position by the given offset [Vector3] in local space." -msgstr "通过给定的åç§»é‡ [Vector3] 改å˜èŠ‚ç‚¹åœ¨å±€éƒ¨ç©ºé—´ä¸çš„ä½ç½®ã€‚" +msgstr "通过给定的局部空间åç§»é‡ [Vector3] 改å˜è¯¥èŠ‚ç‚¹çš„ä½ç½®ã€‚" #: doc/classes/Spatial.xml msgid "Updates the [SpatialGizmo] of this node." -msgstr "更新该节点的 [SpatialGizmo]。" +msgstr "更新这个节点的 [SpatialGizmo]。" #: doc/classes/Spatial.xml msgid "" "The [SpatialGizmo] for this node. Used for example in [EditorSpatialGizmo] " "as custom visualization and editing handles in Editor." msgstr "" -"æ¤èŠ‚ç‚¹çš„ [SpatialGizmo]。例如在 [EditorSpatialGizmo] ä¸ç”¨ä½œç¼–辑器ä¸çš„自定义å¯" -"视化和编辑手柄。" +"这个节点的 [SpatialGizmo]。例如在 [EditorSpatialGizmo] ä¸ç”¨ä½œç¼–辑器ä¸çš„自定义" +"å¯è§†åŒ–和编辑手柄。" + +#: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" +"å…¨å±€å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ï¼Œå•ä½ä¸ºå¼§åº¦ï¼Œä»¥ YXZ 欧拉角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z " +"角)。\n" +"[b]注æ„:[/b]åœ¨æ•°å¦æ„ä¹‰ä¸Šï¼Œæ—‹è½¬æ˜¯ä¸€ä¸ªçŸ©é˜µè€Œä¸æ˜¯ä¸€ä¸ªå‘é‡ã€‚这三个欧拉角是旋转矩" +"é˜µæ¬§æ‹‰è§’å‚æ•°åŒ–çš„ä¸‰ä¸ªç‹¬ç«‹å‚æ•°ï¼Œå˜å‚¨åœ¨ [Vector3] æ•°æ®ç»“æž„ä¸å¹¶ä¸æ˜¯å› 为旋转是一个" +"矢é‡ï¼Œè€Œæ˜¯å› 为 [Vector3] æ˜¯ä¸€ç§æ–¹ä¾¿å˜å‚¨ 3 个浮点数的数æ®ç»“æž„ã€‚å› æ¤ï¼Œå¯¹æ—‹è½¬â€œå‘" +"é‡â€åº”用仿射æ“作是没有æ„义的。" #: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." -msgstr "æ¤èŠ‚ç‚¹çš„ä¸–ç•Œç©ºé—´ï¼ˆå…¨å±€ï¼‰[Transform]。" +msgstr "è¿™ä¸ªèŠ‚ç‚¹çš„ä¸–ç•Œç©ºé—´ï¼ˆå…¨å±€ï¼‰å˜æ¢ [Transform]。" + +#: doc/classes/Spatial.xml +msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "这个节点的全局ä½ç½®ã€‚与 [code]global_transform.origin[/code] ç‰ä»·ã€‚" #: doc/classes/Spatial.xml msgid "" @@ -70686,7 +70909,7 @@ msgid "" "point numbers. Therefore, applying affine operations on the rotation " "\"vector\" is not meaningful." msgstr "" -"å±€éƒ¨å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ä»¥å¼§åº¦è¡¨ç¤ºï¼Œä»¥ YXZ-Euler 角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z " +"å±€éƒ¨å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ï¼Œå•ä½ä¸ºå¼§åº¦ï¼Œä»¥ YXZ 欧拉角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z " "角)。\n" "[b]注æ„:[/b]åœ¨æ•°å¦æ„ä¹‰ä¸Šï¼Œæ—‹è½¬æ˜¯ä¸€ä¸ªçŸ©é˜µè€Œä¸æ˜¯ä¸€ä¸ªå‘é‡ã€‚这三个欧拉角是旋转矩" "é˜µæ¬§æ‹‰è§’å‚æ•°åŒ–çš„ä¸‰ä¸ªç‹¬ç«‹å‚æ•°ï¼Œå˜å‚¨åœ¨ [Vector3] æ•°æ®ç»“æž„ä¸å¹¶ä¸æ˜¯å› 为旋转是一个" @@ -70707,17 +70930,17 @@ msgid "" "transformation matrices in Godot, the scale values will either be all " "positive or all negative." msgstr "" -"æœ¬åœ°å˜æ¢ä¸çš„缩放。\n" +"å±€éƒ¨å˜æ¢çš„缩放部分。\n" "[b]注æ„:[/b]3D ä¸ï¼Œå˜æ¢çŸ©é˜µæ˜¯æ— 法分解出æ£è´Ÿæ··åˆçš„缩放的。由于 Godot ä¸ä½¿ç”¨å˜" "æ¢çŸ©é˜µæ¥è¡¨ç¤ºç¼©æ”¾ï¼Œå¾—到的缩放值è¦ä¹ˆå…¨æ£ã€è¦ä¹ˆå…¨è´Ÿã€‚" #: doc/classes/Spatial.xml msgid "Local space [Transform] of this node, with respect to the parent node." -msgstr "该节点相对于父节点的局部空间 [Transform]。" +msgstr "这个节点相对于父节点的局部空间 [Transform]。" #: doc/classes/Spatial.xml msgid "Local translation of this node." -msgstr "æ¤èŠ‚ç‚¹çš„å±€éƒ¨å˜æ¢ã€‚" +msgstr "è¿™ä¸ªèŠ‚ç‚¹çš„å±€éƒ¨å˜æ¢ã€‚" #: doc/classes/Spatial.xml msgid "" @@ -72688,16 +72911,16 @@ msgstr "ç²¾çµä¸Šä¸€ä¸ªåƒç´ 宽度的大å°ï¼Œä»¥ 3D 缩放。" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " "This is because opaque objects are not sorted, while transparent objects are " "sorted from back to front (subject to priority)." msgstr "" -"设置精çµçš„æ¸²æŸ“优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n" -"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认" -"值)时适用。\n" +"设置该精çµçš„æ¸²æŸ“优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n" +"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant " +"ALPHA_CUT_DISABLED](默认值)时适用。\n" "[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº" "æ–¹å¼ã€‚è¿™æ˜¯å› ä¸ºä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。" @@ -73660,6 +73883,29 @@ msgid "" "\"Godot\"]]))\n" "[/codeblock]" msgstr "" +"æ ¼å¼åŒ–å—符串,将所有的 [code]placeholder[/code] 替æ¢ä¸º [code]values[/code] ä¸" +"çš„å…ƒç´ ã€‚\n" +"[code]values[/code] å¯ä»¥æ˜¯ [Dictionary] 或 [Array]。[code]placeholder[/code] " +"ä¸çš„下划线都会事先被替æ¢ä¸ºå¯¹åº”çš„é”®ã€‚æ•°ç»„å…ƒç´ ä½¿ç”¨å…¶ç´¢å¼•å·ä½œä¸ºé”®ã€‚\n" +"[codeblock]\n" +"# 输出:Waiting for Godot 是 Samuel Beckett çš„æˆå‰§ï¼ŒGodot 引擎由æ¤å¾—å。\n" +"var use_array_values = \"Waiting for {0} 是 {1} çš„æˆå‰§ï¼Œ{0} 引擎由æ¤å¾—" +"å。\"\n" +"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n" +"\n" +"# 输出:第 42 å·ç”¨æˆ·æ˜¯ Godot。\n" +"print(\"第 {id} å·ç”¨æˆ·æ˜¯ {name}。\".format({\"id\": 42, \"name\": " +"\"Godot\"}))\n" +"[/codeblock]\n" +"[code]values[/code] 为数组时还会进行一些é¢å¤–的处ç†ã€‚如果 [code]placeholder[/" +"code] ä¸ä¸åŒ…å«ä¸‹åˆ’线,该数组ä¸çš„å…ƒç´ ä¼šä¾æ¬¡å¯¹å‡ºçŽ°çš„å ä½ç¬¦è¿›è¡Œæ›¿æ¢ï¼›å¦‚果数组元" +"ç´ æ˜¯ä¸€ä¸ªåŒ…å«ä¸¤ä¸ªå…ƒç´ 的数组,那么它就会被解释为键值对。\n" +"[codeblock]\n" +"# 输出:第 42 å·ç”¨æˆ·æ˜¯ Godot。\n" +"print(\"第 {} å·ç”¨æˆ·æ˜¯ {}。\".format([42, \"Godot\"], \"{}\"))\n" +"print(\"第 {id} å·ç”¨æˆ·æ˜¯ {name}。\".format([[\"id\", 42], [\"name\", " +"\"Godot\"]]))\n" +"[/codeblock]" #: doc/classes/String.xml msgid "If the string is a valid file path, returns the base directory name." @@ -73924,7 +74170,6 @@ msgstr "" "[/codeblock]" #: doc/classes/String.xml -#, fuzzy msgid "" "Returns [code]true[/code] if this string contains a valid integer.\n" "[codeblock]\n" @@ -73937,11 +74182,11 @@ msgid "" msgstr "" "如果该å—ç¬¦ä¸²åŒ…å«æœ‰æ•ˆçš„æ•´æ•°ï¼Œåˆ™è¿”回 [code]true[/code]\n" "[codeblock]\n" -"print(\"7\".is_valid_int()) # 输出“Trueâ€\n" -"print(\"14.6\".is_valid_int()) # 输出“Falseâ€\n" -"print(\"L\".is_valid_int()) # 输出“Falseâ€\n" -"print(\"+3\".is_valid_int()) # 输出“Trueâ€\n" -"print(\"-12\".is_valid_int()) # 输出“Trueâ€\n" +"print(\"7\".is_valid_integer()) # 输出“Trueâ€\n" +"print(\"14.6\".is_valid_integer()) # 输出“Falseâ€\n" +"print(\"L\".is_valid_integer()) # 输出“Falseâ€\n" +"print(\"+3\".is_valid_integer()) # 输出“Trueâ€\n" +"print(\"-12\".is_valid_integer()) # 输出“Trueâ€\n" "[/codeblock]" #: doc/classes/String.xml @@ -74483,6 +74728,10 @@ msgid "" "directly from creating a canvas item in the [VisualServer] with [method " "VisualServer.canvas_item_create]." msgstr "" +"使用由给定的 [RID] æ ‡è¯†çš„ç”»å¸ƒé¡¹ç»˜åˆ¶è¿™ä¸ªæ ·å¼ç›’。\n" +"[RID] 值既å¯ä»¥é€šè¿‡å¯¹çŽ°æœ‰çš„åŸºäºŽ [CanvasItem] 节点调用 [method CanvasItem." +"get_canvas_item] 获得,也å¯ä»¥é€šè¿‡ [method VisualServer.canvas_item_create] ç›´" +"接在 [VisualServer] 上创建画布项获得。" #: doc/classes/StyleBox.xml msgid "Returns the size of this [StyleBox] without the margins." @@ -76257,12 +76506,12 @@ msgstr "设置特定行的文本。" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" -"如果 [code]bookmark[/code] 为 true,则为行 [code]line[/code] 设置书ç¾ã€‚如果 " -"[code]bookmark[/code] 为 falseï¼Œåˆ™åˆ é™¤è¯¥ä¹¦ç¾ã€‚\n" +"如果 [code]bookmark[/code] 为 [code]true[/code],则为行 [code]line[/code] " +"设置书ç¾ã€‚如果 [code]bookmark[/code] 为 [code]false[/code]ï¼Œåˆ™åˆ é™¤è¯¥ä¹¦ç¾ã€‚\n" "ä¹¦ç¾æ˜¾ç¤ºåœ¨ [member breakpoint_gutter] ä¸ã€‚" #: doc/classes/TextEdit.xml @@ -76334,9 +76583,8 @@ msgid "If [code]true[/code], a right-click displays the context menu." msgstr "为 [code]true[/code] æ—¶å³é”®å•击会显示上下文èœå•。" #: doc/classes/TextEdit.xml -#, fuzzy msgid "If [code]true[/code], allow drag and drop of selected text." -msgstr "如果为 [code]true[/code],则å¯ä»¥é€‰æ‹©å’Œç¼–辑该值。" +msgstr "如果为 [code]true[/code],则å…许拖放选ä¸çš„æ–‡æœ¬ã€‚" #: doc/classes/TextEdit.xml msgid "" @@ -77018,7 +77266,7 @@ msgid "" msgstr "" "是 [Texture3D] å’Œ [TextureArray] 的基类。ä¸èƒ½ç›´æŽ¥ä½¿ç”¨ï¼Œä½†åŒ…å«è®¿é—®å’Œä½¿ç”¨ " "[Texture3D] å’Œ [TextureArray] 的所有必è¦åŠŸèƒ½ã€‚æ•°æ®æ˜¯ä»¥æ¯å±‚为å•ä½è®¾ç½®çš„。对于 " -"[Texture3D],层指定了深度或 Z-index,它们å¯ä»¥è¢«è§†ä¸ºä¸€å †äºŒç»´åˆ‡ç‰‡ã€‚åŒæ ·åœ°ï¼Œå¯¹" +"[Texture3D],层指定了深度或 Z-index,它们å¯ä»¥è¢«è§†ä¸ºä¸€å † 2D åˆ‡ç‰‡ã€‚åŒæ ·åœ°ï¼Œå¯¹" "于 [TextureArray],层指定了数组层。" #: doc/classes/TextureLayered.xml @@ -77065,7 +77313,7 @@ msgstr "" msgid "" "Sets the data for the specified layer. Data takes the form of a 2-" "dimensional [Image] resource." -msgstr "设置指定图层的数æ®ã€‚æ•°æ®çš„形弿˜¯äºŒç»´çš„[Image]资æºã€‚" +msgstr "设置指定图层的数æ®ã€‚æ•°æ®çš„形弿˜¯äºŒç»´çš„ [Image] 资æºã€‚" #: doc/classes/TextureLayered.xml msgid "Returns a dictionary with all the data used by this texture." @@ -78398,7 +78646,7 @@ msgstr "" #: doc/classes/TileMap.xml msgid "The assigned [TileSet]." -msgstr "指定的[TileSet]图å—集。" +msgstr "指定的 [TileSet] 图å—集。" #: doc/classes/TileMap.xml msgid "Emitted when a tilemap setting has changed." @@ -78735,7 +78983,7 @@ msgstr "返回图å—çš„ [enum TileMode]。" #: doc/classes/TileSet.xml msgid "Returns the tile's Z index (drawing layer)." -msgstr "返回图å—çš„Z索引,å³ç»˜åˆ¶å±‚。" +msgstr "返回图å—çš„ Z 索引(绘制层)。" #: doc/classes/TileSet.xml msgid "Sets a light occluder for the tile." @@ -78807,7 +79055,7 @@ msgstr "å¯ç”¨å›¾å—形状上的å•å‘碰撞。" #: doc/classes/TileSet.xml msgid "Sets a [Transform2D] on a tile's shape." -msgstr "在图å—的形状上设置[Transform2D]。" +msgstr "在图å—的形状上设置 [Transform2D]。" #: doc/classes/TileSet.xml msgid "Sets an array of shapes for the tile, enabling collision." @@ -78823,7 +79071,7 @@ msgstr "设置图å—的纹ç†å移。" #: doc/classes/TileSet.xml msgid "Sets the tile's [enum TileMode]." -msgstr "设置图å—çš„[enum TileMode]。" +msgstr "设置图å—çš„ [enum TileMode]。" #: doc/classes/TileSet.xml msgid "Sets the tile's drawing index." @@ -79060,7 +79308,7 @@ msgid "" "[code]name[/code]. The [code]bias[/code] value is the offset from UTC in " "minutes, since not all time zones are multiples of an hour from UTC." msgstr "" -"以å—典的形å¼è¿”å›žå½“å‰æ—¶åŒºï¼ŒåŒ…å«çš„键为:[code]bias[/code](å倚)和 " +"以å—典的形å¼è¿”å›žå½“å‰æ—¶åŒºï¼ŒåŒ…å«çš„键为:[code]bias[/code](å置)和 " "[code]name[/code](å称)。[code]bias[/code] 的值是从 UTC çš„åç§»é‡ï¼Œå•ä½ä¸º" "åˆ†ï¼Œå› ä¸ºå¹¶ä¸æ˜¯æ‰€æœ‰æ—¶åŒºä¸Ž UTC 的时间差都是整数å€å°æ—¶ã€‚" @@ -79431,7 +79679,7 @@ msgid "" msgstr "" "如果为 [code]true[/code],åªè¦æŒ‰ä¸‹çš„æ‰‹æŒ‡è¿›å‡ºæŒ‰é’®ï¼Œå°±ä¼šå‘出 [signal pressed] " "å’Œ[signal released] ]ä¿¡å·ï¼Œå³ä½¿åŽ‹åŠ›å¼€å§‹äºŽæŒ‰é’®çš„æœ‰æ•ˆåŒºåŸŸä¹‹å¤–ã€‚\n" -"[b]注æ„:[/b]è¿™æ˜¯ä¸€ç§ \"pass-by\" çš„æŒ‰åŽ‹æ¨¡å¼ ï¼Œè€Œä¸æ˜¯ \"bypass\"。" +"[b]注æ„:[/b]这是一ç§â€œpass-byâ€çš„æŒ‰åŽ‹æ¨¡å¼ ï¼Œè€Œä¸æ˜¯â€œbypassâ€ã€‚" #: doc/classes/TouchScreenButton.xml msgid "The button's texture for the pressed state." @@ -79888,7 +80136,6 @@ msgid "Control to show a tree of items." msgstr "ä»¥æ ‘çŠ¶å½¢å¼æ˜¾ç¤ºé¡¹ç›®çš„æŽ§ä»¶ã€‚" #: doc/classes/Tree.xml -#, fuzzy msgid "" "This shows a tree of items that can be selected, expanded and collapsed. The " "tree can have multiple columns with custom controls like text editing, " @@ -79925,8 +80172,8 @@ msgid "" msgstr "" "这展示了一个å¯ä»¥é€‰æ‹©ã€å±•开和折å çš„é¡¹ç›®æ ‘ã€‚è¯¥æ ‘å¯ä»¥æœ‰å¤šåˆ—的自定义控件,如文本" "ç¼–è¾‘ã€æŒ‰é’®å’Œå¼¹å‡ºçª—å£ã€‚它对于结构化显示和互动很有用。\n" -"æ ‘é€šè¿‡ä»£ç 建立,使用[TreeItem]å¯¹è±¡æ¥æž„建结构。它们有一个å•ç‹¬æ ¹èŠ‚ç‚¹ï¼Œä½†å¦‚æžœæ·»" -"åŠ ä¸€ä¸ªè™šæ‹Ÿçš„éšè—æ ¹èŠ‚ç‚¹ï¼Œå°±å¯ä»¥æ¨¡æ‹Ÿå¤šä¸ªæ ¹ã€‚\n" +"æ ‘é€šè¿‡ä»£ç 建立,使用 [TreeItem] å¯¹è±¡æ¥æž„建结构。它们有一个å•ç‹¬æ ¹èŠ‚ç‚¹ï¼Œä½†å¦‚æžœ" +"æ·»åŠ ä¸€ä¸ªè™šæ‹Ÿçš„éšè—æ ¹èŠ‚ç‚¹ï¼Œå°±å¯ä»¥æ¨¡æ‹Ÿå¤šä¸ªæ ¹ã€‚\n" "[codeblock]\n" "func _ready():\n" " var tree = Tree.new()\n" @@ -79937,9 +80184,17 @@ msgstr "" " var subchild1 = tree.create_item(child1)\n" " subchild1.set_text(0, \"Subchild1\")\n" "[/codeblock]\n" -"è¦é历一个[Tree]对象ä¸çš„æ‰€æœ‰[TreeItem]对象,在通过[method get_root]èŽ·å¾—æ ¹ä¹‹" -"åŽï¼Œä½¿ç”¨[method TreeItem.get_next]å’Œ[method TreeItem.get_children]æ–¹æ³•ã€‚ä½ å¯" -"以对一个[TreeItem]使用[method Object.free]æ¥æŠŠå®ƒä»Ž[Tree]ä¸ç§»é™¤ã€‚" +"è¦é历一个 [Tree] 对象ä¸çš„æ‰€æœ‰ [TreeItem] 对象,在通过 [method get_root] 获得" +"æ ¹ä¹‹åŽï¼Œä½¿ç”¨ [method TreeItem.get_next] å’Œ [method TreeItem.get_children] æ–¹" +"æ³•ã€‚ä½ å¯ä»¥å¯¹ä¸€ä¸ª [TreeItem] 使用 [method Object.free] æ¥æŠŠå®ƒä»Ž [Tree] ä¸ç§»" +"除。\n" +"[b]å¢žé‡æœç´¢ï¼š[/b]与 [ItemList] å’Œ [PopupMenu] 类似,[Tree] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶" +"在列表ä¸è¿›è¡Œæœç´¢ã€‚按下与æŸä¸ªæ¡ç›®åç§°é¦–å—æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„" +"第一个æ¡ç›®ã€‚在æ¤ä¹‹åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰" +"键,选ä¸ä»¥è¯¥å—æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å—æ¯å¯¹åº”的按键,直接匹é…" +"并选䏿‰€éœ€çš„æ¡ç›®ã€‚è¿™ä¸¤ä¸ªåŠ¨ä½œéƒ½ä¼šåœ¨æœ€åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—è¡¨é¡¶ç«¯ã€‚ä½ å¯ä»¥é€š" +"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] " +"修改超时时长。" #: doc/classes/Tree.xml msgid "Clears the tree. This removes all items." @@ -80009,7 +80264,7 @@ msgid "" "Returns the rectangle for custom popups. Helper to create custom cell " "controls that display a popup. See [method TreeItem.set_cell_mode]." msgstr "" -"返回自定义弹出窗å£çš„矩形。帮助创建显示弹出å¼çš„自定义å•å…ƒæ ¼æŽ§ä»¶ã€‚å‚阅[method " +"返回自定义弹出窗å£çš„矩形。帮助创建显示弹出å¼çš„自定义å•å…ƒæ ¼æŽ§ä»¶ã€‚è§ [method " "TreeItem.set_cell_mode]。" #: doc/classes/Tree.xml @@ -80022,10 +80277,10 @@ msgid "" "To get the item which the returned drop section is relative to, use [method " "get_item_at_position]." msgstr "" -"返回ä½äºŽ[code]position[/code]的放置部分,如果没有项目,则返回-100。\n" -"在 \"项目上方\"ã€\"项目之上\"å’Œ \"项目下方\"的放置部分将分别返回-1ã€0或1çš„" -"值。请å‚阅[enum DropModeFlags]以了解æ¯ä¸ªæ”¾ç½®éƒ¨åˆ†çš„æè¿°ã€‚\n" -"è¦èŽ·å¾—è¿”å›žçš„æ”¾ç½®éƒ¨åˆ†ç›¸å¯¹é¡¹ï¼Œè¯·ä½¿ç”¨[method get_item_at_position]。" +"返回ä½äºŽ [code]position[/code] 的放置部分,如果没有项目,则返回 -100。\n" +"在“项目上方â€â€œé¡¹ç›®ä¹‹ä¸Šâ€å’Œâ€œé¡¹ç›®ä¸‹æ–¹â€çš„æ”¾ç½®éƒ¨åˆ†å°†åˆ†åˆ«è¿”回 -1ã€0 或 1 的值。请å‚" +"阅 [enum DropModeFlags] 以了解æ¯ä¸ªæ”¾ç½®éƒ¨åˆ†çš„æè¿°ã€‚\n" +"è¦èŽ·å¾—è¿”å›žçš„æ”¾ç½®éƒ¨åˆ†ç›¸å¯¹é¡¹ï¼Œè¯·ä½¿ç”¨ [method get_item_at_position]。" #: doc/classes/Tree.xml msgid "" @@ -80117,7 +80372,7 @@ msgid "" "is_selected]." msgstr "" "返回当å‰èŽ·å¾—ç„¦ç‚¹çš„åˆ—ï¼Œå¦‚æžœæ²¡æœ‰ç„¦ç‚¹åˆ—ï¼Œåˆ™è¿”å›ž -1。\n" -"在[constant SELECT_SINGLE] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—是被选ä¸çš„列。在 [constant " +"在 [constant SELECT_SINGLE] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—是被选ä¸çš„列。在 [constant " "SELECT_ROW] 模å¼ä¸‹ï¼Œå¦‚果有任æ„项被选ä¸ï¼Œç„¦ç‚¹åˆ—总是 0。在 [constant " "SELECT_MULTI] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—æ˜¯ç„¦ç‚¹å…‰æ ‡ä¸‹çš„åˆ—ï¼Œä½†ä¸ä¸€å®šæœ‰åˆ—被选ä¸ã€‚\n" "è¦åˆ¤æ–一个项的æŸä¸€åˆ—是å¦è¢«é€‰ä¸ï¼Œè¯·ä½¿ç”¨ [method TreeItem.is_selected]。" @@ -80142,12 +80397,12 @@ msgid "" "will use their \"min_width\" in a similar fashion to [member Control." "size_flags_stretch_ratio]." msgstr "" -"设置一个列的最å°å®½åº¦ã€‚拥有“Expandâ€æ ‡å¿—的列将以类似于 [member Control." +"设置æŸä¸€åˆ—的最å°å®½åº¦ã€‚拥有“Expandâ€æ ‡å¿—的列将以类似于 [member Control." "size_flags_stretch_ratio] 的方å¼ä½¿ç”¨å…¶â€œmin_widthâ€æœ€å°å®½åº¦ã€‚" #: doc/classes/Tree.xml msgid "Sets the title of a column." -msgstr "è®¾ç½®ä¸€ä¸ªåˆ—çš„æ ‡é¢˜ã€‚" +msgstr "设置æŸä¸€åˆ—çš„æ ‡é¢˜ã€‚" #: doc/classes/Tree.xml msgid "" @@ -80321,7 +80576,7 @@ msgid "" "other flags." msgstr "" "ç¦ç”¨æ‰€æœ‰æ”¾ç½®éƒ¨åˆ†ï¼Œä½†ä»ç„¶å…许通过 [method get_drop_section_at_position] 检" -"测“物å“上â€çš„æ”¾ç½®éƒ¨åˆ†ã€‚\n" +"测“项目上â€çš„æ”¾ç½®éƒ¨åˆ†ã€‚\n" "[b]注æ„:[/b]è¿™æ˜¯é»˜è®¤çš„æ ‡å¿—ï¼Œå½“ä¸Žå…¶ä»–æ ‡å¿—ç»“åˆæ—¶ï¼Œå®ƒæ²¡æœ‰æ•ˆæžœã€‚" #: doc/classes/Tree.xml @@ -80385,7 +80640,7 @@ msgid "" "Draws the guidelines if not zero, this acts as a boolean. The guideline is a " "horizontal line drawn at the bottom of each item." msgstr "" -"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å‚考线,这作为一个布尔值。å‚考线是在æ¯ä¸ªé¡¹çš„åº•éƒ¨ç”»çš„ä¸€æ¡æ°´å¹³" +"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å‚考线,行为类似于布尔值。å‚考线是在æ¯ä¸ªé¡¹çš„åº•éƒ¨ç”»çš„ä¸€æ¡æ°´å¹³" "线。" #: doc/classes/Tree.xml @@ -80393,8 +80648,8 @@ msgid "" "Draws the relationship lines if not zero, this acts as a boolean. " "Relationship lines are drawn at the start of child items to show hierarchy." msgstr "" -"如果ä¸ä¸ºé›¶ï¼Œåˆ™ç»˜åˆ¶å…³ç³»çº¿ï¼Œè¿™ä½œä¸ºä¸€ä¸ªå¸ƒå°”值。关系线在å项的开始处绘制,以显示" -"层次结构。" +"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å…³ç³»çº¿ï¼Œè¡Œä¸ºç±»ä¼¼äºŽå¸ƒå°”值。关系线在å项的开始处绘制,以显示层" +"次结构。" #: doc/classes/Tree.xml msgid "" @@ -80657,19 +80912,20 @@ msgstr "返回使用 [method set_metadata] 为指定列设置的元数æ®ã€‚" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." -msgstr "è¿”å›žæ ‘ä¸çš„下一个 TreeItem,如果没有,则返回一个空对象。" +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." +msgstr "è¿”å›žæ ‘ä¸çš„下一个兄弟 TreeItem,如果没有,则返回一个空对象。" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." msgstr "" -"è¿”å›žæ ‘ä¸ä¸‹ä¸€ä¸ªå¯è§çš„ TreeItem,如果没有,则返回空对象。\n" -"如果 [code]wrap[/code] 被å¯ç”¨ï¼Œå½“在最åŽä¸€ä¸ªå¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•å°†çŽ¯ç»•åˆ°æ ‘" +"è¿”å›žæ ‘ä¸ä¸‹ä¸€ä¸ªå¯è§çš„兄弟 TreeItem,如果没有,则返回空对象。\n" +"如果å¯ç”¨äº† [code]wrap[/code],当在最åŽä¸€ä¸ªå¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•å°†çŽ¯ç»•åˆ°æ ‘" "ä¸çš„第一个å¯è§å…ƒç´ ,å¦åˆ™å®ƒå°†è¿”回 [code]null[/code]。" #: doc/classes/TreeItem.xml @@ -80678,19 +80934,20 @@ msgstr "返回父级 TreeItem,如果没有,则返回一个空对象。" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." -msgstr "è¿”å›žæ ‘ä¸çš„å‰ä¸€ä¸ª TreeItem,如果没有,则返回一个空对象。" +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." +msgstr "è¿”å›žæ ‘ä¸çš„å‰ä¸€ä¸ªå…„弟 TreeItem,如果没有,则返回一个空对象。" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." msgstr "" -"è¿”å›žæ ‘ä¸å‰ä¸€ä¸ªå¯è§çš„ TreeItem,如果没有,则返回 null 对象。\n" -"如果 [code]wrap[/code] 被å¯ç”¨ï¼Œå½“在第一个å¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•å°†çŽ¯ç»•åˆ°æ ‘ä¸" +"è¿”å›žæ ‘ä¸å‰ä¸€ä¸ªå¯è§çš„兄弟 TreeItem,如果没有,则返回 null 对象。\n" +"如果å¯ç”¨äº† [code]wrap[/code],当在第一个å¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•å°†çŽ¯ç»•åˆ°æ ‘ä¸" "最åŽä¸€ä¸ªå¯è§å…ƒç´ ,å¦åˆ™å®ƒå°†è¿”回 [code]null[/code]。" #: doc/classes/TreeItem.xml @@ -82385,7 +82642,7 @@ msgstr "[VBoxContainer] çš„å…ƒç´ ä¹‹é—´çš„åž‚ç›´ç©ºé—´ã€‚" #: doc/classes/Vector2.xml msgid "Vector used for 2D math." -msgstr "用于二维数å¦çš„å‘é‡ã€‚" +msgstr "用于 2D æ•°å¦çš„å‘é‡ã€‚" #: doc/classes/Vector2.xml msgid "" @@ -82995,11 +83252,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -83106,8 +83363,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -83855,7 +84112,6 @@ msgid "The subdivision amount of the fourth quadrant on the shadow atlas." msgstr "阴影图集上第四象é™çš„细分é‡ã€‚" #: doc/classes/Viewport.xml -#, fuzzy msgid "" "The shadow atlas' resolution (used for omni and spot lights). The value will " "be rounded up to the nearest power of 2.\n" @@ -83865,8 +84121,9 @@ msgid "" "manually (typically at least [code]256[/code])." msgstr "" "阴影图集的分辨率(用于全å‘光和èšå…‰ï¼‰ã€‚该值将四èˆäº”入到最接近的 2 的幂。\n" -"[b]注æ„:[/b]如果设置为 0,阴影将ä¸å¯è§ã€‚由于用户创建的视区默认值为 0ï¼Œå› æ¤å¿…" -"须手动将æ¤å€¼è®¾ç½®ä¸ºå¤§äºŽ 0。" +"[b]注æ„:[/b]如果设置为 [code]0[/code],点阴影和方å‘阴影[i]都[/i]å°†ä¸å¯è§ã€‚ç”±" +"于用户创建的视区默认值为 [code]0[/code]ï¼Œå› æ¤å¿…须手动将æ¤å€¼è®¾ç½®ä¸ºå¤§äºŽ " +"[code]0[/code](一般至少是 [code]256[/code])。" #: doc/classes/Viewport.xml msgid "" @@ -83896,7 +84153,7 @@ msgstr "如果为 [code]true[/code],尺寸é‡å†™ä¹Ÿä¼šå½±å“拉伸。" msgid "" "If [code]true[/code], the viewport should render its background as " "transparent." -msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—åº”ä½¿å…¶èƒŒæ™¯æ¸²æŸ“ä¸ºé€æ˜Žã€‚" +msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†åŒºåº”ä½¿å…¶èƒŒæ™¯æ¸²æŸ“ä¸ºé€æ˜Žã€‚" #: doc/classes/Viewport.xml msgid "" @@ -83905,6 +84162,9 @@ msgid "" "USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since " "HDR is not supported for 2D." msgstr "" +"视区的渲染模å¼ã€‚\n" +"[b]注æ„:[/b]如果设为 [constant USAGE_2D] 或 [constant " +"USAGE_2D_NO_SAMPLING],则å¯ç”¨ [member hdr] ä¸ä¼šç”Ÿæ•ˆï¼Œå› 为 2D 䏿”¯æŒ HDR。" #: doc/classes/Viewport.xml msgid "" @@ -89008,8 +89268,16 @@ msgid "Sets the viewport's global transformation matrix." msgstr "è®¾ç½®è§†çª—çš„å…¨å±€å˜æ¢çŸ©é˜µã€‚" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." -msgstr "如果为 [code]true[/code],视窗将呈现为 hdr。" +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" +"如果为 " +"[code]true[/code],该视区会渲染至高动æ€èŒƒå›´ï¼ˆHDRï¼‰è€Œä¸æ˜¯æ ‡å‡†åЍæ€èŒƒå›´ï¼ˆSDR)。" +"å¦è¯·å‚阅 [method viewport_set_use_32_bpc_depth]。\n" +"[b]注æ„:[/b]仅在 GLES3 åŽç«¯å¯ç”¨ã€‚" #: doc/classes/VisualServer.xml msgid "If [code]true[/code], the viewport's canvas is not rendered." @@ -89108,6 +89376,19 @@ msgstr "设置视窗的 2D/3D 模å¼ã€‚é€‰é¡¹è§ [enum ViewportUsage] 常é‡ã€‚" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" +"如果为 [code]true[/code],分é…该视区的帧缓冲时将使用完整浮点数精度(32 " +"ä½ï¼‰è€Œä¸æ˜¯åŠæµ®ç‚¹æ•°ç²¾åº¦ï¼ˆ16 ä½ï¼‰ã€‚åªæœ‰åœ¨åŒä¸€ä¸ª [Viewport] 上通过 [method " +"viewport_set_use_32_bpc_depth] å°† HDR 设为 [code]true[/code] 时有效。\n" +"[b]注æ„:[/b]仅在 GLES3 åŽç«¯ä¸å¯ç”¨ã€‚" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" @@ -89237,7 +89518,7 @@ msgstr "ç”±å…个é¢ç»„æˆçš„纹ç†ï¼Œå¯ä»¥åœ¨ç€è‰²å™¨ä¸ä½¿ç”¨ [code]vec3[/co #: doc/classes/VisualServer.xml msgid "An array of 2-dimensional textures." -msgstr "一组二维纹ç†ã€‚" +msgstr "二维纹ç†çš„æ•°ç»„。" #: doc/classes/VisualServer.xml msgid "A 3-dimensional texture with width, height, and depth." @@ -89473,17 +89754,17 @@ msgstr "第三次拆分所å ç”¨çš„é˜´å½±å›¾é›†çš„æ¯”ä¾‹ã€‚ç¬¬å››ä¸ªæ‹†åˆ†å æ® msgid "" "Normal bias used to offset shadow lookup by object normal. Can be used to " "fix self-shadowing artifacts." -msgstr "法线å移,用于抵消物体法线的阴影查找。å¯ä»¥ç”¨æ¥ä¿®å¤è‡ªé˜´å½±çš„伪影。" +msgstr "法线å置,用于抵消物体法线的阴影查找。å¯ä»¥ç”¨æ¥ä¿®å¤è‡ªé˜´å½±çš„伪影。" #: doc/classes/VisualServer.xml msgid "Bias the shadow lookup to fix self-shadowing artifacts." -msgstr "对阴影查找进行å移,以修å¤è‡ªæˆ‘阴影的å‡è±¡ã€‚" +msgstr "对阴影查找进行å置,以修å¤è‡ªæˆ‘阴影的å‡è±¡ã€‚" #: doc/classes/VisualServer.xml msgid "" "Increases bias on further splits to fix self-shadowing that only occurs far " "away from the camera." -msgstr "å¢žåŠ å¯¹è¿›ä¸€æ¥åˆ†å‰²çš„å差,以修å¤ä»…在远离相机的地方å‘生的自身阴影。" +msgstr "å¢žåŠ å¯¹è¿›ä¸€æ¥åˆ†å‰²çš„å置,以修å¤ä»…在远离相机的地方å‘生的自身阴影。" #: doc/classes/VisualServer.xml msgid "Represents the size of the [enum LightParam] enum." @@ -89971,7 +90252,7 @@ msgid "" "Use a specified canvas layer as the background. This can be useful for " "instantiating a 2D scene in a 3D world." msgstr "" -"使用一个指定的画布层作为背景。这对在三维世界ä¸å®žä¾‹åŒ–一个二维场景很有用。" +"使用一个指定的画布层作为背景。这对在 3D 世界ä¸å®žä¾‹åŒ–一个 2D 场景很有用。" #: doc/classes/VisualServer.xml msgid "" @@ -93917,7 +94198,7 @@ msgid "" "current and potential collisions. When using multi-threaded physics, access " "is limited to [code]_physics_process(delta)[/code] in the main thread." msgstr "" -"直接访问世界物ç†äºŒç»´ç©ºé—´çжæ€ã€‚用于查询当å‰å’Œæ½œåœ¨çš„ç¢°æ’žã€‚ä½¿ç”¨å¤šçº¿ç¨‹ç‰©ç†æ—¶ï¼Œè®¿" +"ç›´æŽ¥è®¿é—®ä¸–ç•Œç‰©ç† 2D 空间状æ€ã€‚用于查询当å‰å’Œæ½œåœ¨çš„ç¢°æ’žã€‚ä½¿ç”¨å¤šçº¿ç¨‹ç‰©ç†æ—¶ï¼Œè®¿" "问仅é™äºŽä¸»çº¿ç¨‹ä¸çš„ [code]_physics_process(delta)[/code]。" #: doc/classes/World2D.xml diff --git a/doc/translations/zh_TW.po b/doc/translations/zh_TW.po index 63312338fc..59cd8b199b 100644 --- a/doc/translations/zh_TW.po +++ b/doc/translations/zh_TW.po @@ -948,7 +948,14 @@ msgid "" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml -msgid "Like [method print], but prints only when used in debug mode." +msgid "" +"Like [method print], but includes the current stack frame when running with " +"the debugger turned on.\n" +"Output in the console would look something like this:\n" +"[codeblock]\n" +"Test print\n" +" At: res://test.gd:15:_process()\n" +"[/codeblock]" msgstr "" #: modules/gdscript/doc_classes/@GDScript.xml @@ -7798,8 +7805,8 @@ msgstr "" #: doc/classes/ARVRController.xml msgid "" "The degree to which the controller vibrates. Ranges from [code]0.0[/code] to " -"[code]1.0[/code] with precision [code].01[/code]. If changed, updates " -"[member ARVRPositionalTracker.rumble] accordingly.\n" +"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] " +"accordingly.\n" "This is a useful property to animate if you want the controller to vibrate " "for a limited duration." msgstr "" @@ -10080,7 +10087,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree." msgstr "" #: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml -msgid "Bus on which this audio is playing." +msgid "" +"Bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer.xml @@ -10245,7 +10258,13 @@ msgid "" msgstr "" #: doc/classes/AudioStreamPlayer3D.xml -msgid "The bus on which this audio is playing." +msgid "" +"The bus on which this audio is playing.\n" +"[b]Note:[/b] When setting this property, keep in mind that no validation is " +"performed to see if the given name matches an existing bus. This is because " +"audio bus layouts might be loaded after this property is set. If this given " +"name can't be resolved at runtime, it will fall back to [code]\"Master\"[/" +"code]." msgstr "" #: doc/classes/AudioStreamPlayer3D.xml @@ -11859,7 +11878,12 @@ msgstr "" #: doc/classes/Camera.xml msgid "" -"If [code]true[/code], the ancestor [Viewport] is currently using this camera." +"If [code]true[/code], the ancestor [Viewport] is currently using this " +"camera.\n" +"If multiple cameras are in the scene, one will always be made current. For " +"example, if two [Camera] nodes are present in the scene and only one is " +"current, setting one camera's [member current] to [code]false[/code] will " +"cause the other camera to be made current." msgstr "" #: doc/classes/Camera.xml @@ -20287,7 +20311,7 @@ msgstr "" msgid "" "Saves the editor feature profile to a file in JSON format. It can then be " "imported using the feature profile manager's [b]Import[/b] button or the " -"[method load_from_file] button." +"[method load_from_file] method." msgstr "" #: doc/classes/EditorFeatureProfile.xml @@ -23679,7 +23703,7 @@ msgstr "" #: doc/classes/Environment.xml msgid "" "The tonemapping mode to use. Tonemapping is the process that \"converts\" " -"HDR values to be suitable for rendering on a LDR display. (Godot doesn't " +"HDR values to be suitable for rendering on a SDR display. (Godot doesn't " "support rendering on HDR displays yet.)" msgstr "" @@ -25516,7 +25540,7 @@ msgstr "" #: doc/classes/Geometry.xml msgid "" "Given an array of [Vector2]s representing tiles, builds an atlas. The " -"returned dictionary has two keys: [code]points[/code] is a vector of " +"returned dictionary has two keys: [code]points[/code] is an array of " "[Vector2] that specifies the positions of each tile, [code]size[/code] " "contains the overall size of the whole atlas as [Vector2]." msgstr "" @@ -28566,13 +28590,14 @@ msgstr "" #: doc/classes/HTTPRequest.xml msgid "" -"If set to a value greater than [code]0.0[/code], the HTTP request will time " -"out after [code]timeout[/code] seconds have passed and the request is not " -"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set " -"[member timeout] to a value greater than [code]0.0[/code] to prevent the " -"application from getting stuck if the request fails to get a response in a " -"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent " -"the download from failing if it takes too much time." +"If set to a value greater than [code]0.0[/code] before the request starts, " +"the HTTP request will time out after [code]timeout[/code] seconds have " +"passed and the request is not [i]completed[/i] yet. For small HTTP requests " +"such as REST API usage, set [member timeout] to a value between [code]10.0[/" +"code] and [code]30.0[/code] to prevent the application from getting stuck if " +"the request fails to get a response in a timely manner. For file downloads, " +"leave this to [code]0.0[/code] to prevent the download from failing if it " +"takes too much time." msgstr "" #: doc/classes/HTTPRequest.xml @@ -29988,9 +30013,9 @@ msgid "" "freehand lines is required, input accumulation should generally be disabled " "while the user is drawing the line to get results that closely follow the " "actual input.\n" -"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward " -"compatibility reasons. It is however recommended to enable it for games " -"which don't require very reactive input, as this will decrease CPU usage." +"[b]Note:[/b] Input accumulation is [i]enabled[/i] by default. It is " +"recommended to keep it enabled for games which don't require very reactive " +"input, as this will decrease CPU usage." msgstr "" #: doc/classes/Input.xml @@ -30564,10 +30589,13 @@ msgstr "" msgid "" "Contains mouse and pen motion information. Supports relative, absolute " "positions and speed. See [method Node._input].\n" -"[b]Note:[/b] By default, this event can be emitted multiple times per frame " -"rendered, allowing for precise input reporting, at the expense of CPU usage. " -"You can set [member Input.use_accumulated_input] to [code]true[/code] to let " -"multiple events merge into a single emitted event per frame.\n" +"[b]Note:[/b] The behavior of this event is affected by the value of [member " +"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/" +"pen motion events received from the OS will be merged to emit an accumulated " +"event only once per frame rendered at most. When set to [code]false[/code], " +"the events will be emitted as received, which means that they can be emitted " +"multiple times per frame rendered, allowing for precise input reporting at " +"the expense of CPU usage.\n" "[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider " "implementing [url=https://en.wikipedia.org/wiki/" "Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to " @@ -30580,6 +30608,12 @@ msgstr "" #: doc/classes/InputEventMouseMotion.xml msgid "" +"Returns [code]true[/code] when using the eraser end of a stylus pen.\n" +"[b]Note:[/b] This property is implemented on Linux, macOS and Windows." +msgstr "" + +#: doc/classes/InputEventMouseMotion.xml +msgid "" "Represents the pressure the user puts on the pen. Ranges from [code]0.0[/" "code] to [code]1.0[/code]." msgstr "" @@ -32616,7 +32650,7 @@ msgstr "" msgid "" "Sets the render priority for the text outline. Higher priority objects will " "be sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32632,7 +32666,7 @@ msgstr "" msgid "" "Sets the render priority for the text. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -32662,7 +32696,7 @@ msgstr "" #: doc/classes/Label3D.xml msgid "" -"If set, text can be seen from the back as well. If not, the texture is " +"If set, text can be seen from the back as well. If not, the text is " "invisible when looking at it from behind." msgstr "" @@ -36798,7 +36832,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The cost of entering this region from another region can be controlled with " "the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The cost of traveling distances inside this region can be controlled with " "the [member travel_cost] multiplier." @@ -37061,7 +37095,7 @@ msgid "" "two regions. They must share a similar edge.\n" "The pathfinding cost of entering this region from another region can be " "controlled with the [member enter_cost] value.\n" -"[b]Note[/b]: This value is not added to the path cost when the start " +"[b]Note:[/b] This value is not added to the path cost when the start " "position is already inside this region.\n" "The pathfinding cost of traveling distances inside this region can be " "controlled with the [member travel_cost] multiplier." @@ -37179,6 +37213,52 @@ msgstr "" msgid "Control activation of this server." msgstr "" +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be controlled from a " +"script." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"A [NetworkedMultiplayerPeer] implementation that can be used as a [member " +"MultiplayerAPI.network_peer] and controlled from a script.\n" +"Its purpose is to allow adding a new backend for the high-Level multiplayer " +"API without needing to use GDNative." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Deliver a packet to the local [MultiplayerAPI].\n" +"When your script receives a packet from other peers over the network " +"(originating from the [signal packet_generated] signal on the sending peer), " +"passing it to this method will deliver it locally." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Initialize the peer with the given [code]peer_id[/code] (must be between 1 " +"and 2147483647)." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Set the state of the connection. See [enum NetworkedMultiplayerPeer." +"ConnectionStatus]." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "Set the max packet size that this peer can handle." +msgstr "" + +#: doc/classes/NetworkedMultiplayerCustom.xml +msgid "" +"Emitted when the local [MultiplayerAPI] generates a packet.\n" +"Your script should take this packet and send it to the requested peer over " +"the network (which should call [method deliver_packet] with the data when " +"it's received)." +msgstr "" + #: modules/enet/doc_classes/NetworkedMultiplayerENet.xml msgid "" "PacketPeer implementation using the [url=http://enet.bespin.org/index." @@ -39876,7 +39956,13 @@ msgid "See [enum ShadowDetail]." msgstr "" #: doc/classes/OmniLight.xml -msgid "See [enum ShadowMode]." +msgid "" +"The shadow rendering mode to use for this [OmniLight]. See [enum " +"ShadowMode].\n" +"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that " +"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 " +"series don't support cubemap shadows and will fall back to dual paraboloid " +"shadows as a result." msgstr "" #: doc/classes/OmniLight.xml @@ -39888,7 +39974,8 @@ msgstr "" #: doc/classes/OmniLight.xml msgid "" "Shadows are rendered to a cubemap. Slower than [constant " -"SHADOW_DUAL_PARABOLOID], but higher-quality." +"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that " +"feature support for depth cubemaps." msgstr "" #: doc/classes/OmniLight.xml @@ -45518,6 +45605,13 @@ msgstr "" msgid "Changes the byte at the given index." msgstr "" +#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml +#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml +#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml +#: doc/classes/PoolVector3Array.xml +msgid "Sorts the elements of the array in ascending order." +msgstr "" + #: doc/classes/PoolByteArray.xml msgid "" "Returns the slice of the [PoolByteArray] between indices (inclusive) as a " @@ -54447,7 +54541,8 @@ msgid "" "SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A " "[SceneTreeTween] might become invalid when it has finished tweening, is " "killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid " -"[SceneTreeTween]s can't have [Tweener]s appended." +"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use " +"[method interpolate_value]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -54487,15 +54582,16 @@ msgstr "" msgid "" "Sets the number of times the tweening sequence will be repeated, i.e. " "[code]set_loops(2)[/code] will run the animation twice.\n" -"Calling this method without arguments will make the [Tween] run infinitely, " -"until either it is killed with [method kill], the [Tween]'s bound node is " -"freed, or all the animated objects have been freed (which makes further " -"animation impossible).\n" +"Calling this method without arguments will make the [SceneTreeTween] run " +"infinitely, until either it is killed with [method kill], the " +"[SceneTreeTween]'s bound node is freed, or all the animated objects have " +"been freed (which makes further animation impossible).\n" "[b]Warning:[/b] Make sure to always add some duration/delay when using " "infinite loops. To prevent the game freezing, 0-duration looped animations " "(e.g. a single [CallbackTweener] with no delay) are stopped after a small " -"number of loops, which may produce unexpected results. If a [Tween]'s " -"lifetime depends on some node, always use [method bind_node]." +"number of loops, which may produce unexpected results. If a " +"[SceneTreeTween]'s lifetime depends on some node, always use [method " +"bind_node]." msgstr "" #: doc/classes/SceneTreeTween.xml @@ -55972,11 +56068,30 @@ msgid "" msgstr "" #: doc/classes/Spatial.xml +msgid "" +"Rotation part of the global transformation in radians, specified in terms of " +"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" +"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " +"vector. The three Euler angles, which are the three independent parameters " +"of the Euler-angle parametrization of the rotation matrix, are stored in a " +"[Vector3] data structure not because the rotation is a vector, but only " +"because [Vector3] exists as a convenient data-structure to store 3 floating-" +"point numbers. Therefore, applying affine operations on the rotation " +"\"vector\" is not meaningful." +msgstr "" + +#: doc/classes/Spatial.xml msgid "World space (global) [Transform] of this node." msgstr "" #: doc/classes/Spatial.xml msgid "" +"Global position of this node. This is equivalent to [code]global_transform." +"origin[/code]." +msgstr "" + +#: doc/classes/Spatial.xml +msgid "" "Rotation part of the local transformation in radians, specified in terms of " "YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n" "[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a " @@ -57647,7 +57762,7 @@ msgstr "" msgid "" "Sets the render priority for the sprite. Higher priority objects will be " "sorted in front of lower priority objects.\n" -"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant " +"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant " "ALPHA_CUT_DISABLED] (default value).\n" "[b]Note:[/b] This only applies to sorting of transparent objects. This will " "not impact how transparent objects are sorted relative to opaque objects. " @@ -60549,8 +60664,8 @@ msgstr "" #: doc/classes/TextEdit.xml msgid "" -"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes " -"the bookmark if [code]bookmark[/code] is false.\n" +"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/" +"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n" "Bookmarks are shown in the [member breakpoint_gutter]." msgstr "" @@ -64184,13 +64299,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next TreeItem in the tree or a null object if there is none." +"Returns the next sibling TreeItem in the tree or a null object if there is " +"none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the next visible TreeItem in the tree or a null object if there is " -"none.\n" +"Returns the next visible sibling TreeItem in the tree or a null object if " +"there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the first " "visible element in the tree when called on the last visible element, " "otherwise it returns [code]null[/code]." @@ -64202,13 +64318,14 @@ msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous TreeItem in the tree or a null object if there is none." +"Returns the previous sibling TreeItem in the tree or a null object if there " +"is none." msgstr "" #: doc/classes/TreeItem.xml msgid "" -"Returns the previous visible TreeItem in the tree or a null object if there " -"is none.\n" +"Returns the previous visible sibling TreeItem in the tree or a null object " +"if there is none.\n" "If [code]wrap[/code] is enabled, the method will wrap around to the last " "visible element in the tree when called on the first visible element, " "otherwise it returns [code]null[/code]." @@ -66021,11 +66138,11 @@ msgstr "" #: doc/classes/VehicleBody.xml msgid "" "Accelerates the vehicle by applying an engine force. The vehicle is only " -"speed up if the wheels that have [member VehicleWheel.use_as_traction] set " -"to [code]true[/code] and are in contact with a surface. The [member " -"RigidBody.mass] of the vehicle has an effect on the acceleration of the " -"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 " -"range for acceleration.\n" +"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to " +"[code]true[/code] and are in contact with a surface. The [member RigidBody." +"mass] of the vehicle has an effect on the acceleration of the vehicle. For a " +"vehicle with a mass set to 1000, try a value in the 25 - 50 range for " +"acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " "you will need to add logic for this if you wish to simulate gears.\n" "A negative value will result in the vehicle reversing." @@ -66105,8 +66222,8 @@ msgstr "" #: doc/classes/VehicleWheel.xml msgid "" -"Accelerates the wheel by applying an engine force. The wheel is only speed " -"up if it is in contact with a surface. The [member RigidBody.mass] of the " +"Accelerates the wheel by applying an engine force. The wheel is only sped up " +"if it is in contact with a surface. The [member RigidBody.mass] of the " "vehicle has an effect on the acceleration of the vehicle. For a vehicle with " "a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n" "[b]Note:[/b] The simulation does not take the effect of gears into account, " @@ -71122,7 +71239,11 @@ msgid "Sets the viewport's global transformation matrix." msgstr "" #: doc/classes/VisualServer.xml -msgid "If [code]true[/code], the viewport renders to hdr." +msgid "" +"If [code]true[/code], the viewport renders to high dynamic range (HDR) " +"instead of standard dynamic range (SDR). See also [method " +"viewport_set_use_32_bpc_depth].\n" +"[b]Note:[/b] Only available on the GLES3 backend." msgstr "" #: doc/classes/VisualServer.xml @@ -71207,6 +71328,15 @@ msgstr "" #: doc/classes/VisualServer.xml msgid "" +"If [code]true[/code], allocates the viewport's framebuffer with full " +"floating-point precision (32-bit) instead of half floating-point precision " +"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used " +"on the same [Viewport] to set HDR to [code]true[/code].\n" +"[b]Note:[/b] Only available on the GLES3 backend." +msgstr "" + +#: doc/classes/VisualServer.xml +msgid "" "If [code]true[/code], the viewport uses augmented or virtual reality " "technologies. See [ARVRInterface]." msgstr "" diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index 276e69e470..cc38c2352f 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -38,7 +38,7 @@ #define kOutputBus 0 #define kInputBus 1 -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData) { @@ -72,7 +72,7 @@ Error AudioDriverCoreAudio::init() { AudioComponentDescription desc; memset(&desc, 0, sizeof(desc)); desc.componentType = kAudioUnitType_Output; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; @@ -85,7 +85,7 @@ Error AudioDriverCoreAudio::init() { OSStatus result = AudioComponentInstanceNew(comp, &audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -135,7 +135,7 @@ Error AudioDriverCoreAudio::init() { // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32)); ERR_FAIL_COND_V(result != noErr, FAILED); #endif @@ -313,7 +313,7 @@ void AudioDriverCoreAudio::finish() { ERR_PRINT("AudioUnitUninitialize failed"); } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -339,7 +339,7 @@ Error AudioDriverCoreAudio::capture_init() { AudioComponentDescription desc; memset(&desc, 0, sizeof(desc)); desc.componentType = kAudioUnitType_Output; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; @@ -352,7 +352,7 @@ Error AudioDriverCoreAudio::capture_init() { OSStatus result = AudioComponentInstanceNew(comp, &input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -370,7 +370,7 @@ Error AudioDriverCoreAudio::capture_init() { ERR_FAIL_COND_V(result != noErr, FAILED); UInt32 size; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioDeviceID deviceId; size = sizeof(AudioDeviceID); AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; @@ -447,7 +447,7 @@ void AudioDriverCoreAudio::capture_finish() { ERR_PRINT("AudioUnitUninitialize failed"); } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -491,7 +491,7 @@ Error AudioDriverCoreAudio::capture_stop() { return OK; } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED Array AudioDriverCoreAudio::_get_device_list(bool capture) { Array list; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index f86037f092..7fac8a99ed 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef COREAUDIO_ENABLED - #ifndef AUDIO_DRIVER_COREAUDIO_H #define AUDIO_DRIVER_COREAUDIO_H +#ifdef COREAUDIO_ENABLED + #include "servers/audio_server.h" #import <AudioUnit/AudioUnit.h> -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #import <CoreAudio/AudioHardware.h> #endif @@ -58,7 +58,7 @@ class AudioDriverCoreAudio : public AudioDriver { Vector<int32_t> samples_in; Vector<int16_t> input_buf; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED Array _get_device_list(bool capture = false); void _set_device(const String &device, bool capture = false); @@ -106,7 +106,7 @@ public: bool try_lock(); void stop(); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED virtual Array get_device_list(); virtual String get_device(); virtual void set_device(String device); @@ -120,6 +120,6 @@ public: ~AudioDriverCoreAudio() {} }; -#endif +#endif // COREAUDIO_ENABLED -#endif +#endif // AUDIO_DRIVER_COREAUDIO_H diff --git a/drivers/coremidi/midi_driver_coremidi.h b/drivers/coremidi/midi_driver_coremidi.h index 0085141c6d..ac2ad99eb3 100644 --- a/drivers/coremidi/midi_driver_coremidi.h +++ b/drivers/coremidi/midi_driver_coremidi.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef COREMIDI_ENABLED - #ifndef MIDI_DRIVER_COREMIDI_H #define MIDI_DRIVER_COREMIDI_H +#ifdef COREMIDI_ENABLED + #include "core/os/midi_driver.h" #include "core/templates/vector.h" @@ -57,5 +57,6 @@ public: virtual ~MIDIDriverCoreMidi(); }; -#endif // MIDI_DRIVER_COREMIDI_H #endif // COREMIDI_ENABLED + +#endif // MIDI_DRIVER_COREMIDI_H diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub index ddeec6f4c6..7e8bd22960 100644 --- a/drivers/gl_context/SCsub +++ b/drivers/gl_context/SCsub @@ -2,7 +2,7 @@ Import("env") -if env["platform"] in ["haiku", "osx", "windows", "linuxbsd"]: +if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]: # Thirdparty source files thirdparty_dir = "#thirdparty/glad/" thirdparty_sources = [ diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp index c8e6c2b476..de0181f887 100644 --- a/drivers/gles3/effects/copy_effects.cpp +++ b/drivers/gles3/effects/copy_effects.cpp @@ -111,6 +111,7 @@ CopyEffects::~CopyEffects() { glDeleteVertexArrays(1, &screen_triangle_array); glDeleteBuffers(1, &quad); glDeleteVertexArrays(1, &quad_array); + copy.shader.version_free(copy.shader_version); } void CopyEffects::copy_to_rect(const Rect2i &p_rect) { diff --git a/drivers/gles3/effects/copy_effects.h b/drivers/gles3/effects/copy_effects.h index 1cf1ac9404..b863e76579 100644 --- a/drivers/gles3/effects/copy_effects.h +++ b/drivers/gles3/effects/copy_effects.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COPY_GL_H -#define COPY_GL_H +#ifndef COPY_EFFECTS_GLES3_H +#define COPY_EFFECTS_GLES3_H #ifdef GLES3_ENABLED @@ -70,4 +70,5 @@ public: } //namespace GLES3 #endif // GLES3_ENABLED -#endif // !COPY_GL_H + +#endif // COPY_EFFECTS_GLES3_H diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h index 22bf3bb017..350eb459cf 100644 --- a/drivers/gles3/environment/fog.h +++ b/drivers/gles3/environment/fog.h @@ -59,4 +59,4 @@ public: #endif // GLES3_ENABLED -#endif // !FOG_GLES3_H +#endif // FOG_GLES3_H diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h index b633520784..7a0634f22b 100644 --- a/drivers/gles3/environment/gi.h +++ b/drivers/gles3/environment/gi.h @@ -93,4 +93,4 @@ public: #endif // GLES3_ENABLED -#endif // !GI_GLES3_H +#endif // GI_GLES3_H diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 82f7450bc2..83154acd51 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -135,7 +135,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target); Transform3D screen_transform; - screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); @@ -183,7 +183,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW); - GLuint global_buffer = material_storage->global_variables_get_uniform_buffer(); + GLuint global_buffer = material_storage->global_shader_uniforms_get_uniform_buffer(); glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -815,10 +815,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item _bind_canvas_texture(texture, current_filter, current_repeat, r_index); if (instance_count == 1) { GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES); - } else if (instance_count > 1) { - GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED); } else { - ERR_PRINT("Must have at least one mesh instance to draw mesh"); + GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED); } uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh); @@ -882,7 +880,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item } else { glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface)); } - } else if (instance_count > 1) { + } else { if (use_index_buffer) { glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count); } else { @@ -1217,7 +1215,7 @@ void RasterizerCanvasGLES3::reset_canvas() { void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { } -void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { +void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) { } void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { @@ -1570,7 +1568,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { glBindBuffer(GL_UNIFORM_BUFFER, 0); String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n"; global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n"; @@ -1610,6 +1608,8 @@ void fragment() { RasterizerCanvasGLES3::~RasterizerCanvasGLES3() { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + memdelete_arr(state.instance_data_array); + GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version); material_storage->material_free(default_canvas_group_material); material_storage->shader_free(default_canvas_group_shader); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index caf649aaf6..f920e37130 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_CANVAS_OPENGL_H -#define RASTERIZER_CANVAS_OPENGL_H +#ifndef RASTERIZER_CANVAS_GLES3_H +#define RASTERIZER_CANVAS_GLES3_H #ifdef GLES3_ENABLED @@ -209,7 +209,7 @@ public: void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); void reset_canvas(); - void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); + void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache); virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override; @@ -262,4 +262,5 @@ public: }; #endif // GLES3_ENABLED -#endif // RASTERIZER_CANVAS_OPENGL_H + +#endif // RASTERIZER_CANVAS_GLES3_H diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 613a7f37d9..33303b1e38 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -69,7 +69,7 @@ #endif #endif -#if !defined(IPHONE_ENABLED) && !defined(JAVASCRIPT_ENABLED) +#if !defined(IOS_ENABLED) && !defined(JAVASCRIPT_ENABLED) // We include EGL below to get debug callback on GLES2 platforms, // but EGL is not available on iOS. #define CAN_DEBUG diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index e842b6d70c..97543af0d5 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_OPENGL_H -#define RASTERIZER_OPENGL_H +#ifndef RASTERIZER_GLES3_H +#define RASTERIZER_GLES3_H #ifdef GLES3_ENABLED @@ -112,4 +112,4 @@ public: #endif // GLES3_ENABLED -#endif +#endif // RASTERIZER_GLES3_H diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 989d0de496..7207a6efbb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/templates/sort_array.h" #include "servers/rendering/rendering_server_default.h" +#include "servers/rendering/rendering_server_globals.h" #include "storage/config.h" #include "storage/light_storage.h" #include "storage/mesh_storage.h" @@ -39,15 +40,9 @@ #ifdef GLES3_ENABLED -uint64_t RasterizerSceneGLES3::auto_exposure_counter = 2; - RasterizerSceneGLES3 *RasterizerSceneGLES3::singleton = nullptr; -RasterizerSceneGLES3 *RasterizerSceneGLES3::get_singleton() { - return singleton; -} - -RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { +RenderGeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); @@ -57,176 +52,36 @@ RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_c ginstance->data->base = p_base; ginstance->data->base_type = type; - _geometry_instance_mark_dirty(ginstance); + ginstance->_mark_dirty(); return ginstance; } -void RasterizerSceneGLES3::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->skeleton = p_skeleton; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_override = p_override; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_overlay = p_overlay; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->surface_materials = p_materials; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ERR_FAIL_COND(!ginstance); - ginstance->mesh_instance = p_mesh_instance; - - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->transform = p_transform; - ginstance->mirror = p_transform.basis.determinant() < 0; - ginstance->data->aabb = p_aabb; - ginstance->transformed_aabb = p_transformed_aabb; - - Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); - // handle non uniform scale here - - float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); - float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); - ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; - - ginstance->lod_model_scale = max_scale; -} - -void RasterizerSceneGLES3::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->layer_mask = p_layer_mask; -} - -void RasterizerSceneGLES3::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lod_bias = p_lod_bias; -} - -void RasterizerSceneGLES3::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1); -} - -void RasterizerSceneGLES3::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->fade_near = p_enable_near; - ginstance->fade_near_begin = p_near_begin; - ginstance->fade_near_end = p_near_end; - ginstance->fade_far = p_enable_far; - ginstance->fade_far_begin = p_far_begin; - ginstance->fade_far_end = p_far_end; -} - -void RasterizerSceneGLES3::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->parent_fade_alpha = p_alpha; -} - -void RasterizerSceneGLES3::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_baked_light = p_enable; - - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_dynamic_gi = p_enable; - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->shader_parameters_offset = p_offset; - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->cast_double_sided_shadows = p_enable; - _geometry_instance_mark_dirty(ginstance); -} - uint32_t RasterizerSceneGLES3::geometry_instance_get_pair_mask() { return (1 << RS::INSTANCE_LIGHT); } -void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - +void RasterizerSceneGLES3::GeometryInstanceGLES3::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) { GLES3::Config *config = GLES3::Config::get_singleton(); - ginstance->omni_light_count = 0; - ginstance->spot_light_count = 0; - ginstance->omni_lights.clear(); - ginstance->spot_lights.clear(); + omni_light_count = 0; + spot_light_count = 0; + omni_lights.clear(); + spot_lights.clear(); for (uint32_t i = 0; i < p_light_instance_count; i++) { - RS::LightType type = light_instance_get_type(p_light_instances[i]); + RS::LightType type = RasterizerSceneGLES3::get_singleton()->light_instance_get_type(p_light_instances[i]); switch (type) { case RS::LIGHT_OMNI: { - if (ginstance->omni_light_count < (uint32_t)config->max_lights_per_object) { - ginstance->omni_lights.push_back(p_light_instances[i]); - ginstance->omni_light_count++; + if (omni_light_count < (uint32_t)config->max_lights_per_object) { + omni_lights.push_back(p_light_instances[i]); + omni_light_count++; } } break; case RS::LIGHT_SPOT: { - if (ginstance->spot_light_count < (uint32_t)config->max_lights_per_object) { - ginstance->spot_lights.push_back(p_light_instances[i]); - ginstance->spot_light_count++; + if (spot_light_count < (uint32_t)config->max_lights_per_object) { + spot_lights.push_back(p_light_instances[i]); + spot_light_count++; } } break; default: @@ -235,21 +90,7 @@ void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstan } } -void RasterizerSceneGLES3::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_instance) { +void RasterizerSceneGLES3::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); GeometryInstanceSurface *surf = ginstance->surface_caches; @@ -262,24 +103,29 @@ void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_i geometry_instance_alloc.free(ginstance); } -void RasterizerSceneGLES3::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - if (ginstance->dirty_list_element.in_list()) { +void RasterizerSceneGLES3::GeometryInstanceGLES3::_mark_dirty() { + if (dirty_list_element.in_list()) { return; } //clear surface caches - GeometryInstanceSurface *surf = ginstance->surface_caches; + GeometryInstanceSurface *surf = surface_caches; while (surf) { GeometryInstanceSurface *next = surf->next; - geometry_instance_surface_alloc.free(surf); + RasterizerSceneGLES3::get_singleton()->geometry_instance_surface_alloc.free(surf); surf = next; } - ginstance->surface_caches = nullptr; + surface_caches = nullptr; - geometry_instance_dirty_list.add(&ginstance->dirty_list_element); + RasterizerSceneGLES3::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element); +} + +void RasterizerSceneGLES3::GeometryInstanceGLES3::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { +} + +void RasterizerSceneGLES3::GeometryInstanceGLES3::set_lightmap_capture(const Color *p_sh9) { } void RasterizerSceneGLES3::_update_dirty_geometry_instances() { @@ -295,7 +141,7 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::Dep case Dependency::DEPENDENCY_CHANGED_PARTICLES: case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata); @@ -310,7 +156,7 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::Dep } void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { - static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { @@ -467,7 +313,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3 } } -void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) { GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); @@ -650,8 +496,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { while (sky) { if (sky->radiance == 0) { - sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) + 1; - + sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) - 1; // Left uninitialized, will attach a texture at render time glGenFramebuffers(1, &sky->radiance_framebuffer); @@ -678,7 +523,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); glGenTextures(1, &sky->raw_radiance); glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance); @@ -699,7 +544,8 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } @@ -715,13 +561,13 @@ void RasterizerSceneGLES3::_update_dirty_skys() { dirty_sky_list = nullptr; } -void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) { +void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) { GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); GLES3::SkyMaterialData *material = nullptr; - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); RID sky_material; @@ -856,22 +702,23 @@ void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, } if (!sky->radiance) { + _invalidate_sky(sky); _update_dirty_skys(); } } } -void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); ERR_FAIL_COND(!sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { ERR_FAIL_COND(!sky); @@ -901,18 +748,18 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p ERR_FAIL_COND(!shader_data); // Camera - CameraMatrix camera; + Projection camera; - if (p_env->sky_custom_fov) { + if (environment_get_sky_custom_fov(p_env)) { float near_plane = p_projection.get_z_near(); float far_plane = p_projection.get_z_far(); float aspect = p_projection.get_aspect(); - camera.set_perspective(p_env->sky_custom_fov, aspect, near_plane, far_plane); + camera.set_perspective(environment_get_sky_custom_fov(p_env), aspect, near_plane, far_plane); } else { camera = p_projection; } - Basis sky_transform = p_env->sky_orientation; + Basis sky_transform = environment_get_sky_orientation(p_env); sky_transform.invert(); sky_transform = p_transform.basis * sky_transform; @@ -926,17 +773,17 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p glDrawArrays(GL_TRIANGLES, 0, 3); } -void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); ERR_FAIL_COND(!sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { ERR_FAIL_COND(!sky); @@ -990,7 +837,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera int max_processing_layer = sky->mipmap_count; // Update radiance cubemap - if (sky->reflection_dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) { + if (sky->reflection_dirty && (sky->processing_layer > max_processing_layer || update_single_frame)) { static const Vector3 view_normals[6] = { Vector3(+1, 0, 0), Vector3(-1, 0, 0), @@ -1008,9 +855,9 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera Vector3(0, -1, 0) }; - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, 0.01, 10.0); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); cm = correction * cm; @@ -1051,6 +898,45 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera } } +// Helper functions for IBL filtering + +Vector3 importance_sample_GGX(Vector2 xi, float roughness4) { + // Compute distribution direction + float phi = 2.0 * Math_PI * xi.x; + float cos_theta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); + float sin_theta = sqrt(1.0 - cos_theta * cos_theta); + + // Convert to spherical direction + Vector3 half_vector; + half_vector.x = sin_theta * cos(phi); + half_vector.y = sin_theta * sin(phi); + half_vector.z = cos_theta; + + return half_vector; +} + +float distribution_GGX(float NdotH, float roughness4) { + float NdotH2 = NdotH * NdotH; + float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); + denom = Math_PI * denom * denom; + + return roughness4 / denom; +} + +float radical_inverse_vdC(uint32_t bits) { + bits = (bits << 16) | (bits >> 16); + bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); + bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); + bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); + bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); + + return float(bits) * 2.3283064365386963e-10; +} + +Vector2 hammersley(uint32_t i, uint32_t N) { + return Vector2(float(i) / float(N), radical_inverse_vdC(i)); +} + void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); @@ -1062,27 +948,68 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { if (p_base_layer == 0) { glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + // Copy over base layer without filtering. mode = CubemapFilterShaderGLES3::MODE_COPY; - - //Copy over base layer } - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); int size = p_sky->radiance_size >> p_base_layer; glViewport(0, 0, size, size); glBindVertexArray(sky_globals.screen_triangle_array); material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, sky_globals.ggx_samples, scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, float(p_base_layer) / (p_sky->mipmap_count - 1.0), scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_SIZE, float(size), scene_globals.cubemap_filter_shader_version, mode); + + if (p_base_layer > 0) { + const uint32_t sample_counts[4] = { 1, sky_globals.ggx_samples / 4, sky_globals.ggx_samples / 2, sky_globals.ggx_samples }; + uint32_t sample_count = sample_counts[MIN(3, p_base_layer)]; + + float roughness = float(p_base_layer) / (p_sky->mipmap_count); + float roughness4 = roughness * roughness; + roughness4 *= roughness4; + + float solid_angle_texel = 4.0 * Math_PI / float(6 * size * size); + + LocalVector<float> sample_directions; + sample_directions.resize(4 * sample_count); + + uint32_t index = 0; + float weight = 0.0; + for (uint32_t i = 0; i < sample_count; i++) { + Vector2 xi = hammersley(i, sample_count); + Vector3 dir = importance_sample_GGX(xi, roughness4); + Vector3 light_vec = (2.0 * dir.z * dir - Vector3(0.0, 0.0, 1.0)); + + if (light_vec.z < 0.0) { + continue; + } + + sample_directions[index * 4] = light_vec.x; + sample_directions[index * 4 + 1] = light_vec.y; + sample_directions[index * 4 + 2] = light_vec.z; + + float D = distribution_GGX(dir.z, roughness4); + float pdf = D * dir.z / (4.0 * dir.z) + 0.0001; + + float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); + + float mip_level = MAX(0.5 * log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_base_layer - 3)), 1.0); + + sample_directions[index * 4 + 3] = mip_level; + weight += light_vec.z; + index++; + } + + glUniform4fv(material_storage->shaders.cubemap_filter_shader.version_get_uniform(CubemapFilterShaderGLES3::SAMPLE_DIRECTIONS_MIP, scene_globals.cubemap_filter_shader_version, mode), sample_count, sample_directions.ptr()); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::WEIGHT, weight, scene_globals.cubemap_filter_shader_version, mode); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, index, scene_globals.cubemap_filter_shader_version, mode); + } for (int i = 0; i < 6; i++) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_sky->radiance, p_base_layer); #ifdef DEBUG_ENABLED GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); + if (status != GL_FRAMEBUFFER_COMPLETE) { + WARN_PRINT("Could not bind sky radiance face: " + itos(i) + ", status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status)); + } #endif material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, scene_globals.cubemap_filter_shader_version, mode); @@ -1099,84 +1026,6 @@ Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bo /* ENVIRONMENT API */ -RID RasterizerSceneGLES3::environment_allocate() { - return environment_owner.allocate_rid(); -} - -void RasterizerSceneGLES3::environment_initialize(RID p_rid) { - environment_owner.initialize_rid(p_rid); -} - -void RasterizerSceneGLES3::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->background = p_bg; -} - -void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky = p_sky; -} - -void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_scale) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_custom_fov = p_scale; -} - -void RasterizerSceneGLES3::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_orientation = p_orientation; -} - -void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_color = p_color; -} - -void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env, float p_energy) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_energy = p_energy; -} - -void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->canvas_max_layer = p_max_layer; -} - -void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->ambient_light = p_color; - env->ambient_source = p_ambient; - env->ambient_light_energy = p_energy; - env->ambient_sky_contribution = p_sky_contribution; - env->reflection_source = p_reflection_source; -} - -void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); - env->glow_enabled = p_enable; - env->glow_levels = p_levels; - env->glow_intensity = p_intensity; - env->glow_strength = p_strength; - env->glow_mix = p_mix; - env->glow_bloom = p_bloom_threshold; - env->glow_blend_mode = p_blend_mode; - env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; - env->glow_hdr_bleed_scale = p_hdr_bleed_scale; - env->glow_hdr_luminance_cap = p_hdr_luminance_cap; - env->glow_map_strength = p_glow_map_strength; - env->glow_map = p_glow_map; -} - void RasterizerSceneGLES3::environment_glow_set_use_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; } @@ -1185,35 +1034,15 @@ void RasterizerSceneGLES3::environment_glow_set_use_high_quality(bool p_enable) glow_high_quality = p_enable; } -void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->ssr_enabled = p_enable; - env->ssr_max_steps = p_max_steps; - env->ssr_fade_in = p_fade_int; - env->ssr_fade_out = p_fade_out; - env->ssr_depth_tolerance = p_depth_tolerance; -} - void RasterizerSceneGLES3::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { } -void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); -} - void RasterizerSceneGLES3::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { } -void RasterizerSceneGLES3::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) { -} void RasterizerSceneGLES3::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { } -void RasterizerSceneGLES3::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { -} - void RasterizerSceneGLES3::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { } @@ -1223,49 +1052,6 @@ void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_converge(RS::Environm void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) { } -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->exposure = p_exposure; - env->tone_mapper = p_tone_mapper; - if (!env->auto_exposure && p_auto_exposure) { - env->auto_exposure_version = ++auto_exposure_counter; - } - env->auto_exposure = p_auto_exposure; - env->white = p_white; - env->min_luminance = p_min_luminance; - env->max_luminance = p_max_luminance; - env->auto_exp_speed = p_auto_exp_speed; - env->auto_exp_scale = p_auto_exp_scale; -} - -void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->adjustments_enabled = p_enable; - env->adjustments_brightness = p_brightness; - env->adjustments_contrast = p_contrast; - env->adjustments_saturation = p_saturation; - env->use_1d_color_correction = p_use_1d_color_correction; - env->color_correction = p_color_correction; -} - -void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->fog_enabled = p_enable; - env->fog_light_color = p_light_color; - env->fog_light_energy = p_light_energy; - env->fog_sun_scatter = p_sun_scatter; - env->fog_density = p_density; - env->fog_height = p_height; - env->fog_height_density = p_height_density; - env->fog_aerial_perspective = p_aerial_perspective; -} - -void RasterizerSceneGLES3::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { -} - void RasterizerSceneGLES3::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { } @@ -1273,27 +1059,9 @@ void RasterizerSceneGLES3::environment_set_volumetric_fog_filter_active(bool p_e } Ref<Image> RasterizerSceneGLES3::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Ref<Image>()); return Ref<Image>(); } -bool RasterizerSceneGLES3::is_environment(RID p_env) const { - return environment_owner.owns(p_env); -} - -RS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) const { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); - return env->background; -} - -int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) const { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->canvas_max_layer; -} - RID RasterizerSceneGLES3::camera_effects_allocate() { return RID(); } @@ -1313,10 +1081,10 @@ void RasterizerSceneGLES3::camera_effects_set_dof_blur(RID p_camera_effects, boo void RasterizerSceneGLES3::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { } -void RasterizerSceneGLES3::shadows_quality_set(RS::ShadowQuality p_quality) { +void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { } -void RasterizerSceneGLES3::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RasterizerSceneGLES3::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { } RID RasterizerSceneGLES3::light_instance_create(RID p_light) { @@ -1345,7 +1113,7 @@ void RasterizerSceneGLES3::light_instance_set_aabb(RID p_light_instance, const A light_instance->aabb = p_aabb; } -void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { +void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { } void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { @@ -1431,7 +1199,7 @@ bool RasterizerSceneGLES3::voxel_gi_needs_update(RID p_probe) const { return false; } -void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) { +void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { } void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { @@ -1608,9 +1376,9 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const // Needs to be called after _setup_lights so that directional_light_count is accurate. void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo GLES3::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); @@ -1633,18 +1401,17 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da scene_state.ubo.time = time; if (is_environment(p_render_data->environment)) { - Environment *env = environment_owner.get_or_null(p_render_data->environment); - RS::EnvironmentBG env_bg = env->background; - RS::EnvironmentAmbientSource ambient_src = env->ambient_source; + RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment); + RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment); - float bg_energy = env->bg_energy; + float bg_energy = environment_get_bg_energy(p_render_data->environment); scene_state.ubo.ambient_light_color_energy[3] = bg_energy; - scene_state.ubo.ambient_color_sky_mix = env->ambient_sky_contribution; + scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment); //ambient if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { - Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : env->bg_color; + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; @@ -1653,14 +1420,14 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da scene_state.ubo.use_ambient_light = true; scene_state.ubo.use_ambient_cubemap = false; } else { - float energy = env->ambient_light_energy; - Color color = env->ambient_light; + float energy = environment_get_ambient_light_energy(p_render_data->environment); + Color color = environment_get_ambient_light(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; - Basis sky_transform = env->sky_orientation; + Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; GLES3::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; @@ -1668,27 +1435,27 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da } //specular - RS::EnvironmentReflectionSource ref_src = env->reflection_source; + RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment); if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { scene_state.ubo.use_reflection_cubemap = true; } else { scene_state.ubo.use_reflection_cubemap = false; } - scene_state.ubo.fog_enabled = env->fog_enabled; - scene_state.ubo.fog_density = env->fog_density; - scene_state.ubo.fog_height = env->fog_height; - scene_state.ubo.fog_height_density = env->fog_height_density; - scene_state.ubo.fog_aerial_perspective = env->fog_aerial_perspective; + scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); + scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); + scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); + scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); + scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - Color fog_color = env->fog_light_color.srgb_to_linear(); - float fog_energy = env->fog_light_energy; + Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); + float fog_energy = environment_get_fog_light_energy(p_render_data->environment); scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - scene_state.ubo.fog_sun_scatter = env->fog_sun_scatter; + scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); } else { } @@ -1883,7 +1650,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0; - light_data.shadow_enabled = false; + light_data.shadow_opacity = 0.0; } // TODO, to avoid stalls, should rotate between 3 buffers based on frame index. @@ -1905,7 +1672,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b glBindBuffer(GL_UNIFORM_BUFFER, 0); } -void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { +void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); RENDER_TIMESTAMP("Setup 3D Scene"); @@ -1970,7 +1737,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * // Fill Light lists here ////////// - GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_variables_get_uniform_buffer(); + GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_uniforms_get_uniform_buffer(); glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer); Color clear_color; @@ -1980,8 +1747,6 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * clear_color = texture_storage->get_default_clear_color(); } - Environment *env = environment_owner.get_or_null(p_environment); - bool fb_cleared = false; Size2i screen_size; @@ -1991,10 +1756,10 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * bool use_wireframe = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME; SceneState::TonemapUBO tonemap_ubo; - if (env) { - tonemap_ubo.exposure = env->exposure; - tonemap_ubo.white = env->white; - tonemap_ubo.tonemapper = int32_t(env->tone_mapper); + if (render_data.environment.is_valid()) { + tonemap_ubo.exposure = environment_get_exposure(render_data.environment); + tonemap_ubo.white = environment_get_white(render_data.environment); + tonemap_ubo.tonemapper = int32_t(environment_get_tone_mapper(render_data.environment)); } if (scene_state.tonemap_buffer == 0) { @@ -2017,25 +1782,25 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (env) { - RS::EnvironmentBG bg_mode = env->background; - float bg_energy = env->bg_energy; + } else if (render_data.environment.is_valid()) { + RS::EnvironmentBG bg_mode = environment_get_background(render_data.environment); + float bg_energy = environment_get_bg_energy(render_data.environment); switch (bg_mode) { case RS::ENV_BG_CLEAR_COLOR: { clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (env->fog_enabled) { + if (environment_get_fog_enabled(render_data.environment)) { draw_sky_fog_only = true; GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); } } break; case RS::ENV_BG_COLOR: { - clear_color = env->bg_color; + clear_color = environment_get_bg_color(render_data.environment); clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (env->fog_enabled) { + if (environment_get_fog_enabled(render_data.environment)) { draw_sky_fog_only = true; GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); } @@ -2055,20 +1820,20 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * } } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) { + if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); - CameraMatrix projection = render_data.cam_projection; + Projection projection = render_data.cam_projection; if (render_data.reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * render_data.cam_projection; } - _setup_sky(env, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size); + _setup_sky(render_data.environment, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size); - if (env->sky.is_valid()) { - if (env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY || (env->reflection_source == RS::ENV_REFLECTION_SOURCE_BG && env->background == RS::ENV_BG_SKY)) { - _update_sky_radiance(env, projection, render_data.cam_transform); + if (environment_get_sky(render_data.environment).is_valid()) { + if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) { + _update_sky_radiance(render_data.environment, projection, render_data.cam_transform); } } else { // do not try to draw sky if invalid @@ -2148,7 +1913,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS; } - if (!env || (env && !env->fog_enabled)) { + if (render_data.environment.is_null() || (render_data.environment.is_valid() && !environment_get_fog_enabled(render_data.environment))) { spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; } } @@ -2172,7 +1937,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED; scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; - _draw_sky(env, render_data.cam_projection, render_data.cam_transform); + _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform); } RENDER_TIMESTAMP("Render 3D Transparent Pass"); @@ -2221,11 +1986,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { - Environment *env = environment_owner.get_or_null(p_render_data->environment); glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 2); GLuint texture_to_bind = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_CUBEMAP_BLACK))->tex_id; - if (env) { - Sky *sky = sky_owner.get_or_null(env->sky); + if (p_render_data->environment.is_valid()) { + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_render_data->environment)); if (sky && sky->radiance != 0) { texture_to_bind = sky->radiance; // base_spec_constant |= USE_RADIANCE_MAP; @@ -2490,10 +2254,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } } -void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { } -void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { +void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) { } void RasterizerSceneGLES3::set_time(double p_time, double p_step) { @@ -2510,7 +2274,7 @@ RID RasterizerSceneGLES3::render_buffers_create() { return render_buffers_owner.make_rid(rb); } -void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { +void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); @@ -2543,7 +2307,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_ glGenTextures(1, &rb->depth_texture); glBindTexture(GL_TEXTURE_2D, rb->depth_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -2624,8 +2388,8 @@ TypedArray<Image> RasterizerSceneGLES3::bake_render_uv2(RID p_base, const Vector } bool RasterizerSceneGLES3::free(RID p_rid) { - if (environment_owner.owns(p_rid)) { - environment_owner.free(p_rid); + if (is_environment(p_rid)) { + environment_free(p_rid); } else if (sky_owner.owns(p_rid)) { Sky *sky = sky_owner.get_or_null(p_rid); ERR_FAIL_COND_V(!sky, false); @@ -2661,6 +2425,8 @@ void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter } RasterizerSceneGLES3::RasterizerSceneGLES3() { + singleton = this; + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); @@ -2705,7 +2471,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() { { String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n"; global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n"; global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n"; @@ -2744,13 +2510,17 @@ void fragment() { sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n"; material_storage->shaders.sky_shader.initialize(global_defines); sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create(); material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); + } - material_storage->shaders.cubemap_filter_shader.initialize(); + { + String global_defines; + global_defines += "\n#define MAX_SAMPLE_COUNT " + itos(sky_globals.ggx_samples) + "\n"; + material_storage->shaders.cubemap_filter_shader.initialize(global_defines); scene_globals.cubemap_filter_shader_version = material_storage->shaders.cubemap_filter_shader.version_create(); material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, CubemapFilterShaderGLES3::MODE_DEFAULT); } @@ -2820,36 +2590,6 @@ void sky() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind } - // Radical inverse vdc cache texture used for cubemap filtering. - { - glGenTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); - - uint8_t radical_inverse[512]; - - for (uint32_t i = 0; i < 512; i++) { - uint32_t bits = i; - - bits = (bits << 16) | (bits >> 16); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); - bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); - bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); - - float value = float(bits) * 2.3283064365386963e-10; - radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255)); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 512, 1, 0, GL_RED, GL_UNSIGNED_BYTE, radical_inverse); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling - - glBindTexture(GL_TEXTURE_2D, 0); - } #ifdef GLES_OVER_GL glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); #endif @@ -2886,6 +2626,8 @@ RasterizerSceneGLES3::~RasterizerSceneGLES3() { glDeleteBuffers(1, &sky_globals.directional_light_buffer); memdelete_arr(sky_globals.directional_lights); memdelete_arr(sky_globals.last_frame_directional_lights); + + singleton = nullptr; } #endif // GLES3_ENABLED diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 53b76011fe..a54d87a3a3 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_SCENE_OPENGL_H -#define RASTERIZER_SCENE_OPENGL_H +#ifndef RASTERIZER_SCENE_GLES3_H +#define RASTERIZER_SCENE_GLES3_H #ifdef GLES3_ENABLED -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/paged_allocator.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" @@ -96,18 +96,18 @@ struct RenderDataGLES3 { Transform3D cam_transform = Transform3D(); Transform3D inv_cam_transform = Transform3D(); - CameraMatrix cam_projection = CameraMatrix(); + Projection cam_projection = Projection(); bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; float z_near = 0.0; float z_far = 0.0; - const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; + const PagedArray<RenderGeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *reflection_probes = nullptr; RID environment = RID(); @@ -165,7 +165,7 @@ private: float inv_spot_attenuation; float cos_spot_angle; float specular_amount; - uint32_t shadow_enabled; + float shadow_opacity; }; static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes"); @@ -210,7 +210,7 @@ private: mutable RID_Owner<LightInstance> light_instance_owner; - struct GeometryInstanceGLES3; + class GeometryInstanceGLES3; // Cached data for drawing surfaces struct GeometryInstanceSurface { @@ -265,33 +265,16 @@ private: GeometryInstanceGLES3 *owner = nullptr; }; - struct GeometryInstanceGLES3 : public GeometryInstance { + class GeometryInstanceGLES3 : public RenderGeometryInstanceBase { + public: //used during rendering - bool mirror = false; - bool non_uniform_scale = false; - float lod_bias = 0.0; - float lod_model_scale = 1.0; - AABB transformed_aabb; //needed for LOD - float depth = 0; - uint32_t flags_cache = 0; bool store_transform_cache = true; - int32_t shader_parameters_offset = -1; - uint32_t layer_mask = 1; int32_t instance_count = 0; - RID mesh_instance; bool can_sdfgi = false; bool using_projectors = false; bool using_softshadows = false; - bool fade_near = false; - float fade_near_begin = 0; - float fade_near_end = 0; - bool fade_far = false; - float fade_far_begin = 0; - float fade_far_end = 0; - float force_alpha = 1.0; - float parent_fade_alpha = 1.0; uint32_t omni_light_count = 0; LocalVector<RID> omni_lights; @@ -301,35 +284,22 @@ private: LocalVector<uint32_t> spot_light_gl_cache; //used during setup - uint32_t base_flags = 0; - Transform3D transform; GeometryInstanceSurface *surface_caches = nullptr; SelfList<GeometryInstanceGLES3> dirty_list_element; - struct Data { - //data used less often goes into regular heap - RID base; - RS::InstanceType base_type; - - RID skeleton; - Vector<RID> surface_materials; - RID material_override; - RID material_overlay; - AABB aabb; - - bool use_dynamic_gi = false; - bool use_baked_light = false; - bool cast_double_sided_shadows = false; - bool mirror = false; - bool dirty_dependencies = false; + GeometryInstanceGLES3() : + dirty_list_element(this) {} - DependencyTracker dependency_tracker; - }; + virtual void _mark_dirty() override; + virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; + virtual void set_lightmap_capture(const Color *p_sh9) override; - Data *data = nullptr; + virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override; + virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - GeometryInstanceGLES3() : - dirty_list_element(this) {} + virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override {} }; enum { @@ -357,8 +327,7 @@ private: void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); - void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); - void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance); void _update_dirty_geometry_instances(); struct SceneState { @@ -570,88 +539,8 @@ protected: /* Environment */ - struct Environment { - // BG - RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR; - RID sky; - float sky_custom_fov = 0.0; - Basis sky_orientation; - Color bg_color; - float bg_energy = 1.0; - int canvas_max_layer = 0; - RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG; - Color ambient_light; - float ambient_light_energy = 1.0; - float ambient_sky_contribution = 1.0; - RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; - Color ao_color; - - /// Tonemap - - RS::EnvironmentToneMapper tone_mapper; - float exposure = 1.0; - float white = 1.0; - bool auto_exposure = false; - float min_luminance = 0.2; - float max_luminance = 8.0; - float auto_exp_speed = 0.2; - float auto_exp_scale = 0.5; - uint64_t auto_exposure_version = 0; - - // Fog - bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); - float fog_light_energy = 1.0; - float fog_sun_scatter = 0.0; - float fog_density = 0.001; - float fog_height = 0.0; - float fog_height_density = 0.0; //can be negative to invert effect - float fog_aerial_perspective = 0.0; - - /// Glow - bool glow_enabled = false; - Vector<float> glow_levels; - float glow_intensity = 0.8; - float glow_strength = 1.0; - float glow_bloom = 0.0; - float glow_mix = 0.01; - RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; - float glow_hdr_bleed_threshold = 1.0; - float glow_hdr_luminance_cap = 12.0; - float glow_hdr_bleed_scale = 2.0; - float glow_map_strength = 1.0; - RID glow_map = RID(); - - /// SSAO - bool ssao_enabled = false; - float ssao_radius = 1.0; - float ssao_intensity = 2.0; - float ssao_power = 1.5; - float ssao_detail = 0.5; - float ssao_horizon = 0.06; - float ssao_sharpness = 0.98; - float ssao_direct_light_affect = 0.0; - float ssao_ao_channel_affect = 0.0; - - /// SSR - bool ssr_enabled = false; - int ssr_max_steps = 64; - float ssr_fade_in = 0.15; - float ssr_fade_out = 2.0; - float ssr_depth_tolerance = 0.2; - - /// Adjustments - bool adjustments_enabled = false; - float adjustments_brightness = 1.0f; - float adjustments_contrast = 1.0f; - float adjustments_saturation = 1.0f; - bool use_1d_color_correction = false; - RID color_correction = RID(); - }; - RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; - bool ssao_using_half_size = false; float ssao_adaptive_target = 0.5; int ssao_blur_passes = 2; float ssao_fadeout_from = 50.0; @@ -661,10 +550,6 @@ protected: bool glow_high_quality = false; RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; - static uint64_t auto_exposure_counter; - - mutable RID_Owner<Environment, true> environment_owner; - /* Sky */ struct SkyGlobals { @@ -730,44 +615,23 @@ protected: Sky *dirty_sky_list = nullptr; mutable RID_Owner<Sky, true> sky_owner; - void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); + void _setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); void _invalidate_sky(Sky *p_sky); void _update_dirty_skys(); - void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform); void _filter_sky_radiance(Sky *p_sky, int p_base_layer); - void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform); void _free_sky_data(Sky *p_sky); public: + static RasterizerSceneGLES3 *get_singleton() { return singleton; } + RasterizerCanvasGLES3 *canvas; - GeometryInstance *geometry_instance_create(RID p_base) override; - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override; - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override; - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override; - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override; - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override; - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override; - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override; - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override; - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override; - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override; - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override; - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override; + RenderGeometryInstance *geometry_instance_create(RID p_base) override; + void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; uint32_t geometry_instance_get_pair_mask() override; - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override; - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override; - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override; - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override; - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override; /* SHADOW ATLAS API */ @@ -804,49 +668,24 @@ public: /* ENVIRONMENT API */ - RID environment_allocate() override; - void environment_initialize(RID p_rid) override; - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override; - void environment_set_sky(RID p_env, RID p_sky) override; - void environment_set_sky_custom_fov(RID p_env, float p_scale) override; - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override; - void environment_set_bg_color(RID p_env, const Color &p_color) override; - void environment_set_bg_energy(RID p_env, float p_energy) override; - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override; - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override; - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override; void environment_glow_set_use_bicubic_upscale(bool p_enable) override; void environment_glow_set_use_high_quality(bool p_enable) override; - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override; void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override; - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override; + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override; - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override; - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override; - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override; - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override; - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override; void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override; void environment_set_volumetric_fog_filter_active(bool p_enable) override; Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override; - bool is_environment(RID p_env) const override; - RS::EnvironmentBG environment_get_background(RID p_env) const override; - int environment_get_canvas_max_layer(RID p_env) const override; - RID camera_effects_allocate() override; void camera_effects_initialize(RID p_rid) override; void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override; @@ -855,13 +694,13 @@ public: void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override; void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override; - void shadows_quality_set(RS::ShadowQuality p_quality) override; - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override; + void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; + void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; RID light_instance_create(RID p_light) override; void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override; void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override; - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; + void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; void light_instance_mark_visible(RID p_light_instance) override; _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { @@ -900,13 +739,13 @@ public: RID voxel_gi_instance_create(RID p_voxel_gi) override; void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override; bool voxel_gi_needs_update(RID p_probe) const override; - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override; + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override; void voxel_gi_set_quality(RS::VoxelGIQuality) override; - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; + void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override; void set_scene_pass(uint64_t p_pass) override { scene_pass = p_pass; @@ -923,7 +762,7 @@ public: } RID render_buffers_create() override; - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; void gi_set_use_half_resolution(bool p_enable) override; void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override; @@ -941,11 +780,10 @@ public: void decals_set_filter(RS::DecalFilter p_filter) override; void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override; - static RasterizerSceneGLES3 *get_singleton(); RasterizerSceneGLES3(); ~RasterizerSceneGLES3(); }; #endif // GLES3_ENABLED -#endif // RASTERIZER_SCENE_OPENGL_H +#endif // RASTERIZER_SCENE_GLES3_H diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index e1385669cd..2b72549b5b 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_OPENGL_H -#define SHADER_OPENGL_H +#ifndef SHADER_GLES3_H +#define SHADER_GLES3_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/os/mutex.h" #include "core/string/string_builder.h" #include "core/templates/hash_map.h" @@ -248,5 +248,6 @@ public: virtual ~ShaderGLES3(); }; -#endif // SHADER_OPENGL_H -#endif +#endif // GLES3_ENABLED + +#endif // SHADER_GLES3_H diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index e08a15e59d..852dccf415 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -58,8 +58,8 @@ struct DrawData { uvec4 lights; }; -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; layout(std140) uniform CanvasData { //ubo:0 diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index ebf0c08ec4..88464876f1 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -29,19 +29,15 @@ uniform samplerCube source_cube; //texunit:0 /* clang-format on */ uniform int face_id; -uniform float roughness; -uniform float face_size; -uniform int sample_count; -//Todo, profile on low end hardware to see if fixed loop is faster -#ifdef USE_FIXED_SAMPLES -#define FIXED_SAMPLE_COUNT 32 +#ifndef MODE_DIRECT_WRITE +uniform int sample_count; +uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT]; +uniform float weight; #endif in highp vec2 uv_interp; -uniform sampler2D radical_inverse_vdc_cache; // texunit:1 - layout(location = 0) out vec4 frag_color; #define M_PI 3.14159265359 @@ -93,48 +89,6 @@ vec3 texelCoordToVec(vec2 uv, int faceID) { return normalize(result); } -vec3 ImportanceSampleGGX(vec2 xi, float roughness4) { - // Compute distribution direction - float Phi = 2.0 * M_PI * xi.x; - float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); - float SinTheta = sqrt(1.0 - CosTheta * CosTheta); - - // Convert to spherical direction - vec3 H; - H.x = SinTheta * cos(Phi); - H.y = SinTheta * sin(Phi); - H.z = CosTheta; - - return H; -} - -float DistributionGGX(float NdotH, float roughness4) { - float NdotH2 = NdotH * NdotH; - float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); - denom = M_PI * denom * denom; - - return roughness4 / denom; -} - -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - -float radical_inverse_VdC(int i) { - return texture(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x; -} - -vec2 Hammersley(int i, int N) { - return vec2(float(i) / float(N), radical_inverse_VdC(i)); -} - void main() { vec3 color = vec3(0.0); vec2 uv = uv_interp; @@ -145,9 +99,6 @@ void main() { #else vec4 sum = vec4(0.0); - float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size); - float roughness2 = roughness * roughness; - float roughness4 = roughness2 * roughness2; vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); mat3 T; T[0] = normalize(cross(UpVector, N)); @@ -155,32 +106,15 @@ void main() { T[2] = N; for (int sample_num = 0; sample_num < sample_count; sample_num++) { - vec2 xi = Hammersley(sample_num, sample_count); - - vec3 H = T * ImportanceSampleGGX(xi, roughness4); - float NdotH = dot(N, H); - vec3 L = (2.0 * NdotH * H - N); - - float NdotL = clamp(dot(N, L), 0.0, 1.0); - - if (NdotL > 0.0) { - float D = DistributionGGX(NdotH, roughness4); - float pdf = D * NdotH / (4.0 * NdotH) + 0.0001; - - float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); - - float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel); - - vec3 val = textureLod(source_cube, L, mipLevel).rgb; - // Mix using linear - val = srgb_to_linear(val); - - sum.rgb += val * NdotL; - sum.a += NdotL; - } + vec4 sample_direction_mip = sample_directions_mip[sample_num]; + vec3 L = T * sample_direction_mip.xyz; + vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb; + // Mix using linear + val = srgb_to_linear(val); + sum.rgb += val * sample_direction_mip.z; } - sum /= sum.a; + sum /= weight; sum.rgb = linear_to_srgb(sum.rgb); frag_color = vec4(sum.rgb, 1.0); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 4f2be8bf60..84daf839e9 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -104,8 +104,8 @@ layout(location = 14) in highp vec4 instance_xform2; layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw. #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; layout(std140) uniform SceneData { // ubo:2 @@ -399,8 +399,8 @@ uniform samplerCube radiance_map; // texunit:-2 #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; /* Material Uniforms */ @@ -495,7 +495,7 @@ struct LightData { //this structure needs to be as packed as possible mediump float cone_attenuation; mediump float cone_angle; mediump float specular_amount; - bool shadow_enabled; + mediump float shadow_opacity; }; #ifndef DISABLE_LIGHT_OMNI layout(std140) uniform OmniLightData { // ubo:5 @@ -686,7 +686,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using cheap approximate specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(50.0 * f0.g, 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -751,7 +754,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (omni_lights[idx].size > 0.0) { float t = omni_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, @@ -800,7 +803,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (spot_lights[idx].size > 0.0) { float t = spot_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, @@ -1049,6 +1052,7 @@ void main() { #else vec3 ref_vec = reflect(-view, normal); #endif + ref_vec = mix(ref_vec, normal, roughness * roughness); float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb; @@ -1107,7 +1111,7 @@ void main() { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 50ab38bc31..eb1befe38e 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -42,8 +42,8 @@ uniform sampler2D half_res; //texunit:-2 uniform sampler2D quarter_res; //texunit:-3 #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; struct DirectionalLightData { diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index f2809734a9..30b5919526 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -64,7 +64,14 @@ Config::Config() { #else float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float"); etc2_supported = true; +#if defined(ANDROID_ENABLED) || defined(IPHONE_ENABLED) + // Some Android devices report support for S3TC but we don't expect that and don't export the textures. + // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs). + // For good measure we do the same hack for iOS, just in case. + s3tc_supported = false; +#else s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); +#endif rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); #endif diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index db76aa79fb..b83c83f425 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -90,4 +90,4 @@ public: #endif // GLES3_ENABLED -#endif // !CONFIG_GLES3_H +#endif // CONFIG_GLES3_H diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 22578c9e91..2e4bfdc15b 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -70,6 +70,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) { light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0; + light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0; light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0; light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0; diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 575ab93eab..857a0261fa 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -342,6 +342,6 @@ public: } // namespace GLES3 -#endif // !GLES3_ENABLED +#endif // GLES3_ENABLED -#endif // !LIGHT_STORAGE_GLES3_H +#endif // LIGHT_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index aa19826953..26441fc726 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -176,75 +176,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_UINT: { @@ -271,75 +282,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_FLOAT: { @@ -504,6 +526,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[1] = v.y; gui[2] = v.z; gui[3] = v.w; + } else if (value.get_type() == Variant::VECTOR4) { + Vector4 v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } else { Plane v = value; @@ -660,7 +689,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[i + 15] = 1; } } - } else { + } else if (value.get_type() == Variant::TRANSFORM3D) { Transform3D v = value; gui[0] = v.basis.rows[0][0]; gui[1] = v.basis.rows[1][0]; @@ -681,6 +710,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[13] = v.origin.y; gui[14] = v.origin.z; gui[15] = 1; + } else { + Projection v = value; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + gui[i * 4 + j] = v.matrix[i][j]; + } + } } } break; default: { @@ -937,7 +973,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it - GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key); uint32_t index = 0; if (gv) { index = gv->buffer_index; @@ -993,9 +1029,9 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (uses_global_buffer != (global_buffer_E != nullptr)) { if (uses_global_buffer) { - global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self); + global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self); } else { - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); global_buffer_E = nullptr; } } @@ -1006,20 +1042,20 @@ MaterialData::~MaterialData() { if (global_buffer_E) { //unregister global buffers - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); } if (global_texture_E) { //unregister global textures for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } } //unregister material from those using global textures - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); } if (uniform_buffer) { @@ -1050,7 +1086,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (p_texture_uniforms[i].global) { uses_global_textures = true; - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name); if (v) { if (v->buffer_index >= 0) { WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); @@ -1120,6 +1156,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_BLACK); } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_TRANSPARENT); + } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_ANISO); } break; @@ -1222,7 +1261,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (E.value != global_textures_pass) { to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1236,9 +1275,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet //handle registering/unregistering global textures if (uses_global_textures != (global_texture_E != nullptr)) { if (uses_global_textures) { - global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self); + global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self); } else { - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); global_texture_E = nullptr; } } @@ -1305,22 +1344,22 @@ MaterialStorage::MaterialStorage() { material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func; material_data_request_func[RS::SHADER_FOG] = nullptr; - static_assert(sizeof(GlobalVariables::Value) == 16); + static_assert(sizeof(GlobalShaderUniforms::Value) == 16); - global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); - if (global_variables.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) { - global_variables.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size); + global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); + if (global_shader_uniforms.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) { + global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size); WARN_PRINT("Project setting: rendering/limits/global_shader_variables/buffer_size exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size)); } - global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); - memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); - global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); - global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - glGenBuffers(1, &global_variables.buffer); - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, nullptr, GL_DYNAMIC_DRAW); + global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size); + memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + glGenBuffers(1, &global_shader_uniforms.buffer); + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); { @@ -1378,6 +1417,7 @@ MaterialStorage::MaterialStorage() { actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; + actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; @@ -1457,7 +1497,7 @@ MaterialStorage::MaterialStorage() { actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; - actions.renames["FOG"] = "custom_fog"; + actions.renames["FOG"] = "fog"; actions.renames["RADIANCE"] = "custom_radiance"; actions.renames["IRRADIANCE"] = "custom_irradiance"; actions.renames["BONE_INDICES"] = "bone_attrib"; @@ -1468,6 +1508,11 @@ MaterialStorage::MaterialStorage() { actions.renames["CUSTOM3"] = "custom3_attrib"; actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz"; + actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; + actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz"; + actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; @@ -1613,7 +1658,7 @@ ShaderCompiler::DefaultIdentifierActions actions; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; particles_shader.compiler.initialize(actions); */ @@ -1675,25 +1720,25 @@ ShaderCompiler::DefaultIdentifierActions actions; MaterialStorage::~MaterialStorage() { //shaders.copy.version_free(shaders.copy_version); - memdelete_arr(global_variables.buffer_values); - memdelete_arr(global_variables.buffer_usage); - memdelete_arr(global_variables.buffer_dirty_regions); - glDeleteBuffers(1, &global_variables.buffer); + memdelete_arr(global_shader_uniforms.buffer_values); + memdelete_arr(global_shader_uniforms.buffer_usage); + memdelete_arr(global_shader_uniforms.buffer_dirty_regions); + glDeleteBuffers(1, &global_shader_uniforms.buffer); singleton = nullptr; } -/* GLOBAL VARIABLE API */ +/* GLOBAL SHADER UNIFORM API */ -int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { +int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) { int32_t idx = 0; - while (idx + p_elements <= global_variables.buffer_size) { - if (global_variables.buffer_usage[idx].elements == 0) { + while (idx + p_elements <= global_shader_uniforms.buffer_size) { + if (global_shader_uniforms.buffer_usage[idx].elements == 0) { bool valid = true; for (uint32_t i = 1; i < p_elements; i++) { - if (global_variables.buffer_usage[idx + i].elements > 0) { + if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) { valid = false; - idx += i + global_variables.buffer_usage[idx + i].elements; + idx += i + global_shader_uniforms.buffer_usage[idx + i].elements; break; } } @@ -1704,17 +1749,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { return idx; } else { - idx += global_variables.buffer_usage[idx].elements; + idx += global_shader_uniforms.buffer_usage[idx].elements; } } return -1; } -void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { +void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; bool b = p_value; bv.x = b ? 1.0 : 0.0; bv.y = 0.0; @@ -1723,7 +1768,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_BVEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1731,7 +1776,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1739,7 +1784,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1747,7 +1792,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = (bvec & 8) ? 1.0 : 0.0; } break; case RS::GLOBAL_VAR_TYPE_INT: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; int32_t v = p_value; bv.x = v; bv.y = 0; @@ -1755,7 +1800,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC2: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1763,7 +1808,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC3: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1771,7 +1816,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC4: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1779,7 +1824,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_RECT2I: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Rect2i v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1787,7 +1832,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_UINT: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; uint32_t v = p_value; bv.x = v; bv.y = 0; @@ -1795,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC2: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1803,7 +1848,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC3: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1811,7 +1856,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC4: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1819,7 +1864,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_FLOAT: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; float v = p_value; bv.x = v; bv.y = 0; @@ -1827,7 +1872,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector2 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1835,7 +1880,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector3 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1843,7 +1888,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Plane v = p_value; bv.x = v.normal.x; bv.y = v.normal.y; @@ -1851,14 +1896,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.d; } break; case RS::GLOBAL_VAR_TYPE_COLOR: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Color v = p_value; bv.x = v.r; bv.y = v.g; bv.z = v.b; bv.w = v.a; - GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; + GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1]; //v = v.srgb_to_linear(); bv_linear.x = v.r; bv_linear.y = v.g; @@ -1867,7 +1912,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_RECT2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Rect2 v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1875,7 +1920,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_MAT2: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 4) { m2.resize(4); @@ -1892,7 +1937,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT3: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Basis v = p_value; bv[0].x = v.rows[0][0]; bv[0].y = v.rows[1][0]; @@ -1911,7 +1956,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT4: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 16) { @@ -1940,7 +1985,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform2D v = p_value; bv[0].x = v.columns[0][0]; bv[0].y = v.columns[0][1]; @@ -1959,7 +2004,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform3D v = p_value; bv[0].x = v.basis.rows[0][0]; bv[0].y = v.basis.rows[1][0]; @@ -1988,15 +2033,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } } -void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { +void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { int32_t prev_chunk = -1; for (int32_t i = 0; i < p_elements; i++) { - int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; if (chunk != prev_chunk) { - if (!global_variables.buffer_dirty_regions[chunk]) { - global_variables.buffer_dirty_regions[chunk] = true; - global_variables.buffer_dirty_region_count++; + if (!global_shader_uniforms.buffer_dirty_regions[chunk]) { + global_shader_uniforms.buffer_dirty_regions[chunk] = true; + global_shader_uniforms.buffer_dirty_region_count++; } } @@ -2004,16 +2049,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_ } } -void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { - ERR_FAIL_COND(global_variables.variables.has(p_name)); - GlobalVariables::Variable gv; +void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) { + ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable gv; gv.type = p_type; gv.value = p_value; gv.buffer_index = -1; if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { //is texture - global_variables.must_update_texture_materials = true; //normally there are none + global_shader_uniforms.must_update_texture_materials = true; //normally there are none } else { gv.buffer_elements = 1; if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { @@ -2030,56 +2075,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa } //is vector, allocate in buffer and update index - gv.buffer_index = _global_variable_allocate(gv.buffer_elements); + gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements); ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); - global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - global_variables.must_update_buffer_materials = true; //normally there are none + global_shader_uniforms.must_update_buffer_materials = true; //normally there are none } - global_variables.variables[p_name] = gv; + global_shader_uniforms.variables[p_name] = gv; } -void MaterialStorage::global_variable_remove(const StringName &p_name) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) { + if (!global_shader_uniforms.variables.has(p_name)) { return; } - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; if (gv.buffer_index >= 0) { - global_variables.buffer_usage[gv.buffer_index].elements = 0; - global_variables.must_update_buffer_materials = true; + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0; + global_shader_uniforms.must_update_buffer_materials = true; } else { - global_variables.must_update_texture_materials = true; + global_shader_uniforms.must_update_texture_materials = true; } - global_variables.variables.erase(p_name); + global_shader_uniforms.variables.erase(p_name); } -Vector<StringName> MaterialStorage::global_variable_get_list() const { +Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } Vector<StringName> names; - for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) { names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; } -void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!global_variables.variables.has(p_name)); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; +void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.value = p_value; if (gv.override.get_type() == Variant::NIL) { if (gv.buffer_index >= 0) { //buffer - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -2092,26 +2137,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } } -void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) { + if (!global_shader_uniforms.variables.has(p_name)) { return; //variable may not exist } ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.override = p_value; if (gv.buffer_index >= 0) { //buffer if (gv.override.get_type() == Variant::NIL) { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); } else { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override); } - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -2123,35 +2168,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } } -Variant MaterialStorage::global_variable_get(const StringName &p_name) const { +Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); } - if (!global_variables.variables.has(p_name)) { + if (!global_shader_uniforms.variables.has(p_name)) { return Variant(); } - return global_variables.variables[p_name].value; + return global_shader_uniforms.variables[p_name].value; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const { - if (!global_variables.variables.has(p_name)) { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const { + if (!global_shader_uniforms.variables.has(p_name)) { return RS::GLOBAL_VAR_TYPE_MAX; } - return global_variables.variables[p_name].type; + return global_shader_uniforms.variables[p_name].type; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); } - return global_variable_get_type_internal(p_name); + return global_shader_uniform_get_type_internal(p_name); } -void MaterialStorage::global_variables_load_settings(bool p_load_textures) { +void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) { List<PropertyInfo> settings; ProjectSettings::get_singleton()->get_property_list(&settings); @@ -2196,11 +2241,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { "samplerCube", }; - RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX; for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { if (global_var_type_names[i] == type) { - gvtype = RS::GlobalVariableType(i); + gvtype = RS::GlobalShaderUniformType(i); break; } } @@ -2222,47 +2267,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { value = resource; } - if (global_variables.variables.has(name)) { + if (global_shader_uniforms.variables.has(name)) { //has it, update it - global_variable_set(name, value); + global_shader_uniform_set(name, value); } else { - global_variable_add(name, gvtype, value); + global_shader_uniform_add(name, gvtype, value); } } } } -void MaterialStorage::global_variables_clear() { - global_variables.variables.clear(); +void MaterialStorage::global_shader_uniforms_clear() { + global_shader_uniforms.variables.clear(); } -GLuint MaterialStorage::global_variables_get_uniform_buffer() const { - return global_variables.buffer; +GLuint MaterialStorage::global_shader_uniforms_get_uniform_buffer() const { + return global_shader_uniforms.buffer; } -int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) { - ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); - int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - global_variables.instance_buffer_pos[p_instance] = pos; //save anyway +int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) { + ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1); + int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); - global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; + global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; return pos; } -void MaterialStorage::global_variables_instance_free(RID p_instance) { - ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); - int32_t pos = global_variables.instance_buffer_pos[p_instance]; +void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) { + ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance)); + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos >= 0) { - global_variables.buffer_usage[pos].elements = 0; + global_shader_uniforms.buffer_usage[pos].elements = 0; } - global_variables.instance_buffer_pos.erase(p_instance); + global_shader_uniforms.instance_buffer_pos.erase(p_instance); } -void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { - if (!global_variables.instance_buffer_pos.has(p_instance)) { +void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) { + if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) { return; //just not allocated, ignore } - int32_t pos = global_variables.instance_buffer_pos[p_instance]; + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos < 0) { return; //again, not allocated, ignore @@ -2283,11 +2328,14 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind ShaderLanguage::TYPE_VEC3, // vec3 ShaderLanguage::TYPE_IVEC3, //vec3i ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //vec4 + ShaderLanguage::TYPE_IVEC4, //vec4i ShaderLanguage::TYPE_VEC4, //plane ShaderLanguage::TYPE_VEC4, //quat ShaderLanguage::TYPE_MAX, //aabb not supported here ShaderLanguage::TYPE_MAX, //basis not supported here ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_MAX, //projection not supported here ShaderLanguage::TYPE_VEC4 //color }; @@ -2297,59 +2345,59 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind pos += p_index; - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]); - _global_variable_mark_buffer_dirty(pos, 1); + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos]); + _global_shader_uniform_mark_buffer_dirty(pos, 1); } -void MaterialStorage::_update_global_variables() { +void MaterialStorage::_update_global_shader_uniforms() { MaterialStorage *material_storage = MaterialStorage::get_singleton(); - if (global_variables.buffer_dirty_region_count > 0) { - uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (total_regions / global_variables.buffer_dirty_region_count <= 4) { + if (global_shader_uniforms.buffer_dirty_region_count > 0) { + uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; + if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) { // 25% of regions dirty, just update all buffer - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions); } else { - uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); + uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); for (uint32_t i = 0; i < total_regions; i++) { - if (global_variables.buffer_dirty_regions[i]) { - glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); - global_variables.buffer_dirty_regions[i] = false; + if (global_shader_uniforms.buffer_dirty_regions[i]) { + glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]); + global_shader_uniforms.buffer_dirty_regions[i] = false; } } glBindBuffer(GL_UNIFORM_BUFFER, 0); } - global_variables.buffer_dirty_region_count = 0; + global_shader_uniforms.buffer_dirty_region_count = 0; } - if (global_variables.must_update_buffer_materials) { + if (global_shader_uniforms.must_update_buffer_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_buffer) { + for (const RID &E : global_shader_uniforms.materials_using_buffer) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, true, false); } - global_variables.must_update_buffer_materials = false; + global_shader_uniforms.must_update_buffer_materials = false; } - if (global_variables.must_update_texture_materials) { + if (global_shader_uniforms.must_update_texture_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_texture) { + for (const RID &E : global_shader_uniforms.materials_using_texture) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, false, true); } - global_variables.must_update_texture_materials = false; + global_shader_uniforms.must_update_texture_materials = false; } } @@ -2461,17 +2509,24 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } } +void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { + GLES3::Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->path_hint = p_path; +} + String MaterialStorage::shader_get_code(RID p_shader) const { const GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, String()); return shader->code; } -void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { +void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const { GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (shader->data) { - return shader->data->get_param_list(p_param_list); + return shader->data->get_shader_uniform_list(p_param_list); } } @@ -2703,14 +2758,14 @@ bool MaterialStorage::material_casts_shadows(RID p_material) { return true; //by default everything casts shadows } -void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { +void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) { GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); if (material->shader && material->shader->data) { material->shader->data->get_instance_param_list(r_parameters); if (material->next_pass.is_valid()) { - material_get_instance_shader_parameters(material->next_pass, r_parameters); + material_get_instance_shader_uniforms(material->next_pass, r_parameters); } } } @@ -2818,7 +2873,7 @@ void CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p } } -void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -2832,7 +2887,22 @@ void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -3040,7 +3110,7 @@ void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_te } } -void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { RBMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -3055,7 +3125,22 @@ void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -3350,7 +3435,7 @@ void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_ } } -void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SceneShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { RBMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -3365,7 +3450,22 @@ void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 6ad277c2b9..2ca47351a4 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -54,7 +54,7 @@ namespace GLES3 { struct ShaderData { virtual void set_code(const String &p_Code) = 0; virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; virtual bool is_param_texture(const StringName &p_param) const = 0; @@ -73,6 +73,7 @@ struct Material; struct Shader { ShaderData *data = nullptr; String code; + String path_hint; RS::ShaderMode mode; HashMap<StringName, HashMap<int, RID>> default_texture_parameter; HashSet<Material *> owners; @@ -163,7 +164,7 @@ struct CanvasShaderData : public ShaderData { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -214,7 +215,7 @@ struct SkyShaderData : public ShaderData { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -334,7 +335,7 @@ struct SceneShaderData : public ShaderData { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -364,15 +365,15 @@ struct SceneMaterialData : public MaterialData { MaterialData *_create_scene_material_func(ShaderData *p_shader); -/* Global variable structs */ -struct GlobalVariables { +/* Global shader uniform structs */ +struct GlobalShaderUniforms { enum { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { HashSet<RID> texture_materials; // materials using this - RS::GlobalVariableType type; + RS::GlobalShaderUniformType type; Variant value; Variant override; int32_t buffer_index; //for vectors @@ -428,13 +429,13 @@ private: friend struct MaterialData; static MaterialStorage *singleton; - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - GlobalVariables global_variables; + GlobalShaderUniforms global_shader_uniforms; - int32_t _global_variable_allocate(uint32_t p_elements); - void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); - void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); + int32_t _global_shader_uniform_allocate(uint32_t p_elements); + void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value); + void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements); /* SHADER API */ @@ -487,7 +488,7 @@ public: p_array[11] = 0; } - static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { p_array[i * 4 + j] = p_mtx.matrix[i][j]; @@ -507,28 +508,28 @@ public: ShaderCompiler compiler_sky; } shaders; - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - void _update_global_variables(); + void _update_global_shader_uniforms(); - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override; - virtual void global_variable_remove(const StringName &p_name) override; - virtual Vector<StringName> global_variable_get_list() const override; + virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override; + virtual void global_shader_uniform_remove(const StringName &p_name) override; + virtual Vector<StringName> global_shader_uniform_get_list() const override; - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override; - virtual Variant global_variable_get(const StringName &p_name) const override; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override; - RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_shader_uniform_get(const StringName &p_name) const override; + virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override; + RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const; - virtual void global_variables_load_settings(bool p_load_textures = true) override; - virtual void global_variables_clear() override; + virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override; + virtual void global_shader_uniforms_clear() override; - virtual int32_t global_variables_instance_allocate(RID p_instance) override; - virtual void global_variables_instance_free(RID p_instance) override; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override; + virtual void global_shader_uniforms_instance_free(RID p_instance) override; + virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override; - GLuint global_variables_get_uniform_buffer() const; + GLuint global_shader_uniforms_get_uniform_buffer() const; /* SHADER API */ @@ -542,8 +543,9 @@ public: virtual void shader_free(RID p_rid) override; virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) override; virtual String shader_get_code(RID p_shader) const override; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; + virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; @@ -574,7 +576,7 @@ public: virtual bool material_is_animated(RID p_material) override; virtual bool material_casts_shadows(RID p_material) override; - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; + virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override; @@ -597,4 +599,4 @@ public: #endif // GLES3_ENABLED -#endif // !MATERIAL_STORAGE_GLES3_H +#endif // MATERIAL_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 88b81805fa..667ba4f5e6 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1347,7 +1347,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b _multimesh_mark_all_dirty(multimesh, false, true); //update AABB } else if (multimesh->mesh.is_valid()) { //if we have a mesh set, we need to re-generate the AABB from the new data - const float *data = multimesh->data_cache.ptr(); + const float *data = p_buffer.ptr(); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index c51cd5dcd6..339380b3b0 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -543,4 +543,4 @@ public: #endif // GLES3_ENABLED -#endif // !MESH_STORAGE_GLES3_H +#endif // MESH_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h index cf47ada5d5..84d1f94d8c 100644 --- a/drivers/gles3/storage/particles_storage.h +++ b/drivers/gles3/storage/particles_storage.h @@ -137,4 +137,4 @@ public: #endif // GLES3_ENABLED -#endif // !PARTICLES_STORAGE_GLES3_H +#endif // PARTICLES_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index c05f516548..543638e8ff 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -115,6 +115,17 @@ TextureStorage::TextureStorage() { texture_2d_layered_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK], images, RS::TEXTURE_LAYERED_CUBEMAP); } + { // transparent black + Ref<Image> image; + image.instantiate(); + image->create(4, 4, true, Image::FORMAT_RGBA8); + image->fill(Color(0, 0, 0, 0)); + image->generate_mipmaps(); + + default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT] = texture_allocate(); + texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT], image); + } + { Ref<Image> image; image.instantiate(); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index de887f9184..71f713bc9f 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -103,6 +103,7 @@ namespace GLES3 { enum DefaultGLTexture { DEFAULT_GL_TEXTURE_WHITE, DEFAULT_GL_TEXTURE_BLACK, + DEFAULT_GL_TEXTURE_TRANSPARENT, DEFAULT_GL_TEXTURE_NORMAL, DEFAULT_GL_TEXTURE_ANISO, DEFAULT_GL_TEXTURE_DEPTH, @@ -546,6 +547,16 @@ public: void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps); void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color); void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region); + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{}; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{}; + + void bind_framebuffer(GLuint framebuffer) { + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + } + + void bind_framebuffer_system() { + glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); + } String get_framebuffer_error(GLenum p_status); }; @@ -567,6 +578,6 @@ inline String TextureStorage::get_framebuffer_error(GLenum p_status) { } // namespace GLES3 -#endif // !GLES3_ENABLED +#endif // GLES3_ENABLED -#endif // !TEXTURE_STORAGE_GLES3_H +#endif // TEXTURE_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp index a00210a2ab..654104722b 100644 --- a/drivers/gles3/storage/utilities.cpp +++ b/drivers/gles3/storage/utilities.cpp @@ -293,7 +293,7 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de /* MISC */ void Utilities::update_dirty_resources() { - MaterialStorage::get_singleton()->_update_global_variables(); + MaterialStorage::get_singleton()->_update_global_shader_uniforms(); MaterialStorage::get_singleton()->_update_queued_materials(); //MeshStorage::get_singleton()->_update_dirty_skeletons(); MeshStorage::get_singleton()->_update_dirty_multimeshes(); diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h index 523033886c..e054f2f816 100644 --- a/drivers/gles3/storage/utilities.h +++ b/drivers/gles3/storage/utilities.h @@ -156,4 +156,4 @@ public: #endif // GLES3_ENABLED -#endif // !UTILITIES_GLES3_H +#endif // UTILITIES_GLES3_H diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 522cc901d4..9bcfb720d3 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -45,4 +45,4 @@ public: ImageLoaderPNG(); }; -#endif +#endif // IMAGE_LOADER_PNG_H diff --git a/drivers/png/png_driver_common.h b/drivers/png/png_driver_common.h index 62302bbdbb..24546d4402 100644 --- a/drivers/png/png_driver_common.h +++ b/drivers/png/png_driver_common.h @@ -43,4 +43,4 @@ Error png_to_image(const uint8_t *p_source, size_t p_size, bool p_force_linear, Error image_to_png(const Ref<Image> &p_image, Vector<uint8_t> &p_buffer); } // namespace PNGDriverCommon -#endif +#endif // PNG_DRIVER_COMMON_H diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 704ddca726..275f3240d7 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -35,7 +35,7 @@ #include "drivers/png/png_driver_common.h" #include "scene/resources/texture.h" -Error ResourceSaverPNG::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceSaverPNG::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<ImageTexture> texture = p_resource; ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as PNG."); diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 1a681faaec..260a643a1b 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -39,7 +39,7 @@ public: static Error save_image(const String &p_path, const Ref<Image> &p_img); static Vector<uint8_t> save_image_to_buffer(const Ref<Image> &p_img); - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; diff --git a/drivers/register_driver_types.h b/drivers/register_driver_types.h index c008d93185..41f95b57e7 100644 --- a/drivers/register_driver_types.h +++ b/drivers/register_driver_types.h @@ -37,4 +37,4 @@ void unregister_core_driver_types(); void register_driver_types(); void unregister_driver_types(); -#endif +#endif // REGISTER_DRIVER_TYPES_H diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 39dbadf3cd..b8b72b8d30 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -516,4 +516,4 @@ DirAccessUnix::~DirAccessUnix() { list_dir_end(); } -#endif //posix_enabled +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 5e2129b74a..f5dca7c282 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -52,43 +52,44 @@ protected: virtual bool is_hidden(const String &p_name); public: - virtual Error list_dir_begin(); ///< This starts dir listing - virtual String get_next(); - virtual bool current_is_dir() const; - virtual bool current_is_hidden() const; + virtual Error list_dir_begin() override; ///< This starts dir listing + virtual String get_next() override; + virtual bool current_is_dir() const override; + virtual bool current_is_hidden() const override; - virtual void list_dir_end(); ///< + virtual void list_dir_end() override; ///< - virtual int get_drive_count(); - virtual String get_drive(int p_drive); - virtual int get_current_drive(); - virtual bool drives_are_shortcuts(); + virtual int get_drive_count() override; + virtual String get_drive(int p_drive) override; + virtual int get_current_drive() override; + virtual bool drives_are_shortcuts() override; - virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success - virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location - virtual Error make_dir(String p_dir); + virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success + virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location + virtual Error make_dir(String p_dir) override; - virtual bool file_exists(String p_file); - virtual bool dir_exists(String p_dir); - virtual bool is_readable(String p_dir); - virtual bool is_writable(String p_dir); + virtual bool file_exists(String p_file) override; + virtual bool dir_exists(String p_dir) override; + virtual bool is_readable(String p_dir) override; + virtual bool is_writable(String p_dir) override; virtual uint64_t get_modified_time(String p_file); - virtual Error rename(String p_path, String p_new_path); - virtual Error remove(String p_path); + virtual Error rename(String p_path, String p_new_path) override; + virtual Error remove(String p_path) override; - virtual bool is_link(String p_file); - virtual String read_link(String p_file); - virtual Error create_link(String p_source, String p_target); + virtual bool is_link(String p_file) override; + virtual String read_link(String p_file) override; + virtual Error create_link(String p_source, String p_target) override; - virtual uint64_t get_space_left(); + virtual uint64_t get_space_left() override; - virtual String get_filesystem_type() const; + virtual String get_filesystem_type() const override; DirAccessUnix(); ~DirAccessUnix(); }; -#endif //UNIX ENABLED -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED + +#endif // DIR_ACCESS_UNIX_H diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 99836b7bea..388ad479b9 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -339,4 +339,4 @@ FileAccessUnix::~FileAccessUnix() { _close(); } -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 0261b8be53..297c34e454 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -54,37 +54,38 @@ class FileAccessUnix : public FileAccess { public: static CloseNotificationFunc close_notification_func; - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual String get_path() const; /// returns the path for the current open file - virtual String get_path_absolute() const; /// returns the absolute path for the current open file + virtual String get_path() const override; /// returns the path for the current open file + virtual String get_path_absolute() const override; /// returns the absolute path for the current open file - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes - virtual bool file_exists(const String &p_path); ///< return true if a file exists + virtual bool file_exists(const String &p_path) override; ///< return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file); - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); + virtual uint64_t _get_modified_time(const String &p_file) override; + virtual uint32_t _get_unix_permissions(const String &p_file) override; + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; FileAccessUnix() {} virtual ~FileAccessUnix(); }; -#endif -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED + +#endif // FILE_ACCESS_UNIX_H diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 2deeb79957..0dc2efedc1 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -95,12 +95,12 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result); if (s != 0) { - ERR_PRINT("getaddrinfo failed! Cannot resolve hostname."); + print_verbose("getaddrinfo failed! Cannot resolve hostname."); return; } if (result == nullptr || result->ai_addr == nullptr) { - ERR_PRINT("Invalid response from getaddrinfo"); + print_verbose("Invalid response from getaddrinfo"); if (result) { freeaddrinfo(result); } diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 06fcdb6e17..798d02095c 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -50,4 +50,5 @@ public: }; #endif + #endif // IP_UNIX_H diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h index 867513099a..5558114cb1 100644 --- a/drivers/unix/net_socket_posix.h +++ b/drivers/unix/net_socket_posix.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NET_SOCKET_UNIX_H -#define NET_SOCKET_UNIX_H +#ifndef NET_SOCKET_POSIX_H +#define NET_SOCKET_POSIX_H #include "core/io/net_socket.h" @@ -104,4 +104,4 @@ public: ~NetSocketPosix(); }; -#endif +#endif // NET_SOCKET_POSIX_H diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 091287c652..5bf14056ab 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -65,7 +65,7 @@ #include <time.h> #include <unistd.h> -#if defined(OSX_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) +#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) // Random location for getentropy. Fitting. #include <sys/random.h> #define UNIX_GET_ENTROPY diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index a1ed4bd501..f4609a565b 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -98,6 +98,6 @@ public: virtual ~UnixTerminalLogger(); }; -#endif +#endif // UNIX_ENABLED -#endif +#endif // OS_UNIX_H diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h index 697a96a6f9..cc6617eb25 100644 --- a/drivers/unix/syslog_logger.h +++ b/drivers/unix/syslog_logger.h @@ -43,6 +43,6 @@ public: virtual ~SyslogLogger(); }; -#endif +#endif // UNIX_ENABLED -#endif +#endif // SYSLOG_LOGGER_H diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index 9cd3ecbe90..672adcba72 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -35,4 +35,4 @@ void init_thread_posix(); #endif -#endif +#endif // THREAD_POSIX_H diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index b6ceb1cdea..a076c0ac54 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -15,11 +15,11 @@ if env["use_volk"]: if env["platform"] == "android": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_ANDROID_KHR"]) -elif env["platform"] == "iphone": +elif env["platform"] == "ios": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_IOS_MVK"]) -elif env["platform"] == "linuxbsd": +elif env["platform"] == "linuxbsd" and env["x11"]: env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_XLIB_KHR"]) -elif env["platform"] == "osx": +elif env["platform"] == "macos": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_MACOS_MVK"]) elif env["platform"] == "windows": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_WIN32_KHR"]) @@ -40,7 +40,7 @@ elif env["platform"] == "android": # Our current NDK version only provides old Vulkan headers, # so we have to limit VMA. env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1000000"]) -elif env["platform"] == "osx" or env["platform"] == "iphone": +elif env["platform"] == "macos" or env["platform"] == "ios": # MoltenVK supports only Vulkan 1.1 API, limit VMA to the same version. env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1001000"]) diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 9b491be128..89daa2af64 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -36,6 +36,7 @@ #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/templates/hashfuncs.h" +#include "core/version.h" #include "drivers/vulkan/vulkan_context.h" #include "thirdparty/misc/smolv.h" @@ -106,7 +107,7 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID return buffer; } -static void update_external_dependency_for_store(VkSubpassDependency &dependency, bool is_sampled, bool is_storage, bool is_depth) { +static void update_external_dependency_for_store(VkSubpassDependency2KHR &dependency, bool is_sampled, bool is_storage, bool is_depth) { // Transitioning from write to read, protect the shaders that may use this next // Allow for copies/image layout transitions dependency.dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; @@ -1758,6 +1759,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } + if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + image_create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; + } + if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) { image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; } @@ -1829,6 +1834,11 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T if (p_format.usage_bits & TEXTURE_USAGE_STORAGE_ATOMIC_BIT && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) { ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image."); } + + // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported. + if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format.format != DATA_FORMAT_R8_UINT) { + ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as VRS attachment."); + } } //some view validation @@ -1994,6 +2004,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T } RID id = texture_owner.make_rid(texture); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif if (p_data.size()) { for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) { @@ -2123,6 +2136,9 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID texture.owner = p_with_texture; RID id = texture_owner.make_rid(texture); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif _add_dependency(id, p_with_texture); return id; @@ -2242,6 +2258,9 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat } RID id = texture_owner.make_rid(texture); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif return id; } @@ -2367,6 +2386,9 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p texture.owner = p_with_texture; RID id = texture_owner.make_rid(texture); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif _add_dependency(id, p_with_texture); return id; @@ -3349,6 +3371,11 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f return false; } + // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported. + if (p_usage & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format != DATA_FORMAT_R8_UINT) { + return false; + } + return true; } @@ -3362,17 +3389,24 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // From Section 7.1 of Vulkan API Spec v1.1.148 + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | // From Section 7.1 of Vulkan API Spec v1.1.148 + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR; VkPipelineStageFlags reading_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; - VkSubpassDependency dependencies[2] = { { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0 }, - { 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0 } }; - VkSubpassDependency &dependency_from_external = dependencies[0]; - VkSubpassDependency &dependency_to_external = dependencies[1]; + VkSubpassDependency2KHR dependencies[2] = { + { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0, 0 }, + { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0, 0 } + }; + VkSubpassDependency2KHR &dependency_from_external = dependencies[0]; + VkSubpassDependency2KHR &dependency_to_external = dependencies[1]; LocalVector<int32_t> attachment_last_pass; attachment_last_pass.resize(p_attachments.size()); - Vector<VkAttachmentDescription> attachments; + // These are only used if we use multiview but we need to define them in scope. + const uint32_t view_mask = (1 << p_view_count) - 1; + const uint32_t correlation_mask = (1 << p_view_count) - 1; + + Vector<VkAttachmentDescription2KHR> attachments; Vector<int> attachment_remap; for (int i = 0; i < p_attachments.size(); i++) { @@ -3383,10 +3417,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE); ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE); - ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)), - VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set."); + ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT)), + VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth-stencil, input or VRS) bit set."); - VkAttachmentDescription description = {}; + VkAttachmentDescription2KHR description = {}; + description.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR; + description.pNext = nullptr; description.flags = 0; description.format = vulkan_formats[p_attachments[i].format]; description.samples = rasterization_sample_count[p_attachments[i].samples]; @@ -3395,83 +3431,95 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF bool is_storage = p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT; bool is_depth = p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write - // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs. - // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that - // stage - - switch (is_depth ? p_initial_depth_action : p_initial_action) { - case INITIAL_ACTION_CLEAR_REGION: - case INITIAL_ACTION_CLEAR: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_KEEP: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_DROP: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_CLEAR_REGION_CONTINUE: - case INITIAL_ACTION_CONTINUE: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; + // We can setup a framebuffer where we write to our VRS texture to set it up. + // We make the assumption here that if our texture is actually used as our VRS attachment, + // it is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses. + bool is_vrs = p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && i == p_passes[0].vrs_attachment; + + if (is_vrs) { + // For VRS we only read, there is no writing to this texture + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } else { + // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write + // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs. + // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that + // stage + + switch (is_depth ? p_initial_depth_action : p_initial_action) { + case INITIAL_ACTION_CLEAR_REGION: + case INITIAL_ACTION_CLEAR: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_KEEP: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_DROP: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_CLEAR_REGION_CONTINUE: + case INITIAL_ACTION_CONTINUE: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + default: { + ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here } - } break; - default: { - ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here } } @@ -3485,6 +3533,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF if (p_passes[last_pass].depth_attachment == i) { used_last = true; } + } else if (is_vrs) { + if (p_passes[last_pass].vrs_attachment == i) { + used_last = true; + } } else { if (p_passes[last_pass].resolve_attachments.size()) { //if using resolve attachments, check resolve attachments @@ -3526,58 +3578,69 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } } - switch (is_depth ? final_depth_action : final_action) { - case FINAL_ACTION_READ: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true); - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - // TODO: What does this mean about the next usage (and thus appropriate dependency masks - } - } break; - case FINAL_ACTION_DISCARD: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - } - } break; - case FINAL_ACTION_CONTINUE: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - } + if (is_vrs) { + // We don't change our VRS texture during this process - } break; - default: { - ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + // TODO do we need to update our external dependency ? + // update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); + } else { + switch (is_depth ? final_depth_action : final_action) { + case FINAL_ACTION_READ: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true); + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + // TODO: What does this mean about the next usage (and thus appropriate dependency masks + } + } break; + case FINAL_ACTION_DISCARD: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } else { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + } + } break; + case FINAL_ACTION_CONTINUE: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } else { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + } + + } break; + default: { + ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here + } } } @@ -3586,12 +3649,14 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF attachments.push_back(description); } - LocalVector<VkSubpassDescription> subpasses; - LocalVector<LocalVector<VkAttachmentReference>> color_reference_array; - LocalVector<LocalVector<VkAttachmentReference>> input_reference_array; - LocalVector<LocalVector<VkAttachmentReference>> resolve_reference_array; + LocalVector<VkSubpassDescription2KHR> subpasses; + LocalVector<LocalVector<VkAttachmentReference2KHR>> color_reference_array; + LocalVector<LocalVector<VkAttachmentReference2KHR>> input_reference_array; + LocalVector<LocalVector<VkAttachmentReference2KHR>> resolve_reference_array; LocalVector<LocalVector<uint32_t>> preserve_reference_array; - LocalVector<VkAttachmentReference> depth_reference_array; + LocalVector<VkAttachmentReference2KHR> depth_reference_array; + LocalVector<VkAttachmentReference2KHR> vrs_reference_array; + LocalVector<VkFragmentShadingRateAttachmentInfoKHR> vrs_attachment_info_array; subpasses.resize(p_passes.size()); color_reference_array.resize(p_passes.size()); @@ -3599,20 +3664,25 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF resolve_reference_array.resize(p_passes.size()); preserve_reference_array.resize(p_passes.size()); depth_reference_array.resize(p_passes.size()); + vrs_reference_array.resize(p_passes.size()); + vrs_attachment_info_array.resize(p_passes.size()); - LocalVector<VkSubpassDependency> subpass_dependencies; + LocalVector<VkSubpassDependency2KHR> subpass_dependencies; for (int i = 0; i < p_passes.size(); i++) { const FramebufferPass *pass = &p_passes[i]; - LocalVector<VkAttachmentReference> &color_references = color_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &color_references = color_reference_array[i]; TextureSamples texture_samples = TEXTURE_SAMPLES_1; bool is_multisample_first = true; + void *subpass_nextptr = nullptr; for (int j = 0; j < pass->color_attachments.size(); j++) { int32_t attachment = pass->color_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3631,14 +3701,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; color_references.push_back(reference); } - LocalVector<VkAttachmentReference> &input_references = input_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &input_references = input_reference_array[i]; for (int j = 0; j < pass->input_attachments.size(); j++) { int32_t attachment = pass->input_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3650,10 +3723,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; // TODO we need to set this here, possibly VK_IMAGE_ASPECT_COLOR_BIT ?? input_references.push_back(reference); } - LocalVector<VkAttachmentReference> &resolve_references = resolve_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &resolve_references = resolve_reference_array[i]; if (pass->resolve_attachments.size() > 0) { ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), VK_NULL_HANDLE, "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ")."); @@ -3661,7 +3735,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } for (int j = 0; j < pass->resolve_attachments.size(); j++) { int32_t attachment = pass->resolve_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3676,10 +3752,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; resolve_references.push_back(reference); } - VkAttachmentReference &depth_stencil_reference = depth_reference_array[i]; + VkAttachmentReference2KHR &depth_stencil_reference = depth_reference_array[i]; + depth_stencil_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + depth_stencil_reference.pNext = nullptr; if (pass->depth_attachment != FramebufferPass::ATTACHMENT_UNUSED) { int32_t attachment = pass->depth_attachment; @@ -3688,6 +3767,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass."); depth_stencil_reference.attachment = attachment_remap[attachment]; depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_stencil_reference.aspectMask = 0; attachment_last_pass[attachment] = i; if (is_multisample_first) { @@ -3702,6 +3782,32 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF depth_stencil_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; } + if (context->get_vrs_capabilities().attachment_vrs_supported && pass->vrs_attachment != FramebufferPass::ATTACHMENT_UNUSED) { + int32_t attachment = pass->vrs_attachment; + ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), VRS attachment."); + ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as VRS, but it's not a VRS attachment."); + ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer VRS attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass."); + + VkAttachmentReference2KHR &vrs_reference = vrs_reference_array[i]; + vrs_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + vrs_reference.pNext = nullptr; + vrs_reference.attachment = attachment_remap[attachment]; + vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + vrs_reference.aspectMask = 0; + + Size2i texel_size = context->get_vrs_capabilities().max_texel_size; + + VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i]; + vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR; + vrs_attachment_info.pNext = nullptr; + vrs_attachment_info.pFragmentShadingRateAttachment = &vrs_reference; + vrs_attachment_info.shadingRateAttachmentTexelSize = { uint32_t(texel_size.x), uint32_t(texel_size.y) }; + + attachment_last_pass[attachment] = i; + + subpass_nextptr = &vrs_attachment_info; + } + LocalVector<uint32_t> &preserve_references = preserve_reference_array[i]; for (int j = 0; j < pass->preserve_attachments.size(); j++) { @@ -3718,9 +3824,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } } - VkSubpassDescription &subpass = subpasses[i]; + VkSubpassDescription2KHR &subpass = subpasses[i]; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR; + subpass.pNext = subpass_nextptr; subpass.flags = 0; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + if (p_view_count == 1) { + // VUID-VkSubpassDescription2-multiview-06558: If the multiview feature is not enabled, viewMask must be 0. + subpass.viewMask = 0; + } else { + subpass.viewMask = view_mask; + } subpass.inputAttachmentCount = input_references.size(); if (input_references.size()) { subpass.pInputAttachments = input_references.ptr(); @@ -3757,7 +3871,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } if (i > 0) { - VkSubpassDependency dependency; + VkSubpassDependency2KHR dependency; + dependency.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR; + dependency.pNext = nullptr; dependency.srcSubpass = i - 1; dependency.dstSubpass = i; dependency.srcStageMask = 0; @@ -3767,6 +3883,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependency.viewOffset = 0; subpass_dependencies.push_back(dependency); } /* @@ -3784,10 +3901,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF */ } - VkRenderPassCreateInfo render_pass_create_info; - render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + VkRenderPassCreateInfo2KHR render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR; render_pass_create_info.pNext = nullptr; render_pass_create_info.flags = 0; + render_pass_create_info.attachmentCount = attachments.size(); render_pass_create_info.pAttachments = attachments.ptr(); render_pass_create_info.subpassCount = subpasses.size(); @@ -3804,13 +3922,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF render_pass_create_info.pDependencies = nullptr; } - // These are only used if we use multiview but we need to define them in scope. - const uint32_t view_mask = (1 << p_view_count) - 1; - const uint32_t correlation_mask = (1 << p_view_count) - 1; + if (p_view_count == 1) { + // VUID-VkRenderPassCreateInfo2-viewMask-03057: If the VkSubpassDescription2::viewMask member of all elements of pSubpasses is 0, correlatedViewMaskCount must be 0. + render_pass_create_info.correlatedViewMaskCount = 0; + render_pass_create_info.pCorrelatedViewMasks = nullptr; + } else { + render_pass_create_info.correlatedViewMaskCount = 1; + render_pass_create_info.pCorrelatedViewMasks = &correlation_mask; + } + Vector<uint32_t> view_masks; VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info; if (p_view_count > 1) { + // this may no longer be needed with the new settings already including this + const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities(); // For now this only works with multiview! @@ -3837,8 +3963,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } VkRenderPass render_pass; - VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); - ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass failed with error " + itos(res) + "."); + VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass); + ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass2KHR failed with error " + itos(res) + "."); return render_pass; } @@ -3857,7 +3983,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c passes.push_back(pass); return framebuffer_format_create_multipass(p_format, passes, p_view_count); } -RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count) { +RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count) { _THREAD_SAFE_METHOD_ FramebufferFormatKey key; @@ -3899,9 +4025,12 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c return E->get(); } - VkSubpassDescription subpass; + VkSubpassDescription2KHR subpass; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR; + subpass.pNext = nullptr; subpass.flags = 0; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.viewMask = 0; subpass.inputAttachmentCount = 0; //unsupported for now subpass.pInputAttachments = nullptr; subpass.colorAttachmentCount = 0; @@ -3911,8 +4040,8 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; - VkRenderPassCreateInfo render_pass_create_info; - render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + VkRenderPassCreateInfo2KHR render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR; render_pass_create_info.pNext = nullptr; render_pass_create_info.flags = 0; render_pass_create_info.attachmentCount = 0; @@ -3921,11 +4050,13 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c render_pass_create_info.pSubpasses = &subpass; render_pass_create_info.dependencyCount = 0; render_pass_create_info.pDependencies = nullptr; + render_pass_create_info.correlatedViewMaskCount = 0; + render_pass_create_info.pCorrelatedViewMasks = nullptr; VkRenderPass render_pass; - VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); + VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass); - ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass for empty fb failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass2KHR for empty fb failed with error " + itos(res) + "."); if (render_pass == VK_NULL_HANDLE) { //was likely invalid return INVALID_ID; @@ -3963,7 +4094,11 @@ RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, Textur framebuffer.size = p_size; framebuffer.view_count = 1; - return framebuffer_owner.make_rid(framebuffer); + RID id = framebuffer_owner.make_rid(framebuffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) { @@ -3978,6 +4113,8 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { pass.depth_attachment = i; + } else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + pass.vrs_attachment = i; } else { pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED); } @@ -3989,7 +4126,7 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac return framebuffer_create_multipass(p_texture_attachments, passes, p_format_check, p_view_count); } -RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) { +RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) { _THREAD_SAFE_METHOD_ Vector<AttachmentFormat> attachments; @@ -4008,6 +4145,10 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex size.width = texture->width; size.height = texture->height; size_set = true; + } else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + // If this is not the first attachement we assume this is used as the VRS attachment + // in this case this texture will be 1/16th the size of the color attachement. + // So we skip the size check } else { ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(), "All textures in a framebuffer should be the same size."); @@ -4037,6 +4178,9 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex framebuffer.view_count = p_view_count; RID id = framebuffer_owner.make_rid(framebuffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif for (int i = 0; i < p_texture_attachments.size(); i++) { if (p_texture_attachments[i].is_valid()) { @@ -4056,6 +4200,22 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_get_form return framebuffer->format_id; } +bool RenderingDeviceVulkan::framebuffer_is_valid(RID p_framebuffer) const { + _THREAD_SAFE_METHOD_ + + return framebuffer_owner.owns(p_framebuffer); +} + +void RenderingDeviceVulkan::framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) { + _THREAD_SAFE_METHOD_ + + Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer); + ERR_FAIL_COND(!framebuffer); + + framebuffer->invalidated_callback = p_callback; + framebuffer->invalidated_callback_userdata = p_userdata; +} + /*****************/ /**** SAMPLER ****/ /*****************/ @@ -4098,7 +4258,11 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) { VkResult res = vkCreateSampler(device, &sampler_create_info, nullptr, &sampler); ERR_FAIL_COND_V_MSG(res, RID(), "vkCreateSampler failed with error " + itos(res) + "."); - return sampler_owner.make_rid(sampler); + RID id = sampler_owner.make_rid(sampler); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } /**********************/ @@ -4127,7 +4291,11 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vec _buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false); } - return vertex_buffer_owner.make_rid(buffer); + RID id = vertex_buffer_owner.make_rid(buffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } // Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated @@ -4288,7 +4456,11 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff _buffer_update(&index_buffer, 0, r, data_size); _buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false); } - return index_buffer_owner.make_rid(index_buffer); + RID id = index_buffer_owner.make_rid(index_buffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) { @@ -4556,7 +4728,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa #define SHADER_BINARY_VERSION 3 String RenderingDeviceVulkan::shader_get_binary_cache_key() const { - return "Vulkan-SV" + itos(SHADER_BINARY_VERSION); + return "Vulkan-SV" + itos(SHADER_BINARY_VERSION) + "-" + String(VERSION_NUMBER) + "-" + String(VERSION_HASH); } struct RenderingDeviceVulkanShaderBinaryDataBinding { @@ -4730,7 +4902,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve } if (may_be_writable) { - info.writable = !(bool)(binding.type_description->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE); + info.writable = !(binding.type_description->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) && !(binding.block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE); } else { info.writable = false; } @@ -4757,6 +4929,10 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve ERR_FAIL_COND_V_MSG(uniform_info[set][k].length != info.length, Vector<uint8_t>(), "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size."); + //also, verify that it has the same writability + ERR_FAIL_COND_V_MSG(uniform_info[set][k].writable != info.writable, Vector<uint8_t>(), + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different writability."); + //just append stage mask and return uniform_info.write[set].write[k].stages |= 1 << stage; exists = true; @@ -5056,7 +5232,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_ ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID()); uint32_t bin_version = decode_uint32(binptr + 4); - ERR_FAIL_COND_V(bin_version > SHADER_BINARY_VERSION, RID()); + ERR_FAIL_COND_V(bin_version != SHADER_BINARY_VERSION, RID()); uint32_t bin_data_size = decode_uint32(binptr + 8); @@ -5381,7 +5557,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_ ERR_FAIL_V_MSG(RID(), error_text); } - return shader_owner.make_rid(shader); + RID id = shader_owner.make_rid(shader); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) { @@ -5414,7 +5594,11 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve _buffer_update(&buffer, 0, r, data_size); _buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false); } - return uniform_buffer_owner.make_rid(buffer); + RID id = uniform_buffer_owner.make_rid(buffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) { @@ -5485,7 +5669,11 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF } //allocate the view - return texture_buffer_owner.make_rid(texture_buffer); + RID id = texture_buffer_owner.make_rid(texture_buffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_allocate(const DescriptorPoolKey &p_key) { @@ -6064,6 +6252,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, uniform_set.shader_id = p_shader; RID id = uniform_set_owner.make_rid(uniform_set); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif //add dependencies _add_dependency(id, p_shader); for (uint32_t i = 0; i < uniform_count; i++) { @@ -6089,7 +6280,7 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) { return uniform_set_owner.owns(p_uniform_set); } -void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) { +void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) { UniformSet *us = uniform_set_owner.get_or_null(p_uniform_set); ERR_FAIL_COND(!us); us->invalidated_callback = p_callback; @@ -6552,11 +6743,28 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma dynamic_state_create_info.dynamicStateCount = dynamic_states.size(); dynamic_state_create_info.pDynamicStates = dynamic_states.ptr(); + void *graphics_pipeline_nextptr = nullptr; + + VkPipelineFragmentShadingRateStateCreateInfoKHR vrs_create_info; + if (context->get_vrs_capabilities().attachment_vrs_supported) { + // If VRS is used, this defines how the different VRS types are combined. + // combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) VRS + // combinerOps[1] decides how we use the output of combinerOps[0] and our attachment VRS + + vrs_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR; + vrs_create_info.pNext = nullptr; + vrs_create_info.fragmentSize = { 4, 4 }; + vrs_create_info.combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // We don't use pipeline/primitive VRS so this really doesn't matter + vrs_create_info.combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // always use the outcome of attachment VRS if enabled + + graphics_pipeline_nextptr = &vrs_create_info; + } + //finally, pipeline create info VkGraphicsPipelineCreateInfo graphics_pipeline_create_info; graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - graphics_pipeline_create_info.pNext = nullptr; + graphics_pipeline_create_info.pNext = graphics_pipeline_nextptr; graphics_pipeline_create_info.flags = 0; Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages; @@ -6669,6 +6877,9 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma #endif //create ID to associate with this pipeline RID id = render_pipeline_owner.make_rid(pipeline); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif //now add all the dependencies _add_dependency(id, p_shader); return id; @@ -6721,7 +6932,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi const PipelineSpecializationConstant &psc = p_specialization_constants[j]; if (psc.constant_id == sc.constant.constant_id) { ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type."); - data_ptr[i] = sc.constant.int_value; + data_ptr[i] = psc.int_value; break; } } @@ -6758,6 +6969,9 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi //create ID to associate with this pipeline RID id = compute_pipeline_owner.make_rid(pipeline); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif //now add all the dependencies _add_dependency(id, p_shader); return id; @@ -6905,8 +7119,10 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); if (texture) { attachments.push_back(texture->view); - ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG); - ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG); + if (!(texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) { // VRS attachment will be a different size. + ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG); + ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG); + } } } framebuffer_create_info.attachmentCount = attachments.size(); @@ -7041,7 +7257,6 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff } void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) { - ERR_FAIL_COND_MSG(p_clear_color && p_clear_colors.size() != framebuffer->texture_ids.size(), "Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(framebuffer->texture_ids.size()) + ")."); Vector<VkClearAttachment> clear_attachments; int color_index = 0; int texture_index = 0; @@ -7130,11 +7345,14 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu } } - if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values + if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values int color_count = 0; for (int i = 0; i < framebuffer->texture_ids.size(); i++) { Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); - if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { + // We only check for our VRS usage bit if this is not the first texture id. + // If it is the first we're likely populating our VRS texture. + // Bit dirty but.. + if (!texture || (!(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) { color_count++; } } @@ -7227,7 +7445,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p } } - if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values + if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values int color_count = 0; for (int i = 0; i < framebuffer->texture_ids.size(); i++) { @@ -8535,6 +8753,11 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) { } else if (framebuffer_owner.owns(p_id)) { Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id); frames[frame].framebuffers_to_dispose_of.push_back(*framebuffer); + + if (framebuffer->invalidated_callback != nullptr) { + framebuffer->invalidated_callback(framebuffer->invalidated_callback_userdata); + } + framebuffer_owner.free(p_id); } else if (sampler_owner.owns(p_id)) { VkSampler *sampler = sampler_owner.get_or_null(p_id); @@ -8995,17 +9218,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de { device_capabilities.version_major = p_context->get_vulkan_major(); device_capabilities.version_minor = p_context->get_vulkan_minor(); - - // get info about subgroups - VulkanContext::SubgroupCapabilities subgroup_capabilities = p_context->get_subgroup_capabilities(); - device_capabilities.subgroup_size = subgroup_capabilities.size; - device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd(); - device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd(); - - // get info about further features - VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities(); - device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; - device_capabilities.supports_fsr_half_float = p_context->get_shader_capabilities().shader_float16_is_supported && p_context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported; } context = p_context; @@ -9354,7 +9566,7 @@ String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) cons return frames[frame].timestamp_result_names[p_index]; } -uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) { +uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const { switch (p_limit) { case LIMIT_MAX_BOUND_UNIFORM_SETS: return limits.maxBoundDescriptorSets; @@ -9424,7 +9636,18 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) { return limits.maxComputeWorkGroupSize[1]; case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z: return limits.maxComputeWorkGroupSize[2]; - + case LIMIT_SUBGROUP_SIZE: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.size; + } + case LIMIT_SUBGROUP_IN_SHADERS: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.supported_stages_flags_rd(); + } + case LIMIT_SUBGROUP_OPERATIONS: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.supported_operations_flags_rd(); + } default: ERR_FAIL_V(0); } @@ -9524,6 +9747,25 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() { return rd; } +bool RenderingDeviceVulkan::has_feature(const Features p_feature) const { + switch (p_feature) { + case SUPPORTS_MULTIVIEW: { + VulkanContext::MultiviewCapabilities multiview_capabilies = context->get_multiview_capabilities(); + return multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; + } break; + case SUPPORTS_FSR_HALF_FLOAT: { + return context->get_shader_capabilities().shader_float16_is_supported && context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported; + } break; + case SUPPORTS_ATTACHMENT_VRS: { + VulkanContext::VRSCapabilities vrs_capabilities = context->get_vrs_capabilities(); + return vrs_capabilities.attachment_vrs_supported; + } break; + default: { + return false; + } + } +} + RenderingDeviceVulkan::RenderingDeviceVulkan() { device_capabilities.device_family = DEVICE_VULKAN; } diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index ec9e864370..d98ac1114b 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -241,6 +241,7 @@ class RenderingDeviceVulkan : public RenderingDevice { Vector<AttachmentFormat> attachments; Vector<FramebufferPass> passes; uint32_t view_count = 1; + bool operator<(const FramebufferFormatKey &p_key) const { if (view_count != p_key.view_count) { return view_count < p_key.view_count; @@ -391,6 +392,8 @@ class RenderingDeviceVulkan : public RenderingDevice { uint32_t storage_mask = 0; Vector<RID> texture_ids; + InvalidationCallback invalidated_callback = nullptr; + void *invalidated_callback_userdata = nullptr; struct Version { VkFramebuffer framebuffer = VK_NULL_HANDLE; @@ -746,7 +749,7 @@ class RenderingDeviceVulkan : public RenderingDevice { LocalVector<AttachableTexture> attachable_textures; //used for validation Vector<Texture *> mutable_sampled_textures; //used for layout change Vector<Texture *> mutable_storage_textures; //used for layout change - UniformSetInvalidatedCallback invalidated_callback = nullptr; + InvalidationCallback invalidated_callback = nullptr; void *invalidated_callback_userdata = nullptr; }; @@ -1058,13 +1061,15 @@ public: /*********************/ virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1); - virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1); + virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1); virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1); virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0); virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1); - virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1); + virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1); virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID); + virtual bool framebuffer_is_valid(RID p_framebuffer) const; + virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata); virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer); @@ -1109,7 +1114,7 @@ public: virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set); virtual bool uniform_set_is_valid(RID p_uniform_set); - virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata); + virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata); virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL); @@ -1203,7 +1208,7 @@ public: /**** Limits ****/ /****************/ - virtual uint64_t limit_get(Limit p_limit); + virtual uint64_t limit_get(Limit p_limit) const; virtual void prepare_screen_for_drawing(); void initialize(VulkanContext *p_context, bool p_local_device = false); @@ -1234,6 +1239,8 @@ public: virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0); + virtual bool has_feature(const Features p_feature) const; + RenderingDeviceVulkan(); ~RenderingDeviceVulkan(); }; diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 2bf173a398..a9a8ce68ac 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -48,6 +48,18 @@ VulkanHooks *VulkanContext::vulkan_hooks = nullptr; +VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { + if (fpCreateRenderPass2KHR == nullptr) { + fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetInstanceProcAddr(inst, "vkCreateRenderPass2KHR"); + } + + if (fpCreateRenderPass2KHR == nullptr) { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } else { + return (fpCreateRenderPass2KHR)(device, pCreateInfo, pAllocator, pRenderPass); + } +} + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -215,13 +227,13 @@ VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char *const *c Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) { static const LocalVector<LocalVector<const char *>> instance_validation_layers_alt{ - // Preferred set of validation layers + // Preferred set of validation layers. { "VK_LAYER_KHRONOS_validation" }, - // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers + // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers. { "VK_LAYER_LUNARG_standard_validation" }, - // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers + // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers. { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" } }; @@ -269,7 +281,7 @@ typedef VkResult(VKAPI_PTR *_vkEnumerateInstanceVersion)(uint32_t *); Error VulkanContext::_obtain_vulkan_version() { // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html#_description - // for Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android. + // For Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android. _vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); if (func != nullptr) { uint32_t api_version; @@ -279,15 +291,15 @@ Error VulkanContext::_obtain_vulkan_version() { vulkan_minor = VK_API_VERSION_MINOR(api_version); vulkan_patch = VK_API_VERSION_PATCH(api_version); } else { - // according to the documentation this shouldn't fail with anything except a memory allocation error - // in which case we're in deep trouble anyway + // According to the documentation this shouldn't fail with anything except a memory allocation error + // in which case we're in deep trouble anyway. ERR_FAIL_V(ERR_CANT_CREATE); } } else { print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0."); } - // we don't go above 1.2 + // We don't go above 1.2. if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) { vulkan_major = 1; vulkan_minor = 2; @@ -303,7 +315,7 @@ Error VulkanContext::_initialize_extensions() { enabled_extension_count = 0; enabled_debug_utils = false; enabled_debug_report = false; - /* Look for instance extensions */ + // Look for instance extensions. VkBool32 surfaceExtFound = 0; VkBool32 platformSurfaceExtFound = 0; memset(extension_names, 0, sizeof(extension_names)); @@ -403,7 +415,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const { res += ", STAGE_COMPUTE"; } - /* these are not defined on Android GRMBL */ + // These are not defined on Android GRMBL. if (supportedStages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) { res += ", STAGE_RAYGEN_KHR"; } @@ -429,7 +441,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const { res += ", STAGE_MESH_NV"; } - return res.substr(2); // remove first ", " + return res.substr(2); // Remove first ", " } uint32_t VulkanContext::SubgroupCapabilities::supported_operations_flags_rd() const { @@ -494,19 +506,22 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const { res += ", FEATURE_PARTITIONED_NV"; } - return res.substr(2); // remove first ", " + return res.substr(2); // Remove first ", " } Error VulkanContext::_check_capabilities() { // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html // https://www.khronos.org/blog/vulkan-subgroup-tutorial - // for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. + // For Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. - // so we check if the functions are accessible by getting their function pointers and skipping if not - // (note that the desktop loader does a better job here but the android loader doesn't) + // So we check if the functions are accessible by getting their function pointers and skipping if not + // (note that the desktop loader does a better job here but the android loader doesn't.) - // assume not supported until proven otherwise + // Assume not supported until proven otherwise. + vrs_capabilities.pipeline_vrs_supported = false; + vrs_capabilities.primitive_vrs_supported = false; + vrs_capabilities.attachment_vrs_supported = false; multiview_capabilities.is_supported = false; multiview_capabilities.geometry_shader_is_supported = false; multiview_capabilities.tessellation_shader_is_supported = false; @@ -523,17 +538,25 @@ Error VulkanContext::_check_capabilities() { storage_buffer_capabilities.storage_push_constant_16_is_supported = false; storage_buffer_capabilities.storage_input_output_16 = false; - // check for extended features + // Check for extended features. PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2"); if (vkGetPhysicalDeviceFeatures2_func == nullptr) { - // In Vulkan 1.0 might be accessible under its original extension name + // In Vulkan 1.0 might be accessible under its original extension name. vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR"); } if (vkGetPhysicalDeviceFeatures2_func != nullptr) { - // check our extended features + // Check our extended features. + VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = { + /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, + /*pNext*/ nullptr, + /*pipelineFragmentShadingRate*/ false, + /*primitiveFragmentShadingRate*/ false, + /*attachmentFragmentShadingRate*/ false, + }; + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = { /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR, - /*pNext*/ nullptr, + /*pNext*/ &vrs_features, /*shaderFloat16*/ false, /*shaderInt8*/ false, }; @@ -561,6 +584,10 @@ Error VulkanContext::_check_capabilities() { vkGetPhysicalDeviceFeatures2_func(gpu, &device_features); + vrs_capabilities.pipeline_vrs_supported = vrs_features.pipelineFragmentShadingRate; + vrs_capabilities.primitive_vrs_supported = vrs_features.primitiveFragmentShadingRate; + vrs_capabilities.attachment_vrs_supported = vrs_features.attachmentFragmentShadingRate; + multiview_capabilities.is_supported = multiview_features.multiview; multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader; multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader; @@ -574,31 +601,40 @@ Error VulkanContext::_check_capabilities() { storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16; } - // check extended properties + // Check extended properties. PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); if (device_properties_func == nullptr) { - // In Vulkan 1.0 might be accessible under its original extension name + // In Vulkan 1.0 might be accessible under its original extension name. device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR"); } if (device_properties_func != nullptr) { + VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties; VkPhysicalDeviceMultiviewProperties multiviewProperties; VkPhysicalDeviceSubgroupProperties subgroupProperties; VkPhysicalDeviceProperties2 physicalDeviceProperties; + void *nextptr = nullptr; subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; - subgroupProperties.pNext = nullptr; - - physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + subgroupProperties.pNext = nextptr; + nextptr = &subgroupProperties; if (multiview_capabilities.is_supported) { multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; - multiviewProperties.pNext = &subgroupProperties; + multiviewProperties.pNext = nextptr; - physicalDeviceProperties.pNext = &multiviewProperties; - } else { - physicalDeviceProperties.pNext = &subgroupProperties; + nextptr = &multiviewProperties; + } + + if (vrs_capabilities.attachment_vrs_supported) { + vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; + vrsProperties.pNext = nextptr; + + nextptr = &vrsProperties; } + physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + physicalDeviceProperties.pNext = nextptr; + device_properties_func(gpu, &physicalDeviceProperties); subgroup_capabilities.size = subgroupProperties.subgroupSize; @@ -609,6 +645,28 @@ Error VulkanContext::_check_capabilities() { // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; + if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) { + print_verbose("- Vulkan Variable Rate Shading supported:"); + if (vrs_capabilities.pipeline_vrs_supported) { + print_verbose(" Pipeline fragment shading rate"); + } + if (vrs_capabilities.primitive_vrs_supported) { + print_verbose(" Primitive fragment shading rate"); + } + if (vrs_capabilities.attachment_vrs_supported) { + // TODO expose these somehow to the end user + vrs_capabilities.min_texel_size.x = vrsProperties.minFragmentShadingRateAttachmentTexelSize.width; + vrs_capabilities.min_texel_size.y = vrsProperties.minFragmentShadingRateAttachmentTexelSize.height; + vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width; + vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height; + + print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")")); + } + + } else { + print_verbose("- Vulkan Variable Rate Shading not supported"); + } + if (multiview_capabilities.is_supported) { multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount; multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex; @@ -635,10 +693,10 @@ Error VulkanContext::_check_capabilities() { } Error VulkanContext::_create_instance() { - /* obtain version */ + // Obtain Vulkan version. _obtain_vulkan_version(); - /* initialise extensions */ + // Initialize extensions. { Error err = _initialize_extensions(); if (err != OK) { @@ -726,8 +784,7 @@ Error VulkanContext::_create_instance() { #endif if (enabled_debug_utils) { - // Setup VK_EXT_debug_utils function pointers always (we use them for - // debug labels and names). + // Setup VK_EXT_debug_utils function pointers always (we use them for debug labels and names). CreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT"); DestroyDebugUtilsMessengerEXT = @@ -800,7 +857,7 @@ Error VulkanContext::_create_instance() { } Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { - /* Make initial call to query gpu_count, then second call for gpu info*/ + // Make initial call to query gpu_count, then second call for gpu info. uint32_t gpu_count = 0; VkResult err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -836,7 +893,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { return ERR_CANT_CREATE; } - // not really needed but nice to print the correct entry + // Not really needed but nice to print the correct entry. for (uint32_t i = 0; i < gpu_count; ++i) { if (physical_devices[i] == gpu) { device_index = i; @@ -948,13 +1005,13 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { free(physical_devices); - /* Look for device extensions */ + // Look for device extensions. uint32_t device_extension_count = 0; VkBool32 swapchainExtFound = 0; enabled_extension_count = 0; memset(extension_names, 0, sizeof(extension_names)); - /* Get identifier properties */ + // Get identifier properties. vkGetPhysicalDeviceProperties(gpu, &gpu_props); device_name = gpu_props.deviceName; @@ -996,9 +1053,16 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { extension_names[enabled_extension_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; } if (!strcmp(VK_KHR_MULTIVIEW_EXTENSION_NAME, device_extensions[i].extensionName)) { - // if multiview is supported, enable it + // If multiview is supported, enable it. extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME; } + if (!strcmp(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, device_extensions[i].extensionName)) { + // if shading rate image is supported, enable it + extension_names[enabled_extension_count++] = VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME; + } if (enabled_extension_count >= MAX_EXTENSIONS) { free(device_extensions); ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG"); @@ -1049,19 +1113,18 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { " extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n" "vkCreateInstance Failure"); - /* Call with nullptr data to get count */ + // Call with nullptr data to get count. vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr); ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE); queue_props = (VkQueueFamilyProperties *)malloc(queue_family_count * sizeof(VkQueueFamilyProperties)); vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, queue_props); - // Query fine-grained feature support for this device. // If app has specific feature requirements it should check supported // features based on this query vkGetPhysicalDeviceFeatures(gpu, &physical_device_features); - physical_device_features.robustBufferAccess = false; //turn off robust buffer access, which can hamper performance on some hardware + physical_device_features.robustBufferAccess = false; // Turn off robust buffer access, which can hamper performance on some hardware. #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \ { \ @@ -1076,7 +1139,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(inst, GetSwapchainImagesKHR); - // get info about what our vulkan driver is capable off + // Gets capability info for current Vulkan driver. { Error res = _check_capabilities(); if (res != OK) { @@ -1110,11 +1173,23 @@ Error VulkanContext::_create_device() { }; nextptr = &shader_features; + VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features; + if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) { + // insert into our chain to enable these features if they are available + vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; + vrs_features.pNext = nextptr; + vrs_features.pipelineFragmentShadingRate = vrs_capabilities.pipeline_vrs_supported; + vrs_features.primitiveFragmentShadingRate = vrs_capabilities.primitive_vrs_supported; + vrs_features.attachmentFragmentShadingRate = vrs_capabilities.attachment_vrs_supported; + + nextptr = &vrs_features; + } + VkPhysicalDeviceVulkan11Features vulkan11features; VkPhysicalDevice16BitStorageFeaturesKHR storage_feature; VkPhysicalDeviceMultiviewFeatures multiview_features; if (vulkan_major > 1 || vulkan_minor >= 2) { - // In Vulkan 1.2 and newer we use a newer struct to enable various features + // In Vulkan 1.2 and newer we use a newer struct to enable various features. vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; vulkan11features.pNext = nextptr; @@ -1132,7 +1207,7 @@ Error VulkanContext::_create_device() { vulkan11features.shaderDrawParameters = 0; nextptr = &vulkan11features; } else { - // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features + // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features. storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR; storage_feature.pNext = nextptr; storage_feature.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported; @@ -1161,7 +1236,7 @@ Error VulkanContext::_create_device() { /*ppEnabledLayerNames*/ nullptr, /*enabledExtensionCount*/ enabled_extension_count, /*ppEnabledExtensionNames*/ (const char *const *)extension_names, - /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here + /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here. }; if (separate_present_queue) { queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; @@ -1193,7 +1268,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { } // Search for a graphics and a present queue in the array of queue - // families, try to find one that supports both + // families, try to find one that supports both. uint32_t graphicsQueueFamilyIndex = UINT32_MAX; uint32_t presentQueueFamilyIndex = UINT32_MAX; for (uint32_t i = 0; i < queue_family_count; i++) { @@ -1223,7 +1298,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { free(supportsPresent); - // Generate error if could not find both a graphics and a present queue + // Generate error if could not find both a graphics and a present queue. ERR_FAIL_COND_V_MSG(graphicsQueueFamilyIndex == UINT32_MAX || presentQueueFamilyIndex == UINT32_MAX, ERR_CANT_CREATE, "Could not find both graphics and present queues\n"); @@ -1279,7 +1354,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { color_space = surfFormats[0].colorSpace; } else { // These should be ordered with the ones we want to use on top and fallback modes further down - // we want an 32bit RGBA unsigned normalised buffer or similar + // we want a 32bit RGBA unsigned normalised buffer or similar. const VkFormat allowed_formats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM @@ -1291,7 +1366,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { ERR_FAIL_V_MSG(ERR_CANT_CREATE, "formatCount less than 1"); } - // Find the first format that we support + // Find the first format that we support. format = VK_FORMAT_UNDEFINED; for (uint32_t af = 0; af < allowed_formats_count && format == VK_FORMAT_UNDEFINED; af++) { for (uint32_t sf = 0; sf < formatCount && format == VK_FORMAT_UNDEFINED; sf++) { @@ -1323,7 +1398,7 @@ Error VulkanContext::_create_semaphores() { VkResult err; // Create semaphores to synchronize acquiring presentable buffers before - // rendering and waiting for drawing to be complete before presenting + // rendering and waiting for drawing to be complete before presenting. VkSemaphoreCreateInfo semaphoreCreateInfo = { /*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, /*pNext*/ nullptr, @@ -1331,7 +1406,7 @@ Error VulkanContext::_create_semaphores() { }; // Create fences that we can use to throttle if we get too far - // ahead of the image presents + // ahead of the image presents. VkFenceCreateInfo fence_ci = { /*sType*/ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, /*pNext*/ nullptr, @@ -1351,7 +1426,7 @@ Error VulkanContext::_create_semaphores() { } frame_index = 0; - // Get Memory information and properties + // Get Memory information and properties. vkGetPhysicalDeviceMemoryProperties(gpu, &memory_properties); return OK; @@ -1426,7 +1501,7 @@ bool VulkanContext::window_is_valid_swapchain(DisplayServer::WindowID p_window) VkRenderPass VulkanContext::window_get_render_pass(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); Window *w = &windows[p_window]; - //vulkan use of currentbuffer + // Vulkan use of currentbuffer. return w->render_pass; } @@ -1434,7 +1509,7 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE); Window *w = &windows[p_window]; - //vulkan use of currentbuffer + // Vulkan use of currentbuffer. if (w->swapchain_image_resources != VK_NULL_HANDLE) { return w->swapchain_image_resources[w->current_buffer].framebuffer; } else { @@ -1459,7 +1534,7 @@ Error VulkanContext::_clean_up_swap_chain(Window *window) { } vkDeviceWaitIdle(device); - //this destroys images associated it seems + // This destroys images associated it seems. fpDestroySwapchainKHR(device, window->swapchain, nullptr); window->swapchain = VK_NULL_HANDLE; vkDestroyRenderPass(device, window->render_pass, nullptr); @@ -1485,7 +1560,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { _clean_up_swap_chain(window); } - // Check the surface capabilities and formats + // Check the surface capabilities and formats. VkSurfaceCapabilitiesKHR surfCapabilities; err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, window->surface, &surfCapabilities); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -1502,7 +1577,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { } VkExtent2D swapchainExtent; - // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. + // Width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) { // If the surface size is undefined, the size is set to the size // of the images requested, which must fit within the minimum and @@ -1522,7 +1597,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { swapchainExtent.height = surfCapabilities.maxImageExtent.height; } } else { - // If the surface size is defined, the swap chain size must match + // If the surface size is defined, the swap chain size must match. swapchainExtent = surfCapabilities.currentExtent; window->width = surfCapabilities.currentExtent.width; window->height = surfCapabilities.currentExtent.height; @@ -1530,7 +1605,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { if (window->width == 0 || window->height == 0) { free(presentModes); - //likely window minimized, no swapchain created + // Likely window minimized, no swapchain created. return OK; } // The FIFO present mode is guaranteed by the spec to be supported @@ -1591,8 +1666,23 @@ Error VulkanContext::_update_swap_chain(Window *window) { if (present_mode_available) { window->presentMode = requested_present_mode; } else { - WARN_PRINT("Requested VSync mode is not available!"); - window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default + String present_mode_string; + switch (window->vsync_mode) { + case DisplayServer::VSYNC_MAILBOX: + present_mode_string = "Mailbox"; + break; + case DisplayServer::VSYNC_ADAPTIVE: + present_mode_string = "Adaptive"; + break; + case DisplayServer::VSYNC_ENABLED: + present_mode_string = "Enabled"; + break; + case DisplayServer::VSYNC_DISABLED: + present_mode_string = "Disabled"; + break; + } + WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_string)); + window->vsync_mode = DisplayServer::VSYNC_ENABLED; // Set to default. } print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode))); @@ -1601,13 +1691,13 @@ Error VulkanContext::_update_swap_chain(Window *window) { // Determine the number of VkImages to use in the swap chain. // Application desires to acquire 3 images at a time for triple - // buffering + // buffering. uint32_t desiredNumOfSwapchainImages = 3; if (desiredNumOfSwapchainImages < surfCapabilities.minImageCount) { desiredNumOfSwapchainImages = surfCapabilities.minImageCount; } // If maxImageCount is 0, we can ask for as many images as we want; - // otherwise we're limited to maxImageCount + // otherwise we're limited to maxImageCount. if ((surfCapabilities.maxImageCount > 0) && (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) { // Application must settle for fewer images than desired: desiredNumOfSwapchainImages = surfCapabilities.maxImageCount; @@ -1620,7 +1710,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { preTransform = surfCapabilities.currentTransform; } - // Find a supported composite alpha mode - one of these is guaranteed to be set + // Find a supported composite alpha mode - one of these is guaranteed to be set. VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, @@ -1667,7 +1757,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); if (swapchainImageCount == 0) { - //assign here for the first time. + // Assign here for the first time. swapchainImageCount = sp_image_count; } else { ERR_FAIL_COND_V(swapchainImageCount != sp_image_count, ERR_BUG); @@ -1725,7 +1815,9 @@ Error VulkanContext::_update_swap_chain(Window *window) { /******** FRAMEBUFFER ************/ { - const VkAttachmentDescription attachment = { + const VkAttachmentDescription2KHR attachment = { + /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR, + /*pNext*/ nullptr, /*flags*/ 0, /*format*/ format, /*samples*/ VK_SAMPLE_COUNT_1_BIT, @@ -1737,14 +1829,20 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*finalLayout*/ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }; - const VkAttachmentReference color_reference = { + const VkAttachmentReference2KHR color_reference = { + /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, + /*pNext*/ nullptr, /*attachment*/ 0, /*layout*/ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*aspectMask*/ 0, }; - const VkSubpassDescription subpass = { + const VkSubpassDescription2KHR subpass = { + /*sType*/ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, + /*pNext*/ nullptr, /*flags*/ 0, /*pipelineBindPoint*/ VK_PIPELINE_BIND_POINT_GRAPHICS, + /*viewMask*/ 0, /*inputAttachmentCount*/ 0, /*pInputAttachments*/ nullptr, /*colorAttachmentCount*/ 1, @@ -1754,8 +1852,9 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*preserveAttachmentCount*/ 0, /*pPreserveAttachments*/ nullptr, }; - const VkRenderPassCreateInfo rp_info = { - /*sTyp*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + + const VkRenderPassCreateInfo2KHR rp_info = { + /*sType*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, /*pNext*/ nullptr, /*flags*/ 0, /*attachmentCount*/ 1, @@ -1764,9 +1863,11 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*pSubpasses*/ &subpass, /*dependencyCount*/ 0, /*pDependencies*/ nullptr, + /*correlatedViewMaskCount*/ 0, + /*pCorrelatedViewMasks*/ nullptr, }; - err = vkCreateRenderPass(device, &rp_info, nullptr, &window->render_pass); + err = vkCreateRenderPass2KHR(device, &rp_info, nullptr, &window->render_pass); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); for (uint32_t i = 0; i < swapchainImageCount; i++) { @@ -1839,7 +1940,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { } } - //reset current buffer + // Reset current buffer. window->current_buffer = 0; return OK; @@ -1874,16 +1975,16 @@ void VulkanContext::append_command_buffer(VkCommandBuffer p_command_buffer) { } void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { - // ensure everything else pending is executed + // Ensure everything else pending is executed. vkDeviceWaitIdle(device); - //flush the pending setup buffer + // Flush the pending setup buffer. bool setup_flushable = p_flush_setup && command_buffer_queue[0]; bool pending_flushable = p_flush_pending && command_buffer_count > 1; if (setup_flushable) { - //use a fence to wait for everything done + // Use a fence to wait for everything done. VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = nullptr; @@ -1900,7 +2001,7 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { } if (pending_flushable) { - //use a fence to wait for everything done + // Use a fence to wait for everything to finish. VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -1928,7 +2029,7 @@ Error VulkanContext::prepare_buffers() { VkResult err; - // Ensure no more than FRAME_LAG renderings are outstanding + // Ensure no more than FRAME_LAG renderings are outstanding. vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX); vkResetFences(device, 1, &fences[frame_index]); @@ -1948,13 +2049,13 @@ Error VulkanContext::prepare_buffers() { w->image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer); if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // swapchain is out of date (e.g. the window was resized) and + // Swapchain is out of date (e.g. the window was resized) and // must be recreated: print_verbose("Vulkan: Early out of date swapchain, recreating."); - //resize_notify(); + // resize_notify(); _update_swap_chain(w); } else if (err == VK_SUBOPTIMAL_KHR) { - // swapchain is not as optimal as it could be, but the platform's + // Swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. print_verbose("Vulkan: Early suboptimal swapchain."); break; @@ -2001,7 +2102,7 @@ Error VulkanContext::swap_buffers() { uint32_t commands_to_submit = 0; if (command_buffer_queue[0] == nullptr) { - //no setup command, but commands to submit, submit from the first and skip command + // No setup command, but commands to submit, submit from the first and skip command. if (command_buffer_count > 1) { commands_ptr = command_buffer_queue.ptr() + 1; commands_to_submit = command_buffer_count - 1; @@ -2044,7 +2145,7 @@ Error VulkanContext::swap_buffers() { if (separate_present_queue) { // If we are using separate queues, change image ownership to the // present queue before presenting, waiting for the draw complete - // semaphore and signalling the ownership released semaphore when finished + // semaphore and signalling the ownership released semaphore when finished. VkFence nullFence = VK_NULL_HANDLE; pipe_stage_flags[0] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; submit_info.waitSemaphoreCount = 1; @@ -2071,7 +2172,7 @@ Error VulkanContext::swap_buffers() { } // If we are using separate queues, we have to wait for image ownership, - // otherwise wait for draw complete + // otherwise wait for draw complete. VkPresentInfoKHR present = { /*sType*/ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, /*pNext*/ nullptr, @@ -2176,12 +2277,12 @@ Error VulkanContext::swap_buffers() { frame_index %= FRAME_LAG; if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // swapchain is out of date (e.g. the window was resized) and + // Swapchain is out of date (e.g. the window was resized) and // must be recreated: print_verbose("Vulkan: Swapchain is out of date, recreating."); resize_notify(); } else if (err == VK_SUBOPTIMAL_KHR) { - // swapchain is not as optimal as it could be, but the platform's + // Swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. print_verbose("Vulkan: Swapchain is suboptimal."); } else { @@ -2226,7 +2327,7 @@ VkPhysicalDeviceLimits VulkanContext::get_device_limits() const { RID VulkanContext::local_device_create() { LocalDevice ld; - { //create device + { // Create device. VkResult err; float queue_priorities[1] = { 0.0 }; VkDeviceQueueCreateInfo queues[2]; @@ -2247,13 +2348,13 @@ RID VulkanContext::local_device_create() { /*ppEnabledLayerNames */ nullptr, /*enabledExtensionCount */ enabled_extension_count, /*ppEnabledExtensionNames */ (const char *const *)extension_names, - /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here + /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here. }; err = vkCreateDevice(gpu, &sdevice, nullptr, &ld.device); ERR_FAIL_COND_V(err, RID()); } - { //create graphics queue + { // Create graphics queue. vkGetDeviceQueue(ld.device, graphics_queue_family_index, 0, &ld.queue); } @@ -2315,7 +2416,7 @@ void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String return; } - CharString cs = p_label_name.utf8().get_data(); + CharString cs = p_label_name.utf8(); VkDebugUtilsLabelEXT label; label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; label.pNext = nullptr; @@ -2331,7 +2432,7 @@ void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, Strin if (!enabled_debug_utils) { return; } - CharString cs = p_label_name.utf8().get_data(); + CharString cs = p_label_name.utf8(); VkDebugUtilsLabelEXT label; label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; label.pNext = nullptr; @@ -2385,12 +2486,12 @@ String VulkanContext::get_device_pipeline_cache_uuid() const { } DisplayServer::VSyncMode VulkanContext::get_vsync_mode(DisplayServer::WindowID p_window) const { - ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get VSync mode for window with WindowID " + itos(p_window) + " because it does not exist."); + ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist."); return windows[p_window].vsync_mode; } void VulkanContext::set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) { - ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set VSync mode for window with WindowID " + itos(p_window) + " because it does not exist."); + ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist."); windows[p_window].vsync_mode = p_mode; _update_swap_chain(&windows[p_window]); } diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index e96facfacb..35e7ce7db8 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -69,6 +69,15 @@ public: uint32_t max_instance_count; }; + struct VRSCapabilities { + bool pipeline_vrs_supported; // We can specify our fragment rate on a pipeline level + bool primitive_vrs_supported; // We can specify our fragment rate on each drawcall + bool attachment_vrs_supported; // We can provide a density map attachment on our framebuffer + + Size2i min_texel_size; + Size2i max_texel_size; + }; + struct ShaderCapabilities { bool shader_float16_is_supported; bool shader_int8_is_supported; @@ -104,6 +113,7 @@ private: uint32_t vulkan_patch = 0; SubgroupCapabilities subgroup_capabilities; MultiviewCapabilities multiview_capabilities; + VRSCapabilities vrs_capabilities; ShaderCapabilities shader_capabilities; StorageBufferCapabilities storage_buffer_capabilities; @@ -206,6 +216,7 @@ private: PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr; PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr; PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr; + PFN_vkCreateRenderPass2KHR fpCreateRenderPass2KHR = nullptr; VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE; VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE; @@ -256,12 +267,16 @@ protected: Error _get_preferred_validation_layers(uint32_t *count, const char *const **names); public: + // Extension calls + VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass); + uint32_t get_vulkan_major() const { return vulkan_major; }; uint32_t get_vulkan_minor() const { return vulkan_minor; }; - SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; }; - MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; }; - ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; }; - StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; }; + const SubgroupCapabilities &get_subgroup_capabilities() const { return subgroup_capabilities; }; + const MultiviewCapabilities &get_multiview_capabilities() const { return multiview_capabilities; }; + const VRSCapabilities &get_vrs_capabilities() const { return vrs_capabilities; }; + const ShaderCapabilities &get_shader_capabilities() const { return shader_capabilities; }; + const StorageBufferCapabilities &get_storage_buffer_capabilities() const { return storage_buffer_capabilities; }; VkDevice get_device(); VkPhysicalDevice get_physical_device(); @@ -315,4 +330,4 @@ public: virtual ~VulkanContext(); }; -#endif // VULKAN_DEVICE_H +#endif // VULKAN_CONTEXT_H diff --git a/drivers/vulkan/vulkan_hooks.h b/drivers/vulkan/vulkan_hooks.h index 3f244b4d45..dec2042d0d 100644 --- a/drivers/vulkan/vulkan_hooks.h +++ b/drivers/vulkan/vulkan_hooks.h @@ -45,4 +45,4 @@ public: virtual ~VulkanHooks(){}; }; -#endif +#endif // VULKAN_HOOKS_H diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 89ed90e97b..9058077a1f 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -120,4 +120,5 @@ public: }; #endif // WASAPI_ENABLED + #endif // AUDIO_DRIVER_WASAPI_H diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index fbb07ddef8..c2835b3347 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -54,33 +54,33 @@ class DirAccessWindows : public DirAccess { bool _cishidden = false; public: - virtual Error list_dir_begin(); ///< This starts dir listing - virtual String get_next(); - virtual bool current_is_dir() const; - virtual bool current_is_hidden() const; - virtual void list_dir_end(); ///< + virtual Error list_dir_begin() override; ///< This starts dir listing + virtual String get_next() override; + virtual bool current_is_dir() const override; + virtual bool current_is_hidden() const override; + virtual void list_dir_end() override; ///< - virtual int get_drive_count(); - virtual String get_drive(int p_drive); + virtual int get_drive_count() override; + virtual String get_drive(int p_drive) override; - virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success - virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location + virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success + virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location - virtual bool file_exists(String p_file); - virtual bool dir_exists(String p_dir); + virtual bool file_exists(String p_file) override; + virtual bool dir_exists(String p_dir) override; - virtual Error make_dir(String p_dir); + virtual Error make_dir(String p_dir) override; - virtual Error rename(String p_path, String p_new_path); - virtual Error remove(String p_path); + virtual Error rename(String p_path, String p_new_path) override; + virtual Error remove(String p_path) override; - virtual bool is_link(String p_file) { return false; }; - virtual String read_link(String p_file) { return p_file; }; - virtual Error create_link(String p_source, String p_target) { return FAILED; }; + virtual bool is_link(String p_file) override { return false; }; + virtual String read_link(String p_file) override { return p_file; }; + virtual Error create_link(String p_source, String p_target) override { return FAILED; }; - uint64_t get_space_left(); + uint64_t get_space_left() override; - virtual String get_filesystem_type() const; + virtual String get_filesystem_type() const override; DirAccessWindows(); ~DirAccessWindows(); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 5d67b6ca4f..8629bb936b 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -51,33 +51,33 @@ class FileAccessWindows : public FileAccess { void _close(); public: - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual bool is_open() const; ///< true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file + virtual bool is_open() const override; ///< true when file is open - virtual String get_path() const; /// returns the path for the current open file - virtual String get_path_absolute() const; /// returns the absolute path for the current open file + virtual String get_path() const override; /// returns the path for the current open file + virtual String get_path_absolute() const override; /// returns the absolute path for the current open file - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_length() const; ///< get size of the file + virtual void seek(uint64_t p_position) override; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file + virtual uint64_t get_position() const override; ///< get position in the file + virtual uint64_t get_length() const override; ///< get size of the file - virtual bool eof_reached() const; ///< reading passed EOF + virtual bool eof_reached() const override; ///< reading passed EOF - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; ///< get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; ///< get last error + virtual Error get_error() const override; ///< get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes - virtual bool file_exists(const String &p_name); ///< return true if a file exists + virtual bool file_exists(const String &p_name) override; ///< return true if a file exists - uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file); - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); + uint64_t _get_modified_time(const String &p_file) override; + virtual uint32_t _get_unix_permissions(const String &p_file) override; + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; FileAccessWindows() {} virtual ~FileAccessWindows(); diff --git a/drivers/winmidi/midi_driver_winmidi.h b/drivers/winmidi/midi_driver_winmidi.h index 6572ba0c16..e42f3df4cf 100644 --- a/drivers/winmidi/midi_driver_winmidi.h +++ b/drivers/winmidi/midi_driver_winmidi.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef WINMIDI_ENABLED - #ifndef MIDI_DRIVER_WINMIDI_H #define MIDI_DRIVER_WINMIDI_H +#ifdef WINMIDI_ENABLED + #include "core/os/midi_driver.h" #include "core/templates/vector.h" @@ -57,5 +57,6 @@ public: virtual ~MIDIDriverWinMidi(); }; -#endif // MIDI_DRIVER_WINMIDI_H #endif // WINMIDI_ENABLED + +#endif // MIDI_DRIVER_WINMIDI_H diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h index 9072269a0e..81432ceb8e 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.h +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -106,4 +106,4 @@ public: ~AudioDriverXAudio2() {} }; -#endif +#endif // AUDIO_DRIVER_XAUDIO2_H diff --git a/editor/SCsub b/editor/SCsub index a596c7d364..c217f162b4 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -76,7 +76,7 @@ if env["tools"]: # Editor translations to_include = ( - "ar,bg,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,lv,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,th,tr,uk,vi,zh_CN,zh_TW" + "ar,bg,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,lv,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,sv,th,tr,uk,vi,zh_CN,zh_TW" ).split(",") tlist = [env.Dir("#editor/translations").abspath + "/" + f + ".po" for f in to_include] env.Depends("#editor/editor_translations.gen.h", tlist) @@ -113,6 +113,7 @@ if env["tools"]: env.add_source_files(env.editor_sources, "register_exporters.gen.cpp") SConscript("debugger/SCsub") + SConscript("export/SCsub") SConscript("fileserver/SCsub") SConscript("icons/SCsub") SConscript("import/SCsub") diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 698390a61e..462f314471 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -720,7 +720,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() { for (int i = 0; i < MOD_MAX; i++) { String name = mods[i]; mod_checkboxes[i] = memnew(CheckBox); - mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled), varray(i)); + mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled).bind(i)); mod_checkboxes[i]->set_text(name); mod_container->add_child(mod_checkboxes[i]); } @@ -1199,7 +1199,7 @@ void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) { ActionMapEditor::ActionMapEditor() { // Main Vbox Container VBoxContainer *main_vbox = memnew(VBoxContainer); - main_vbox->set_anchors_and_offsets_preset(PRESET_WIDE); + main_vbox->set_anchors_and_offsets_preset(PRESET_FULL_RECT); add_child(main_vbox); HBoxContainer *top_hbox = memnew(HBoxContainer); diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index d8c40a97a7..1ca3c5bac0 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -209,4 +209,4 @@ public: ActionMapEditor(); }; -#endif +#endif // ACTION_MAP_EDITOR_H diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 391cd009f1..ab9afda803 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -654,9 +654,9 @@ void AnimationBezierTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) { void AnimationBezierTrackEdit::set_editor(AnimationTrackEditor *p_editor) { editor = p_editor; - connect("clear_selection", Callable(editor, "_clear_selection"), varray(false)); - connect("select_key", Callable(editor, "_key_selected"), varray(), CONNECT_DEFERRED); - connect("deselect_key", Callable(editor, "_key_deselected"), varray(), CONNECT_DEFERRED); + connect("clear_selection", Callable(editor, "_clear_selection").bind(false)); + connect("select_key", Callable(editor, "_key_selected"), CONNECT_DEFERRED); + connect("deselect_key", Callable(editor, "_key_deselected"), CONNECT_DEFERRED); } void AnimationBezierTrackEdit::_play_position_draw() { @@ -1593,7 +1593,7 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() { play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); add_child(play_position); - play_position->set_anchors_and_offsets_preset(PRESET_WIDE); + play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT); play_position->connect("draw", callable_mp(this, &AnimationBezierTrackEdit::_play_position_draw)); set_focus_mode(FOCUS_CLICK); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 19b259489f..83047caf98 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -37,6 +37,7 @@ #include "editor/editor_scale.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "scene/animation/animation_player.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" @@ -1890,7 +1891,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() { play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); add_child(play_position); - play_position->set_anchors_and_offsets_preset(PRESET_WIDE); + play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT); play_position->connect("draw", callable_mp(this, &AnimationTimelineEdit::_play_position_draw)); add_track = memnew(MenuButton); @@ -2919,7 +2920,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { add_child(path_popup); path = memnew(LineEdit); path_popup->add_child(path); - path->set_anchors_and_offsets_preset(PRESET_WIDE); + path->set_anchors_and_offsets_preset(PRESET_FULL_RECT); path->connect("text_submitted", callable_mp(this, &AnimationTrackEdit::_path_submitted)); } @@ -3212,7 +3213,7 @@ AnimationTrackEdit::AnimationTrackEdit() { play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); add_child(play_position); - play_position->set_anchors_and_offsets_preset(PRESET_WIDE); + play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT); play_position->connect("draw", callable_mp(this, &AnimationTrackEdit::_play_position_draw)); set_focus_mode(FOCUS_CLICK); set_mouse_filter(MOUSE_FILTER_PASS); // Scroll has to work too for selection. @@ -3428,7 +3429,7 @@ void AnimationTrackEditor::set_root(Node *p_root) { root = p_root; if (root) { - root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), make_binds(), CONNECT_ONESHOT); + root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), CONNECT_ONESHOT); } _update_tracks(); @@ -3725,11 +3726,11 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) { } } -void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_beziers) { +void AnimationTrackEditor::_insert_track(bool p_reset_wanted, bool p_create_beziers) { undo_redo->create_action(TTR("Anim Insert")); Ref<Animation> reset_anim; - if (p_create_reset) { + if (p_reset_wanted) { reset_anim = _create_and_get_reset_animation(); } @@ -3739,26 +3740,14 @@ void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_bezi if (insert_data.front()->get().advance) { advance = true; } - next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_create_reset, reset_anim, p_create_beziers); + next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_reset_wanted, reset_anim, p_create_beziers); insert_data.pop_front(); } undo_redo->commit_action(); if (advance) { - float step = animation->get_step(); - if (step == 0) { - step = 1; - } - - float pos = timeline->get_play_position(); - - pos = Math::snapped(pos + step, step); - if (pos > animation->get_length()) { - pos = animation->get_length(); - } - set_anim_pos(pos); - emit_signal(SNAME("timeline_changed"), pos, true, false); + _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY); } } @@ -4086,12 +4075,20 @@ void AnimationTrackEditor::_confirm_insert_list() { } TrackIndices next_tracks(animation.ptr(), reset_anim.ptr()); + bool advance = false; while (insert_data.size()) { + if (insert_data.front()->get().advance) { + advance = true; + } next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, create_reset, reset_anim, insert_confirm_bezier->is_pressed()); insert_data.pop_front(); } undo_redo->commit_action(); + + if (advance) { + _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY); + } } PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val) { @@ -4207,9 +4204,42 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool return subindices; } -AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers) { +AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_reset_wanted, Ref<Animation> p_reset_anim, bool p_create_beziers) { bool created = false; - if (p_id.track_idx < 0) { + + bool create_normal_track = p_id.track_idx < 0; + bool create_reset_track = p_reset_wanted && track_type_is_resettable(p_id.type); + + Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE; + if (create_normal_track || create_reset_track) { + if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) { + // Hack. + NodePath np; + animation->add_track(p_id.type); + animation->track_set_path(animation->get_track_count() - 1, p_id.path); + PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np); + animation->remove_track(animation->get_track_count() - 1); // Hack. + + if (h.type == Variant::FLOAT || + h.type == Variant::VECTOR2 || + h.type == Variant::RECT2 || + h.type == Variant::VECTOR3 || + h.type == Variant::AABB || + h.type == Variant::QUATERNION || + h.type == Variant::COLOR || + h.type == Variant::PLANE || + h.type == Variant::TRANSFORM2D || + h.type == Variant::TRANSFORM3D) { + update_mode = Animation::UPDATE_CONTINUOUS; + } + + if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) { + update_mode = Animation::UPDATE_TRIGGER; + } + } + } + + if (create_normal_track) { if (p_create_beziers) { bool valid; Vector<String> subindices = _get_bezier_subindices_for_type(p_id.value.get_type(), &valid); @@ -4219,7 +4249,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD id.type = Animation::TYPE_BEZIER; id.value = p_id.value.get(subindices[i].substr(1, subindices[i].length())); id.path = String(p_id.path) + subindices[i]; - p_next_tracks = _confirm_insert(id, p_next_tracks, p_create_reset, p_reset_anim, false); + p_next_tracks = _confirm_insert(id, p_next_tracks, p_reset_wanted, p_reset_anim, false); } return p_next_tracks; @@ -4227,37 +4257,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD } created = true; undo_redo->create_action(TTR("Anim Insert Track & Key")); - Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE; - - if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) { - // Wants a new track. - - { - // Hack. - NodePath np; - animation->add_track(p_id.type); - animation->track_set_path(animation->get_track_count() - 1, p_id.path); - PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np); - animation->remove_track(animation->get_track_count() - 1); // Hack. - - if (h.type == Variant::FLOAT || - h.type == Variant::VECTOR2 || - h.type == Variant::RECT2 || - h.type == Variant::VECTOR3 || - h.type == Variant::AABB || - h.type == Variant::QUATERNION || - h.type == Variant::COLOR || - h.type == Variant::PLANE || - h.type == Variant::TRANSFORM2D || - h.type == Variant::TRANSFORM3D) { - update_mode = Animation::UPDATE_CONTINUOUS; - } - - if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) { - update_mode = Animation::UPDATE_TRIGGER; - } - } - } p_id.track_idx = p_next_tracks.normal; @@ -4320,8 +4319,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD } } - if (p_create_reset && track_type_is_resettable(p_id.type)) { - bool create_reset_track = true; + if (create_reset_track) { Animation *reset_anim = p_reset_anim.ptr(); for (int i = 0; i < reset_anim->get_track_count(); i++) { if (reset_anim->track_get_path(i) == p_id.path) { @@ -4332,6 +4330,9 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD if (create_reset_track) { undo_redo->add_do_method(reset_anim, "add_track", p_id.type); undo_redo->add_do_method(reset_anim, "track_set_path", p_next_tracks.reset, p_id.path); + if (p_id.type == Animation::TYPE_VALUE) { + undo_redo->add_do_method(reset_anim, "value_track_set_update_mode", p_next_tracks.reset, update_mode); + } undo_redo->add_do_method(reset_anim, "track_insert_key", p_next_tracks.reset, 0.0f, value); undo_redo->add_undo_method(reset_anim, "remove_track", reset_anim->get_track_count()); p_next_tracks.reset++; @@ -4514,20 +4515,20 @@ void AnimationTrackEditor::_update_tracks() { } track_edit->connect("timeline_changed", callable_mp(this, &AnimationTrackEditor::_timeline_changed)); - track_edit->connect("remove_request", callable_mp(this, &AnimationTrackEditor::_track_remove_request), varray(), CONNECT_DEFERRED); - track_edit->connect("dropped", callable_mp(this, &AnimationTrackEditor::_dropped_track), varray(), CONNECT_DEFERRED); - track_edit->connect("insert_key", callable_mp(this, &AnimationTrackEditor::_insert_key_from_track), varray(i), CONNECT_DEFERRED); - track_edit->connect("select_key", callable_mp(this, &AnimationTrackEditor::_key_selected), varray(i), CONNECT_DEFERRED); - track_edit->connect("deselect_key", callable_mp(this, &AnimationTrackEditor::_key_deselected), varray(i), CONNECT_DEFERRED); + track_edit->connect("remove_request", callable_mp(this, &AnimationTrackEditor::_track_remove_request), CONNECT_DEFERRED); + track_edit->connect("dropped", callable_mp(this, &AnimationTrackEditor::_dropped_track), CONNECT_DEFERRED); + track_edit->connect("insert_key", callable_mp(this, &AnimationTrackEditor::_insert_key_from_track).bind(i), CONNECT_DEFERRED); + track_edit->connect("select_key", callable_mp(this, &AnimationTrackEditor::_key_selected).bind(i), CONNECT_DEFERRED); + track_edit->connect("deselect_key", callable_mp(this, &AnimationTrackEditor::_key_deselected).bind(i), CONNECT_DEFERRED); track_edit->connect("move_selection_begin", callable_mp(this, &AnimationTrackEditor::_move_selection_begin)); track_edit->connect("move_selection", callable_mp(this, &AnimationTrackEditor::_move_selection)); track_edit->connect("move_selection_commit", callable_mp(this, &AnimationTrackEditor::_move_selection_commit)); track_edit->connect("move_selection_cancel", callable_mp(this, &AnimationTrackEditor::_move_selection_cancel)); - track_edit->connect("duplicate_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DUPLICATE_SELECTION), CONNECT_DEFERRED); - track_edit->connect("duplicate_transpose_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DUPLICATE_TRANSPOSED), CONNECT_DEFERRED); - track_edit->connect("create_reset_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_ADD_RESET_KEY), CONNECT_DEFERRED); - track_edit->connect("delete_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DELETE_SELECTION), CONNECT_DEFERRED); + track_edit->connect("duplicate_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DUPLICATE_SELECTION), CONNECT_DEFERRED); + track_edit->connect("duplicate_transpose_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DUPLICATE_TRANSPOSED), CONNECT_DEFERRED); + track_edit->connect("create_reset_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_ADD_RESET_KEY), CONNECT_DEFERRED); + track_edit->connect("delete_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DELETE_SELECTION), CONNECT_DEFERRED); } } @@ -5593,7 +5594,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) { emit_signal(SNAME("timeline_changed"), pos, true, false); } -void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) { +void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event, bool p_timeline_only) { if (animation.is_null()) { return; } @@ -5617,7 +5618,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) { } set_anim_pos(pos); - emit_signal(SNAME("timeline_changed"), pos, true, false); + emit_signal(SNAME("timeline_changed"), pos, true, p_timeline_only); } void AnimationTrackEditor::_edit_menu_pressed(int p_option) { @@ -5965,8 +5966,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { _update_key_edit(); } } break; + case EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY: case EDIT_GOTO_NEXT_STEP: { - goto_next_step(false); + goto_next_step(false, p_option == EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY); } break; case EDIT_GOTO_PREV_STEP: { goto_prev_step(false); @@ -6109,7 +6111,8 @@ float AnimationTrackEditor::snap_time(float p_value, bool p_relative) { void AnimationTrackEditor::_show_imported_anim_warning() { // It looks terrible on a single line but the TTR extractor doesn't support line breaks yet. - EditorNode::get_singleton()->show_warning(TTR("This animation belongs to an imported scene, so changes to imported tracks will not be saved.\n\nTo enable the ability to add custom tracks, navigate to the scene's import settings and set\n\"Animation > Storage\" to \"Files\", enable \"Animation > Keep Custom Tracks\", then re-import.\nAlternatively, use an import preset that imports animations to separate files."), + EditorNode::get_singleton()->show_warning( + TTR("This animation belongs to an imported scene, so changes to imported tracks will not be saved.\n\nTo modify this animation, navigate to the scene's Advanced Import settings and select the animation.\nSome options, including looping, are available here. To add custom tracks, enable \"Save To File\" and\n\"Keep Custom Tracks\"."), TTR("Warning: Editing imported animation")); } @@ -6241,7 +6244,7 @@ AnimationTrackEditor::AnimationTrackEditor() { info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); main_panel->add_child(info_message); timeline = memnew(AnimationTimelineEdit); @@ -6295,6 +6298,7 @@ AnimationTrackEditor::AnimationTrackEditor() { imported_anim_warning = memnew(Button); imported_anim_warning->hide(); + imported_anim_warning->set_text(TTR("Imported Scene")); imported_anim_warning->set_tooltip(TTR("Warning: Editing imported animation")); imported_anim_warning->connect("pressed", callable_mp(this, &AnimationTrackEditor::_show_imported_anim_warning)); bottom_hb->add_child(imported_anim_warning); @@ -6474,7 +6478,7 @@ AnimationTrackEditor::AnimationTrackEditor() { optimize_max_angle->set_value(22); optimize_dialog->set_ok_button_text(TTR("Optimize")); - optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_OPTIMIZE_ANIMATION_CONFIRM)); + optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM)); // @@ -6500,7 +6504,7 @@ AnimationTrackEditor::AnimationTrackEditor() { cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)")); cleanup_dialog->set_ok_button_text(TTR("Clean-Up")); - cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM)); + cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_CLEAN_UP_ANIMATION_CONFIRM)); // scale_dialog = memnew(ConfirmationDialog); @@ -6512,7 +6516,7 @@ AnimationTrackEditor::AnimationTrackEditor() { scale->set_max(99999); scale->set_step(0.001); vbc->add_margin_child(TTR("Scale Ratio:"), scale); - scale_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_SCALE_CONFIRM)); + scale_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_SCALE_CONFIRM)); add_child(scale_dialog); track_copy_dialog = memnew(ConfirmationDialog); @@ -6533,7 +6537,7 @@ AnimationTrackEditor::AnimationTrackEditor() { track_copy_select->set_v_size_flags(SIZE_EXPAND_FILL); track_copy_select->set_hide_root(true); track_vbox->add_child(track_copy_select); - track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_COPY_TRACKS_CONFIRM)); + track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_COPY_TRACKS_CONFIRM)); } AnimationTrackEditor::~AnimationTrackEditor() { diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 55c3bd922a..cb7d3c7d96 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -33,11 +33,14 @@ #include "editor/editor_data.h" #include "editor/editor_spin_slider.h" -#include "editor/property_editor.h" #include "editor/property_selector.h" +#include "scene/3d/node_3d.h" +#include "scene/gui/check_box.h" #include "scene/gui/control.h" #include "scene/gui/menu_button.h" +#include "scene/gui/option_button.h" +#include "scene/gui/panel_container.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" @@ -375,8 +378,8 @@ class AnimationTrackEditor : public VBoxContainer { reset = p_reset_anim ? p_reset_anim->get_track_count() : 0; } }; - TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers); - void _insert_track(bool p_create_reset, bool p_create_beziers); + TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_reset_wanted, Ref<Animation> p_reset_anim, bool p_create_beziers); + void _insert_track(bool p_reset_wanted, bool p_create_beziers); void _root_removed(); @@ -518,6 +521,7 @@ public: EDIT_ADD_RESET_KEY, EDIT_DELETE_SELECTION, EDIT_GOTO_NEXT_STEP, + EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation. EDIT_GOTO_PREV_STEP, EDIT_APPLY_RESET, EDIT_OPTIMIZE_ANIMATION, @@ -563,7 +567,7 @@ public: void goto_prev_step(bool p_from_mouse_event); /** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */ - void goto_next_step(bool p_from_mouse_event); + void goto_next_step(bool p_from_mouse_event, bool p_timeline_only = false); MenuButton *get_edit_menu(); AnimationTrackEditor(); diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index bea95d873e..b9e52ad7ad 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -153,6 +153,8 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) { singleton->call_deferred(SNAME("_update_emit"), preview->id); } + preview->preview->version++; + preview->playback->stop(); preview->generating.clear(); @@ -171,7 +173,7 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref< Preview *preview = &previews[p_stream->get_instance_id()]; preview->base_stream = p_stream; - preview->playback = preview->base_stream->instance_playback(); + preview->playback = preview->base_stream->instantiate_playback(); preview->generating.set(); preview->id = p_stream->get_instance_id(); @@ -198,6 +200,7 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref< if (preview->playback.is_valid()) { preview->thread = memnew(Thread); + preview->thread->set_name("AudioStreamPreviewGenerator"); preview->thread->start(_preview_thread, preview); } diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h index 307dd93b34..0e3c8f70d2 100644 --- a/editor/audio_stream_preview.h +++ b/editor/audio_stream_preview.h @@ -43,8 +43,10 @@ class AudioStreamPreview : public RefCounted { float length; friend class AudioStreamPreviewGenerator; + uint64_t version = 1; public: + uint64_t get_version() const { return version; } float get_length() const; float get_max(float p_time, float p_time_next) const; float get_min(float p_time, float p_time_next) const; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 50abe8bc36..b0eb384efc 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -332,7 +332,7 @@ void FindReplaceBar::_update_results_count() { if (results_count_to_current > results_count) { results_count_to_current = results_count_to_current - results_count; - } else if (results_count_to_current == 0) { + } else if (results_count_to_current <= 0) { results_count_to_current = results_count; } @@ -824,12 +824,15 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { if (k->is_pressed()) { if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) { _zoom_in(); + accept_event(); } if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) { _zoom_out(); + accept_event(); } if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) { _reset_zoom(); + accept_event(); } } } @@ -1042,6 +1045,8 @@ void CodeTextEditor::update_editor_settings() { guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/line_length_guideline_soft_column")); } text_editor->set_line_length_guidelines(guideline_cols); + } else { + text_editor->set_line_length_guidelines(TypedArray<int>()); } } @@ -1594,6 +1599,10 @@ void CodeTextEditor::set_error_pos(int p_line, int p_column) { error_column = p_column; } +Point2i CodeTextEditor::get_error_pos() const { + return Point2i(error_line, error_column); +} + void CodeTextEditor::goto_error() { if (!error->get_text().is_empty()) { if (text_editor->get_line_count() != error_line) { diff --git a/editor/code_editor.h b/editor/code_editor.h index e2441cec2b..49679cc700 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -253,13 +253,14 @@ public: void update_editor_settings(); void set_error(const String &p_error); void set_error_pos(int p_line, int p_column); + Point2i get_error_pos() const; void update_line_and_column() { _line_col_changed(); } CodeEdit *get_text_editor() { return text_editor; } FindReplaceBar *get_find_replace_bar() { return find_replace_bar; } void set_find_replace_bar(FindReplaceBar *p_bar); void remove_find_replace_bar(); virtual void apply_code() {} - void goto_error(); + virtual void goto_error(); void toggle_bookmark(); void goto_next_bookmark(); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index ce94edd583..6fdd9563fb 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -627,7 +627,7 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) { Callable callable = p_cd.get_callable(); undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(p_cd.signal), String(p_cd.method))); - undo_redo->add_do_method(source, "connect", p_cd.signal, callable, varray(), p_cd.flags); + undo_redo->add_do_method(source, "connect", p_cd.signal, callable, p_cd.flags); undo_redo->add_undo_method(source, "disconnect", p_cd.signal, callable); undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index dcfde8800a..d141d1a880 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -97,7 +97,7 @@ public: for (int i = 0; i < binds.size(); i++) { argptrs[i] = &binds[i]; } - return Callable(target, method).bind(argptrs, binds.size()); + return Callable(target, method).bindp(argptrs, binds.size()); } else { return Callable(target, method); } diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index c41eeb520a..e6168f4924 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -34,6 +34,7 @@ #include "core/os/keyboard.h" #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -378,7 +379,7 @@ void CreateDialog::_confirmed() { } { - Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE); + Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE); if (f.is_valid()) { f->store_line(selected_item); @@ -655,7 +656,7 @@ void CreateDialog::_save_and_update_favorite_list() { TreeItem *root = favorites->create_item(); { - Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); + Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); if (f.is_valid()) { for (int i = 0; i < favorite_list.size(); i++) { String l = favorite_list[i]; @@ -680,7 +681,7 @@ void CreateDialog::_save_and_update_favorite_list() { } void CreateDialog::_load_favorites_and_history() { - String dir = EditorSettings::get_singleton()->get_project_settings_dir(); + String dir = EditorPaths::get_singleton()->get_project_settings_dir(); Ref<FileAccess> f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ); if (f.is_valid()) { while (!f->eof_reached()) { diff --git a/editor/create_dialog.h b/editor/create_dialog.h index dc8618a1c0..04094108ad 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -125,4 +125,4 @@ public: CreateDialog(); }; -#endif +#endif // CREATE_DIALOG_H diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index 0caeb90108..3c3e4faa6f 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -34,6 +34,7 @@ #include "editor/debugger/script_editor_debugger.h" #include "editor/editor_node.h" #include "editor/editor_run_native.h" +#include "editor/export/editor_export_platform.h" #include "editor/plugins/script_editor_plugin.h" void DebugAdapterParser::_bind_methods() { diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.h b/editor/debugger/debug_adapter/debug_adapter_parser.h index f458151e17..ee32306146 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.h +++ b/editor/debugger/debug_adapter/debug_adapter_parser.h @@ -93,4 +93,4 @@ public: Dictionary ev_breakpoint(const DAP::Breakpoint &p_breakpoint, const bool &p_enabled) const; }; -#endif +#endif // DEBUG_ADAPTER_PARSER_H diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index 92ea0f15e9..4c445eb766 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -37,6 +37,7 @@ #include "editor/doc_tools.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" DebugAdapterProtocol *DebugAdapterProtocol::singleton = nullptr; diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h index a17e550dfc..29f577ef97 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.h +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h @@ -152,4 +152,4 @@ public: ~DebugAdapterProtocol(); }; -#endif +#endif // DEBUG_ADAPTER_PROTOCOL_H diff --git a/editor/debugger/debug_adapter/debug_adapter_server.cpp b/editor/debugger/debug_adapter/debug_adapter_server.cpp index e9fc7ec913..41e6b1f308 100644 --- a/editor/debugger/debug_adapter/debug_adapter_server.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_server.cpp @@ -33,6 +33,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" DebugAdapterServer::DebugAdapterServer() { _EDITOR_DEF("network/debug_adapter/remote_port", remote_port); diff --git a/editor/debugger/debug_adapter/debug_adapter_server.h b/editor/debugger/debug_adapter/debug_adapter_server.h index a2b01f92c6..633739eaae 100644 --- a/editor/debugger/debug_adapter/debug_adapter_server.h +++ b/editor/debugger/debug_adapter/debug_adapter_server.h @@ -54,4 +54,4 @@ public: void stop(); }; -#endif +#endif // DEBUG_ADAPTER_SERVER_H diff --git a/editor/debugger/debug_adapter/debug_adapter_types.h b/editor/debugger/debug_adapter/debug_adapter_types.h index fd66905f9b..eb10184ab3 100644 --- a/editor/debugger/debug_adapter/debug_adapter_types.h +++ b/editor/debugger/debug_adapter/debug_adapter_types.h @@ -278,4 +278,4 @@ struct Variable { } // namespace DAP -#endif +#endif // DEBUG_ADAPTER_TYPES_H diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp index 0e3d424a4b..58206efc20 100644 --- a/editor/debugger/editor_debugger_inspector.cpp +++ b/editor/debugger/editor_debugger_inspector.cpp @@ -126,25 +126,25 @@ void EditorDebuggerInspector::_object_selected(ObjectID p_object) { } ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { - EditorDebuggerRemoteObject *debugObj = nullptr; + EditorDebuggerRemoteObject *debug_obj = nullptr; SceneDebuggerObject obj; obj.deserialize(p_arr); ERR_FAIL_COND_V(obj.id.is_null(), ObjectID()); if (remote_objects.has(obj.id)) { - debugObj = remote_objects[obj.id]; + debug_obj = remote_objects[obj.id]; } else { - debugObj = memnew(EditorDebuggerRemoteObject); - debugObj->remote_object_id = obj.id; - debugObj->type_name = obj.class_name; - remote_objects[obj.id] = debugObj; - debugObj->connect("value_edited", callable_mp(this, &EditorDebuggerInspector::_object_edited)); + debug_obj = memnew(EditorDebuggerRemoteObject); + debug_obj->remote_object_id = obj.id; + debug_obj->type_name = obj.class_name; + remote_objects[obj.id] = debug_obj; + debug_obj->connect("value_edited", callable_mp(this, &EditorDebuggerInspector::_object_edited)); } - int old_prop_size = debugObj->prop_list.size(); + int old_prop_size = debug_obj->prop_list.size(); - debugObj->prop_list.clear(); + debug_obj->prop_list.clear(); int new_props_added = 0; HashSet<String> changed; for (int i = 0; i < obj.properties.size(); i++) { @@ -165,12 +165,14 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { var = ResourceLoader::load(path); if (pinfo.hint_string == "Script") { - if (debugObj->get_script() != var) { - debugObj->set_script(Ref<RefCounted>()); + if (debug_obj->get_script() != var) { + debug_obj->set_script(Ref<RefCounted>()); Ref<Script> script(var); if (!script.is_null()) { - ScriptInstance *script_instance = script->placeholder_instance_create(debugObj); - debugObj->set_script_and_instance(var, script_instance); + ScriptInstance *script_instance = script->placeholder_instance_create(debug_obj); + if (script_instance) { + debug_obj->set_script_and_instance(var, script_instance); + } } } } @@ -178,27 +180,27 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { } //always add the property, since props may have been added or removed - debugObj->prop_list.push_back(pinfo); + debug_obj->prop_list.push_back(pinfo); - if (!debugObj->prop_values.has(pinfo.name)) { + if (!debug_obj->prop_values.has(pinfo.name)) { new_props_added++; - debugObj->prop_values[pinfo.name] = var; + debug_obj->prop_values[pinfo.name] = var; } else { - if (bool(Variant::evaluate(Variant::OP_NOT_EQUAL, debugObj->prop_values[pinfo.name], var))) { - debugObj->prop_values[pinfo.name] = var; + if (bool(Variant::evaluate(Variant::OP_NOT_EQUAL, debug_obj->prop_values[pinfo.name], var))) { + debug_obj->prop_values[pinfo.name] = var; changed.insert(pinfo.name); } } } - if (old_prop_size == debugObj->prop_list.size() && new_props_added == 0) { + if (old_prop_size == debug_obj->prop_list.size() && new_props_added == 0) { //only some may have changed, if so, then update those, if exist for (const String &E : changed) { - emit_signal(SNAME("object_property_updated"), debugObj->remote_object_id, E); + emit_signal(SNAME("object_property_updated"), debug_obj->remote_object_id, E); } } else { //full update, because props were added or removed - debugObj->update(); + debug_obj->update(); } return obj.id; } diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h index 0e73928558..5aac4dbf11 100644 --- a/editor/debugger/editor_debugger_inspector.h +++ b/editor/debugger/editor_debugger_inspector.h @@ -30,6 +30,7 @@ #ifndef EDITOR_DEBUGGER_INSPECTOR_H #define EDITOR_DEBUGGER_INSPECTOR_H + #include "editor/editor_inspector.h" class EditorDebuggerRemoteObject : public Object { diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index e13af59d69..472e53c0e8 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -92,17 +92,17 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { ScriptEditorDebugger *node = memnew(ScriptEditorDebugger); int id = tabs->get_tab_count(); - node->connect("stop_requested", callable_mp(this, &EditorDebuggerNode::_debugger_wants_stop), varray(id)); - node->connect("stopped", callable_mp(this, &EditorDebuggerNode::_debugger_stopped), varray(id)); - node->connect("stack_frame_selected", callable_mp(this, &EditorDebuggerNode::_stack_frame_selected), varray(id)); - node->connect("error_selected", callable_mp(this, &EditorDebuggerNode::_error_selected), varray(id)); - node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected), varray(id)); + node->connect("stop_requested", callable_mp(this, &EditorDebuggerNode::_debugger_wants_stop).bind(id)); + node->connect("stopped", callable_mp(this, &EditorDebuggerNode::_debugger_stopped).bind(id)); + node->connect("stack_frame_selected", callable_mp(this, &EditorDebuggerNode::_stack_frame_selected).bind(id)); + node->connect("error_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id)); + node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id)); node->connect("clear_execution", callable_mp(this, &EditorDebuggerNode::_clear_execution)); - node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked), varray(id)); - node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated), varray(id)); - node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated), varray(id)); - node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated), varray(id)); - node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested), varray(id)); + node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked).bind(id)); + node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated).bind(id)); + node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated).bind(id)); + node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated).bind(id)); + node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested).bind(id)); node->connect("errors_cleared", callable_mp(this, &EditorDebuggerNode::_update_errors)); if (tabs->get_tab_count() > 0) { diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index d50cbec291..4c9ad49ac4 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -205,4 +205,5 @@ public: void add_debugger_plugin(const Ref<Script> &p_script); void remove_debugger_plugin(const Ref<Script> &p_script); }; + #endif // EDITOR_DEBUGGER_NODE_H diff --git a/editor/debugger/editor_debugger_server.h b/editor/debugger/editor_debugger_server.h index adf9a27c71..f3805f54d8 100644 --- a/editor/debugger/editor_debugger_server.h +++ b/editor/debugger/editor_debugger_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_DEBUGGER_CONNECTION_H -#define EDITOR_DEBUGGER_CONNECTION_H +#ifndef EDITOR_DEBUGGER_SERVER_H +#define EDITOR_DEBUGGER_SERVER_H #include "core/debugger/remote_debugger_peer.h" #include "core/object/ref_counted.h" @@ -57,4 +57,4 @@ public: virtual Ref<RemoteDebuggerPeer> take_connection() = 0; }; -#endif // EDITOR_DEBUGGER_CONNECTION_H +#endif // EDITOR_DEBUGGER_SERVER_H diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index bdab1cfecb..dbd2c61d44 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -225,6 +225,39 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int updating_scene_tree = false; } +Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) { + if (get_button_id_at_position(p_point) != -1) { + return Variant(); + } + + TreeItem *selected = get_selected(); + if (!selected) { + return Variant(); + } + + String path = selected->get_text(0); + + HBoxContainer *hb = memnew(HBoxContainer); + TextureRect *tf = memnew(TextureRect); + tf->set_texture(selected->get_icon(0)); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + hb->add_child(tf); + Label *label = memnew(Label(path)); + hb->add_child(label); + set_drag_preview(hb); + + if (!selected->get_parent() || !selected->get_parent()->get_parent()) { + path = "."; + } else { + while (selected->get_parent()->get_parent() != get_root()) { + selected = selected->get_parent(); + path = selected->get_text(0) + "/" + path; + } + } + + return vformat("\"%s\"", path); +} + String EditorDebuggerTree::get_selected_path() { if (!get_selected()) { return ""; diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h index bba524039e..5b2df8abd5 100644 --- a/editor/debugger/editor_debugger_tree.h +++ b/editor/debugger/editor_debugger_tree.h @@ -65,10 +65,13 @@ protected: void _notification(int p_what); public: + virtual Variant get_drag_data(const Point2 &p_point) override; + String get_selected_path(); ObjectID get_selected_object(); int get_current_debugger(); // Would love to have one tree for every debugger. void update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger); EditorDebuggerTree(); }; + #endif // EDITOR_DEBUGGER_TREE_H diff --git a/editor/debugger/editor_network_profiler.h b/editor/debugger/editor_network_profiler.h index d2e70a083d..aea7ce3eec 100644 --- a/editor/debugger/editor_network_profiler.h +++ b/editor/debugger/editor_network_profiler.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORNETWORKPROFILER_H -#define EDITORNETWORKPROFILER_H +#ifndef EDITOR_NETWORK_PROFILER_H +#define EDITOR_NETWORK_PROFILER_H #include "scene/debugger/scene_debugger.h" #include "scene/gui/box_container.h" @@ -69,4 +69,4 @@ public: EditorNetworkProfiler(); }; -#endif //EDITORNETWORKPROFILER_H +#endif // EDITOR_NETWORK_PROFILER_H diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index 50eef7b8b8..55d025f675 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -393,7 +393,7 @@ EditorPerformanceProfiler::EditorPerformanceProfiler() { info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); monitor_draw->add_child(info_message); for (int i = 0; i < Performance::MONITOR_MAX; i++) { diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h index cb01a1819f..df92125258 100644 --- a/editor/debugger/editor_profiler.h +++ b/editor/debugger/editor_profiler.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORPROFILER_H -#define EDITORPROFILER_H +#ifndef EDITOR_PROFILER_H +#define EDITOR_PROFILER_H #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -165,4 +165,4 @@ public: EditorProfiler(); }; -#endif // EDITORPROFILER_H +#endif // EDITOR_PROFILER_H diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index ee67cbdaea..6f3dd1793c 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -796,7 +796,7 @@ EditorVisualProfiler::EditorVisualProfiler() { frame_delay->set_wait_time(0.1); frame_delay->set_one_shot(true); add_child(frame_delay); - frame_delay->connect("timeout", callable_mp(this, &EditorVisualProfiler::_update_frame), make_binds(false)); + frame_delay->connect("timeout", callable_mp(this, &EditorVisualProfiler::_update_frame).bind(false)); plot_delay = memnew(Timer); plot_delay->set_wait_time(0.1); diff --git a/editor/debugger/editor_visual_profiler.h b/editor/debugger/editor_visual_profiler.h index 4e5169da9e..8aa9e7b308 100644 --- a/editor/debugger/editor_visual_profiler.h +++ b/editor/debugger/editor_visual_profiler.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_FRAME_PROFILER_H -#define EDITOR_FRAME_PROFILER_H +#ifndef EDITOR_VISUAL_PROFILER_H +#define EDITOR_VISUAL_PROFILER_H #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -144,4 +144,4 @@ public: EditorVisualProfiler(); }; -#endif // EDITOR_FRAME_PROFILER_H +#endif // EDITOR_VISUAL_PROFILER_H diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index f8b82ecc51..ac2e958c5b 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -50,7 +50,6 @@ #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" -#include "editor/property_editor.h" #include "main/performance.h" #include "scene/3d/camera_3d.h" #include "scene/debugger/scene_debugger.h" @@ -753,7 +752,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da const Variant *args[2] = { &cmd, &data }; Variant retval; Callable::CallError err; - c.call(args, 2, retval, err); + c.callp(args, 2, retval, err); ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(c, args, 2, err)); ERR_FAIL_COND_MSG(retval.get_type() != Variant::BOOL, "Error calling 'capture' to callable: " + String(c) + ". Return type is not bool."); parsed = retval; @@ -1877,7 +1876,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() { profiler = memnew(EditorProfiler); profiler->set_name(TTR("Profiler")); tabs->add_child(profiler); - profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_SCRIPTS_SERVERS)); + profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_SCRIPTS_SERVERS)); profiler->connect("break_request", callable_mp(this, &ScriptEditorDebugger::_profiler_seeked)); } @@ -1885,14 +1884,14 @@ ScriptEditorDebugger::ScriptEditorDebugger() { visual_profiler = memnew(EditorVisualProfiler); visual_profiler->set_name(TTR("Visual Profiler")); tabs->add_child(visual_profiler); - visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_VISUAL)); + visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_VISUAL)); } { //network profiler network_profiler = memnew(EditorNetworkProfiler); network_profiler->set_name(TTR("Network Profiler")); tabs->add_child(network_profiler); - network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_NETWORK)); + network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_NETWORK)); } { //monitors diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index aa03b7e252..43961a7ceb 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -37,6 +37,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/margin_container.h" void DependencyEditor::_searched(const String &p_path) { @@ -58,6 +59,9 @@ void DependencyEditor::_load_pressed(Object *p_item, int p_cell, int p_button, M search->set_title(TTR("Search Replacement For:") + " " + replacing.get_file()); + // Set directory to closest existing directory. + search->set_current_dir(replacing.get_base_dir()); + search->clear_filters(); List<String> ext; ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0), &ext); @@ -413,6 +417,45 @@ void DependencyRemoveDialog::_find_all_removed_dependencies(EditorFileSystemDire } } +void DependencyRemoveDialog::_find_localization_remaps_of_removed_files(Vector<RemovedDependency> &p_removed) { + for (KeyValue<String, String> &files : all_remove_files) { + const String &path = files.key; + + // Look for dependencies in the translation remaps. + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { + Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); + + if (remaps.has(path)) { + RemovedDependency dep; + dep.file = TTR("Localization remap"); + dep.file_type = ""; + dep.dependency = path; + dep.dependency_folder = files.value; + p_removed.push_back(dep); + } + + Array remap_keys = remaps.keys(); + for (int j = 0; j < remap_keys.size(); j++) { + PackedStringArray remapped_files = remaps[remap_keys[j]]; + for (int k = 0; k < remapped_files.size(); k++) { + int splitter_pos = remapped_files[k].rfind(":"); + String res_path = remapped_files[k].substr(0, splitter_pos); + if (res_path == path) { + String locale_name = remapped_files[k].substr(splitter_pos + 1); + + RemovedDependency dep; + dep.file = vformat(TTR("Localization remap for path '%s' and locale '%s'."), remap_keys[j], locale_name); + dep.file_type = ""; + dep.dependency = path; + dep.dependency_folder = files.value; + p_removed.push_back(dep); + } + } + } + } + } +} + void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed) { owners->clear(); owners->create_item(); // root @@ -469,6 +512,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector< Vector<RemovedDependency> removed_deps; _find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps); + _find_localization_remaps_of_removed_files(removed_deps); removed_deps.sort(); if (removed_deps.is_empty()) { owners->hide(); diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h index 96d82d58eb..6e39015ec3 100644 --- a/editor/dependency_editor.h +++ b/editor/dependency_editor.h @@ -119,6 +119,7 @@ class DependencyRemoveDialog : public ConfirmationDialog { void _find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder); void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed); + void _find_localization_remaps_of_removed_files(Vector<RemovedDependency> &p_removed); void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed); void ok_pressed() override; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index a6c7970264..a819458417 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -39,6 +39,7 @@ #include "core/object/script_language.h" #include "core/string/translation.h" #include "core/version.h" +#include "editor/editor_settings.h" #include "scene/resources/theme.h" // Used for a hack preserving Mono properties on non-Mono builds. @@ -363,8 +364,15 @@ void DocTools::generate(bool p_basic_types) { List<PropertyInfo> properties; List<PropertyInfo> own_properties; - if (name == "ProjectSettings") { - // Special case for project settings, so settings can be documented. + + // Special case for editor and project settings, so they can be documented. + if (name == "EditorSettings") { + // We don't create the full blown EditorSettings (+ config file) with `create()`, + // instead we just make a local instance to get default values. + Ref<EditorSettings> edset = memnew(EditorSettings); + edset->get_property_list(&properties); + own_properties = properties; + } else if (name == "ProjectSettings") { ProjectSettings::get_singleton()->get_property_list(&properties); own_properties = properties; } else { @@ -402,6 +410,13 @@ void DocTools::generate(bool p_basic_types) { bool default_value_valid = false; Variant default_value; + if (name == "EditorSettings") { + if (E.name == "resource_local_to_scene" || E.name == "resource_name" || E.name == "resource_path" || E.name == "script") { + // Don't include spurious properties in the generated EditorSettings class reference. + continue; + } + } + if (name == "ProjectSettings") { // Special case for project settings, so that settings are not taken from the current project's settings if (E.name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E.name)) { @@ -424,8 +439,6 @@ void DocTools::generate(bool p_basic_types) { } } - //used to track uninitialized values using valgrind - //print_line("getting default value for " + String(name) + "." + String(E.name)); if (default_value_valid && default_value.get_type() != Variant::OBJECT) { prop.default_value = default_value.get_construct_string().replace("\n", " "); } @@ -498,53 +511,7 @@ void DocTools::generate(bool p_basic_types) { } DocData::MethodDoc method; - - method.name = E.name; - - if (E.flags & METHOD_FLAG_VIRTUAL) { - method.qualifiers = "virtual"; - } - - if (E.flags & METHOD_FLAG_CONST) { - if (!method.qualifiers.is_empty()) { - method.qualifiers += " "; - } - method.qualifiers += "const"; - } - - if (E.flags & METHOD_FLAG_VARARG) { - if (!method.qualifiers.is_empty()) { - method.qualifiers += " "; - } - method.qualifiers += "vararg"; - } - - if (E.flags & METHOD_FLAG_STATIC) { - if (!method.qualifiers.is_empty()) { - method.qualifiers += " "; - } - method.qualifiers += "static"; - } - - for (int i = -1; i < E.arguments.size(); i++) { - if (i == -1) { -#ifdef DEBUG_METHODS_ENABLED - DocData::return_doc_from_retinfo(method, E.return_val); -#endif - } else { - const PropertyInfo &arginfo = E.arguments[i]; - DocData::ArgumentDoc argument; - DocData::argument_doc_from_arginfo(argument, arginfo); - - int darg_idx = i - (E.arguments.size() - E.default_arguments.size()); - if (darg_idx >= 0) { - Variant default_arg = E.default_arguments[darg_idx]; - argument.default_value = default_arg.get_construct_string().replace("\n", " "); - } - - method.arguments.push_back(argument); - } - } + DocData::method_doc_from_methodinfo(method, E, ""); Vector<Error> errs = ClassDB::get_method_error_return_values(name, E.name); if (errs.size()) { diff --git a/editor/doc_tools.h b/editor/doc_tools.h index 843cdf87a6..b3e45c6472 100644 --- a/editor/doc_tools.h +++ b/editor/doc_tools.h @@ -53,4 +53,4 @@ public: Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size); }; -#endif // DOC_DATA_H +#endif // DOC_TOOLS_H diff --git a/editor/editor_about.h b/editor/editor_about.h index 6f05700582..971843f6d2 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -75,4 +75,4 @@ public: ~EditorAbout(); }; -#endif +#endif // EDITOR_ABOUT_H diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 3d4bee4b4e..8dc8a0ab6b 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -100,8 +100,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { extension_guess["tga"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")); extension_guess["webp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")); - extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamSample"), SNAME("EditorIcons")); - extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOGGVorbis"), SNAME("EditorIcons")); + extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamWAV"), SNAME("EditorIcons")); + extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOggVorbis"), SNAME("EditorIcons")); extension_guess["mp3"] = tree->get_theme_icon(SNAME("AudioStreamMP3"), SNAME("EditorIcons")); extension_guess["scn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); @@ -112,6 +112,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { extension_guess["glb"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); extension_guess["gdshader"] = tree->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")); + extension_guess["gdshaderinc"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")); extension_guess["gd"] = tree->get_theme_icon(SNAME("GDScript"), SNAME("EditorIcons")); if (Engine::get_singleton()->has_singleton("GodotSharp")) { extension_guess["cs"] = tree->get_theme_icon(SNAME("CSharpScript"), SNAME("EditorIcons")); diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index c44f4c5d22..9c88116336 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORASSETINSTALLER_H -#define EDITORASSETINSTALLER_H +#ifndef EDITOR_ASSET_INSTALLER_H +#define EDITOR_ASSET_INSTALLER_H #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" @@ -59,4 +59,4 @@ public: EditorAssetInstaller(); }; -#endif // EDITORASSETINSTALLER_H +#endif // EDITOR_ASSET_INSTALLER_H diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index fa365c4368..b6d7bbc45f 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -37,6 +37,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "filesystem_dock.h" #include "scene/resources/font.h" #include "servers/audio_server.h" @@ -1007,11 +1008,11 @@ void EditorAudioBuses::_update_buses() { bool is_master = (i == 0); EditorAudioBus *audio_bus = memnew(EditorAudioBus(this, is_master)); bus_hb->add_child(audio_bus); - audio_bus->connect("delete_request", callable_mp(this, &EditorAudioBuses::_delete_bus), varray(audio_bus), CONNECT_DEFERRED); - audio_bus->connect("duplicate_request", callable_mp(this, &EditorAudioBuses::_duplicate_bus), varray(), CONNECT_DEFERRED); - audio_bus->connect("vol_reset_request", callable_mp(this, &EditorAudioBuses::_reset_bus_volume), varray(audio_bus), CONNECT_DEFERRED); + audio_bus->connect("delete_request", callable_mp(this, &EditorAudioBuses::_delete_bus).bind(audio_bus), CONNECT_DEFERRED); + audio_bus->connect("duplicate_request", callable_mp(this, &EditorAudioBuses::_duplicate_bus), CONNECT_DEFERRED); + audio_bus->connect("vol_reset_request", callable_mp(this, &EditorAudioBuses::_reset_bus_volume).bind(audio_bus), CONNECT_DEFERRED); audio_bus->connect("drop_end_request", callable_mp(this, &EditorAudioBuses::_request_drop_end)); - audio_bus->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), varray(), CONNECT_DEFERRED); + audio_bus->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED); } } @@ -1154,7 +1155,7 @@ void EditorAudioBuses::_request_drop_end() { bus_hb->add_child(drop_end); drop_end->set_custom_minimum_size(Object::cast_to<Control>(bus_hb->get_child(0))->get_size()); - drop_end->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), varray(), CONNECT_DEFERRED); + drop_end->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED); } } @@ -1174,7 +1175,7 @@ void EditorAudioBuses::_drop_at_index(int p_bus, int p_index) { void EditorAudioBuses::_server_save() { Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout(); - ResourceSaver::save(edited_path, state); + ResourceSaver::save(state, edited_path); } void EditorAudioBuses::_select_layout() { @@ -1244,7 +1245,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) { AudioServer::get_singleton()->set_bus_layout(empty_state); } - Error err = ResourceSaver::save(p_string, AudioServer::get_singleton()->generate_bus_layout()); + Error err = ResourceSaver::save(AudioServer::get_singleton()->generate_bus_layout(), p_string); if (err != OK) { EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_string)); diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index e1e0bb0a64..0eda7016d3 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -112,4 +112,4 @@ public: ~EditorAutoloadSettings(); }; -#endif +#endif // EDITOR_AUTOLOAD_SETTINGS_H diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp new file mode 100644 index 0000000000..0f0ab4a339 --- /dev/null +++ b/editor/editor_build_profile.cpp @@ -0,0 +1,899 @@ +/*************************************************************************/ +/* editor_build_profile.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_build_profile.h" + +#include "core/io/dir_access.h" +#include "core/io/json.h" +#include "editor/editor_file_dialog.h" +#include "editor/editor_file_system.h" +#include "editor/editor_node.h" +#include "editor/editor_property_name_processor.h" +#include "editor/editor_scale.h" +#include "editor/editor_settings.h" + +const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = { + // This maps to SCons build options. + "disable_3d", + "disable_2d_physics", + "disable_3d_physics", + "disable_navigation", + "openxr", + "rendering_device", // FIXME: there's no scons option to disable rendering device + "opengl3", + "vulkan", + "module_text_server_fb_enabled", + "module_text_server_adv_enabled", + "module_freetype_enabled", + "brotli", + "graphite", + "module_msdfgen_enabled" +}; + +const bool EditorBuildProfile::build_option_disabled_by_default[BUILD_OPTION_MAX] = { + // This maps to SCons build options. + false, // 3D + false, // PHYSICS_2D + false, // PHYSICS_3D + false, // NAVIGATION + false, // XR + false, // RENDERING_DEVICE + false, // OPENGL + false, // VULKAN + true, // TEXT_SERVER_FALLBACK + false, // TEXT_SERVER_COMPLEX + false, // DYNAMIC_FONTS + false, // WOFF2_FONTS + false, // GRPAHITE_FONTS + false, // MSDFGEN +}; + +const bool EditorBuildProfile::build_option_disable_values[BUILD_OPTION_MAX] = { + // This maps to SCons build options. + true, // 3D + true, // PHYSICS_2D + true, // PHYSICS_3D + true, // NAVIGATION + false, // XR + false, // RENDERING_DEVICE + false, // OPENGL + false, // VULKAN + false, // TEXT_SERVER_FALLBACK + false, // TEXT_SERVER_COMPLEX + false, // DYNAMIC_FONTS + false, // WOFF2_FONTS + false, // GRPAHITE_FONTS + false, // MSDFGEN +}; + +const EditorBuildProfile::BuildOptionCategory EditorBuildProfile::build_option_category[BUILD_OPTION_MAX] = { + BUILD_OPTION_CATEGORY_GENERAL, // 3D + BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_2D + BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_3D + BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION + BUILD_OPTION_CATEGORY_GENERAL, // XR + BUILD_OPTION_CATEGORY_GENERAL, // RENDERING_DEVICE + BUILD_OPTION_CATEGORY_GENERAL, // OPENGL + BUILD_OPTION_CATEGORY_GENERAL, // VULKAN + BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_FALLBACK + BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_COMPLEX + BUILD_OPTION_CATEGORY_TEXT_SERVER, // DYNAMIC_FONTS + BUILD_OPTION_CATEGORY_TEXT_SERVER, // WOFF2_FONTS + BUILD_OPTION_CATEGORY_TEXT_SERVER, // GRPAHITE_FONTS + BUILD_OPTION_CATEGORY_TEXT_SERVER, // MSDFGEN +}; + +void EditorBuildProfile::set_disable_class(const StringName &p_class, bool p_disabled) { + if (p_disabled) { + disabled_classes.insert(p_class); + } else { + disabled_classes.erase(p_class); + } +} + +bool EditorBuildProfile::is_class_disabled(const StringName &p_class) const { + if (p_class == StringName()) { + return false; + } + return disabled_classes.has(p_class) || is_class_disabled(ClassDB::get_parent_class_nocheck(p_class)); +} + +void EditorBuildProfile::set_item_collapsed(const StringName &p_class, bool p_collapsed) { + if (p_collapsed) { + collapsed_classes.insert(p_class); + } else { + collapsed_classes.erase(p_class); + } +} + +bool EditorBuildProfile::is_item_collapsed(const StringName &p_class) const { + return collapsed_classes.has(p_class); +} + +void EditorBuildProfile::set_disable_build_option(BuildOption p_build_option, bool p_disable) { + ERR_FAIL_INDEX(p_build_option, BUILD_OPTION_MAX); + build_options_disabled[p_build_option] = p_disable; +} + +void EditorBuildProfile::clear_disabled_classes() { + disabled_classes.clear(); + collapsed_classes.clear(); +} + +bool EditorBuildProfile::is_build_option_disabled(BuildOption p_build_option) const { + ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, false); + return build_options_disabled[p_build_option]; +} + +bool EditorBuildProfile::get_build_option_disable_value(BuildOption p_build_option) { + ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, false); + return build_option_disable_values[p_build_option]; +} + +void EditorBuildProfile::set_force_detect_classes(const String &p_classes) { + force_detect_classes = p_classes; +} + +String EditorBuildProfile::get_force_detect_classes() const { + return force_detect_classes; +} + +String EditorBuildProfile::get_build_option_name(BuildOption p_build_option) { + ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String()); + const char *build_option_names[BUILD_OPTION_MAX] = { + TTRC("3D Engine"), + TTRC("2D Physics"), + TTRC("3D Physics"), + TTRC("Navigation"), + TTRC("XR"), + TTRC("RenderingDevice"), + TTRC("OpenGL"), + TTRC("Vulkan"), + TTRC("Text Server: Fallback"), + TTRC("Text Server: Advanced"), + TTRC("TTF, OTF, Type 1, WOFF1 Fonts"), + TTRC("WOFF2 Fonts"), + TTRC("SIL Graphite Fonts"), + TTRC("Multi-channel Signed Distance Field Font Rendering"), + }; + return TTRGET(build_option_names[p_build_option]); +} + +String EditorBuildProfile::get_build_option_description(BuildOption p_build_option) { + ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String()); + + const char *build_option_descriptions[BUILD_OPTION_MAX] = { + TTRC("3D Nodes as well as RenderingServer access to 3D features."), + TTRC("2D Physics nodes and PhysicsServer2D."), + TTRC("3D Physics nodes and PhysicsServer3D."), + TTRC("Navigation, both 2D and 3D."), + TTRC("XR (AR and VR)."), + TTRC("RenderingDevice based rendering (if disabled, the OpenGL back-end is required)."), + TTRC("OpenGL back-end (if disabled, the RenderingDevice back-end is required)."), + TTRC("Vulkan back-end of RenderingDevice."), + TTRC("Fallback implementation of Text Server\nSupports basic text layouts."), + TTRC("Text Server implementation powered by ICU and HarfBuzz libraries.\nSupports complex text layouts, BiDi, and contextual OpenType font features."), + TTRC("TrueType, OpenType, Type 1, and WOFF1 font format support using FreeType library (if disabled, WOFF2 support is also disabled)."), + TTRC("WOFF2 font format support using FreeType and Brotli libraries."), + TTRC("SIL Graphite smart font technology support (supported by Advanced Text Server only)."), + TTRC("Multi-channel signed distance field font rendering support using msdfgen library (pre-rendered MSDF fonts can be used even if this option disabled)."), + }; + + return TTRGET(build_option_descriptions[p_build_option]); +} + +EditorBuildProfile::BuildOptionCategory EditorBuildProfile::get_build_option_category(BuildOption p_build_option) { + ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, BUILD_OPTION_CATEGORY_GENERAL); + return build_option_category[p_build_option]; +} + +String EditorBuildProfile::get_build_option_category_name(BuildOptionCategory p_build_option_category) { + ERR_FAIL_INDEX_V(p_build_option_category, BUILD_OPTION_CATEGORY_MAX, String()); + + const char *build_option_subcategories[BUILD_OPTION_CATEGORY_MAX]{ + TTRC("General Features:"), + TTRC("Text Rendering and Font Options:"), + }; + + return TTRGET(build_option_subcategories[p_build_option_category]); +} + +Error EditorBuildProfile::save_to_file(const String &p_path) { + Dictionary data; + data["type"] = "build_profile"; + Array dis_classes; + for (const StringName &E : disabled_classes) { + dis_classes.push_back(String(E)); + } + dis_classes.sort(); + data["disabled_classes"] = dis_classes; + + Dictionary dis_build_options; + for (int i = 0; i < BUILD_OPTION_MAX; i++) { + if (build_options_disabled[i] != build_option_disabled_by_default[i]) { + if (build_options_disabled[i]) { + dis_build_options[build_option_identifiers[i]] = build_option_disable_values[i]; + } else { + dis_build_options[build_option_identifiers[i]] = !build_option_disable_values[i]; + } + } + } + + data["disabled_build_options"] = dis_build_options; + + if (!force_detect_classes.is_empty()) { + data["force_detect_classes"] = force_detect_classes; + } + + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); + + JSON json; + String text = json.stringify(data, "\t"); + f->store_string(text); + return OK; +} + +Error EditorBuildProfile::load_from_file(const String &p_path) { + Error err; + String text = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) { + return err; + } + + JSON json; + err = json.parse(text); + if (err != OK) { + ERR_PRINT("Error parsing '" + p_path + "' on line " + itos(json.get_error_line()) + ": " + json.get_error_message()); + return ERR_PARSE_ERROR; + } + + Dictionary data = json.get_data(); + + if (!data.has("type") || String(data["type"]) != "build_profile") { + ERR_PRINT("Error parsing '" + p_path + "', it's not a build profile."); + return ERR_PARSE_ERROR; + } + + disabled_classes.clear(); + + if (data.has("disabled_classes")) { + Array disabled_classes_arr = data["disabled_classes"]; + for (int i = 0; i < disabled_classes_arr.size(); i++) { + disabled_classes.insert(disabled_classes_arr[i]); + } + } + + for (int i = 0; i < BUILD_OPTION_MAX; i++) { + build_options_disabled[i] = build_option_disabled_by_default[i]; + } + + if (data.has("disabled_build_options")) { + Dictionary disabled_build_options_arr = data["disabled_build_options"]; + List<Variant> keys; + disabled_build_options_arr.get_key_list(&keys); + + for (const Variant &K : keys) { + String key = K; + + for (int i = 0; i < BUILD_OPTION_MAX; i++) { + String f = build_option_identifiers[i]; + if (f == key) { + build_options_disabled[i] = true; + break; + } + } + } + } + + if (data.has("force_detect_classes")) { + force_detect_classes = data["force_detect_classes"]; + } + + return OK; +} + +void EditorBuildProfile::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_disable_class", "class_name", "disable"), &EditorBuildProfile::set_disable_class); + ClassDB::bind_method(D_METHOD("is_class_disabled", "class_name"), &EditorBuildProfile::is_class_disabled); + + ClassDB::bind_method(D_METHOD("set_disable_build_option", "build_option", "disable"), &EditorBuildProfile::set_disable_build_option); + ClassDB::bind_method(D_METHOD("is_build_option_disabled", "build_option"), &EditorBuildProfile::is_build_option_disabled); + + ClassDB::bind_method(D_METHOD("get_build_option_name", "build_option"), &EditorBuildProfile::_get_build_option_name); + + ClassDB::bind_method(D_METHOD("save_to_file", "path"), &EditorBuildProfile::save_to_file); + ClassDB::bind_method(D_METHOD("load_from_file", "path"), &EditorBuildProfile::load_from_file); + + BIND_ENUM_CONSTANT(BUILD_OPTION_3D); + BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_2D); + BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_3D); + BIND_ENUM_CONSTANT(BUILD_OPTION_NAVIGATION); + BIND_ENUM_CONSTANT(BUILD_OPTION_XR); + BIND_ENUM_CONSTANT(BUILD_OPTION_RENDERING_DEVICE); + BIND_ENUM_CONSTANT(BUILD_OPTION_OPENGL); + BIND_ENUM_CONSTANT(BUILD_OPTION_VULKAN); + BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_FALLBACK); + BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_ADVANCED); + BIND_ENUM_CONSTANT(BUILD_OPTION_DYNAMIC_FONTS); + BIND_ENUM_CONSTANT(BUILD_OPTION_WOFF2_FONTS); + BIND_ENUM_CONSTANT(BUILD_OPTION_GRPAHITE_FONTS); + BIND_ENUM_CONSTANT(BUILD_OPTION_MSDFGEN); + BIND_ENUM_CONSTANT(BUILD_OPTION_MAX); + + BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_GENERAL); + BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_TEXT_SERVER); + BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_MAX); +} + +EditorBuildProfile::EditorBuildProfile() { + for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) { + build_options_disabled[i] = build_option_disabled_by_default[i]; + } +} + +////////////////////////// + +void EditorBuildProfileManager::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + String last_file = EditorSettings::get_singleton()->get_project_metadata("build_profile", "last_file_path", ""); + if (!last_file.is_empty()) { + _import_profile(last_file); + } + if (edited.is_null()) { + edited.instantiate(); + _update_edited_profile(); + } + + } break; + } +} + +void EditorBuildProfileManager::_profile_action(int p_action) { + last_action = Action(p_action); + + switch (p_action) { + case ACTION_RESET: { + confirm_dialog->set_text("Reset the edited profile?"); + confirm_dialog->popup_centered(); + } break; + case ACTION_LOAD: { + import_profile->popup_file_dialog(); + } break; + case ACTION_SAVE: { + if (!profile_path->get_text().is_empty()) { + Error err = edited->save_to_file(profile_path->get_text()); + if (err != OK) { + EditorNode::get_singleton()->show_warning(TTR("File saving failed.")); + } + break; + } + [[fallthrough]]; + } + case ACTION_SAVE_AS: { + export_profile->popup_file_dialog(); + export_profile->set_current_file(profile_path->get_text()); + } break; + case ACTION_NEW: { + confirm_dialog->set_text("Create a new profile?"); + confirm_dialog->popup_centered(); + } break; + case ACTION_DETECT: { + confirm_dialog->set_text("This will scan all files in the current project to detect used classes."); + confirm_dialog->popup_centered(); + } break; + case ACTION_MAX: { + } break; + } +} + +void EditorBuildProfileManager::_find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected) { + if (p_dir == nullptr) { + return; + } + + for (int i = 0; i < p_dir->get_file_count(); i++) { + String p = p_dir->get_file_path(i); + + uint64_t timestamp = 0; + String md5; + + if (p_cache.has(p)) { + const DetectedFile &cache = p_cache[p]; + // Check if timestamp and MD5 match. + timestamp = FileAccess::get_modified_time(p); + bool cache_valid = true; + if (cache.timestamp != timestamp) { + md5 = FileAccess::get_md5(p); + if (md5 != cache.md5) { + cache_valid = false; + } + } + + if (cache_valid) { + r_detected.insert(p, cache); + continue; + } + } + + // Not cached, or cache invalid. + + DetectedFile cache; + + HashSet<StringName> classes; + ResourceLoader::get_classes_used(p, &classes); + + for (const StringName &E : classes) { + cache.classes.push_back(E); + } + + if (md5.is_empty()) { + cache.timestamp = FileAccess::get_modified_time(p); + cache.md5 = FileAccess::get_md5(p); + } else { + cache.timestamp = timestamp; + cache.md5 = md5; + } + + r_detected.insert(p, cache); + } + + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _find_files(p_dir->get_subdir(i), p_cache, r_detected); + } +} + +void EditorBuildProfileManager::_detect_classes() { + HashMap<String, DetectedFile> previous_file_cache; + + Ref<FileAccess> f = FileAccess::open("res://.godot/editor/used_class_cache", FileAccess::READ); + if (f.is_valid()) { + while (!f->eof_reached()) { + String l = f->get_line(); + Vector<String> fields = l.split("::"); + if (fields.size() == 4) { + String path = fields[0]; + DetectedFile df; + df.timestamp = fields[1].to_int(); + df.md5 = fields[2]; + df.classes = fields[3].split(","); + previous_file_cache.insert(path, df); + } + } + f.unref(); + } + + HashMap<String, DetectedFile> updated_file_cache; + + _find_files(EditorFileSystem::get_singleton()->get_filesystem(), previous_file_cache, updated_file_cache); + + HashSet<StringName> used_classes; + + // Find classes and update the disk cache in the process. + f = FileAccess::open("res://.godot/editor/used_class_cache", FileAccess::WRITE); + + for (const KeyValue<String, DetectedFile> &E : updated_file_cache) { + String l = E.key + "::" + itos(E.value.timestamp) + "::" + E.value.md5 + "::"; + for (int i = 0; i < E.value.classes.size(); i++) { + String c = E.value.classes[i]; + if (i > 0) { + l += ","; + } + l += c; + used_classes.insert(c); + } + f->store_line(l); + } + + f.unref(); + + // Add forced ones. + + Vector<String> force_detect = edited->get_force_detect_classes().split(","); + for (int i = 0; i < force_detect.size(); i++) { + String c = force_detect[i].strip_edges(); + if (c.is_empty()) { + continue; + } + used_classes.insert(c); + } + + // Filter all classes to discard inherited ones. + + HashSet<StringName> all_used_classes; + + for (const StringName &E : used_classes) { + StringName c = E; + if (!ClassDB::class_exists(c)) { + // Maybe this is an old class that got replaced? try getting compat class. + c = ClassDB::get_compatibility_class(c); + if (!c) { + // No luck, skip. + continue; + } + } + while (c) { + all_used_classes.insert(c); + c = ClassDB::get_parent_class(c); + } + } + + edited->clear_disabled_classes(); + + List<StringName> all_classes; + ClassDB::get_class_list(&all_classes); + + for (const StringName &E : all_classes) { + if (all_used_classes.has(E)) { + // This class is valid, do nothing. + continue; + } + + StringName p = ClassDB::get_parent_class(E); + if (!p || all_used_classes.has(p)) { + // If no parent, or if the parent is enabled, then add to disabled classes. + // This way we avoid disabling redundant classes. + edited->set_disable_class(E, true); + } + } +} + +void EditorBuildProfileManager::_action_confirm() { + switch (last_action) { + case ACTION_RESET: { + edited.instantiate(); + _update_edited_profile(); + } break; + case ACTION_LOAD: { + } break; + case ACTION_SAVE: { + } break; + case ACTION_SAVE_AS: { + } break; + case ACTION_NEW: { + profile_path->set_text(""); + edited.instantiate(); + _update_edited_profile(); + } break; + case ACTION_DETECT: { + _detect_classes(); + _update_edited_profile(); + } break; + case ACTION_MAX: { + } break; + } +} + +void EditorBuildProfileManager::_fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected) { + TreeItem *class_item = class_list->create_item(p_parent); + class_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + class_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_class, "Node")); + String text = p_class; + + bool disabled = edited->is_class_disabled(p_class); + if (disabled) { + class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); + } + + class_item->set_text(0, text); + class_item->set_editable(0, true); + class_item->set_selectable(0, true); + class_item->set_metadata(0, p_class); + + bool collapsed = edited->is_item_collapsed(p_class); + class_item->set_collapsed(collapsed); + + if (p_class == p_selected) { + class_item->select(0); + } + if (disabled) { + // Class disabled, do nothing else (do not show further). + return; + } + + class_item->set_checked(0, true); // If it's not disabled, its checked. + + List<StringName> child_classes; + ClassDB::get_direct_inheriters_from_class(p_class, &child_classes); + child_classes.sort_custom<StringName::AlphCompare>(); + + for (const StringName &name : child_classes) { + if (String(name).begins_with("Editor") || ClassDB::get_api_type(name) != ClassDB::API_CORE) { + continue; + } + _fill_classes_from(class_item, name, p_selected); + } +} + +void EditorBuildProfileManager::_class_list_item_selected() { + if (updating_build_options) { + return; + } + + TreeItem *item = class_list->get_selected(); + if (!item) { + return; + } + + Variant md = item->get_metadata(0); + if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) { + String class_name = md; + String class_description; + + DocTools *dd = EditorHelp::get_doc_data(); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(class_name); + if (E) { + class_description = DTR(E->value.brief_description); + } + + description_bit->set_text(class_description); + } else if (md.get_type() == Variant::INT) { + int build_option_id = md; + String build_option_description = EditorBuildProfile::get_build_option_description(EditorBuildProfile::BuildOption(build_option_id)); + + description_bit->set_text(TTRGET(build_option_description)); + return; + } else { + return; + } +} + +void EditorBuildProfileManager::_class_list_item_edited() { + if (updating_build_options) { + return; + } + + TreeItem *item = class_list->get_edited(); + if (!item) { + return; + } + + bool checked = item->is_checked(0); + + Variant md = item->get_metadata(0); + if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) { + String class_selected = md; + edited->set_disable_class(class_selected, !checked); + _update_edited_profile(); + } else if (md.get_type() == Variant::INT) { + int build_option_selected = md; + edited->set_disable_build_option(EditorBuildProfile::BuildOption(build_option_selected), !checked); + } +} + +void EditorBuildProfileManager::_class_list_item_collapsed(Object *p_item) { + if (updating_build_options) { + return; + } + + TreeItem *item = Object::cast_to<TreeItem>(p_item); + if (!item) { + return; + } + + Variant md = item->get_metadata(0); + if (md.get_type() != Variant::STRING && md.get_type() != Variant::STRING_NAME) { + return; + } + + String class_name = md; + bool collapsed = item->is_collapsed(); + edited->set_item_collapsed(class_name, collapsed); +} + +void EditorBuildProfileManager::_update_edited_profile() { + String class_selected; + int build_option_selected = -1; + + if (class_list->get_selected()) { + Variant md = class_list->get_selected()->get_metadata(0); + if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) { + class_selected = md; + } else if (md.get_type() == Variant::INT) { + build_option_selected = md; + } + } + + class_list->clear(); + + updating_build_options = true; + + TreeItem *root = class_list->create_item(); + + HashMap<EditorBuildProfile::BuildOptionCategory, TreeItem *> subcats; + for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_CATEGORY_MAX; i++) { + TreeItem *build_cat; + build_cat = class_list->create_item(root); + + build_cat->set_text(0, EditorBuildProfile::get_build_option_category_name(EditorBuildProfile::BuildOptionCategory(i))); + subcats[EditorBuildProfile::BuildOptionCategory(i)] = build_cat; + } + + for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) { + TreeItem *build_option; + build_option = class_list->create_item(subcats[EditorBuildProfile::get_build_option_category(EditorBuildProfile::BuildOption(i))]); + + build_option->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + build_option->set_text(0, EditorBuildProfile::get_build_option_name(EditorBuildProfile::BuildOption(i))); + build_option->set_selectable(0, true); + build_option->set_editable(0, true); + build_option->set_metadata(0, i); + if (!edited->is_build_option_disabled(EditorBuildProfile::BuildOption(i))) { + build_option->set_checked(0, true); + } + + if (i == build_option_selected) { + build_option->select(0); + } + } + + TreeItem *classes = class_list->create_item(root); + classes->set_text(0, TTR("Nodes and Classes:")); + + _fill_classes_from(classes, "Node", class_selected); + _fill_classes_from(classes, "Resource", class_selected); + + force_detect_classes->set_text(edited->get_force_detect_classes()); + + updating_build_options = false; + + _class_list_item_selected(); +} + +void EditorBuildProfileManager::_force_detect_classes_changed(const String &p_text) { + if (updating_build_options) { + return; + } + edited->set_force_detect_classes(force_detect_classes->get_text()); +} + +void EditorBuildProfileManager::_import_profile(const String &p_path) { + Ref<EditorBuildProfile> profile; + profile.instantiate(); + Error err = profile->load_from_file(p_path); + String basefile = p_path.get_file(); + if (err != OK) { + EditorNode::get_singleton()->show_warning(vformat(TTR("File '%s' format is invalid, import aborted."), basefile)); + return; + } + + profile_path->set_text(p_path); + EditorSettings::get_singleton()->set_project_metadata("build_profile", "last_file_path", p_path); + + edited = profile; + _update_edited_profile(); +} + +void EditorBuildProfileManager::_export_profile(const String &p_path) { + ERR_FAIL_COND(edited.is_null()); + Error err = edited->save_to_file(p_path); + if (err != OK) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving profile to path: '%s'."), p_path)); + } else { + profile_path->set_text(p_path); + EditorSettings::get_singleton()->set_project_metadata("build_profile", "last_file_path", p_path); + } +} + +Ref<EditorBuildProfile> EditorBuildProfileManager::get_current_profile() { + return edited; +} + +EditorBuildProfileManager *EditorBuildProfileManager::singleton = nullptr; + +void EditorBuildProfileManager::_bind_methods() { + ClassDB::bind_method("_update_selected_profile", &EditorBuildProfileManager::_update_edited_profile); +} + +EditorBuildProfileManager::EditorBuildProfileManager() { + VBoxContainer *main_vbc = memnew(VBoxContainer); + add_child(main_vbc); + + HBoxContainer *path_hbc = memnew(HBoxContainer); + profile_path = memnew(LineEdit); + path_hbc->add_child(profile_path); + profile_path->set_editable(true); + profile_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); + + profile_actions[ACTION_NEW] = memnew(Button(TTR("New"))); + path_hbc->add_child(profile_actions[ACTION_NEW]); + profile_actions[ACTION_NEW]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_NEW)); + + profile_actions[ACTION_LOAD] = memnew(Button(TTR("Load"))); + path_hbc->add_child(profile_actions[ACTION_LOAD]); + profile_actions[ACTION_LOAD]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_LOAD)); + + profile_actions[ACTION_SAVE] = memnew(Button(TTR("Save"))); + path_hbc->add_child(profile_actions[ACTION_SAVE]); + profile_actions[ACTION_SAVE]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_SAVE)); + + profile_actions[ACTION_SAVE_AS] = memnew(Button(TTR("Save As"))); + path_hbc->add_child(profile_actions[ACTION_SAVE_AS]); + profile_actions[ACTION_SAVE_AS]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_SAVE_AS)); + + main_vbc->add_margin_child(TTR("Profile:"), path_hbc); + + main_vbc->add_child(memnew(HSeparator)); + + HBoxContainer *profiles_hbc = memnew(HBoxContainer); + + profile_actions[ACTION_RESET] = memnew(Button(TTR("Reset to Defaults"))); + profiles_hbc->add_child(profile_actions[ACTION_RESET]); + profile_actions[ACTION_RESET]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_RESET)); + + profile_actions[ACTION_DETECT] = memnew(Button(TTR("Detect from Project"))); + profiles_hbc->add_child(profile_actions[ACTION_DETECT]); + profile_actions[ACTION_DETECT]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_DETECT)); + + main_vbc->add_margin_child(TTR("Actions:"), profiles_hbc); + + class_list = memnew(Tree); + class_list->set_hide_root(true); + class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); + class_list->connect("cell_selected", callable_mp(this, &EditorBuildProfileManager::_class_list_item_selected)); + class_list->connect("item_edited", callable_mp(this, &EditorBuildProfileManager::_class_list_item_edited), CONNECT_DEFERRED); + class_list->connect("item_collapsed", callable_mp(this, &EditorBuildProfileManager::_class_list_item_collapsed)); + // It will be displayed once the user creates or chooses a profile. + main_vbc->add_margin_child(TTR("Configure Engine Build Profile:"), class_list, true); + + description_bit = memnew(EditorHelpBit); + description_bit->set_custom_minimum_size(Size2(0, 80) * EDSCALE); + main_vbc->add_margin_child(TTR("Description:"), description_bit, false); + + confirm_dialog = memnew(ConfirmationDialog); + add_child(confirm_dialog); + confirm_dialog->set_title(TTR("Please Confirm:")); + confirm_dialog->connect("confirmed", callable_mp(this, &EditorBuildProfileManager::_action_confirm)); + + import_profile = memnew(EditorFileDialog); + add_child(import_profile); + import_profile->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + import_profile->add_filter("*.build", TTR("Egine Build Profile")); + import_profile->connect("files_selected", callable_mp(this, &EditorBuildProfileManager::_import_profile)); + import_profile->set_title(TTR("Load Profile")); + import_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + + export_profile = memnew(EditorFileDialog); + add_child(export_profile); + export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + export_profile->add_filter("*.build", TTR("Egine Build Profile")); + export_profile->connect("file_selected", callable_mp(this, &EditorBuildProfileManager::_export_profile)); + export_profile->set_title(TTR("Export Profile")); + export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + + force_detect_classes = memnew(LineEdit); + main_vbc->add_margin_child(TTR("Forced classes on detect:"), force_detect_classes); + force_detect_classes->connect("text_changed", callable_mp(this, &EditorBuildProfileManager::_force_detect_classes_changed)); + + set_title(TTR("Edit Build Configuration Profile")); + + singleton = this; +} diff --git a/editor/editor_build_profile.h b/editor/editor_build_profile.h new file mode 100644 index 0000000000..606c415429 --- /dev/null +++ b/editor/editor_build_profile.h @@ -0,0 +1,191 @@ +/*************************************************************************/ +/* editor_build_profile.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_BUILD_PROFILE_H +#define EDITOR_BUILD_PROFILE_H + +#include "core/io/file_access.h" +#include "core/object/ref_counted.h" +#include "editor/editor_help.h" +#include "scene/gui/dialogs.h" +#include "scene/gui/option_button.h" +#include "scene/gui/separator.h" +#include "scene/gui/split_container.h" +#include "scene/gui/tree.h" + +class EditorBuildProfile : public RefCounted { + GDCLASS(EditorBuildProfile, RefCounted); + +public: + enum BuildOption { + BUILD_OPTION_3D, + BUILD_OPTION_PHYSICS_2D, + BUILD_OPTION_PHYSICS_3D, + BUILD_OPTION_NAVIGATION, + BUILD_OPTION_XR, + BUILD_OPTION_RENDERING_DEVICE, + BUILD_OPTION_OPENGL, + BUILD_OPTION_VULKAN, + BUILD_OPTION_TEXT_SERVER_FALLBACK, + BUILD_OPTION_TEXT_SERVER_ADVANCED, + BUILD_OPTION_DYNAMIC_FONTS, + BUILD_OPTION_WOFF2_FONTS, + BUILD_OPTION_GRPAHITE_FONTS, + BUILD_OPTION_MSDFGEN, + BUILD_OPTION_MAX, + }; + + enum BuildOptionCategory { + BUILD_OPTION_CATEGORY_GENERAL, + BUILD_OPTION_CATEGORY_TEXT_SERVER, + BUILD_OPTION_CATEGORY_MAX, + }; + +private: + HashSet<StringName> disabled_classes; + + HashSet<StringName> collapsed_classes; + + String force_detect_classes; + + bool build_options_disabled[BUILD_OPTION_MAX] = {}; + static const char *build_option_identifiers[BUILD_OPTION_MAX]; + static const bool build_option_disabled_by_default[BUILD_OPTION_MAX]; + static const bool build_option_disable_values[BUILD_OPTION_MAX]; + static const BuildOptionCategory build_option_category[BUILD_OPTION_MAX]; + + String _get_build_option_name(BuildOption p_build_option) { return get_build_option_name(p_build_option); } + +protected: + static void _bind_methods(); + +public: + void set_disable_class(const StringName &p_class, bool p_disabled); + bool is_class_disabled(const StringName &p_class) const; + + void set_item_collapsed(const StringName &p_class, bool p_collapsed); + bool is_item_collapsed(const StringName &p_class) const; + + void set_disable_build_option(BuildOption p_build_option, bool p_disable); + bool is_build_option_disabled(BuildOption p_build_option) const; + + void set_force_detect_classes(const String &p_classes); + String get_force_detect_classes() const; + + void clear_disabled_classes(); + + Error save_to_file(const String &p_path); + Error load_from_file(const String &p_path); + + static String get_build_option_name(BuildOption p_build_option); + static String get_build_option_description(BuildOption p_build_option); + static bool get_build_option_disable_value(BuildOption p_build_option); + static BuildOptionCategory get_build_option_category(BuildOption p_build_option); + + static String get_build_option_category_name(BuildOptionCategory p_build_option_category); + + EditorBuildProfile(); +}; + +VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption) +VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory) + +class EditorFileSystemDirectory; + +class EditorBuildProfileManager : public AcceptDialog { + GDCLASS(EditorBuildProfileManager, AcceptDialog); + + enum Action { + ACTION_NEW, + ACTION_RESET, + ACTION_LOAD, + ACTION_SAVE, + ACTION_SAVE_AS, + ACTION_DETECT, + ACTION_MAX + }; + + Action last_action = ACTION_NEW; + + ConfirmationDialog *confirm_dialog = nullptr; + Button *profile_actions[ACTION_MAX]; + + Tree *class_list = nullptr; + EditorHelpBit *description_bit = nullptr; + + EditorFileDialog *import_profile = nullptr; + EditorFileDialog *export_profile = nullptr; + + LineEdit *profile_path = nullptr; + + LineEdit *force_detect_classes = nullptr; + + void _profile_action(int p_action); + void _action_confirm(); + + void _update_edited_profile(); + void _fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected); + + Ref<EditorBuildProfile> edited; + + void _import_profile(const String &p_path); + void _export_profile(const String &p_path); + + bool updating_build_options = false; + + void _class_list_item_selected(); + void _class_list_item_edited(); + void _class_list_item_collapsed(Object *p_item); + void _detect_classes(); + + void _force_detect_classes_changed(const String &p_text); + + struct DetectedFile { + uint32_t timestamp = 0; + String md5; + Vector<String> classes; + }; + + void _find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected); + + static EditorBuildProfileManager *singleton; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + Ref<EditorBuildProfile> get_current_profile(); + + static EditorBuildProfileManager *get_singleton() { return singleton; } + EditorBuildProfileManager(); +}; + +#endif // EDITOR_BUILD_PROFILE_H diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index c1cd7f9c7b..ba1f2fd6af 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -32,6 +32,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/control.h" #include "scene/gui/tree.h" @@ -199,7 +200,7 @@ void EditorCommandPalette::add_command(String p_command_name, String p_key_name, } Command command; command.name = p_command_name; - command.callable = p_action.bind(argptrs, arguments.size()); + command.callable = p_action.bindp(argptrs, arguments.size()); command.shortcut = p_shortcut_text; commands[p_key_name] = command; @@ -225,7 +226,7 @@ void EditorCommandPalette::_add_command(String p_command_name, String p_key_name void EditorCommandPalette::execute_command(String &p_command_key) { ERR_FAIL_COND_MSG(!commands.has(p_command_key), p_command_key + " not found."); commands[p_command_key].last_used = OS::get_singleton()->get_unix_time(); - commands[p_command_key].callable.call_deferred(nullptr, 0); + commands[p_command_key].callable.call_deferredp(nullptr, 0); _save_history(); } @@ -311,8 +312,8 @@ EditorCommandPalette::EditorCommandPalette() { search_options = memnew(Tree); search_options->connect("item_activated", callable_mp(this, &EditorCommandPalette::_confirmed)); - search_options->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(false)); - search_options->connect("nothing_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(true)); + search_options->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false)); + search_options->connect("nothing_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(true)); search_options->create_item(); search_options->set_hide_root(true); search_options->set_columns(2); diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h index 124703cca4..b3e84771d0 100644 --- a/editor/editor_command_palette.h +++ b/editor/editor_command_palette.h @@ -101,4 +101,4 @@ public: Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, Key p_keycode = Key::NONE, String p_command = ""); -#endif //EDITOR_COMMAND_PALETTE_H +#endif // EDITOR_COMMAND_PALETTE_H diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index e9e3320a3d..2d4945db14 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -1028,7 +1028,7 @@ void EditorSelection::add_node(Node *p_node) { } selection[p_node] = meta; - p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed), varray(p_node), CONNECT_ONESHOT); + p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONESHOT); } void EditorSelection::remove_node(Node *p_node) { diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index 4cbc0cf25d..4071722185 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -81,15 +81,15 @@ void EditorDirDialog::reload(const String &p_path) { void EditorDirDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload), make_binds("")); + EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind("")); reload(); if (!tree->is_connected("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed))) { - tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), varray(), CONNECT_DEFERRED); + tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), CONNECT_DEFERRED); } if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &EditorDirDialog::reload))) { - EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload), make_binds("")); + EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind("")); } } break; diff --git a/editor/editor_export.h b/editor/editor_export.h deleted file mode 100644 index 6f41736d2d..0000000000 --- a/editor/editor_export.h +++ /dev/null @@ -1,532 +0,0 @@ -/*************************************************************************/ -/* editor_export.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_H -#define EDITOR_EXPORT_H - -#include "core/io/dir_access.h" -#include "core/io/resource.h" -#include "scene/gui/rich_text_label.h" -#include "scene/main/node.h" -#include "scene/main/timer.h" -#include "scene/resources/texture.h" - -class FileAccess; -class EditorExportPlatform; -class EditorFileSystemDirectory; -struct EditorProgress; - -class EditorExportPreset : public RefCounted { - GDCLASS(EditorExportPreset, RefCounted); - -public: - enum ExportFilter { - EXPORT_ALL_RESOURCES, - EXPORT_SELECTED_SCENES, - EXPORT_SELECTED_RESOURCES, - EXCLUDE_SELECTED_RESOURCES, - }; - - enum ScriptExportMode { - MODE_SCRIPT_TEXT, - MODE_SCRIPT_COMPILED, - }; - -private: - Ref<EditorExportPlatform> platform; - ExportFilter export_filter = EXPORT_ALL_RESOURCES; - String include_filter; - String exclude_filter; - String export_path; - - String exporter; - HashSet<String> selected_files; - bool runnable = false; - - friend class EditorExport; - friend class EditorExportPlatform; - - List<PropertyInfo> properties; - HashMap<StringName, Variant> values; - - String name; - - 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; - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; - -public: - Ref<EditorExportPlatform> get_platform() const; - - bool has(const StringName &p_property) const { return values.has(p_property); } - - void update_files_to_export(); - - Vector<String> get_files_to_export() const; - - void add_export_file(const String &p_path); - void remove_export_file(const String &p_path); - bool has_export_file(const String &p_path); - - void set_name(const String &p_name); - String get_name() const; - - void set_runnable(bool p_enable); - bool is_runnable() const; - - void set_export_filter(ExportFilter p_filter); - ExportFilter get_export_filter() const; - - void set_include_filter(const String &p_include); - String get_include_filter() const; - - void set_exclude_filter(const String &p_exclude); - String get_exclude_filter() const; - - void set_custom_features(const String &p_custom_features); - String get_custom_features() const; - - 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; - - void set_script_encryption_key(const String &p_key); - String get_script_encryption_key() const; - - const List<PropertyInfo> &get_properties() const { return properties; } - - EditorExportPreset() {} -}; - -struct SharedObject { - String path; - Vector<String> tags; - String target; - - SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) : - path(p_path), - tags(p_tags), - target(p_target) { - } - - SharedObject() {} -}; - -class EditorExportPlatform : public RefCounted { - GDCLASS(EditorExportPlatform, RefCounted); - -public: - 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); - - enum ExportMessageType { - EXPORT_MESSAGE_NONE, - EXPORT_MESSAGE_INFO, - EXPORT_MESSAGE_WARNING, - EXPORT_MESSAGE_ERROR, - }; - - struct ExportMessage { - ExportMessageType msg_type; - String category; - String text; - }; - -private: - struct SavedData { - uint64_t ofs = 0; - uint64_t size = 0; - bool encrypted = false; - Vector<uint8_t> md5; - CharString path_utf8; - - bool operator<(const SavedData &p_data) const { - return path_utf8 < p_data.path_utf8; - } - }; - - struct PackData { - Ref<FileAccess> f; - Vector<SavedData> file_ofs; - EditorProgress *ep = nullptr; - Vector<SharedObject> *so_files = nullptr; - }; - - struct ZipData { - void *zip = nullptr; - EditorProgress *ep = nullptr; - }; - - struct FeatureContainers { - HashSet<String> features; - Vector<String> features_pv; - }; - - Vector<ExportMessage> messages; - - void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths); - void _export_find_dependencies(const String &p_path, HashSet<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, 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(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude); - void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude); - - static Error _add_shared_object(void *p_userdata, const SharedObject &p_so); - -protected: - struct ExportNotifier { - ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); - ~ExportNotifier(); - }; - - FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug); - - bool exists_export_template(String template_file_name, String *err) const; - String find_export_template(String template_file_name, String *err = nullptr) const; - void gen_export_flags(Vector<String> &r_flags, int p_flags); - -public: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) = 0; - - struct ExportOption { - PropertyInfo option; - Variant default_value; - - ExportOption(const PropertyInfo &p_info, const Variant &p_default) : - option(p_info), - default_value(p_default) { - } - ExportOption() {} - }; - - virtual Ref<EditorExportPreset> create_preset(); - - virtual void clear_messages() { messages.clear(); } - virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) { - ExportMessage msg; - msg.category = p_category; - msg.text = p_message; - msg.msg_type = p_type; - messages.push_back(msg); - switch (p_type) { - case EXPORT_MESSAGE_INFO: { - print_line(vformat("%s: %s\n", msg.category, msg.text)); - } break; - case EXPORT_MESSAGE_WARNING: { - WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text)); - } break; - case EXPORT_MESSAGE_ERROR: { - ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text)); - } break; - default: - break; - } - } - - virtual int get_message_count() const { - return messages.size(); - } - - virtual ExportMessage get_message(int p_index) const { - ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage()); - return messages[p_index]; - } - - virtual ExportMessageType get_worst_message_type() const { - ExportMessageType worst_type = EXPORT_MESSAGE_NONE; - for (int i = 0; i < messages.size(); i++) { - worst_type = MAX(worst_type, messages[i].msg_type); - } - return worst_type; - } - - virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err); - - virtual void get_export_options(List<ExportOption> *r_options) = 0; - virtual bool should_update_export_options() { return false; } - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } - - virtual String get_os_name() const = 0; - virtual String get_name() const = 0; - virtual Ref<Texture2D> get_logo() const = 0; - - Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); - - Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); - Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); - - virtual bool poll_export() { return false; } - virtual int get_options_count() const { return 0; } - virtual String get_options_tooltip() const { return ""; } - virtual Ref<ImageTexture> get_option_icon(int p_index) const; - virtual String get_option_label(int p_device) const { return ""; } - virtual String get_option_tooltip(int p_device) const { return ""; } - - enum DebugFlags { - DEBUG_FLAG_DUMB_CLIENT = 1, - DEBUG_FLAG_REMOTE_DEBUG = 2, - DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4, - DEBUG_FLAG_VIEW_COLLISONS = 8, - DEBUG_FLAG_VIEW_NAVIGATION = 16, - }; - - virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; } - virtual Ref<Texture2D> get_run_icon() const { return get_logo(); } - - String test_etc2() const; - virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0; - - virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0; - virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0; - virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - virtual void get_platform_features(List<String> *r_features) = 0; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0; - virtual String get_debug_protocol() const { return "tcp://"; } - - EditorExportPlatform(); -}; - -class EditorExportPlugin : public RefCounted { - GDCLASS(EditorExportPlugin, RefCounted); - - friend class EditorExportPlatform; - - Ref<EditorExportPreset> export_preset; - - Vector<SharedObject> shared_objects; - struct ExtraFile { - String path; - Vector<uint8_t> data; - bool remap = false; - }; - Vector<ExtraFile> extra_files; - bool skipped = false; - - Vector<String> ios_frameworks; - Vector<String> ios_embedded_frameworks; - Vector<String> ios_project_static_libs; - String ios_plist_content; - String ios_linker_flags; - Vector<String> ios_bundle_files; - String ios_cpp_code; - - Vector<String> osx_plugin_files; - - _FORCE_INLINE_ void _clear() { - shared_objects.clear(); - extra_files.clear(); - skipped = false; - } - - _FORCE_INLINE_ void _export_end() { - ios_frameworks.clear(); - ios_embedded_frameworks.clear(); - ios_bundle_files.clear(); - ios_plist_content = ""; - ios_linker_flags = ""; - ios_cpp_code = ""; - osx_plugin_files.clear(); - } - - void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features); - void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags); - void _export_end_script(); - -protected: - void set_export_preset(const Ref<EditorExportPreset> &p_preset); - Ref<EditorExportPreset> get_export_preset() const; - - void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap); - void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String()); - - void add_ios_framework(const String &p_path); - void add_ios_embedded_framework(const String &p_path); - void add_ios_project_static_lib(const String &p_path); - void add_ios_plist_content(const String &p_plist_content); - void add_ios_linker_flags(const String &p_flags); - void add_ios_bundle_file(const String &p_path); - void add_ios_cpp_code(const String &p_code); - void add_osx_plugin_file(const String &p_path); - - void skip(); - - virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features); - virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags); - - static void _bind_methods(); - - GDVIRTUAL3(_export_file, String, String, Vector<String>) - GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t) - GDVIRTUAL0(_export_end) - -public: - Vector<String> get_ios_frameworks() const; - Vector<String> get_ios_embedded_frameworks() const; - Vector<String> get_ios_project_static_libs() const; - String get_ios_plist_content() const; - String get_ios_linker_flags() const; - Vector<String> get_ios_bundle_files() const; - String get_ios_cpp_code() const; - const Vector<String> &get_osx_plugin_files() const; - - EditorExportPlugin(); -}; - -class EditorExport : public Node { - GDCLASS(EditorExport, Node); - - Vector<Ref<EditorExportPlatform>> export_platforms; - Vector<Ref<EditorExportPreset>> export_presets; - Vector<Ref<EditorExportPlugin>> export_plugins; - - StringName _export_presets_updated; - - Timer *save_timer = nullptr; - bool block_save = false; - - static EditorExport *singleton; - - void _save(); - -protected: - friend class EditorExportPreset; - void save_presets(); - - void _notification(int p_what); - static void _bind_methods(); - -public: - static EditorExport *get_singleton() { return singleton; } - - void add_export_platform(const Ref<EditorExportPlatform> &p_platform); - int get_export_platform_count(); - Ref<EditorExportPlatform> get_export_platform(int p_idx); - - void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1); - int get_export_preset_count() const; - Ref<EditorExportPreset> get_export_preset(int p_idx); - void remove_export_preset(int p_idx); - - void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin); - void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin); - Vector<Ref<EditorExportPlugin>> get_export_plugins(); - - void load_config(); - void update_export_presets(); - bool poll_export_platforms(); - - EditorExport(); - ~EditorExport(); -}; - -class EditorExportPlatformPC : public EditorExportPlatform { - GDCLASS(EditorExportPlatformPC, EditorExportPlatform); - -private: - Ref<ImageTexture> logo; - String name; - String os_name; - - int chmod_flags = -1; - -public: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; - - virtual void get_export_options(List<ExportOption> *r_options) override; - - virtual String get_name() const override; - virtual String get_os_name() const override; - virtual Ref<Texture2D> get_logo() const override; - - virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; - virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; - virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); - virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0; - - virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); - virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; }; - virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); - - void set_extension(const String &p_extension, const String &p_feature_key = "default"); - void set_name(const String &p_name); - void set_os_name(const String &p_name); - - void set_logo(const Ref<Texture2D> &p_logo); - - void add_platform_feature(const String &p_feature); - virtual void get_platform_features(List<String> *r_features) override; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override; - - int get_chmod_flags() const; - void set_chmod_flags(int p_flags); - - virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { - return Error::OK; - } -}; - -class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin { - GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin); - -public: - virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override; - EditorExportTextSceneToBinaryPlugin(); -}; - -#endif // EDITOR_IMPORT_EXPORT_H diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 9e2d56b2b9..f0bf9fd5b3 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -34,6 +34,7 @@ #include "core/io/json.h" #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_property_name_processor.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -314,7 +315,7 @@ void EditorFeatureProfileManager::_notification(int p_what) { current_profile = EDITOR_GET("_default_feature_profile"); if (!current_profile.is_empty()) { current.instantiate(); - Error err = current->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(current_profile + ".profile")); + Error err = current->load_from_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(current_profile + ".profile")); if (err != OK) { ERR_PRINT("Error loading default feature profile: " + current_profile); current_profile = String(); @@ -323,6 +324,11 @@ void EditorFeatureProfileManager::_notification(int p_what) { } _update_profile_list(current_profile); } break; + + case NOTIFICATION_THEME_CHANGED: { + // Make sure that the icons are correctly adjusted if the theme's lightness was switched. + _update_selected_profile(); + } break; } } @@ -340,7 +346,7 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr if (p_select_profile.is_empty()) { //default, keep if (profile_list->get_selected() >= 0) { selected_profile = profile_list->get_item_metadata(profile_list->get_selected()); - if (!FileAccess::exists(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(selected_profile + ".profile"))) { + if (!FileAccess::exists(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(selected_profile + ".profile"))) { selected_profile = String(); //does not exist } } @@ -349,8 +355,8 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr } Vector<String> profiles; - Ref<DirAccess> d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir()); - ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'."); + Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_feature_profiles_dir()); + ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorPaths::get_singleton()->get_feature_profiles_dir() + "'."); d->list_dir_begin(); while (true) { @@ -452,8 +458,8 @@ void EditorFeatureProfileManager::_profile_action(int p_action) { void EditorFeatureProfileManager::_erase_selected_profile() { String selected = _get_selected_profile(); ERR_FAIL_COND(selected.is_empty()); - Ref<DirAccess> da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir()); - ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'."); + Ref<DirAccess> da = DirAccess::open(EditorPaths::get_singleton()->get_feature_profiles_dir()); + ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorPaths::get_singleton()->get_feature_profiles_dir() + "'."); da->remove(selected + ".profile"); if (selected == current_profile) { @@ -469,7 +475,7 @@ void EditorFeatureProfileManager::_create_new_profile() { EditorNode::get_singleton()->show_warning(TTR("Profile must be a valid filename and must not contain '.'")); return; } - String file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(name + ".profile"); + String file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(name + ".profile"); if (FileAccess::exists(file)) { EditorNode::get_singleton()->show_warning(TTR("Profile with this name already exists.")); return; @@ -748,8 +754,8 @@ void EditorFeatureProfileManager::_update_selected_profile() { } else { //reload edited, if different from current edited.instantiate(); - Error err = edited->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile")); - ERR_FAIL_COND_MSG(err != OK, "Error when loading EditorSettings from file '" + EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile") + "'."); + Error err = edited->load_from_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile")); + ERR_FAIL_COND_MSG(err != OK, "Error when loading editor feature profile from file '" + EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile") + "'."); } updating_features = true; @@ -804,7 +810,7 @@ void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths return; } - String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile); + String dst_file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(basefile); if (FileAccess::exists(dst_file)) { EditorNode::get_singleton()->show_warning(vformat(TTR("Profile '%s' already exists. Remove it first before importing, import aborted."), basefile.get_basename())); @@ -819,7 +825,7 @@ void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths Error err = profile->load_from_file(p_paths[i]); ERR_CONTINUE(err != OK); String basefile = p_paths[i].get_file(); - String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile); + String dst_file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(basefile); profile->save_to_file(dst_file); } @@ -843,7 +849,7 @@ void EditorFeatureProfileManager::_save_and_update() { ERR_FAIL_COND(edited_path.is_empty()); ERR_FAIL_COND(edited.is_null()); - edited->save_to_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(edited_path + ".profile")); + edited->save_to_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(edited_path + ".profile")); if (edited == current) { update_timer->start(); @@ -883,7 +889,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Reset to Default"))); name_hbc->add_child(profile_actions[PROFILE_CLEAR]); profile_actions[PROFILE_CLEAR]->set_disabled(true); - profile_actions[PROFILE_CLEAR]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_CLEAR)); + profile_actions[PROFILE_CLEAR]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_CLEAR)); main_vbc->add_margin_child(TTR("Current Profile:"), name_hbc); @@ -897,12 +903,12 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { profile_actions[PROFILE_NEW] = memnew(Button(TTR("Create Profile"))); profiles_hbc->add_child(profile_actions[PROFILE_NEW]); - profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_NEW)); + profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_NEW)); profile_actions[PROFILE_ERASE] = memnew(Button(TTR("Remove Profile"))); profiles_hbc->add_child(profile_actions[PROFILE_ERASE]); profile_actions[PROFILE_ERASE]->set_disabled(true); - profile_actions[PROFILE_ERASE]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_ERASE)); + profile_actions[PROFILE_ERASE]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_ERASE)); main_vbc->add_margin_child(TTR("Available Profiles:"), profiles_hbc); @@ -911,18 +917,18 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { profile_actions[PROFILE_SET] = memnew(Button(TTR("Make Current"))); current_profile_hbc->add_child(profile_actions[PROFILE_SET]); profile_actions[PROFILE_SET]->set_disabled(true); - profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_SET)); + profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_SET)); current_profile_hbc->add_child(memnew(VSeparator)); profile_actions[PROFILE_IMPORT] = memnew(Button(TTR("Import"))); current_profile_hbc->add_child(profile_actions[PROFILE_IMPORT]); - profile_actions[PROFILE_IMPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_IMPORT)); + profile_actions[PROFILE_IMPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_IMPORT)); profile_actions[PROFILE_EXPORT] = memnew(Button(TTR("Export"))); current_profile_hbc->add_child(profile_actions[PROFILE_EXPORT]); profile_actions[PROFILE_EXPORT]->set_disabled(true); - profile_actions[PROFILE_EXPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_EXPORT)); + profile_actions[PROFILE_EXPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_EXPORT)); main_vbc->add_child(current_profile_hbc); @@ -939,7 +945,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { class_list->set_hide_root(true); class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected)); - class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), varray(), CONNECT_DEFERRED); + class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), CONNECT_DEFERRED); class_list->connect("item_collapsed", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_collapsed)); // It will be displayed once the user creates or chooses a profile. class_list_vbc->hide(); @@ -957,7 +963,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { property_list->set_hide_root(true); property_list->set_hide_folding(true); property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); - property_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_property_item_edited), varray(), CONNECT_DEFERRED); + property_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_property_item_edited), CONNECT_DEFERRED); // It will be displayed once the user creates or chooses a profile. property_list_vbc->hide(); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 9f446ab38f..2f1134e8ef 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1681,7 +1681,7 @@ EditorFileDialog::EditorFileDialog() { mode_thumbnails = memnew(Button); mode_thumbnails->set_flat(true); - mode_thumbnails->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_THUMBNAILS)); + mode_thumbnails->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS)); mode_thumbnails->set_toggle_mode(true); mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS); mode_thumbnails->set_button_group(view_mode_group); @@ -1690,7 +1690,7 @@ EditorFileDialog::EditorFileDialog() { mode_list = memnew(Button); mode_list->set_flat(true); - mode_list->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_LIST)); + mode_list->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST)); mode_list->set_toggle_mode(true); mode_list->set_pressed(display_mode == DISPLAY_LIST); mode_list->set_button_group(view_mode_group); @@ -1816,9 +1816,9 @@ EditorFileDialog::EditorFileDialog() { _update_drives(); connect("confirmed", callable_mp(this, &EditorFileDialog::_action_pressed)); - item_list->connect("item_selected", callable_mp(this, &EditorFileDialog::_item_selected), varray(), CONNECT_DEFERRED); - item_list->connect("multi_selected", callable_mp(this, &EditorFileDialog::_multi_selected), varray(), CONNECT_DEFERRED); - item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected), varray()); + item_list->connect("item_selected", callable_mp(this, &EditorFileDialog::_item_selected), CONNECT_DEFERRED); + item_list->connect("multi_selected", callable_mp(this, &EditorFileDialog::_multi_selected), CONNECT_DEFERRED); + item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected).bind()); item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_items_clear_selection)); dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted)); file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted)); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index adbba98897..1a105c7fe8 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -36,9 +36,11 @@ #include "core/io/resource_importer.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" #include "core/variant/variant_parser.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_resource_preview.h" #include "editor/editor_settings.h" @@ -217,7 +219,7 @@ void EditorFileSystem::_scan_filesystem() { String project = ProjectSettings::get_singleton()->get_resource_path(); - String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME); + String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME); { Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ); @@ -287,7 +289,7 @@ void EditorFileSystem::_scan_filesystem() { } } - String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4"); + String update_cache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4"); if (FileAccess::exists(update_cache)) { { @@ -330,7 +332,7 @@ void EditorFileSystem::_scan_filesystem() { void EditorFileSystem::_save_filesystem_cache() { group_file_cache.clear(); - String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME); + String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME); Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions."); @@ -872,7 +874,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->modified_time = 0; fi->import_modified_time = 0; - fi->import_valid = ResourceLoader::is_import_valid(path); + fi->import_valid = fi->type == "TextFile" ? true : ResourceLoader::is_import_valid(path); ItemAction ia; ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT; @@ -1023,7 +1025,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->type = "TextFile"; } fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); - fi->import_valid = ResourceLoader::is_import_valid(path); + fi->import_valid = fi->type == "TextFile" ? true : ResourceLoader::is_import_valid(path); fi->import_group_file = ResourceLoader::get_import_group_file(path); { @@ -1455,7 +1457,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p void EditorFileSystem::_save_late_updated_files() { //files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file - String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4"); + String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4"); Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions."); for (const String &E : late_update_files) { @@ -2024,7 +2026,7 @@ void EditorFileSystem::_reimport_file(const String &p_file, const HashMap<String fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->type = importer->get_resource_type(); fs->files[cpos]->uid = uid; - fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); + fs->files[cpos]->import_valid = fs->files[cpos]->type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file); if (ResourceUID::get_singleton()->has_id(uid)) { ResourceUID::get_singleton()->set_id(uid, p_file); @@ -2137,7 +2139,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { data.reimport_from = from; data.reimport_files = reimport_files.ptr(); - import_threads.begin_work(i - from + 1, this, &EditorFileSystem::_reimport_thread, &data); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &EditorFileSystem::_reimport_thread, &data, i - from + 1, -1, false, vformat(TTR("Import resources of type: %s"), reimport_files[from].importer)); int current_index = from - 1; do { if (current_index < data.max_index) { @@ -2145,9 +2147,9 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { pr.step(reimport_files[current_index].path.get_file(), current_index); } OS::get_singleton()->delay_usec(1); - } while (!import_threads.is_done_dispatching()); + } while (!WorkerThreadPool::get_singleton()->is_group_task_completed(group_task)); - import_threads.end_work(); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); importer->import_threaded_end(); } @@ -2430,12 +2432,10 @@ EditorFileSystem::EditorFileSystem() { scan_total = 0; update_script_classes_queued.clear(); - import_threads.init(); ResourceUID::get_singleton()->clear(); //will be updated on scan ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path); } EditorFileSystem::~EditorFileSystem() { - import_threads.finish(); ResourceSaver::set_get_resource_id_for_path(nullptr); } diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 07b1132046..f4e69b95e7 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -36,7 +36,6 @@ #include "core/os/thread_safe.h" #include "core/templates/hash_set.h" #include "core/templates/safe_refcount.h" -#include "core/templates/thread_work_pool.h" #include "scene/main/node.h" class FileAccess; @@ -275,8 +274,6 @@ class EditorFileSystem : public Node { HashSet<String> group_file_cache; - ThreadWorkPool import_threads; - struct ImportThreadData { const ImportFile *reimport_files; int reimport_from; diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index 8c508494c0..c1d6e505db 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -30,9 +30,10 @@ #include "editor_folding.h" +#include "core/io/config_file.h" #include "core/io/file_access.h" #include "editor/editor_inspector.h" -#include "editor/editor_settings.h" +#include "editor/editor_paths.h" Vector<String> EditorFolding::_get_unfolds(const Object *p_object) { Vector<String> sections; @@ -55,7 +56,7 @@ void EditorFolding::save_resource_folding(const Ref<Resource> &p_resource, const config->set_value("folding", "sections_unfolded", unfolds); String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; - file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file); config->save(file); } @@ -73,7 +74,7 @@ void EditorFolding::load_resource_folding(Ref<Resource> p_resource, const String config.instantiate(); String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; - file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file); if (config->load(file) != OK) { return; @@ -149,7 +150,7 @@ void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path config->set_value("folding", "nodes_folded", nodes_folded); String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; - file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file); config->save(file); } @@ -157,9 +158,9 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { Ref<ConfigFile> config; config.instantiate(); - String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String path = EditorPaths::get_singleton()->get_project_settings_dir(); String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; - file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file); if (config->load(file) != OK) { return; @@ -213,7 +214,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { bool EditorFolding::has_folding_data(const String &p_path) { String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; - file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file); return FileAccess::exists(file); } diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index d58dc98f07..a02051c8ee 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -102,7 +102,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { // - macOS doesn't use font hinting. // - Windows uses ClearType, which is in between "Light" and "Normal" hinting. // - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light". -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED font_hinting = TextServer::HINTING_NONE; #else font_hinting = TextServer::HINTING_LIGHT; diff --git a/editor/editor_fonts.h b/editor/editor_fonts.h index e450af00da..c8b60b0198 100644 --- a/editor/editor_fonts.h +++ b/editor/editor_fonts.h @@ -35,4 +35,4 @@ void editor_register_fonts(Ref<Theme> p_theme); -#endif +#endif // EDITOR_FONTS_H diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index a674451d1e..5c3038c468 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1718,6 +1718,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { List<String> tag_stack; bool code_tag = false; + bool codeblock_tag = false; int pos = 0; while (pos < bbcode.length()) { @@ -1729,7 +1730,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { if (brk_pos > pos) { String text = bbcode.substr(pos, brk_pos - pos); - if (!code_tag) { + if (!code_tag && !codeblock_tag) { text = text.replace("\n", "\n\n"); } p_rt->add_text(text); @@ -1743,7 +1744,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { if (brk_end == -1) { String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos); - if (!code_tag) { + if (!code_tag && !codeblock_tag) { text = text.replace("\n", "\n\n"); } p_rt->add_text(text); @@ -1767,12 +1768,20 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { if (tag != "/img") { p_rt->pop(); if (code_tag) { + // Pop both color and background color. + p_rt->pop(); + p_rt->pop(); + } else if (codeblock_tag) { + // Pop color, cell and table. + p_rt->pop(); + p_rt->pop(); p_rt->pop(); } } code_tag = false; + codeblock_tag = false; - } else if (code_tag) { + } else if (code_tag || codeblock_tag) { p_rt->add_text("["); pos = brk_pos + 1; @@ -1781,24 +1790,32 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { const String link_tag = tag.substr(0, tag_end); const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); + // Use monospace font with translucent colored background color to make clickable references + // easier to distinguish from inline code and other text. p_rt->push_font(doc_code_font); p_rt->push_color(link_color); + p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15)); p_rt->push_meta("@" + link_tag + " " + link_target); p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : "")); p_rt->pop(); p_rt->pop(); p_rt->pop(); + p_rt->pop(); pos = brk_end + 1; } else if (doc->class_list.has(tag)) { // Class reference tag such as [Node2D] or [SceneTree]. + // Use monospace font with translucent colored background color to make clickable references + // easier to distinguish from inline code and other text. p_rt->push_font(doc_code_font); p_rt->push_color(link_color); + p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15)); p_rt->push_meta("#" + tag); p_rt->add_text(tag); p_rt->pop(); p_rt->pop(); p_rt->pop(); + p_rt->pop(); pos = brk_end + 1; } else if (tag == "b") { @@ -1811,16 +1828,31 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { p_rt->push_font(doc_italic_font); pos = brk_end + 1; tag_stack.push_front(tag); - } else if (tag == "code" || tag == "codeblock") { - // Use monospace font. + } else if (tag == "code") { + // Use monospace font with translucent background color to make code easier to distinguish from other text. p_rt->push_font(doc_code_font); + p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15)); p_rt->push_color(code_color); code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); + } else if (tag == "codeblock") { + // Use monospace font with translucent background color to make code easier to distinguish from other text. + // Use a single-column table with cell row background color instead of `[bgcolor]`. + // This makes the background color highlight cover the entire block, rather than individual lines. + p_rt->push_font(doc_code_font); + p_rt->push_table(1); + p_rt->push_cell(); + p_rt->set_cell_row_background_color(Color(0.5, 0.5, 0.5, 0.15), Color(0.5, 0.5, 0.5, 0.15)); + p_rt->set_cell_padding(Rect2(10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE)); + p_rt->push_color(code_color); + codeblock_tag = true; + pos = brk_end + 1; + tag_stack.push_front(tag); } else if (tag == "kbd") { - // Use keyboard font with custom color. + // Use keyboard font with custom color and background color. p_rt->push_font(doc_kbd_font); + p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15)); p_rt->push_color(kbd_color); code_tag = true; // Though not strictly a code tag, logic is similar. pos = brk_end + 1; @@ -2057,7 +2089,7 @@ EditorHelp::EditorHelp() { class_desc->connect("finished", callable_mp(this, &EditorHelp::_class_desc_finished)); class_desc->connect("meta_clicked", callable_mp(this, &EditorHelp::_class_desc_select)); class_desc->connect("gui_input", callable_mp(this, &EditorHelp::_class_desc_input)); - class_desc->connect("resized", callable_mp(this, &EditorHelp::_class_desc_resized), varray(false)); + class_desc->connect("resized", callable_mp(this, &EditorHelp::_class_desc_resized).bind(false)); _class_desc_resized(false); // Added second so it opens at the bottom so it won't offset the entire widget. diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index c48b443a0b..297d1226e3 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -34,6 +34,7 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" void EditorHelpSearch::_update_icons() { search_box->set_right_icon(results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); @@ -250,7 +251,7 @@ EditorHelpSearch::EditorHelpSearch() { results_tree->set_hide_root(true); results_tree->set_select_mode(Tree::SELECT_ROW); results_tree->connect("item_activated", callable_mp(this, &EditorHelpSearch::_confirmed)); - results_tree->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(false)); + results_tree->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false)); vbox->add_child(results_tree, true); } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 1711b23547..2064b6f3a1 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -471,6 +471,9 @@ void EditorProperty::update_revert_and_pin_status() { bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, ¤t) && !is_read_only(); if (new_can_revert != can_revert || new_pinned != pinned) { + if (new_can_revert != can_revert) { + emit_signal(SNAME("property_can_revert_changed"), property, new_can_revert); + } can_revert = new_can_revert; pinned = new_pinned; update(); @@ -554,7 +557,7 @@ void EditorProperty::_focusable_focused(int p_index) { } void EditorProperty::add_focusable(Control *p_control) { - p_control->connect("focus_entered", callable_mp(this, &EditorProperty::_focusable_focused), varray(focusables.size())); + p_control->connect("focus_entered", callable_mp(this, &EditorProperty::_focusable_focused).bind(focusables.size())); focusables.push_back(p_control); } @@ -784,6 +787,9 @@ void EditorProperty::expand_all_folding() { void EditorProperty::collapse_all_folding() { } +void EditorProperty::expand_revertable() { +} + void EditorProperty::set_selectable(bool p_selectable) { selectable = p_selectable; } @@ -966,6 +972,7 @@ void EditorProperty::_bind_methods() { ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked"))); ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned"))); + ADD_SIGNAL(MethodInfo("property_can_revert_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "can_revert"))); ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx"))); @@ -1225,12 +1232,15 @@ void EditorInspectorSection::_notification(int p_what) { // Get the section header font. Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")); + Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); // Get the right direction arrow texture, if the section is foldable. Ref<Texture2D> arrow; + bool folded = foldable; if (foldable) { if (object->editor_is_section_unfolded(section)) { arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree")); + folded = false; } else { if (is_layout_rtl()) { arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree")); @@ -1274,28 +1284,71 @@ void EditorInspectorSection::_notification(int p_what) { } draw_rect(header_rect, c); - // Draw header title and folding arrow. - const int arrow_margin = 2; - const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0; - Color color = get_theme_color(SNAME("font_color")); - float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE) - section_indent; - Point2 text_offset = Point2(0, font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2); - HorizontalAlignment text_align = HORIZONTAL_ALIGNMENT_LEFT; - if (rtl) { - text_align = HORIZONTAL_ALIGNMENT_RIGHT; - } else { - text_offset.x = section_indent + Math::round(arrow_width + arrow_margin * EDSCALE); - } - draw_string(font, text_offset.floor(), label, text_align, text_width, font_size, color); + // Draw header title, folding arrow and coutn of revertable properties. + { + int separation = Math::round(2 * EDSCALE); - if (arrow.is_valid()) { - Point2 arrow_position = Point2(0, (header_height - arrow->get_height()) / 2); + int margin_start = section_indent + separation; + int margin_end = separation; + + // - Arrow. + if (arrow.is_valid()) { + Point2 arrow_position; + if (rtl) { + arrow_position.x = get_size().width - (margin_start + arrow->get_width()); + } else { + arrow_position.x = margin_start; + } + arrow_position.y = (header_height - arrow->get_height()) / 2; + draw_texture(arrow, arrow_position); + margin_start += arrow->get_width(); + } + + int available = get_size().width - (margin_start + margin_end); + + // - Count of revertable properties. + String num_revertable_str; + int num_revertable_width = 0; + if (folded && revertable_properties.size()) { + int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x; + + Ref<Font> light_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int light_font_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + Color light_font_color = get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")); + + // Can we fit the long version of the revertable count text? + if (revertable_properties.size() == 1) { + num_revertable_str = "(1 change)"; + } else { + num_revertable_str = vformat("(%d changes)", revertable_properties.size()); + } + num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x; + if (label_width + separation + num_revertable_width > available) { + // We'll have to use the short version. + num_revertable_str = vformat("(%d)", revertable_properties.size()); + num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x; + } + + Point2 text_offset = Point2( + margin_end, + light_font->get_ascent(light_font_size) + (header_height - light_font->get_height(light_font_size)) / 2); + if (!rtl) { + text_offset.x = get_size().width - (text_offset.x + num_revertable_width); + } + draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, light_font_color, TextServer::JUSTIFICATION_NONE); + margin_end += num_revertable_width + separation; + available -= num_revertable_width + separation; + } + + // - Label. + Point2 text_offset = Point2( + margin_start, + font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2); if (rtl) { - arrow_position.x = get_size().width - section_indent - arrow->get_width() - Math::round(arrow_margin * EDSCALE); - } else { - arrow_position.x = section_indent + Math::round(arrow_margin * EDSCALE); + text_offset.x = margin_end; } - draw_texture(arrow, arrow_position.floor()); + HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT; + draw_string(font, text_offset, label, text_align, available, font_size, font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); } // Draw dropping highlight. @@ -1471,6 +1524,22 @@ void EditorInspectorSection::fold() { update(); } +bool EditorInspectorSection::has_revertable_properties() const { + return !revertable_properties.is_empty(); +} + +void EditorInspectorSection::property_can_revert_changed(const String &p_path, bool p_can_revert) { + bool had_revertable_properties = has_revertable_properties(); + if (p_can_revert) { + revertable_properties.insert(p_path); + } else { + revertable_properties.erase(p_path); + } + if (has_revertable_properties() != had_revertable_properties) { + update(); + } +} + void EditorInspectorSection::_bind_methods() { ClassDB::bind_method(D_METHOD("setup", "section", "label", "object", "bg_color", "foldable"), &EditorInspectorSection::setup); ClassDB::bind_method(D_METHOD("get_vbox"), &EditorInspectorSection::get_vbox); @@ -1544,12 +1613,11 @@ void EditorInspectorArray::_rmb_popup_id_pressed(int p_id) { _clear_array(); break; case OPTION_RESIZE_ARRAY: - new_size = count; - new_size_line_edit->set_text(Variant(new_size)); + new_size_spin_box->set_value(count); resize_dialog->get_ok_button()->set_disabled(true); - resize_dialog->popup_centered(); - new_size_line_edit->grab_focus(); - new_size_line_edit->select_all(); + resize_dialog->popup_centered(Size2i(250, 0) * EDSCALE); + new_size_spin_box->get_line_edit()->grab_focus(); + new_size_spin_box->get_line_edit()->select_all(); break; default: break; @@ -1608,7 +1676,7 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MouseButton::RIGHT) { + if (movable && mb->get_button_index() == MouseButton::RIGHT) { popup_array_index_pressed = begin_array_index + p_index; rmb_popup->set_item_disabled(OPTION_MOVE_UP, popup_array_index_pressed == 0); rmb_popup->set_item_disabled(OPTION_MOVE_DOWN, popup_array_index_pressed == count - 1); @@ -1637,49 +1705,118 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) { const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] }; Variant return_value; Callable::CallError call_error; - move_function.call(args_p, 5, return_value, call_error); + move_function.callp(args_p, 5, return_value, call_error); } else { WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name())); } } else if (mode == MODE_USE_COUNT_PROPERTY) { ERR_FAIL_COND(p_to_pos < -1 || p_to_pos > count); - List<PropertyInfo> object_property_list; - object->get_property_list(&object_property_list); - Array properties_as_array = _extract_properties_as_array(object_property_list); - properties_as_array.resize(count); + if (!swap_method.is_empty()) { + ERR_FAIL_COND(!object->has_method(swap_method)); - // For undoing things - undo_redo->add_undo_property(object, count_property, properties_as_array.size()); - for (int i = 0; i < (int)properties_as_array.size(); i++) { - Dictionary d = Dictionary(properties_as_array[i]); - Array keys = d.keys(); - for (int j = 0; j < keys.size(); j++) { - String key = keys[j]; - undo_redo->add_undo_property(object, vformat(key, i), d[key]); - } - } + // Swap method was provided, use it. + if (p_element_index < 0) { + // Add an element at position + undo_redo->add_do_property(object, count_property, count + 1); + if (p_to_pos >= 0) { + for (int i = count; i > p_to_pos; i--) { + undo_redo->add_do_method(object, swap_method, i, i - 1); + } + for (int i = p_to_pos; i < count; i++) { + undo_redo->add_undo_method(object, swap_method, i, i + 1); + } + } + undo_redo->add_undo_property(object, count_property, count); + + } else if (p_to_pos < 0) { + if (count > 0) { + // Remove element at position + undo_redo->add_undo_property(object, count_property, count); + + List<PropertyInfo> object_property_list; + object->get_property_list(&object_property_list); - if (p_element_index < 0) { - // Add an element. - properties_as_array.insert(p_to_pos < 0 ? properties_as_array.size() : p_to_pos, Dictionary()); - } else if (p_to_pos < 0) { - // Delete the element. - properties_as_array.remove_at(p_element_index); + for (int i = p_element_index; i < count - 1; i++) { + undo_redo->add_do_method(object, swap_method, i, i + 1); + } + + for (int i = count; i > p_element_index; i--) { + undo_redo->add_undo_method(object, swap_method, i, i - 1); + } + + String erase_prefix = String(array_element_prefix) + itos(p_element_index); + + for (const PropertyInfo &E : object_property_list) { + if (E.name.begins_with(erase_prefix)) { + undo_redo->add_undo_property(object, E.name, object->get(E.name)); + } + } + + undo_redo->add_do_property(object, count_property, count - 1); + } + } else { + if (p_to_pos > p_element_index) { + p_to_pos--; + } + + if (p_to_pos < p_element_index) { + for (int i = p_element_index; i > p_to_pos; i--) { + undo_redo->add_do_method(object, swap_method, i, i - 1); + } + for (int i = p_to_pos; i < p_element_index; i++) { + undo_redo->add_undo_method(object, swap_method, i, i + 1); + } + } else if (p_to_pos > p_element_index) { + for (int i = p_element_index; i < p_to_pos; i++) { + undo_redo->add_do_method(object, swap_method, i, i + 1); + } + + for (int i = p_to_pos; i > p_element_index; i--) { + undo_redo->add_undo_method(object, swap_method, i, i - 1); + } + } + } } else { - // Move the element. - properties_as_array.insert(p_to_pos, properties_as_array[p_element_index].duplicate()); - properties_as_array.remove_at(p_to_pos < p_element_index ? p_element_index + 1 : p_element_index); - } + // Use standard properties. + List<PropertyInfo> object_property_list; + object->get_property_list(&object_property_list); - // Change the array size then set the properties. - undo_redo->add_do_property(object, count_property, properties_as_array.size()); - for (int i = 0; i < (int)properties_as_array.size(); i++) { - Dictionary d = properties_as_array[i]; - Array keys = d.keys(); - for (int j = 0; j < keys.size(); j++) { - String key = keys[j]; - undo_redo->add_do_property(object, vformat(key, i), d[key]); + Array properties_as_array = _extract_properties_as_array(object_property_list); + properties_as_array.resize(count); + + // For undoing things + undo_redo->add_undo_property(object, count_property, properties_as_array.size()); + for (int i = 0; i < (int)properties_as_array.size(); i++) { + Dictionary d = Dictionary(properties_as_array[i]); + Array keys = d.keys(); + for (int j = 0; j < keys.size(); j++) { + String key = keys[j]; + undo_redo->add_undo_property(object, vformat(key, i), d[key]); + } + } + + if (p_element_index < 0) { + // Add an element. + properties_as_array.insert(p_to_pos < 0 ? properties_as_array.size() : p_to_pos, Dictionary()); + } else if (p_to_pos < 0) { + // Delete the element. + properties_as_array.remove_at(p_element_index); + } else { + // Move the element. + properties_as_array.insert(p_to_pos, properties_as_array[p_element_index].duplicate()); + properties_as_array.remove_at(p_to_pos < p_element_index ? p_element_index + 1 : p_element_index); + } + + // Change the array size then set the properties. + undo_redo->add_do_property(object, count_property, properties_as_array.size()); + for (int i = 0; i < (int)properties_as_array.size(); i++) { + Dictionary d = properties_as_array[i]; + Array keys = d.keys(); + for (int j = 0; j < keys.size(); j++) { + String key = keys[j]; + undo_redo->add_do_property(object, vformat(key, i), d[key]); + } } } } @@ -1712,7 +1849,7 @@ void EditorInspectorArray::_clear_array() { const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] }; Variant return_value; Callable::CallError call_error; - move_function.call(args_p, 5, return_value, call_error); + move_function.callp(args_p, 5, return_value, call_error); } else { WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name())); } @@ -1765,7 +1902,7 @@ void EditorInspectorArray::_resize_array(int p_size) { const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] }; Variant return_value; Callable::CallError call_error; - move_function.call(args_p, 5, return_value, call_error); + move_function.callp(args_p, 5, return_value, call_error); } else { WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name())); } @@ -1784,7 +1921,7 @@ void EditorInspectorArray::_resize_array(int p_size) { const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] }; Variant return_value; Callable::CallError call_error; - move_function.call(args_p, 5, return_value, call_error); + move_function.callp(args_p, 5, return_value, call_error); } else { WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name())); } @@ -1875,36 +2012,21 @@ int EditorInspectorArray::_drop_position() const { return -1; } -void EditorInspectorArray::_new_size_line_edit_text_changed(String p_text) { - bool valid = false; - if (p_text.is_valid_int()) { - int val = p_text.to_int(); - if (val > 0 && val != count) { - valid = true; - } +void EditorInspectorArray::_resize_dialog_confirmed() { + if (int(new_size_spin_box->get_value()) == count) { + return; } - resize_dialog->get_ok_button()->set_disabled(!valid); + + resize_dialog->hide(); + _resize_array(int(new_size_spin_box->get_value())); } -void EditorInspectorArray::_new_size_line_edit_text_submitted(String p_text) { - bool valid = false; - if (p_text.is_valid_int()) { - int val = p_text.to_int(); - if (val > 0 && val != count) { - new_size = val; - valid = true; - } - } - if (valid) { - resize_dialog->hide(); - _resize_array(new_size); - } else { - new_size_line_edit->set_text(Variant(new_size)); - } +void EditorInspectorArray::_new_size_spin_box_value_changed(float p_value) { + resize_dialog->get_ok_button()->set_disabled(int(p_value) == count); } -void EditorInspectorArray::_resize_dialog_confirmed() { - _new_size_line_edit_text_submitted(new_size_line_edit->get_text()); +void EditorInspectorArray::_new_size_spin_box_text_submitted(String p_text) { + _resize_dialog_confirmed(); } void EditorInspectorArray::_setup() { @@ -1919,6 +2041,20 @@ void EditorInspectorArray::_setup() { page = CLAMP(page, 0, max_page); } + Ref<Font> numbers_font; + int numbers_min_w = 0; + + if (numbered) { + numbers_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); + int digits_found = count; + String test; + while (digits_found) { + test += "8"; + digits_found /= 10; + } + numbers_min_w = numbers_font->get_string_size(test).width; + } + for (int i = 0; i < (int)array_elements.size(); i++) { ArrayElement &ae = array_elements[i]; @@ -1931,8 +2067,8 @@ void EditorInspectorArray::_setup() { ae.panel->set_tooltip(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i)); ae.panel->connect("focus_entered", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update)); ae.panel->connect("focus_exited", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update)); - ae.panel->connect("draw", callable_bind(callable_mp(this, &EditorInspectorArray::_panel_draw), i)); - ae.panel->connect("gui_input", callable_bind(callable_mp(this, &EditorInspectorArray::_panel_gui_input), i)); + ae.panel->connect("draw", callable_mp(this, &EditorInspectorArray::_panel_draw).bind(i)); + ae.panel->connect("gui_input", callable_mp(this, &EditorInspectorArray::_panel_gui_input).bind(i)); ae.panel->add_theme_style_override(SNAME("panel"), i % 2 ? odd_style : even_style); elements_vbox->add_child(ae.panel); @@ -1953,19 +2089,38 @@ void EditorInspectorArray::_setup() { ae.margin->add_child(ae.hbox); // Move button. - ae.move_texture_rect = memnew(TextureRect); - ae.move_texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - ae.move_texture_rect->set_default_cursor_shape(Control::CURSOR_MOVE); - if (is_inside_tree()) { - ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); + if (movable) { + ae.move_texture_rect = memnew(TextureRect); + ae.move_texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + ae.move_texture_rect->set_default_cursor_shape(Control::CURSOR_MOVE); + + if (is_inside_tree()) { + ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); + } + ae.hbox->add_child(ae.move_texture_rect); + } + + if (numbered) { + ae.number = memnew(Label); + ae.number->add_theme_font_override("font", numbers_font); + ae.number->set_custom_minimum_size(Size2(numbers_min_w, 0)); + ae.number->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); + ae.number->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); + ae.number->set_text(itos(begin_array_index + i)); + ae.hbox->add_child(ae.number); } - ae.hbox->add_child(ae.move_texture_rect); // Right vbox. ae.vbox = memnew(VBoxContainer); ae.vbox->set_h_size_flags(SIZE_EXPAND_FILL); ae.vbox->set_v_size_flags(SIZE_EXPAND_FILL); ae.hbox->add_child(ae.vbox); + + ae.erase = memnew(Button); + ae.erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + ae.erase->set_v_size_flags(SIZE_SHRINK_CENTER); + ae.erase->connect("pressed", callable_mp(this, &EditorInspectorArray::_remove_item).bind(begin_array_index + i)); + ae.hbox->add_child(ae.erase); } // Hide/show the add button. @@ -1980,7 +2135,14 @@ void EditorInspectorArray::_setup() { } } +void EditorInspectorArray::_remove_item(int p_index) { + _move_element(p_index, -1); +} + Variant EditorInspectorArray::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (!movable) { + return Variant(); + } int index = p_from->get_meta("index"); Dictionary dict; dict["type"] = "property_array_element"; @@ -2002,6 +2164,9 @@ void EditorInspectorArray::drop_data_fw(const Point2 &p_point, const Variant &p_ } bool EditorInspectorArray::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + if (!movable) { + return false; + } // First, update drawing. control_dropping->update(); @@ -2026,18 +2191,24 @@ void EditorInspectorArray::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { Color color = get_theme_color(SNAME("dark_color_1"), SNAME("Editor")); - odd_style->set_bg_color(color.lightened(0.15)); - even_style->set_bg_color(color.darkened(0.15)); + odd_style->set_bg_color(color.darkened(-0.08)); + even_style->set_bg_color(color.darkened(0.08)); for (int i = 0; i < (int)array_elements.size(); i++) { ArrayElement &ae = array_elements[i]; - ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); + if (ae.move_texture_rect) { + ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); + } Size2 min_size = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->get_minimum_size(); ae.margin->add_theme_constant_override("margin_left", min_size.x / 2); ae.margin->add_theme_constant_override("margin_top", min_size.y / 2); ae.margin->add_theme_constant_override("margin_right", min_size.x / 2); ae.margin->add_theme_constant_override("margin_bottom", min_size.y / 2); + + if (ae.erase) { + ae.erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + } } add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -2073,23 +2244,31 @@ void EditorInspectorArray::set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } -void EditorInspectorArray::setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable) { +void EditorInspectorArray::setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_numbered, int p_page_length, const String &p_add_item_text) { count_property = ""; mode = MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION; array_element_prefix = p_array_element_prefix; page = p_page; + movable = p_movable; + page_length = p_page_length; + numbered = p_numbered; EditorInspectorSection::setup(String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable, 0); _setup(); } -void EditorInspectorArray::setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable) { +void EditorInspectorArray::setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_numbered, int p_page_length, const String &p_add_item_text, const String &p_swap_method) { count_property = p_count_property; mode = MODE_USE_COUNT_PROPERTY; array_element_prefix = p_array_element_prefix; page = p_page; + movable = p_movable; + page_length = p_page_length; + numbered = p_numbered; + swap_method = p_swap_method; + add_button->set_text(p_add_item_text); EditorInspectorSection::setup(String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable, 0); _setup(); @@ -2147,10 +2326,11 @@ EditorInspectorArray::EditorInspectorArray() { VBoxContainer *resize_dialog_vbox = memnew(VBoxContainer); resize_dialog->add_child(resize_dialog_vbox); - new_size_line_edit = memnew(LineEdit); - new_size_line_edit->connect("text_changed", callable_mp(this, &EditorInspectorArray::_new_size_line_edit_text_changed)); - new_size_line_edit->connect("text_submitted", callable_mp(this, &EditorInspectorArray::_new_size_line_edit_text_submitted)); - resize_dialog_vbox->add_margin_child(TTRC("New Size:"), new_size_line_edit); + new_size_spin_box = memnew(SpinBox); + new_size_spin_box->set_max(16384); + new_size_spin_box->connect("value_changed", callable_mp(this, &EditorInspectorArray::_new_size_spin_box_value_changed)); + new_size_spin_box->get_line_edit()->connect("text_submitted", callable_mp(this, &EditorInspectorArray::_new_size_spin_box_text_submitted)); + resize_dialog_vbox->add_margin_child(TTRC("New Size:"), new_size_spin_box); vbox->connect("visibility_changed", callable_mp(this, &EditorInspectorArray::_vbox_visibility_changed)); } @@ -2330,7 +2510,7 @@ String EditorInspector::get_selected_path() const { return property_selected; } -void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) { +void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped) { for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) { EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor); current_vbox->add_child(F.property_editor); @@ -2339,14 +2519,14 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit ep->object = object; ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed)); ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed)); - ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED); + ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed)); - ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED); - ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED); + ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED); + ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED); if (F.properties.size()) { if (F.properties.size() == 1) { @@ -2370,6 +2550,10 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit } } + if (p_section) { + ep->connect("property_can_revert_changed", callable_mp(p_section, &EditorInspectorSection::property_can_revert_changed)); + } + ep->set_read_only(read_only); ep->update_property(); ep->_update_pin_flags(); @@ -2466,7 +2650,6 @@ void EditorInspector::update_tree() { List<PropertyInfo> plist; object->get_property_list(&plist, true); - _update_script_class_properties(*object, plist); HashMap<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path; HashMap<String, EditorInspectorArray *> editor_inspector_array_per_prefix; @@ -2476,9 +2659,11 @@ void EditorInspector::update_tree() { // Get the lists of editors to add the beginning. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_begin(object); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } + StringName type_name; + // Get the lists of editors for properties. for (List<PropertyInfo>::Element *E_property = plist.front(); E_property; E_property = E_property->next()) { PropertyInfo &p = E_property->get(); @@ -2549,17 +2734,24 @@ void EditorInspector::update_tree() { category_vbox = nullptr; //reset String type = p.name; + String label = p.name; + type_name = p.name; // Set the category icon. if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { // If we have a category inside a script, search for the first script with a valid icon. Ref<Script> script = ResourceLoader::load(p.hint_string, "Script"); StringName base_type; + StringName name; if (script.is_valid()) { base_type = script->get_instance_base_type(); + name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + if (name != StringName() && label != name) { + label = name; + } } while (script.is_valid()) { - StringName name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); if (name != StringName() && icon_path.length()) { category->icon = ResourceLoader::load(icon_path, "Texture"); @@ -2578,28 +2770,27 @@ void EditorInspector::update_tree() { } // Set the category label. - category->label = type; + category->label = label; if (use_doc_hints) { // Sets the category tooltip to show documentation. - StringName type2 = p.name; - if (!class_descr_cache.has(type2)) { + if (!class_descr_cache.has(type_name)) { String descr; DocTools *dd = EditorHelp::get_doc_data(); - HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type2); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type_name); if (E) { descr = DTR(E->value.brief_description); } - class_descr_cache[type2] = descr; + class_descr_cache[type_name] = descr; } - category->set_tooltip(p.name + "::" + (class_descr_cache[type2].is_empty() ? "" : class_descr_cache[type2])); + category->set_tooltip(p.name + "::" + (class_descr_cache[type_name].is_empty() ? "" : class_descr_cache[type_name])); } // Add editors at the start of a category. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_category(object, p.name); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } continue; @@ -2791,7 +2982,7 @@ void EditorInspector::update_tree() { // Add editors at the start of a group. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_group(object, path); - _parse_added_editors(section->get_vbox(), ped); + _parse_added_editors(section->get_vbox(), section, ped); } vbox_per_path[root_vbox][acc_path] = section->get_vbox(); @@ -2812,26 +3003,52 @@ void EditorInspector::update_tree() { StringName array_element_prefix; Color c = sscolor; c.a /= level; + + Vector<String> class_name_components = String(p.class_name).split(","); + + int page_size = 5; + bool movable = true; + bool numbered = false; + bool foldable = use_folding; + String add_button_text; + String swap_method; + for (int i = (p.type == Variant::NIL ? 1 : 2); i < class_name_components.size(); i++) { + if (class_name_components[i].begins_with("page_size") && class_name_components[i].get_slice_count("=") == 2) { + page_size = class_name_components[i].get_slice("=", 1).to_int(); + } else if (class_name_components[i].begins_with("add_button_text") && class_name_components[i].get_slice_count("=") == 2) { + add_button_text = class_name_components[i].get_slice("=", 1).strip_edges(); + } else if (class_name_components[i] == "static") { + movable = false; + } else if (class_name_components[i] == "numbered") { + numbered = true; + } else if (class_name_components[i] == "unfoldable") { + foldable = false; + } else if (class_name_components[i].begins_with("swap_method") && class_name_components[i].get_slice_count("=") == 2) { + swap_method = class_name_components[i].get_slice("=", 1).strip_edges(); + } + } + if (p.type == Variant::NIL) { // Setup the array to use a method to create/move/delete elements. - array_element_prefix = p.class_name; + array_element_prefix = class_name_components[0]; editor_inspector_array = memnew(EditorInspectorArray); String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path; array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string, property_name_style); int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0; editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding); - editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix)); + editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix)); editor_inspector_array->set_undo_redo(undo_redo); } else if (p.type == Variant::INT) { // Setup the array to use the count property and built-in functions to create/move/delete elements. - Vector<String> class_name_components = String(p.class_name).split(","); - if (class_name_components.size() == 2) { + if (class_name_components.size() >= 2) { array_element_prefix = class_name_components[1]; editor_inspector_array = memnew(EditorInspectorArray); int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0; - editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, use_folding); - editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix)); + + editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, foldable, movable, numbered, page_size, add_button_text, swap_method); + editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix)); + editor_inspector_array->set_undo_redo(undo_redo); } } @@ -2840,6 +3057,7 @@ void EditorInspector::update_tree() { current_vbox->add_child(editor_inspector_array); editor_inspector_array_per_prefix[array_element_prefix] = editor_inspector_array; } + continue; } @@ -2864,7 +3082,7 @@ void EditorInspector::update_tree() { // Build the doc hint, to use as tooltip. // Get the class name. - StringName classname = object->get_class_name(); + StringName classname = type_name == "" ? object->get_class_name() : type_name; if (!object_class.is_empty()) { classname = object_class; } @@ -2973,6 +3191,12 @@ void EditorInspector::update_tree() { editor_property_map[prop].push_back(ep); } } + + EditorInspectorSection *section = Object::cast_to<EditorInspectorSection>(current_vbox->get_parent()); + if (section) { + ep->connect("property_can_revert_changed", callable_mp(section, &EditorInspectorSection::property_can_revert_changed)); + } + ep->set_draw_warning(draw_warning); ep->set_use_folding(use_folding); ep->set_checkable(checkable); @@ -2987,16 +3211,16 @@ void EditorInspector::update_tree() { if (ep) { // Eventually, set other properties/signals after the property editor got added to the tree. bool update_all = (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED); - ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed), varray(update_all)); + ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed).bind(update_all)); ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed)); - ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED); + ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed)); - ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED); - ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED); + ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED); + ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED); if (!doc_info.description.is_empty()) { ep->set_tooltip(property_prefix + p.name + "::" + doc_info.description); } else { @@ -3016,6 +3240,11 @@ void EditorInspector::update_tree() { } if (!hide_metadata) { + // Add 4px of spacing between the "Add Metadata" button and the content above it. + Control *spacer = memnew(Control); + spacer->set_custom_minimum_size(Size2(0, 4) * EDSCALE); + main_vbox->add_child(spacer); + Button *add_md = EditorInspector::create_inspector_action_button(TTR("Add Metadata")); add_md->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); add_md->connect(SNAME("pressed"), callable_mp(this, &EditorInspector::_show_add_meta_dialog)); @@ -3025,7 +3254,7 @@ void EditorInspector::update_tree() { // Get the lists of to add at the end. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_end(object); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } } @@ -3178,6 +3407,44 @@ void EditorInspector::expand_all_folding() { } } +void EditorInspector::expand_revertable() { + HashSet<EditorInspectorSection *> sections_to_unfold[2]; + for (EditorInspectorSection *E : sections) { + if (E->has_revertable_properties()) { + sections_to_unfold[0].insert(E); + } + } + + // Climb up the hierachy doing double buffering with the sets. + int a = 0; + int b = 1; + while (sections_to_unfold[a].size()) { + for (EditorInspectorSection *E : sections_to_unfold[a]) { + E->unfold(); + + Node *n = E->get_parent(); + while (n) { + if (Object::cast_to<EditorInspector>(n)) { + break; + } + if (Object::cast_to<EditorInspectorSection>(n) && !sections_to_unfold[a].has((EditorInspectorSection *)n)) { + sections_to_unfold[b].insert((EditorInspectorSection *)n); + } + n = n->get_parent(); + } + } + + sections_to_unfold[a].clear(); + SWAP(a, b); + } + + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + for (EditorProperty *E : F.value) { + E->expand_revertable(); + } + } +} + void EditorInspector::set_scroll_offset(int p_offset) { set_v_scroll(p_offset); } @@ -3277,14 +3544,23 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo undo_redo->add_undo_property(object, p_name, value); } - PropertyInfo prop_info; - if (ClassDB::get_property_info(object->get_class_name(), p_name, &prop_info)) { - for (const String &linked_prop : prop_info.linked_properties) { - valid = false; - value = object->get(linked_prop, &valid); - if (valid) { - undo_redo->add_undo_property(object, linked_prop, value); - } + List<StringName> linked_properties; + ClassDB::get_linked_properties_info(object->get_class_name(), p_name, &linked_properties); + + for (const StringName &linked_prop : linked_properties) { + valid = false; + Variant undo_value = object->get(linked_prop, &valid); + if (valid) { + undo_redo->add_undo_property(object, linked_prop, undo_value); + } + } + + PackedStringArray linked_properties_dynamic = object->call("_get_linked_undo_properties", p_name, p_value); + for (int i = 0; i < linked_properties_dynamic.size(); i++) { + valid = false; + Variant undo_value = object->get(linked_properties_dynamic[i], &valid); + if (valid) { + undo_redo->add_undo_property(object, linked_properties_dynamic[i], undo_value); } } @@ -3298,7 +3574,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo Variant return_value; Callable::CallError call_error; - callback.call(p_arguments, 4, return_value, call_error); + callback.callp(p_arguments, 4, return_value, call_error); if (call_error.error != Callable::CallError::CALL_OK) { ERR_PRINT("Invalid UndoRedo callback."); } @@ -3558,7 +3834,7 @@ void EditorInspector::_notification(int p_what) { if (refresh_countdown <= 0) { for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { for (EditorProperty *E : F.value) { - if (!E->is_cache_valid()) { + if (E && !E->is_cache_valid()) { E->update_property(); E->update_revert_and_pin_status(); E->update_cache(); @@ -3640,88 +3916,6 @@ void EditorInspector::_feature_profile_changed() { update_tree(); } -void EditorInspector::_update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const { - Ref<Script> script = p_object.get_script(); - if (script.is_null()) { - return; - } - - List<Ref<Script>> classes; - - // NodeC -> NodeB -> NodeA - while (script.is_valid()) { - classes.push_front(script); - script = script->get_base_script(); - } - - if (classes.is_empty()) { - return; - } - - // Script Variables -> to insert: NodeC..B..A -> bottom (insert_here) - List<PropertyInfo>::Element *script_variables = nullptr; - List<PropertyInfo>::Element *bottom = nullptr; - List<PropertyInfo>::Element *insert_here = nullptr; - for (List<PropertyInfo>::Element *E = r_list.front(); E; E = E->next()) { - PropertyInfo &pi = E->get(); - if (pi.name != "Script Variables") { - continue; - } - script_variables = E; - bottom = r_list.insert_after(script_variables, PropertyInfo()); - insert_here = bottom; - break; - } - - HashSet<StringName> added; - for (const Ref<Script> &s : classes) { - String path = s->get_path(); - String name = EditorNode::get_editor_data().script_class_get_name(path); - if (name.is_empty()) { - if (s->is_built_in()) { - if (s->get_name().is_empty()) { - name = TTR("Built-in script"); - } else { - name = vformat("%s (%s)", s->get_name(), TTR("Built-in")); - } - } else { - name = path.get_file(); - } - } - - List<PropertyInfo> props; - s->get_script_property_list(&props); - - // Script Variables -> NodeA -> bottom (insert_here) - List<PropertyInfo>::Element *category = r_list.insert_before(insert_here, PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY)); - - // Script Variables -> NodeA -> A props... -> bottom (insert_here) - for (List<PropertyInfo>::Element *P = props.front(); P; P = P->next()) { - PropertyInfo &pi = P->get(); - if (added.has(pi.name)) { - continue; - } - added.insert(pi.name); - - r_list.insert_before(insert_here, pi); - } - - // Script Variables -> NodeA (insert_here) -> A props... -> bottom - insert_here = category; - } - - // NodeC -> C props... -> NodeB..C.. - if (script_variables) { - r_list.erase(script_variables); - List<PropertyInfo>::Element *to_delete = bottom->next(); - while (to_delete && !(to_delete->get().usage & PROPERTY_USAGE_CATEGORY)) { - r_list.erase(to_delete); - to_delete = bottom->next(); - } - r_list.erase(bottom); - } -} - void EditorInspector::set_restrict_to_basic_settings(bool p_restrict) { restrict_to_basic = p_restrict; update_tree(); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 9542f102cb..baba9ec1f4 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -39,6 +39,7 @@ #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" #include "scene/gui/scroll_container.h" +#include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" class UndoRedo; @@ -184,6 +185,7 @@ public: virtual void expand_all_folding(); virtual void collapse_all_folding(); + virtual void expand_revertable(); virtual Variant get_drag_data(const Point2 &p_point) override; virtual void update_cache(); @@ -281,6 +283,8 @@ class EditorInspectorSection : public Container { Timer *dropping_unfold_timer = nullptr; bool dropping = false; + HashSet<StringName> revertable_properties; + void _test_unfold(); protected: @@ -299,6 +303,9 @@ public: void unfold(); void fold(); + bool has_revertable_properties() const; + void property_can_revert_changed(const String &p_path, bool p_can_revert); + EditorInspectorSection(); ~EditorInspectorSection(); }; @@ -315,6 +322,7 @@ class EditorInspectorArray : public EditorInspectorSection { } mode; StringName count_property; StringName array_element_prefix; + String swap_method; int count = 0; @@ -326,8 +334,7 @@ class EditorInspectorArray : public EditorInspectorSection { Button *add_button = nullptr; AcceptDialog *resize_dialog = nullptr; - int new_size = 0; - LineEdit *new_size_line_edit = nullptr; + SpinBox *new_size_spin_box = nullptr; // Pagination int page_length = 5; @@ -336,6 +343,9 @@ class EditorInspectorArray : public EditorInspectorSection { int begin_array_index = 0; int end_array_index = 0; + bool movable = true; + bool numbered = false; + enum MenuOptions { OPTION_MOVE_UP = 0, OPTION_MOVE_DOWN, @@ -353,7 +363,9 @@ class EditorInspectorArray : public EditorInspectorSection { MarginContainer *margin = nullptr; HBoxContainer *hbox = nullptr; TextureRect *move_texture_rect = nullptr; + Label *number = nullptr; VBoxContainer *vbox = nullptr; + Button *erase = nullptr; }; LocalVector<ArrayElement> array_elements; @@ -378,8 +390,8 @@ class EditorInspectorArray : public EditorInspectorSection { Array _extract_properties_as_array(const List<PropertyInfo> &p_list); int _drop_position() const; - void _new_size_line_edit_text_changed(String p_text); - void _new_size_line_edit_text_submitted(String p_text); + void _new_size_spin_box_value_changed(float p_value); + void _new_size_spin_box_text_submitted(String p_text); void _resize_dialog_confirmed(); void _update_elements_visibility(); @@ -389,6 +401,8 @@ class EditorInspectorArray : public EditorInspectorSection { void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void _remove_item(int p_index); + protected: void _notification(int p_what); static void _bind_methods(); @@ -396,8 +410,8 @@ protected: public: void set_undo_redo(UndoRedo *p_undo_redo); - void setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable); - void setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable); + void setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = ""); + void setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "", const String &p_swap_method = ""); VBoxContainer *get_vbox(int p_index); EditorInspectorArray(); @@ -517,12 +531,11 @@ class EditorInspector : public ScrollContainer { void _edit_request_change(Object *p_object, const String &p_prop); void _filter_changed(const String &p_text); - void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped); + void _parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped); void _vscroll_changed(double); void _feature_profile_changed(); - void _update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const; bool _is_property_disabled_by_feature_profile(const StringName &p_property); @@ -579,6 +592,7 @@ public: void collapse_all_folding(); void expand_all_folding(); + void expand_revertable(); void set_scroll_offset(int p_offset); int get_scroll_offset() const; @@ -602,4 +616,4 @@ public: EditorInspector(); }; -#endif // INSPECTOR_H +#endif // EDITOR_INSPECTOR_H diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index f26f47dbc7..38cc85bb4e 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -33,8 +33,11 @@ #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/center_container.h" +#include "scene/gui/separator.h" #include "scene/resources/font.h" void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { @@ -122,7 +125,7 @@ void EditorLog::_save_state() { Ref<ConfigFile> config; config.instantiate(); // Load and amend existing config if it exists. - config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); const String section = "editor_log"; for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) { @@ -132,7 +135,7 @@ void EditorLog::_save_state() { config->set_value(section, "collapse", collapse); config->set_value(section, "show_search", search_box->is_visible()); - config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); } void EditorLog::_load_state() { @@ -140,7 +143,7 @@ void EditorLog::_load_state() { Ref<ConfigFile> config; config.instantiate(); - config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); // Run the below code even if config->load returns an error, since we want the defaults to be set even if the file does not exist yet. const String section = "editor_log"; diff --git a/editor/editor_log.h b/editor/editor_log.h index 653fba9524..003a148b9b 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -88,7 +88,7 @@ private: toggle_button->add_theme_color_override("icon_color_pressed", Color(1, 1, 1, 1)); toggle_button->set_focus_mode(FOCUS_NONE); // When toggled call the callback and pass the MessageType this button is for. - toggle_button->connect("toggled", p_toggled_callback, varray(type)); + toggle_button->connect("toggled", p_toggled_callback.bind(type)); } int get_message_count() { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index abe431221c..e7946f56da 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -49,6 +49,7 @@ #include "main/main.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/gui/center_container.h" +#include "scene/gui/color_picker.h" #include "scene/gui/control.h" #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" @@ -75,9 +76,9 @@ #include "editor/dependency_editor.h" #include "editor/editor_about.h" #include "editor/editor_audio_buses.h" +#include "editor/editor_build_profile.h" #include "editor/editor_command_palette.h" #include "editor/editor_data.h" -#include "editor/editor_export.h" #include "editor/editor_feature_profile.h" #include "editor/editor_file_dialog.h" #include "editor/editor_file_system.h" @@ -90,6 +91,7 @@ #include "editor/editor_plugin.h" #include "editor/editor_properties.h" #include "editor/editor_property_name_processor.h" +#include "editor/editor_quick_open.h" #include "editor/editor_resource_picker.h" #include "editor/editor_resource_preview.h" #include "editor/editor_run.h" @@ -102,8 +104,11 @@ #include "editor/editor_themes.h" #include "editor/editor_toaster.h" #include "editor/editor_translation_parser.h" -#include "editor/export_template_manager.h" +#include "editor/export/editor_export.h" +#include "editor/export/export_template_manager.h" +#include "editor/export/project_export.h" #include "editor/filesystem_dock.h" +#include "editor/import/audio_stream_import_settings.h" #include "editor/import/dynamic_font_import_settings.h" #include "editor/import/editor_import_collada.h" #include "editor/import/resource_importer_bitmask.h" @@ -131,12 +136,12 @@ #include "editor/plugins/animation_state_machine_editor.h" #include "editor/plugins/animation_tree_editor_plugin.h" #include "editor/plugins/asset_library_editor_plugin.h" -#include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/audio_stream_randomizer_editor_plugin.h" #include "editor/plugins/bit_map_editor_plugin.h" #include "editor/plugins/bone_map_editor_plugin.h" #include "editor/plugins/camera_3d_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/plugins/cast_2d_editor_plugin.h" #include "editor/plugins/collision_polygon_2d_editor_plugin.h" #include "editor/plugins/collision_shape_2d_editor_plugin.h" #include "editor/plugins/control_editor_plugin.h" @@ -146,6 +151,7 @@ #include "editor/plugins/debugger_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/editor_preview_plugins.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/font_config_plugin.h" #include "editor/plugins/gdextension_export_plugin.h" #include "editor/plugins/gpu_particles_2d_editor_plugin.h" @@ -171,8 +177,6 @@ #include "editor/plugins/physical_bone_3d_editor_plugin.h" #include "editor/plugins/polygon_2d_editor_plugin.h" #include "editor/plugins/polygon_3d_editor_plugin.h" -#include "editor/plugins/ray_cast_2d_editor_plugin.h" -#include "editor/plugins/replication_editor_plugin.h" #include "editor/plugins/resource_preloader_editor_plugin.h" #include "editor/plugins/root_motion_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" @@ -197,9 +201,7 @@ #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/plugins/voxel_gi_editor_plugin.h" #include "editor/progress_dialog.h" -#include "editor/project_export.h" #include "editor/project_settings_editor.h" -#include "editor/quick_open.h" #include "editor/register_exporters.h" #include "editor/scene_tree_dock.h" @@ -512,10 +514,10 @@ void EditorNode::_update_from_settings() { uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits"); RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits); - RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality"))); - RS::get_singleton()->shadows_quality_set(shadows_quality); - RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality"))); - RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality); + RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality"))); + RS::get_singleton()->positional_soft_shadow_filter_set_quality(shadows_quality); + RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality"))); + RS::get_singleton()->directional_soft_shadow_filter_set_quality(directional_shadow_quality); float probe_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed"); RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed); RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge"))); @@ -552,6 +554,19 @@ void EditorNode::_update_from_settings() { tree->set_debug_collision_contact_color(GLOBAL_GET("debug/shapes/collision/contact_color")); tree->set_debug_navigation_color(GLOBAL_GET("debug/shapes/navigation/geometry_color")); tree->set_debug_navigation_disabled_color(GLOBAL_GET("debug/shapes/navigation/disabled_geometry_color")); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton_mut()->set_debug_navigation_edge_connection_color(GLOBAL_GET("debug/shapes/navigation/edge_connection_color")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_edge_color(GLOBAL_GET("debug/shapes/navigation/geometry_edge_color")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_color(GLOBAL_GET("debug/shapes/navigation/geometry_face_color")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_edge_disabled_color(GLOBAL_GET("debug/shapes/navigation/geometry_edge_disabled_color")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_disabled_color(GLOBAL_GET("debug/shapes/navigation/geometry_face_disabled_color")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(GLOBAL_GET("debug/shapes/navigation/enable_edge_connections")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections_xray(GLOBAL_GET("debug/shapes/navigation/enable_edge_connections_xray")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_lines(GLOBAL_GET("debug/shapes/navigation/enable_edge_lines")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_lines_xray(GLOBAL_GET("debug/shapes/navigation/enable_edge_lines_xray")); + NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_geometry_face_random_color(GLOBAL_GET("debug/shapes/navigation/enable_geometry_face_random_color")); +#endif // DEBUG_ENABLED } void EditorNode::_select_default_main_screen_plugin() { @@ -923,6 +938,7 @@ void EditorNode::_fs_changed() { // FIXME: Move this to a cleaner location, it's hacky to do this in _fs_changed. String export_error; + Error err = OK; if (!export_defer.preset.is_empty() && !EditorFileSystem::get_singleton()->is_scanning()) { String preset_name = export_defer.preset; // Ensures export_project does not loop infinitely, because notifications may @@ -940,6 +956,7 @@ void EditorNode::_fs_changed() { if (export_preset.is_null()) { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (da->file_exists("res://export_presets.cfg")) { + err = FAILED; export_error = vformat( "Invalid export preset name: %s.\nThe following presets were detected in this project's `export_presets.cfg`:\n\n", preset_name); @@ -948,17 +965,19 @@ void EditorNode::_fs_changed() { export_error += vformat(" \"%s\"\n", EditorExport::get_singleton()->get_export_preset(i)->get_name()); } } else { + err = FAILED; export_error = "This project doesn't have an `export_presets.cfg` file at its root.\nCreate an export preset from the \"Project > Export\" dialog and try again."; } } else { Ref<EditorExportPlatform> platform = export_preset->get_platform(); const String export_path = export_defer.path.is_empty() ? export_preset->get_export_path() : export_defer.path; if (export_path.is_empty()) { + err = FAILED; export_error = vformat("Export preset \"%s\" doesn't have a default export path, and none was specified.", preset_name); } else if (platform.is_null()) { + err = FAILED; export_error = vformat("Export preset \"%s\" doesn't have a matching platform.", preset_name); } else { - Error err = OK; if (export_defer.pack_only) { // Only export .pck or .zip data pack. if (export_path.ends_with(".zip")) { err = platform->export_zip(export_preset, export_defer.debug, export_path); @@ -979,17 +998,18 @@ void EditorNode::_fs_changed() { if (err != OK) { export_error = vformat("Project export for preset \"%s\" failed.", preset_name); } else if (platform->get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) { - export_error = vformat("Project export for preset \"%s\" completed with errors.", preset_name); + export_error = vformat("Project export for preset \"%s\" completed with warnings.", preset_name); } } } - if (!export_error.is_empty()) { + if (err != OK) { ERR_PRINT(export_error); _exit_editor(EXIT_FAILURE); - } else { - _exit_editor(EXIT_SUCCESS); + } else if (!export_error.is_empty()) { + WARN_PRINT(export_error); } + _exit_editor(EXIT_SUCCESS); } } @@ -1029,7 +1049,7 @@ void EditorNode::_sources_changed(bool p_exist) { // Reload the global shader variables, but this time // loading textures, as they are now properly imported. - RenderingServer::get_singleton()->global_variables_load_settings(true); + RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true); // Start preview thread now that it's safe. if (!singleton->cmdline_export_mode) { @@ -1207,7 +1227,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St } String path = ProjectSettings::get_singleton()->localize_path(p_path); - Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS); + Error err = ResourceSaver::save(p_resource, path, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS); if (err != OK) { if (ResourceLoader::is_imported(p_resource->get_path())) { @@ -1358,7 +1378,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) { return; } - String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); Ref<ConfigFile> cf; cf.instantiate(); @@ -1390,7 +1410,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { return; } - String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); Ref<ConfigFile> cf; cf.instantiate(); @@ -1430,7 +1450,7 @@ bool EditorNode::_find_and_save_resource(Ref<Resource> p_res, HashMap<Ref<Resour if (p_res->get_path().is_resource_file()) { if (changed || subchanged) { - ResourceSaver::save(p_res->get_path(), p_res, flags); + ResourceSaver::save(p_res, p_res->get_path(), flags); } processed[p_res] = false; // Because it's a file. return false; @@ -1661,7 +1681,7 @@ int EditorNode::_save_external_resources() { if (ps.is_valid()) { continue; // Do not save PackedScenes, this will mess up the editor. } - ResourceSaver::save(res->get_path(), res, flg); + ResourceSaver::save(res, res->get_path(), flg); saved++; } @@ -1732,7 +1752,7 @@ void EditorNode::_save_scene(String p_file, int idx) { } flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; - err = ResourceSaver::save(p_file, sdata, flg); + err = ResourceSaver::save(sdata, p_file, flg); // This needs to be emitted before saving external resources. emit_signal(SNAME("scene_saved"), p_file); @@ -1794,9 +1814,16 @@ void EditorNode::restart_editor() { _exit_editor(EXIT_SUCCESS); List<String> args; + args.push_back("--path"); args.push_back(ProjectSettings::get_singleton()->get_resource_path()); + args.push_back("-e"); + + if (OS::get_singleton()->is_disable_crash_handler()) { + args.push_back("--disable-crash-handler"); + } + if (!to_reopen.is_empty()) { args.push_back(to_reopen); } @@ -1932,7 +1959,7 @@ void EditorNode::_dialog_action(String p_file) { MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed()); - Error err = ResourceSaver::save(p_file, ml); + Error err = ResourceSaver::save(ml, p_file); if (err) { show_accept(TTR("Error saving MeshLibrary!"), TTR("OK")); return; @@ -2177,6 +2204,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) { bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding")); bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); + bool stay_in_script_editor_on_node_selected = bool(EDITOR_GET("text_editor/behavior/navigation/stay_in_script_editor_on_node_selected")); + bool skip_main_plugin = false; String editable_warning; // None by default. @@ -2213,6 +2242,9 @@ void EditorNode::_edit_current(bool p_skip_foreign) { NodeDock::get_singleton()->set_node(current_node); SceneTreeDock::get_singleton()->set_selected(current_node); InspectorDock::get_singleton()->update(current_node); + if (!inspector_only && !skip_main_plugin) { + skip_main_plugin = stay_in_script_editor_on_node_selected && ScriptEditor::get_singleton()->is_visible_in_tree(); + } } else { NodeDock::get_singleton()->set_node(nullptr); SceneTreeDock::get_singleton()->set_selected(nullptr); @@ -2287,7 +2319,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) { } } - if (main_plugin) { + if (main_plugin && !skip_main_plugin) { // Special case if use of external editor is true. Resource *current_res = Object::cast_to<Resource>(current_obj); if (main_plugin->get_name() == "Script" && !current_obj->is_class("VisualScript") && current_res && !current_res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { @@ -2805,6 +2837,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } } break; + case TOOLS_BUILD_PROFILE_MANAGER: { + build_profile_manager->popup_centered_clamped(Size2(700, 800) * EDSCALE, 0.8); + } break; case RUN_USER_DATA_FOLDER: { // Ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved. OS::get_singleton()->ensure_user_data_dir(); @@ -2990,7 +3025,7 @@ void EditorNode::_tool_menu_option(int p_idx) { Callable callback = tool_menu->get_item_metadata(p_idx); Callable::CallError ce; Variant result; - callback.call(nullptr, 0, result, ce); + callback.callp(nullptr, 0, result, ce); if (ce.error != Callable::CallError::CALL_OK) { String err = Variant::get_callable_error_text(callback, nullptr, 0, ce); @@ -3025,7 +3060,7 @@ void EditorNode::_export_as_menu_option(int p_idx) { Callable callback = export_as_menu->get_item_metadata(p_idx); Callable::CallError ce; Variant result; - callback.call(nullptr, 0, result, ce); + callback.callp(nullptr, 0, result, ce); if (ce.error != Callable::CallError::CALL_OK) { String err = Variant::get_callable_error_text(callback, nullptr, 0, ce); @@ -3230,7 +3265,7 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed Button *tb = memnew(Button); tb->set_flat(true); tb->set_toggle_mode(true); - tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size())); + tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select).bind(singleton->main_editor_buttons.size())); tb->set_name(p_editor->get_name()); tb->set_text(p_editor->get_name()); @@ -3588,6 +3623,13 @@ void EditorNode::set_current_scene(int p_idx) { call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up. } +void EditorNode::setup_color_picker(ColorPicker *picker) { + int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode"); + int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); + picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode); + picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); +} + bool EditorNode::is_scene_open(const String &p_path) { for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { if (editor_data.get_scene_path(i) == p_path) { @@ -4333,22 +4375,22 @@ void EditorNode::_dock_make_float() { window->set_title(dock->get_name()); Panel *p = memnew(Panel); p->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("PanelForeground"), SNAME("EditorStyles"))); - p->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + p->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); window->add_child(p); MarginContainer *margin = memnew(MarginContainer); - margin->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + margin->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); margin->add_theme_constant_override("margin_right", borders.width); margin->add_theme_constant_override("margin_top", borders.height); margin->add_theme_constant_override("margin_left", borders.width); margin->add_theme_constant_override("margin_bottom", borders.height); window->add_child(margin); - dock->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + dock->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); margin->add_child(dock); window->set_wrap_controls(true); window->set_size(dock_size); window->set_position(dock_screen_pos); window->set_transient(true); - window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request), varray(dock)); + window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(dock)); window->set_meta("dock_slot", dock_popup_selected_idx); window->set_meta("dock_index", dock_index); gui_base->add_child(window); @@ -4569,13 +4611,13 @@ void EditorNode::_save_docks() { Ref<ConfigFile> config; config.instantiate(); // Load and amend existing config if it exists. - config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); _save_docks_to_config(config, "docks"); _save_open_scenes_to_config(config, "EditorNode"); editor_data.get_plugin_window_layout(config); - config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); } void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) { @@ -4589,8 +4631,14 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p names += name; } + String config_key = "dock_" + itos(i + 1); + + if (p_layout->has_section_key(p_section, config_key)) { + p_layout->erase_section_key(p_section, config_key); + } + if (!names.is_empty()) { - p_layout->set_value(p_section, "dock_" + itos(i + 1), names); + p_layout->set_value(p_section, config_key, names); } } @@ -4633,7 +4681,7 @@ void EditorNode::_dock_split_dragged(int ofs) { void EditorNode::_load_docks() { Ref<ConfigFile> config; config.instantiate(); - Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); if (err != OK) { // No config. if (overridden_default_layout >= 0) { @@ -4866,7 +4914,7 @@ bool EditorNode::has_scenes_in_session() { } Ref<ConfigFile> config; config.instantiate(); - Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); if (err != OK) { return false; } @@ -5201,7 +5249,7 @@ void EditorNode::_scene_tab_changed(int p_tab) { Button *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { Button *tb = memnew(Button); tb->set_flat(true); - tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(bottom_panel_items.size())); + tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(bottom_panel_items.size())); tb->set_text(p_text); tb->set_toggle_mode(true); tb->set_focus_mode(Control::FOCUS_NONE); @@ -5248,7 +5296,7 @@ void EditorNode::raise_bottom_panel_item(Control *p_item) { for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->disconnect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch)); - bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(i)); + bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(i)); } } @@ -5268,7 +5316,7 @@ void EditorNode::remove_bottom_panel_item(Control *p_item) { for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->disconnect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch)); - bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(i)); + bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(i)); } } @@ -5893,8 +5941,14 @@ EditorNode::EditorNode() { RenderingServer::get_singleton()->set_debug_generate_wireframes(true); + AudioServer::get_singleton()->set_enable_tagging_used_audio_streams(true); + // No navigation server by default if in editor. - NavigationServer3D::get_singleton()->set_active(false); + if (NavigationServer3D::get_singleton()->get_debug_enabled()) { + NavigationServer3D::get_singleton()->set_active(true); + } else { + NavigationServer3D::get_singleton()->set_active(false); + } // No physics by default if in editor. PhysicsServer3D::get_singleton()->set_active(false); @@ -6103,8 +6157,6 @@ EditorNode::EditorNode() { register_exporters(); - ClassDB::set_class_enabled("RootMotionView", true); - EDITOR_DEF("interface/editor/save_on_focus_loss", false); EDITOR_DEF("interface/editor/show_update_spinner", false); EDITOR_DEF("interface/editor/update_continuously", false); @@ -6113,13 +6165,22 @@ EditorNode::EditorNode() { EDITOR_DEF_RST("interface/inspector/default_property_name_style", EditorPropertyNameProcessor::STYLE_CAPITALIZED); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_property_name_style", PROPERTY_HINT_ENUM, "Raw,Capitalized,Localized")); EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0,1,0")); + // The lowest value is equal to the minimum float step for 32-bit floats. + // The step must be set manually, as changing this setting should not change the step here. + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0.0000001,1,0.0000001")); EDITOR_DEF_RST("interface/inspector/disable_folding", false); EDITOR_DEF_RST("interface/inspector/auto_unfold_foreign_scenes", true); EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); - EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary"); + + PackedStringArray open_in_new_inspector_defaults; + // Required for the script editor to work. + open_in_new_inspector_defaults.push_back("Script"); + // Required for the GridMap editor to work. + open_in_new_inspector_defaults.push_back("MeshLibrary"); + EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", open_in_new_inspector_defaults); + EDITOR_DEF("interface/inspector/default_color_picker_mode", 0); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_OKHSL_CIRCLE); @@ -6134,11 +6195,11 @@ EditorNode::EditorNode() { theme_base = memnew(Control); add_child(theme_base); - theme_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + theme_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); gui_base = memnew(Panel); theme_base->add_child(gui_base); - gui_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + gui_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); theme_base->set_theme(theme); gui_base->set_theme(theme); @@ -6156,7 +6217,7 @@ EditorNode::EditorNode() { main_vbox = memnew(VBoxContainer); gui_base->add_child(main_vbox); - main_vbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8); + main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8); main_vbox->add_theme_constant_override("separation", 8 * EDSCALE); menu_hb = memnew(HBoxContainer); @@ -6285,7 +6346,7 @@ EditorNode::EditorNode() { dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE); dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL); dock_slot[i]->set_popup(dock_select_popup); - dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup), varray(i)); + dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup).bind(i)); dock_slot[i]->set_drag_to_rearrange_enabled(true); dock_slot[i]->set_tabs_rearrange_group(1); dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed)); @@ -6333,7 +6394,7 @@ EditorNode::EditorNode() { scene_tabs->set_drag_to_rearrange_enabled(true); scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); scene_tabs->connect("tab_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited)); - scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE)); + scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorNode::_scene_tab_closed).bind(SCENE_TAB_CLOSE)); scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered)); scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit)); scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input)); @@ -6352,7 +6413,7 @@ EditorNode::EditorNode() { scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f)); scene_tabs->add_child(scene_tab_add); - scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_NEW_SCENE)); + scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_NEW_SCENE)); scene_tab_add_ph = memnew(Control); scene_tab_add_ph->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -6404,7 +6465,7 @@ EditorNode::EditorNode() { prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons"))); prev_scene->set_tooltip(TTR("Go to previously opened scene.")); prev_scene->set_disabled(true); - prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_OPEN_PREV)); + prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_OPEN_PREV)); gui_base->add_child(prev_scene); prev_scene->set_position(Point2(3, 24)); prev_scene->hide(); @@ -6415,7 +6476,7 @@ EditorNode::EditorNode() { save_accept = memnew(AcceptDialog); gui_base->add_child(save_accept); - save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), make_binds((int)MenuOptions::FILE_SAVE_AS_SCENE)); + save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::FILE_SAVE_AS_SCENE)); project_export = memnew(ProjectExportDialog); gui_base->add_child(project_export); @@ -6435,6 +6496,9 @@ EditorNode::EditorNode() { scene_import_settings = memnew(SceneImportSettings); gui_base->add_child(scene_import_settings); + audio_stream_import_settings = memnew(AudioStreamImportSettings); + gui_base->add_child(audio_stream_import_settings); + fontdata_import_settings = memnew(DynamicFontImportSettings); gui_base->add_child(fontdata_import_settings); @@ -6443,6 +6507,10 @@ EditorNode::EditorNode() { feature_profile_manager = memnew(EditorFeatureProfileManager); gui_base->add_child(feature_profile_manager); + + build_profile_manager = memnew(EditorBuildProfileManager); + gui_base->add_child(build_profile_manager); + about = memnew(EditorAbout); gui_base->add_child(about); feature_profile_manager->connect("current_feature_profile_changed", callable_mp(this, &EditorNode::_feature_profile_changed)); @@ -6535,6 +6603,10 @@ EditorNode::EditorNode() { p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); p->add_item(TTR("Open User Data Folder"), RUN_USER_DATA_FOLDER); + p->add_separator(); + p->add_item(TTR("Customize Engine Build Configuration..."), TOOLS_BUILD_PROFILE_MANAGER); + p->add_separator(); + plugin_config_dialog = memnew(PluginConfigDialog); plugin_config_dialog->connect("plugin_ready", callable_mp(this, &EditorNode::_on_plugin_ready)); gui_base->add_child(plugin_config_dialog); @@ -6647,7 +6719,7 @@ EditorNode::EditorNode() { play_button->set_toggle_mode(true); play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); play_button->set_focus_mode(Control::FOCUS_NONE); - play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY)); + play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY)); play_button->set_tooltip(TTR("Play the project.")); ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5); @@ -6672,7 +6744,7 @@ EditorNode::EditorNode() { play_hb->add_child(stop_button); stop_button->set_focus_mode(Control::FOCUS_NONE); stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); - stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_STOP)); + stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_STOP)); stop_button->set_tooltip(TTR("Stop the scene.")); stop_button->set_disabled(true); @@ -6690,7 +6762,7 @@ EditorNode::EditorNode() { play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); - play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE)); + play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE)); play_scene_button->set_tooltip(TTR("Play the edited scene.")); ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6); @@ -6703,7 +6775,7 @@ EditorNode::EditorNode() { play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); - play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE)); + play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_CUSTOM_SCENE)); play_custom_scene_button->set_tooltip(TTR("Play custom scene")); ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5); @@ -6770,7 +6842,7 @@ EditorNode::EditorNode() { video_restart_dialog = memnew(ConfirmationDialog); video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor.")); video_restart_dialog->set_ok_button_text(TTR("Save & Restart")); - video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SET_RENDERING_DRIVER_SAVE_AND_RESTART)); + video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SET_RENDERING_DRIVER_SAVE_AND_RESTART)); gui_base->add_child(video_restart_dialog); progress_hb = memnew(BackgroundProgress); @@ -6803,6 +6875,7 @@ EditorNode::EditorNode() { filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request)); filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request)); filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); + get_project_settings()->connect_filesystem_dock_signals(filesystem_dock); // Scene: Top left. dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton()); @@ -6939,8 +7012,8 @@ EditorNode::EditorNode() { custom_build_manage_templates = memnew(ConfirmationDialog); custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates.")); custom_build_manage_templates->set_ok_button_text(TTR("Manage Templates")); - custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE)); - custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_MANAGE_EXPORT_TEMPLATES)); + custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE)); + custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_MANAGE_EXPORT_TEMPLATES)); gui_base->add_child(custom_build_manage_templates); file_android_build_source = memnew(EditorFileDialog); @@ -6960,7 +7033,7 @@ EditorNode::EditorNode() { remove_android_build_template = memnew(ConfirmationDialog); remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again.")); remove_android_build_template->set_ok_button_text(TTR("Show in File Manager")); - remove_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES)); + remove_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES)); gui_base->add_child(remove_android_build_template); file_templates = memnew(EditorFileDialog); @@ -7065,63 +7138,64 @@ EditorNode::EditorNode() { // More visually meaningful to have this later. raise_bottom_panel_item(AnimationPlayerEditor::get_singleton()); - add_editor_plugin(memnew(ReplicationEditorPlugin)); add_editor_plugin(VersionControlEditorPlugin::get_singleton()); - add_editor_plugin(memnew(ShaderEditorPlugin)); - add_editor_plugin(memnew(ShaderFileEditorPlugin)); + // This list is alphabetized, and plugins that depend on Node2D are in their own section below. + add_editor_plugin(memnew(AnimationTreeEditorPlugin)); + add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); + add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin)); + add_editor_plugin(memnew(BitMapEditorPlugin)); + add_editor_plugin(memnew(BoneMapEditorPlugin)); add_editor_plugin(memnew(Camera3DEditorPlugin)); - add_editor_plugin(memnew(ThemeEditorPlugin)); - add_editor_plugin(memnew(MultiMeshEditorPlugin)); + add_editor_plugin(memnew(ControlEditorPlugin)); + add_editor_plugin(memnew(CPUParticles3DEditorPlugin)); + add_editor_plugin(memnew(CurveEditorPlugin)); + add_editor_plugin(memnew(FontEditorPlugin)); + add_editor_plugin(memnew(GPUParticles3DEditorPlugin)); + add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin)); + add_editor_plugin(memnew(GradientEditorPlugin)); + add_editor_plugin(memnew(GradientTexture2DEditorPlugin)); + add_editor_plugin(memnew(InputEventEditorPlugin)); + add_editor_plugin(memnew(LightmapGIEditorPlugin)); + add_editor_plugin(memnew(MaterialEditorPlugin)); + add_editor_plugin(memnew(MeshEditorPlugin)); add_editor_plugin(memnew(MeshInstance3DEditorPlugin)); - add_editor_plugin(memnew(AnimationTreeEditorPlugin)); add_editor_plugin(memnew(MeshLibraryEditorPlugin)); - add_editor_plugin(memnew(StyleBoxEditorPlugin)); - add_editor_plugin(memnew(Sprite2DEditorPlugin)); - add_editor_plugin(memnew(Skeleton2DEditorPlugin)); - add_editor_plugin(memnew(GPUParticles2DEditorPlugin)); - add_editor_plugin(memnew(GPUParticles3DEditorPlugin)); - add_editor_plugin(memnew(CPUParticles2DEditorPlugin)); - add_editor_plugin(memnew(CPUParticles3DEditorPlugin)); - add_editor_plugin(memnew(ResourcePreloaderEditorPlugin)); + add_editor_plugin(memnew(MultiMeshEditorPlugin)); + add_editor_plugin(memnew(OccluderInstance3DEditorPlugin)); + add_editor_plugin(memnew(Path3DEditorPlugin)); + add_editor_plugin(memnew(PhysicalBone3DEditorPlugin)); add_editor_plugin(memnew(Polygon3DEditorPlugin)); - add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin)); - add_editor_plugin(memnew(TilesEditorPlugin)); + add_editor_plugin(memnew(ResourcePreloaderEditorPlugin)); + add_editor_plugin(memnew(ShaderEditorPlugin)); + add_editor_plugin(memnew(ShaderFileEditorPlugin)); + add_editor_plugin(memnew(Skeleton3DEditorPlugin)); + add_editor_plugin(memnew(SkeletonIK3DEditorPlugin)); add_editor_plugin(memnew(SpriteFramesEditorPlugin)); + add_editor_plugin(memnew(StyleBoxEditorPlugin)); + add_editor_plugin(memnew(SubViewportPreviewEditorPlugin)); + add_editor_plugin(memnew(Texture3DEditorPlugin)); + add_editor_plugin(memnew(TextureEditorPlugin)); + add_editor_plugin(memnew(TextureLayeredEditorPlugin)); add_editor_plugin(memnew(TextureRegionEditorPlugin)); + add_editor_plugin(memnew(ThemeEditorPlugin)); add_editor_plugin(memnew(VoxelGIEditorPlugin)); - add_editor_plugin(memnew(LightmapGIEditorPlugin)); - add_editor_plugin(memnew(OccluderInstance3DEditorPlugin)); - add_editor_plugin(memnew(Path2DEditorPlugin)); - add_editor_plugin(memnew(Path3DEditorPlugin)); - add_editor_plugin(memnew(Line2DEditorPlugin)); - add_editor_plugin(memnew(Polygon2DEditorPlugin)); + + // 2D + add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin)); + add_editor_plugin(memnew(CollisionShape2DEditorPlugin)); + add_editor_plugin(memnew(CPUParticles2DEditorPlugin)); + add_editor_plugin(memnew(GPUParticles2DEditorPlugin)); add_editor_plugin(memnew(LightOccluder2DEditorPlugin)); + add_editor_plugin(memnew(Line2DEditorPlugin)); add_editor_plugin(memnew(NavigationPolygonEditorPlugin)); - add_editor_plugin(memnew(GradientEditorPlugin)); - add_editor_plugin(memnew(CollisionShape2DEditorPlugin)); - add_editor_plugin(memnew(CurveEditorPlugin)); - add_editor_plugin(memnew(FontEditorPlugin)); - add_editor_plugin(memnew(TextureEditorPlugin)); - add_editor_plugin(memnew(TextureLayeredEditorPlugin)); - add_editor_plugin(memnew(Texture3DEditorPlugin)); - add_editor_plugin(memnew(AudioStreamEditorPlugin)); - add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin)); - add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); - add_editor_plugin(memnew(Skeleton3DEditorPlugin)); - add_editor_plugin(memnew(SkeletonIK3DEditorPlugin)); - add_editor_plugin(memnew(PhysicalBone3DEditorPlugin)); - add_editor_plugin(memnew(MeshEditorPlugin)); - add_editor_plugin(memnew(MaterialEditorPlugin)); - add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin)); - add_editor_plugin(memnew(InputEventEditorPlugin)); - add_editor_plugin(memnew(SubViewportPreviewEditorPlugin)); - add_editor_plugin(memnew(ControlEditorPlugin)); - add_editor_plugin(memnew(GradientTexture2DEditorPlugin)); - add_editor_plugin(memnew(BitMapEditorPlugin)); - add_editor_plugin(memnew(RayCast2DEditorPlugin)); - add_editor_plugin(memnew(BoneMapEditorPlugin)); + add_editor_plugin(memnew(Path2DEditorPlugin)); + add_editor_plugin(memnew(Polygon2DEditorPlugin)); + add_editor_plugin(memnew(Cast2DEditorPlugin)); + add_editor_plugin(memnew(Skeleton2DEditorPlugin)); + add_editor_plugin(memnew(Sprite2DEditorPlugin)); + add_editor_plugin(memnew(TilesEditorPlugin)); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i)); @@ -7179,6 +7253,7 @@ EditorNode::EditorNode() { vshader_convert.instantiate(); resource_conversion_plugins.push_back(vshader_convert); } + update_spinner_step_msec = OS::get_singleton()->get_ticks_msec(); update_spinner_step_frame = Engine::get_singleton()->get_frames_drawn(); @@ -7250,7 +7325,7 @@ EditorNode::EditorNode() { pick_main_scene = memnew(ConfirmationDialog); gui_base->add_child(pick_main_scene); pick_main_scene->set_ok_button_text(TTR("Select")); - pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_PICK_MAIN_SCENE)); + pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_PICK_MAIN_SCENE)); select_current_scene_button = pick_main_scene->add_button(TTR("Select Current"), true, "select_current"); pick_main_scene->connect("custom_action", callable_mp(this, &EditorNode::_pick_main_scene_custom_action)); diff --git a/editor/editor_node.h b/editor/editor_node.h index 07d565314d..0201e84eaf 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -32,12 +32,11 @@ #define EDITOR_NODE_H #include "core/templates/safe_refcount.h" -#include "editor/editor_export.h" #include "editor/editor_folding.h" #include "editor/editor_native_shader_source_visualizer.h" #include "editor/editor_run.h" +#include "editor/export/editor_export.h" #include "editor/inspector_dock.h" -#include "editor/property_editor.h" typedef void (*EditorNodeInitCallback)(); typedef void (*EditorPluginInitializeCallback)(); @@ -48,6 +47,7 @@ class AudioStreamPreviewGenerator; class BackgroundProgress; class Button; class CenterContainer; +class ColorPicker; class ConfirmationDialog; class Control; class DependencyEditor; @@ -67,6 +67,7 @@ class EditorPlugin; class EditorPluginList; class EditorQuickOpen; class EditorResourcePreview; +class EditorResourceConversionPlugin; class EditorRun; class EditorRunNative; class EditorSettingsDialog; @@ -88,6 +89,7 @@ class ProjectExportDialog; class ProjectSettingsEditor; class RunSettingsDialog; class SceneImportSettings; +class AudioStreamImportSettings; class ScriptCreateDialog; class SubViewport; class TabBar; @@ -95,6 +97,7 @@ class TabContainer; class TextureProgressBar; class VSplitContainer; class Window; +class EditorBuildProfileManager; class EditorNode : public Node { GDCLASS(EditorNode, Node); @@ -163,6 +166,7 @@ private: EDIT_REDO, EDIT_RELOAD_SAVED_SCENE, TOOLS_ORPHAN_RESOURCES, + TOOLS_BUILD_PROFILE_MANAGER, TOOLS_CUSTOM, RESOURCE_SAVE, RESOURCE_SAVE_AS, @@ -377,6 +381,7 @@ private: EditorFileDialog *file = nullptr; ExportTemplateManager *export_template_manager = nullptr; EditorFeatureProfileManager *feature_profile_manager = nullptr; + EditorBuildProfileManager *build_profile_manager = nullptr; EditorFileDialog *file_templates = nullptr; EditorFileDialog *file_export_lib = nullptr; EditorFileDialog *file_script = nullptr; @@ -468,6 +473,7 @@ private: DynamicFontImportSettings *fontdata_import_settings = nullptr; SceneImportSettings *scene_import_settings = nullptr; + AudioStreamImportSettings *audio_stream_import_settings = nullptr; String import_reload_fn; @@ -783,6 +789,8 @@ public: void set_current_version(uint64_t p_version); void set_current_scene(int p_idx); + void setup_color_picker(ColorPicker *picker); + void request_instance_scene(const String &p_path); void request_instantiate_scenes(const Vector<String> &p_files); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 6453db3b0b..dc77b5fea9 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -198,7 +198,7 @@ EditorPath::EditorPath(EditorSelectionHistory *p_history) { history = p_history; MarginContainer *main_mc = memnew(MarginContainer); - main_mc->set_anchors_and_offsets_preset(PRESET_WIDE); + main_mc->set_anchors_and_offsets_preset(PRESET_FULL_RECT); main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE); main_mc->add_theme_constant_override("margin_right", 6 * EDSCALE); add_child(main_mc); diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp index a5c2fe093c..b6364e1ab7 100644 --- a/editor/editor_paths.cpp +++ b/editor/editor_paths.cpp @@ -66,6 +66,30 @@ String EditorPaths::get_self_contained_file() const { return self_contained_file; } +String EditorPaths::get_export_templates_dir() const { + return get_data_dir().plus_file(export_templates_folder); +} + +String EditorPaths::get_project_settings_dir() const { + return get_project_data_dir().plus_file("editor"); +} + +String EditorPaths::get_text_editor_themes_dir() const { + return get_config_dir().plus_file(text_editor_themes_folder); +} + +String EditorPaths::get_script_templates_dir() const { + return get_config_dir().plus_file(script_templates_folder); +} + +String EditorPaths::get_project_script_templates_dir() const { + return ProjectSettings::get_singleton()->get("editor/script/templates_search_path"); +} + +String EditorPaths::get_feature_profiles_dir() const { + return get_config_dir().plus_file(feature_profiles_folder); +} + void EditorPaths::create() { ERR_FAIL_COND(singleton != nullptr); memnew(EditorPaths()); @@ -82,6 +106,8 @@ void EditorPaths::_bind_methods() { ClassDB::bind_method(D_METHOD("get_cache_dir"), &EditorPaths::get_cache_dir); ClassDB::bind_method(D_METHOD("is_self_contained"), &EditorPaths::is_self_contained); ClassDB::bind_method(D_METHOD("get_self_contained_file"), &EditorPaths::get_self_contained_file); + + ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorPaths::get_project_settings_dir); } EditorPaths::EditorPaths() { @@ -153,8 +179,8 @@ EditorPaths::EditorPaths() { } } - if (!dir->dir_exists("templates")) { - dir->make_dir("templates"); + if (!dir->dir_exists(export_templates_folder)) { + dir->make_dir(export_templates_folder); } } @@ -168,14 +194,14 @@ EditorPaths::EditorPaths() { } } - if (!dir->dir_exists("text_editor_themes")) { - dir->make_dir("text_editor_themes"); + if (!dir->dir_exists(text_editor_themes_folder)) { + dir->make_dir(text_editor_themes_folder); } - if (!dir->dir_exists("script_templates")) { - dir->make_dir("script_templates"); + if (!dir->dir_exists(script_templates_folder)) { + dir->make_dir(script_templates_folder); } - if (!dir->dir_exists("feature_profiles")) { - dir->make_dir("feature_profiles"); + if (!dir->dir_exists(feature_profiles_folder)) { + dir->make_dir(feature_profiles_folder); } } @@ -192,7 +218,6 @@ EditorPaths::EditorPaths() { // Validate or create project-specific editor data dir, // including shader cache subdir. - if (Engine::get_singleton()->is_project_manager_hint() || Main::is_cmdline_tool()) { // Nothing to create, use shared editor data dir for shader cache. Engine::get_singleton()->set_shader_cache_path(data_dir); diff --git a/editor/editor_paths.h b/editor/editor_paths.h index 7d863a7c6c..9cff1063c5 100644 --- a/editor/editor_paths.h +++ b/editor/editor_paths.h @@ -45,6 +45,10 @@ class EditorPaths : public Object { String project_data_dir; // Project-specific data (metadata, shader cache, etc.). bool self_contained = false; // Self-contained means everything goes to `editor_data` dir. String self_contained_file; // Self-contained file with configuration. + String export_templates_folder = "export_templates"; + String text_editor_themes_folder = "text_editor_themes"; + String script_templates_folder = "script_templates"; + String feature_profiles_folder = "feature_profiles"; static EditorPaths *singleton; @@ -58,6 +62,12 @@ public: String get_config_dir() const; String get_cache_dir() const; String get_project_data_dir() const; + String get_export_templates_dir() const; + String get_project_settings_dir() const; + String get_text_editor_themes_dir() const; + String get_script_templates_dir() const; + String get_project_script_templates_dir() const; + String get_feature_profiles_dir() const; bool is_self_contained() const; String get_self_contained_file() const; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index d9c2a42114..566c22f5a9 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -31,11 +31,11 @@ #include "editor_plugin.h" #include "editor/editor_command_palette.h" -#include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_resource_preview.h" #include "editor/editor_settings.h" +#include "editor/export/editor_export.h" #include "editor/filesystem_dock.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index c666b4639d..84c63d1021 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -346,4 +346,4 @@ public: } }; -#endif +#endif // EDITOR_PLUGIN_H diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 3a0b875b8c..5a010a66c1 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -37,6 +37,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "scene/gui/margin_container.h" +#include "scene/gui/tree.h" void EditorPluginSettings::_notification(int p_what) { switch (p_what) { diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index 4903a02c4d..9c619066f2 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORPLUGINSETTINGS_H -#define EDITORPLUGINSETTINGS_H +#ifndef EDITOR_PLUGIN_SETTINGS_H +#define EDITOR_PLUGIN_SETTINGS_H #include "core/object/undo_redo.h" #include "editor/editor_data.h" #include "editor/plugin_config_dialog.h" -#include "property_editor.h" -#include "scene/gui/dialogs.h" + +class Tree; class EditorPluginSettings : public VBoxContainer { GDCLASS(EditorPluginSettings, VBoxContainer); @@ -65,4 +65,4 @@ public: EditorPluginSettings(); }; -#endif // EDITORPLUGINSETTINGS_H +#endif // EDITOR_PLUGIN_SETTINGS_H diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index aaa518362c..f434df3a1e 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -133,6 +133,11 @@ void EditorPropertyMultilineText::_text_changed() { void EditorPropertyMultilineText::_open_big_text() { if (!big_text_dialog) { big_text = memnew(TextEdit); + if (expression) { + big_text->set_syntax_highlighter(text->get_syntax_highlighter()); + big_text->add_theme_font_override("font", get_theme_font(SNAME("expression"), SNAME("EditorFonts"))); + big_text->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts"))); + } big_text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_big_text_changed)); big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY); big_text_dialog = memnew(AcceptDialog); @@ -162,12 +167,24 @@ void EditorPropertyMultilineText::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons")); open_big_text->set_icon(df); - Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); - int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); - text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6)); - text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); - text->add_theme_font_size_override("font_size", get_theme_font_size("expression_size", "EditorFonts")); + Ref<Font> font; + int font_size; + if (expression) { + font = get_theme_font(SNAME("expression"), SNAME("EditorFonts")); + font_size = get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts")); + + text->add_theme_font_override("font", font); + text->add_theme_font_size_override("font_size", font_size); + if (big_text) { + big_text->add_theme_font_override("font", font); + big_text->add_theme_font_size_override("font_size", font_size); + } + } else { + font = get_theme_font(SNAME("font"), SNAME("TextEdit")); + font_size = get_theme_font_size(SNAME("font_size"), SNAME("TextEdit")); + } + text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6)); } break; } } @@ -490,13 +507,55 @@ void EditorPropertyPath::_path_focus_exited() { _path_selected(path->get_text()); } +void EditorPropertyPath::_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + const Dictionary drag_data = p_data; + if (!drag_data.has("type")) { + return; + } + if (String(drag_data["type"]) != "files") { + return; + } + const Vector<String> filesPaths = drag_data["files"]; + if (filesPaths.size() == 0) { + return; + } + + emit_changed(get_edited_property(), filesPaths[0]); + update_property(); +} + +bool EditorPropertyPath::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + const Dictionary drag_data = p_data; + if (!drag_data.has("type")) { + return false; + } + if (String(drag_data["type"]) != "files") { + return false; + } + const Vector<String> filesPaths = drag_data["files"]; + if (filesPaths.size() == 0) { + return false; + } + + for (const String &extension : extensions) { + if (filesPaths[0].ends_with(extension.substr(1, extension.size() - 1))) { + return true; + } + } + + return false; +} + void EditorPropertyPath::_bind_methods() { + ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "position", "data", "from"), &EditorPropertyPath::_can_drop_data_fw); + ClassDB::bind_method(D_METHOD("_drop_data_fw", "position", "data", "from"), &EditorPropertyPath::_drop_data_fw); } EditorPropertyPath::EditorPropertyPath() { HBoxContainer *path_hb = memnew(HBoxContainer); add_child(path_hb); path = memnew(LineEdit); + path->set_drag_forwarding(this); path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); path_hb->add_child(path); path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected)); @@ -774,7 +833,7 @@ void EditorPropertyFlags::setup(const Vector<String> &p_options) { CheckBox *cb = memnew(CheckBox); cb->set_text(option); cb->set_clip_text(true); - cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled), varray(i)); + cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled).bind(i)); add_focusable(cb); vbox->add_child(cb); flags.push_back(cb); @@ -1088,6 +1147,17 @@ void EditorPropertyLayersGrid::_bind_methods() { ADD_SIGNAL(MethodInfo("rename_confirmed", PropertyInfo(Variant::INT, "layer_id"), PropertyInfo(Variant::STRING, "new_name"))); } +void EditorPropertyLayers::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + button->set_normal_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); + button->set_pressed_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); + button->set_disabled_texture(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons"))); + } break; + } +} + void EditorPropertyLayers::_set_read_only(bool p_read_only) { button->set_disabled(p_read_only); grid->set_read_only(p_read_only); @@ -1224,9 +1294,9 @@ EditorPropertyLayers::EditorPropertyLayers() { grid->set_h_size_flags(SIZE_EXPAND_FILL); hb->add_child(grid); - button = memnew(Button); + button = memnew(TextureButton); + button->set_stretch_mode(TextureButton::STRETCH_KEEP_CENTERED); button->set_toggle_mode(true); - button->set_text("..."); button->connect("pressed", callable_mp(this, &EditorPropertyLayers::_button_pressed)); hb->add_child(button); @@ -1236,7 +1306,7 @@ EditorPropertyLayers::EditorPropertyLayers() { add_child(layers); layers->set_hide_on_checkable_item_selection(false); layers->connect("id_pressed", callable_mp(this, &EditorPropertyLayers::_menu_pressed)); - layers->connect("popup_hide", callable_mp((BaseButton *)button, &BaseButton::set_pressed), varray(false)); + layers->connect("popup_hide", callable_mp((BaseButton *)button, &BaseButton::set_pressed).bind(false)); EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &EditorPropertyLayers::_refresh_names)); } @@ -1580,6 +1650,11 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) { // which can cause crashes and other issues. p_value = CLAMP(p_value, -1'000'000, 1'000'000); + if (positive_only) { + // Force a positive or zero value if a negative value was manually entered by double-clicking. + p_value = MAX(0.0, p_value); + } + emit_changed(get_edited_property(), p_value); _spin_focus_exited(); } @@ -1591,9 +1666,9 @@ void EditorPropertyEasing::_spin_focus_exited() { easing_draw->update(); } -void EditorPropertyEasing::setup(bool p_full, bool p_flip) { +void EditorPropertyEasing::setup(bool p_positive_only, bool p_flip) { flip = p_flip; - full = p_full; + positive_only = p_positive_only; } void EditorPropertyEasing::_notification(int p_what) { @@ -1601,13 +1676,13 @@ void EditorPropertyEasing::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { preset->clear(); - preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO); preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR); - preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "In", EASING_IN); - preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Out", EASING_OUT); - if (full) { - preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "In-Out", EASING_IN_OUT); - preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Out-In", EASING_OUT_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "Ease In", EASING_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Ease Out", EASING_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO); + if (!positive_only) { + preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "Ease In-Out", EASING_IN_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Ease Out-In", EASING_OUT_IN); } easing_draw->set_custom_minimum_size(Size2(0, get_theme_font(SNAME("font"), SNAME("Label"))->get_height(get_theme_font_size(SNAME("font_size"), SNAME("Label"))) * 2)); } break; @@ -1755,7 +1830,7 @@ EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -1865,7 +1940,7 @@ EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) { } add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2037,7 +2112,7 @@ EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2168,7 +2243,7 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2i::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2i::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2278,7 +2353,7 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) { } add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2420,7 +2495,7 @@ EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3i::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3i::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2521,7 +2596,7 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyPlane::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyPlane::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2613,7 +2688,187 @@ EditorPropertyQuaternion::EditorPropertyQuaternion() { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed).bind(desc[i])); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this + } +} +///////////////////// VECTOR4 ///////////////////////// + +void EditorPropertyVector4::_set_read_only(bool p_read_only) { + for (int i = 0; i < 4; i++) { + spin[i]->set_read_only(p_read_only); + } +}; + +void EditorPropertyVector4::_value_changed(double val, const String &p_name) { + if (setting) { + return; + } + + Vector4 p; + p.x = spin[0]->get_value(); + p.y = spin[1]->get_value(); + p.z = spin[2]->get_value(); + p.w = spin[3]->get_value(); + emit_changed(get_edited_property(), p, p_name); +} + +void EditorPropertyVector4::update_property() { + Vector4 val = get_edited_object()->get(get_edited_property()); + setting = true; + spin[0]->set_value(val.x); + spin[1]->set_value(val.y); + spin[2]->set_value(val.z); + spin[3]->set_value(val.w); + setting = false; +} + +void EditorPropertyVector4::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + const Color *colors = _get_property_colors(); + for (int i = 0; i < 4; i++) { + spin[i]->add_theme_color_override("label_color", colors[i]); + } + } break; + } +} + +void EditorPropertyVector4::_bind_methods() { +} + +void EditorPropertyVector4::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { + for (int i = 0; i < 4; i++) { + spin[i]->set_min(p_min); + spin[i]->set_max(p_max); + spin[i]->set_step(p_step); + spin[i]->set_hide_slider(p_no_slider); + spin[i]->set_allow_greater(true); + spin[i]->set_allow_lesser(true); + // Vector4 is inherently unitless, however someone may want to use it as + // a generic way to store 4 values, so we'll still respect the suffix. + spin[i]->set_suffix(p_suffix); + } +} + +EditorPropertyVector4::EditorPropertyVector4() { + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + + static const char *desc[4] = { "x", "y", "z", "w" }; + for (int i = 0; i < 4; i++) { + spin[i] = memnew(EditorSpinSlider); + spin[i]->set_flat(true); + spin[i]->set_label(desc[i]); + bc->add_child(spin[i]); + add_focusable(spin[i]); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4::_value_changed).bind(desc[i])); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this + } +} + +///////////////////// VECTOR4I ///////////////////////// + +void EditorPropertyVector4i::_set_read_only(bool p_read_only) { + for (int i = 0; i < 4; i++) { + spin[i]->set_read_only(p_read_only); + } +}; + +void EditorPropertyVector4i::_value_changed(double val, const String &p_name) { + if (setting) { + return; + } + + Vector4i p; + p.x = spin[0]->get_value(); + p.y = spin[1]->get_value(); + p.z = spin[2]->get_value(); + p.w = spin[3]->get_value(); + emit_changed(get_edited_property(), p, p_name); +} + +void EditorPropertyVector4i::update_property() { + Vector4i val = get_edited_object()->get(get_edited_property()); + setting = true; + spin[0]->set_value(val.x); + spin[1]->set_value(val.y); + spin[2]->set_value(val.z); + spin[3]->set_value(val.w); + setting = false; +} + +void EditorPropertyVector4i::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + const Color *colors = _get_property_colors(); + for (int i = 0; i < 4; i++) { + spin[i]->add_theme_color_override("label_color", colors[i]); + } + } break; + } +} + +void EditorPropertyVector4i::_bind_methods() { +} + +void EditorPropertyVector4i::setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix) { + for (int i = 0; i < 4; i++) { + spin[i]->set_min(p_min); + spin[i]->set_max(p_max); + spin[i]->set_hide_slider(p_no_slider); + spin[i]->set_allow_greater(true); + spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); + } +} + +EditorPropertyVector4i::EditorPropertyVector4i() { + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + + static const char *desc[4] = { "x", "y", "z", "w" }; + for (int i = 0; i < 4; i++) { + spin[i] = memnew(EditorSpinSlider); + spin[i]->set_flat(true); + spin[i]->set_label(desc[i]); + bc->add_child(spin[i]); + add_focusable(spin[i]); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4i::_value_changed).bind(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -2702,7 +2957,7 @@ EditorPropertyAABB::EditorPropertyAABB() { g->add_child(spin[i]); spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed).bind(desc[i])); } set_bottom_editor(g); } @@ -2793,7 +3048,7 @@ EditorPropertyTransform2D::EditorPropertyTransform2D(bool p_include_origin) { } spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed).bind(desc[i])); } set_bottom_editor(g); } @@ -2883,7 +3138,7 @@ EditorPropertyBasis::EditorPropertyBasis() { g->add_child(spin[i]); spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed).bind(desc[i])); } set_bottom_editor(g); } @@ -2981,11 +3236,116 @@ EditorPropertyTransform3D::EditorPropertyTransform3D() { g->add_child(spin[i]); spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed).bind(desc[i])); } set_bottom_editor(g); } +///////////////////// PROJECTION ///////////////////////// + +void EditorPropertyProjection::_set_read_only(bool p_read_only) { + for (int i = 0; i < 12; i++) { + spin[i]->set_read_only(p_read_only); + } +}; + +void EditorPropertyProjection::_value_changed(double val, const String &p_name) { + if (setting) { + return; + } + + Projection p; + p.matrix[0][0] = spin[0]->get_value(); + p.matrix[0][1] = spin[1]->get_value(); + p.matrix[0][2] = spin[2]->get_value(); + p.matrix[0][3] = spin[3]->get_value(); + p.matrix[1][0] = spin[4]->get_value(); + p.matrix[1][1] = spin[5]->get_value(); + p.matrix[1][2] = spin[6]->get_value(); + p.matrix[1][3] = spin[7]->get_value(); + p.matrix[2][0] = spin[8]->get_value(); + p.matrix[2][1] = spin[9]->get_value(); + p.matrix[2][2] = spin[10]->get_value(); + p.matrix[2][3] = spin[11]->get_value(); + p.matrix[3][0] = spin[12]->get_value(); + p.matrix[3][1] = spin[13]->get_value(); + p.matrix[3][2] = spin[14]->get_value(); + p.matrix[3][3] = spin[15]->get_value(); + + emit_changed(get_edited_property(), p, p_name); +} + +void EditorPropertyProjection::update_property() { + update_using_transform(get_edited_object()->get(get_edited_property())); +} + +void EditorPropertyProjection::update_using_transform(Projection p_transform) { + setting = true; + spin[0]->set_value(p_transform.matrix[0][0]); + spin[1]->set_value(p_transform.matrix[0][1]); + spin[2]->set_value(p_transform.matrix[0][2]); + spin[3]->set_value(p_transform.matrix[0][3]); + spin[4]->set_value(p_transform.matrix[1][0]); + spin[5]->set_value(p_transform.matrix[1][1]); + spin[6]->set_value(p_transform.matrix[1][2]); + spin[7]->set_value(p_transform.matrix[1][3]); + spin[8]->set_value(p_transform.matrix[2][0]); + spin[9]->set_value(p_transform.matrix[2][1]); + spin[10]->set_value(p_transform.matrix[2][2]); + spin[11]->set_value(p_transform.matrix[2][3]); + spin[12]->set_value(p_transform.matrix[3][0]); + spin[13]->set_value(p_transform.matrix[3][1]); + spin[14]->set_value(p_transform.matrix[3][2]); + spin[15]->set_value(p_transform.matrix[3][3]); + setting = false; +} + +void EditorPropertyProjection::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + const Color *colors = _get_property_colors(); + for (int i = 0; i < 16; i++) { + spin[i]->add_theme_color_override("label_color", colors[i % 4]); + } + } break; + } +} + +void EditorPropertyProjection::_bind_methods() { +} + +void EditorPropertyProjection::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { + for (int i = 0; i < 16; i++) { + spin[i]->set_min(p_min); + spin[i]->set_max(p_max); + spin[i]->set_step(p_step); + spin[i]->set_hide_slider(p_no_slider); + spin[i]->set_allow_greater(true); + spin[i]->set_allow_lesser(true); + if (i % 4 == 3) { + spin[i]->set_suffix(p_suffix); + } + } +} + +EditorPropertyProjection::EditorPropertyProjection() { + GridContainer *g = memnew(GridContainer); + g->set_columns(4); + add_child(g); + + static const char *desc[16] = { "xx", "xy", "xz", "xw", "yx", "yy", "yz", "yw", "zx", "zy", "zz", "zw", "wx", "wy", "wz", "ww" }; + for (int i = 0; i < 16; i++) { + spin[i] = memnew(EditorSpinSlider); + spin[i]->set_label(desc[i]); + spin[i]->set_flat(true); + g->add_child(spin[i]); + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + add_focusable(spin[i]); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyProjection::_value_changed).bind(desc[i])); + } + set_bottom_editor(g); +} ////////////// COLOR PICKER ////////////////////// void EditorPropertyColor::_set_read_only(bool p_read_only) { @@ -3007,14 +3367,6 @@ void EditorPropertyColor::_popup_closed() { } } -void EditorPropertyColor::_picker_created() { - // get default color picker mode from editor settings - int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode"); - picker->get_picker()->set_color_mode((ColorPicker::ColorModeType)default_color_mode); - int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); - picker->get_picker()->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); -} - void EditorPropertyColor::_picker_opening() { last_color = picker->get_pick_color(); } @@ -3059,7 +3411,7 @@ EditorPropertyColor::EditorPropertyColor() { picker->set_flat(true); picker->connect("color_changed", callable_mp(this, &EditorPropertyColor::_color_changed)); picker->connect("popup_closed", callable_mp(this, &EditorPropertyColor::_popup_closed)); - picker->connect("picker_created", callable_mp(this, &EditorPropertyColor::_picker_created)); + picker->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(picker->get_picker())); picker->get_popup()->connect("about_to_popup", callable_mp(this, &EditorPropertyColor::_picker_opening)); } @@ -3177,6 +3529,11 @@ bool EditorPropertyNodePath::is_drop_valid(const Dictionary &p_drag_data) const Node *dropped_node = get_tree()->get_edited_scene_root()->get_node(nodes[0]); ERR_FAIL_NULL_V(dropped_node, false); + if (valid_types.is_empty()) { + // No type requirements specified so any type is valid. + return true; + } + for (const StringName &E : valid_types) { if (dropped_node->is_class(E)) { return true; @@ -3321,7 +3678,10 @@ void EditorPropertyResource::_resource_selected(const Ref<Resource> &p_resource, void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) { // Make visual script the correct type. Ref<Script> s = p_resource; + bool is_script = false; if (get_edited_object() && s.is_valid()) { + is_script = true; + InspectorDock::get_singleton()->store_script_properties(get_edited_object()); s->call("set_instance_base_type", get_edited_object()->get_class()); } @@ -3347,6 +3707,11 @@ void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) emit_changed(get_edited_property(), p_resource); update_property(); + if (is_script) { + // Restore properties if script was changed. + InspectorDock::get_singleton()->apply_script_properties(get_edited_object()); + } + // Automatically suggest setting up the path for a ViewportTexture. if (vpt.is_valid() && vpt->get_viewport_path_in_scene().is_empty()) { if (!scene_tree) { @@ -3517,6 +3882,9 @@ void EditorPropertyResource::setup(Object *p_object, const String &p_path, const shader_picker->set_edited_material(Object::cast_to<ShaderMaterial>(p_object)); resource_picker = shader_picker; connect(SNAME("ready"), callable_mp(this, &EditorPropertyResource::_update_preferred_shader)); + } else if (p_base_type == "AudioStream") { + EditorAudioStreamPicker *astream_picker = memnew(EditorAudioStreamPicker); + resource_picker = astream_picker; } else { resource_picker = memnew(EditorResourcePicker); } @@ -3625,6 +3993,12 @@ void EditorPropertyResource::expand_all_folding() { } } +void EditorPropertyResource::expand_revertable() { + if (sub_inspector) { + sub_inspector->expand_revertable(); + } +} + void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { use_sub_inspector = p_enable; } @@ -3806,20 +4180,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ case Variant::FLOAT: { if (p_hint == PROPERTY_HINT_EXP_EASING) { EditorPropertyEasing *editor = memnew(EditorPropertyEasing); - bool full = true; + bool positive_only = false; bool flip = false; - Vector<String> hints = p_hint_text.split(","); + const Vector<String> hints = p_hint_text.split(","); for (int i = 0; i < hints.size(); i++) { - String h = hints[i].strip_edges(); - if (h == "attenuation") { + const String hint = hints[i].strip_edges(); + if (hint == "attenuation") { flip = true; } - if (h == "inout") { - full = true; + if (hint == "positive_only") { + positive_only = true; } } - editor->setup(full, flip); + editor->setup(positive_only, flip); return editor; } else { @@ -3954,6 +4328,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ return editor; } break; + case Variant::VECTOR4: { + EditorPropertyVector4 *editor = memnew(EditorPropertyVector4); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; + + } break; + case Variant::VECTOR4I: { + EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); + return editor; + + } break; case Variant::TRANSFORM2D: { EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); @@ -3991,6 +4379,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ return editor; } break; + case Variant::PROJECTION: { + EditorPropertyProjection *editor = memnew(EditorPropertyProjection); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; + + } break; // misc types case Variant::COLOR: { @@ -4042,11 +4437,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { - String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); - for (int i = 0; i < open_in_new.get_slice_count(","); i++) { - String type = open_in_new.get_slicec(',', i).strip_edges(); + const PackedStringArray open_in_new_inspector = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); + + for (const String &type : open_in_new_inspector) { for (int j = 0; j < p_hint_text.get_slice_count(","); j++) { - String inherits = p_hint_text.get_slicec(',', j); + const String inherits = p_hint_text.get_slicec(',', j); if (ClassDB::is_parent_class(inherits, type)) { editor->set_use_sub_inspector(false); } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 7bec2d0013..c1dfb5cb1e 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -142,6 +142,8 @@ class EditorPropertyPath : public EditorProperty { void _path_selected(const String &p_path); void _path_pressed(); void _path_focus_exited(); + void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; protected: virtual void _set_read_only(bool p_read_only) override; @@ -340,13 +342,14 @@ private: String basename; LayerType layer_type; PopupMenu *layers = nullptr; - Button *button = nullptr; + TextureButton *button = nullptr; void _button_pressed(); void _menu_pressed(int p_menu); void _refresh_names(); protected: + void _notification(int p_what); virtual void _set_read_only(bool p_read_only) override; static void _bind_methods(); @@ -443,6 +446,7 @@ class EditorPropertyEasing : public EditorProperty { bool dragging = false; bool full = false; bool flip = false; + bool positive_only = false; enum { EASING_ZERO, @@ -471,7 +475,7 @@ protected: public: virtual void update_property() override; - void setup(bool p_full, bool p_flip); + void setup(bool p_positive_only, bool p_flip); EditorPropertyEasing(); }; @@ -636,6 +640,40 @@ public: EditorPropertyQuaternion(); }; +class EditorPropertyVector4 : public EditorProperty { + GDCLASS(EditorPropertyVector4, EditorProperty); + EditorSpinSlider *spin[4]; + bool setting = false; + void _value_changed(double p_val, const String &p_name); + +protected: + virtual void _set_read_only(bool p_read_only) override; + void _notification(int p_what); + static void _bind_methods(); + +public: + virtual void update_property() override; + void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String()); + EditorPropertyVector4(); +}; + +class EditorPropertyVector4i : public EditorProperty { + GDCLASS(EditorPropertyVector4i, EditorProperty); + EditorSpinSlider *spin[4]; + bool setting = false; + void _value_changed(double p_val, const String &p_name); + +protected: + virtual void _set_read_only(bool p_read_only) override; + void _notification(int p_what); + static void _bind_methods(); + +public: + virtual void update_property() override; + void setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix = String()); + EditorPropertyVector4i(); +}; + class EditorPropertyAABB : public EditorProperty { GDCLASS(EditorPropertyAABB, EditorProperty); EditorSpinSlider *spin[6]; @@ -705,6 +743,24 @@ public: EditorPropertyTransform3D(); }; +class EditorPropertyProjection : public EditorProperty { + GDCLASS(EditorPropertyProjection, EditorProperty); + EditorSpinSlider *spin[16]; + bool setting = false; + void _value_changed(double p_val, const String &p_name); + +protected: + virtual void _set_read_only(bool p_read_only) override; + void _notification(int p_what); + static void _bind_methods(); + +public: + virtual void update_property() override; + virtual void update_using_transform(Projection p_transform); + void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String()); + EditorPropertyProjection(); +}; + class EditorPropertyColor : public EditorProperty { GDCLASS(EditorPropertyColor, EditorProperty); ColorPickerButton *picker = nullptr; @@ -804,6 +860,7 @@ public: void collapse_all_folding() override; void expand_all_folding() override; + void expand_revertable() override; void set_use_sub_inspector(bool p_enable); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index f1a3fe0c57..9a83082d1e 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -211,7 +211,14 @@ void EditorPropertyArray::update_property() { String array_type_name = Variant::get_type_name(array_type); if (array_type == Variant::ARRAY && subtype != Variant::NIL) { - array_type_name = vformat("%s[%s]", array_type_name, Variant::get_type_name(subtype)); + String type_name; + if (subtype == Variant::OBJECT && subtype_hint == PROPERTY_HINT_RESOURCE_TYPE) { + type_name = subtype_hint_string; + } else { + type_name = Variant::get_type_name(subtype); + } + + array_type_name = vformat("%s[%s]", array_type_name, type_name); } if (array.get_type() == Variant::NIL) { @@ -322,7 +329,7 @@ void EditorPropertyArray::update_property() { reorder_button->set_icon(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE); reorder_button->connect("gui_input", callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input)); - reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down), varray(i + offset)); + reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down).bind(i + offset)); reorder_button->connect("button_up", callable_mp(this, &EditorPropertyArray::_reorder_button_up)); hbox->add_child(reorder_button); @@ -359,11 +366,11 @@ void EditorPropertyArray::update_property() { Button *edit = memnew(Button); edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); hbox->add_child(edit); - edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type), varray(edit, i + offset)); + edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type).bind(edit, i + offset)); } else { Button *remove = memnew(Button); remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed), varray(i + offset)); + remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed).bind(i + offset)); hbox->add_child(remove); } @@ -942,6 +949,18 @@ void EditorPropertyDictionary::update_property() { prop = editor; } break; + case Variant::VECTOR4: { + EditorPropertyVector4 *editor = memnew(EditorPropertyVector4); + editor->setup(-100000, 100000, default_float_step, true); + prop = editor; + + } break; + case Variant::VECTOR4I: { + EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i); + editor->setup(-100000, 100000, true); + prop = editor; + + } break; case Variant::TRANSFORM2D: { EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); editor->setup(-100000, 100000, default_float_step, true); @@ -978,6 +997,12 @@ void EditorPropertyDictionary::update_property() { prop = editor; } break; + case Variant::PROJECTION: { + EditorPropertyProjection *editor = memnew(EditorPropertyProjection); + editor->setup(-100000, 100000, default_float_step, true); + prop = editor; + + } break; // Miscellaneous types. case Variant::COLOR: { @@ -1111,7 +1136,7 @@ void EditorPropertyDictionary::update_property() { Button *edit = memnew(Button); edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); hbox->add_child(edit); - edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type), varray(edit, change_index)); + edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type).bind(edit, change_index)); prop->update_property(); @@ -1350,7 +1375,7 @@ void EditorPropertyLocalizableString::update_property() { Button *edit = memnew(Button); edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); hbox->add_child(edit); - edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index)); + edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item).bind(edit, remove_index)); prop->update_property(); } diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 44623149d0..82aeebe14a 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -81,10 +81,7 @@ class EditorPropertyArray : public EditorProperty { GDCLASS(EditorPropertyArray, EditorProperty); PopupMenu *change_type = nullptr; - bool updating = false; - bool dropping = false; - Ref<EditorPropertyArrayObject> object; int page_length = 20; int page_index = 0; int changing_type_index; @@ -106,29 +103,35 @@ class EditorPropertyArray : public EditorProperty { Button *reorder_selected_button = nullptr; void _page_changed(int p_page); - void _length_changed(double p_page); - void _add_element(); - void _edit_pressed(); - void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); - void _change_type(Object *p_button, int p_index); - void _change_type_menu(int p_index); - - void _object_id_selected(const StringName &p_property, ObjectID p_id); - void _remove_pressed(int p_index); - - void _button_draw(); - bool _is_drop_valid(const Dictionary &p_drag_data) const; - bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; - void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); void _reorder_button_gui_input(const Ref<InputEvent> &p_event); void _reorder_button_down(int p_index); void _reorder_button_up(); protected: + Ref<EditorPropertyArrayObject> object; + + bool updating = false; + bool dropping = false; + static void _bind_methods(); void _notification(int p_what); + virtual void _add_element(); + virtual void _length_changed(double p_page); + virtual void _edit_pressed(); + virtual void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); + virtual void _change_type(Object *p_button, int p_index); + virtual void _change_type_menu(int p_index); + + virtual void _object_id_selected(const StringName &p_property, ObjectID p_id); + virtual void _remove_pressed(int p_index); + + virtual void _button_draw(); + virtual bool _is_drop_valid(const Dictionary &p_drag_data) const; + virtual bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + virtual void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + public: void setup(Variant::Type p_array_type, const String &p_hint_string = ""); virtual void update_property() override; diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 09d2992e07..6c713de94a 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -114,6 +114,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["bidi"] = "BiDi"; capitalize_string_remaps["bp"] = "BP"; capitalize_string_remaps["bpc"] = "BPC"; + capitalize_string_remaps["bpm"] = "BPM"; capitalize_string_remaps["bptc"] = "BPTC"; capitalize_string_remaps["bvh"] = "BVH"; capitalize_string_remaps["ca"] = "CA"; diff --git a/editor/quick_open.cpp b/editor/editor_quick_open.cpp index 4f7f9fc78c..539cb7cd8a 100644 --- a/editor/quick_open.cpp +++ b/editor/editor_quick_open.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* quick_open.cpp */ +/* editor_quick_open.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "quick_open.h" +#include "editor_quick_open.h" #include "core/os/keyboard.h" diff --git a/editor/quick_open.h b/editor/editor_quick_open.h index 843ef47711..e41a8c7e75 100644 --- a/editor/quick_open.h +++ b/editor/editor_quick_open.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* quick_open.h */ +/* editor_quick_open.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 2e78b58e11..e5c1836205 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -30,14 +30,16 @@ #include "editor_resource_picker.h" +#include "editor/audio_stream_preview.h" #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" +#include "editor/editor_quick_open.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/filesystem_dock.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/script_editor_plugin.h" -#include "editor/quick_open.h" #include "editor/scene_tree_dock.h" HashMap<StringName, List<StringName>> EditorResourcePicker::allowed_types_cache; @@ -47,32 +49,37 @@ void EditorResourcePicker::clear_caches() { } void EditorResourcePicker::_update_resource() { - preview_rect->set_texture(Ref<Texture2D>()); - assign_button->set_custom_minimum_size(Size2(1, 1)); + String resource_path; + if (edited_resource.is_valid() && edited_resource->get_path().is_resource_file()) { + resource_path = edited_resource->get_path() + "\n"; + } - if (edited_resource == Ref<Resource>()) { - assign_button->set_icon(Ref<Texture2D>()); - assign_button->set_text(TTR("[empty]")); - assign_button->set_tooltip(""); - } else { - assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); + if (preview_rect) { + preview_rect->set_texture(Ref<Texture2D>()); - if (!edited_resource->get_name().is_empty()) { - assign_button->set_text(edited_resource->get_name()); - } else if (edited_resource->get_path().is_resource_file()) { - assign_button->set_text(edited_resource->get_path().get_file()); + assign_button->set_custom_minimum_size(assign_button_min_size); + + if (edited_resource == Ref<Resource>()) { + assign_button->set_icon(Ref<Texture2D>()); + assign_button->set_text(TTR("[empty]")); + assign_button->set_tooltip(""); } else { - assign_button->set_text(edited_resource->get_class()); - } + assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); - String resource_path; - if (edited_resource->get_path().is_resource_file()) { - resource_path = edited_resource->get_path() + "\n"; + if (!edited_resource->get_name().is_empty()) { + assign_button->set_text(edited_resource->get_name()); + } else if (edited_resource->get_path().is_resource_file()) { + assign_button->set_text(edited_resource->get_path().get_file()); + } else { + assign_button->set_text(edited_resource->get_class()); + } + assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); + + // Preview will override the above, so called at the end. + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); } + } else if (edited_resource.is_valid()) { assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); - - // Preview will override the above, so called at the end. - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); } } @@ -81,28 +88,30 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const return; } - Ref<Script> script = edited_resource; - if (script.is_valid()) { - assign_button->set_text(script->get_path().get_file()); - return; - } + if (preview_rect) { + Ref<Script> script = edited_resource; + if (script.is_valid()) { + assign_button->set_text(script->get_path().get_file()); + return; + } - if (p_preview.is_valid()) { - preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); + if (p_preview.is_valid()) { + preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); - // Resource-specific stretching. - if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) { - preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); - assign_button->set_custom_minimum_size(Size2(1, 1)); - } else { - preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; - assign_button->set_custom_minimum_size(Size2(1, thumbnail_size)); - } + // Resource-specific stretching. + if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) { + preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); + assign_button->set_custom_minimum_size(assign_button_min_size); + } else { + preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + assign_button->set_custom_minimum_size(Size2(MIN(1, assign_button_min_size.x), MIN(thumbnail_size, assign_button_min_size.y))); + } - preview_rect->set_texture(p_preview); - assign_button->set_text(""); + preview_rect->set_texture(p_preview); + assign_button->set_text(""); + } } } @@ -175,6 +184,21 @@ void EditorResourcePicker::_update_menu_items() { edit_menu->add_icon_item(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), TTR("Edit"), OBJ_MENU_EDIT); edit_menu->add_icon_item(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), TTR("Clear"), OBJ_MENU_CLEAR); edit_menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); + + // Check whether the resource has subresources. + List<PropertyInfo> property_list; + edited_resource->get_property_list(&property_list); + bool has_subresources = false; + for (PropertyInfo &p : property_list) { + if ((p.type == Variant::OBJECT) && (p.hint == PROPERTY_HINT_RESOURCE_TYPE) && (p.name != "script")) { + has_subresources = true; + break; + } + } + if (has_subresources) { + edit_menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Make Unique (Recursive)"), OBJ_MENU_MAKE_UNIQUE_RECURSIVE); + } + edit_menu->add_icon_item(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")), TTR("Save"), OBJ_MENU_SAVE); if (edited_resource->get_path().is_resource_file()) { @@ -288,28 +312,22 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { return; } - List<PropertyInfo> property_list; - edited_resource->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - for (const PropertyInfo &pi : property_list) { - Pair<String, Variant> p; - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = edited_resource->get(pi.name); - } + Ref<Resource> unique_resource = edited_resource->duplicate(); + ERR_FAIL_COND(unique_resource.is_null()); - propvalues.push_back(p); + edited_resource = unique_resource; + emit_signal(SNAME("resource_changed"), edited_resource); + _update_resource(); + } break; + + case OBJ_MENU_MAKE_UNIQUE_RECURSIVE: { + if (edited_resource.is_null()) { + return; } - String orig_type = edited_resource->get_class(); - Object *inst = ClassDB::instantiate(orig_type); - Ref<Resource> unique_resource = Ref<Resource>(Object::cast_to<Resource>(inst)); + Ref<Resource> unique_resource = edited_resource->duplicate(true); ERR_FAIL_COND(unique_resource.is_null()); - for (const Pair<String, Variant> &p : propvalues) { - unique_resource->set(p.first, p.second); - } - edited_resource = unique_resource; emit_signal(SNAME("resource_changed"), edited_resource); _update_resource(); @@ -863,10 +881,10 @@ void EditorResourcePicker::_ensure_resource_menu() { edit_menu = memnew(PopupMenu); add_child(edit_menu); edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk)); - edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false)); + edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed).bind(false)); } -EditorResourcePicker::EditorResourcePicker() { +EditorResourcePicker::EditorResourcePicker(bool p_hide_assign_button_controls) { assign_button = memnew(Button); assign_button->set_flat(true); assign_button->set_h_size_flags(SIZE_EXPAND_FILL); @@ -877,13 +895,15 @@ EditorResourcePicker::EditorResourcePicker() { assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw)); assign_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input)); - preview_rect = memnew(TextureRect); - preview_rect->set_ignore_texture_size(true); - preview_rect->set_anchors_and_offsets_preset(PRESET_WIDE); - preview_rect->set_offset(SIDE_TOP, 1); - preview_rect->set_offset(SIDE_BOTTOM, -1); - preview_rect->set_offset(SIDE_RIGHT, -1); - assign_button->add_child(preview_rect); + if (!p_hide_assign_button_controls) { + preview_rect = memnew(TextureRect); + preview_rect->set_ignore_texture_size(true); + preview_rect->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + preview_rect->set_offset(SIDE_TOP, 1); + preview_rect->set_offset(SIDE_BOTTOM, -1); + preview_rect->set_offset(SIDE_RIGHT, -1); + assign_button->add_child(preview_rect); + } edit_button = memnew(Button); edit_button->set_flat(true); @@ -993,3 +1013,176 @@ void EditorShaderPicker::set_preferred_mode(int p_mode) { EditorShaderPicker::EditorShaderPicker() { } + +////////////// + +void EditorAudioStreamPicker::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: + case NOTIFICATION_THEME_CHANGED: { + _update_resource(); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + Ref<AudioStream> audio_stream = get_edited_resource(); + if (audio_stream.is_valid()) { + if (audio_stream->get_length() > 0) { + Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(audio_stream); + if (preview.is_valid()) { + if (preview->get_version() != last_preview_version) { + stream_preview_rect->update(); + last_preview_version = preview->get_version(); + } + } + } + + uint64_t tagged_frame = audio_stream->get_tagged_frame(); + uint64_t diff_frames = AudioServer::get_singleton()->get_mixed_frames() - tagged_frame; + uint64_t diff_msec = diff_frames * 1000 / AudioServer::get_singleton()->get_mix_rate(); + + if (diff_msec < 300) { + uint32_t count = audio_stream->get_tagged_frame_count(); + + bool differ = false; + + if (count != tagged_frame_offset_count) { + differ = true; + } + float offsets[MAX_TAGGED_FRAMES]; + + for (uint32_t i = 0; i < MIN(count, uint32_t(MAX_TAGGED_FRAMES)); i++) { + offsets[i] = audio_stream->get_tagged_frame_offset(i); + if (offsets[i] != tagged_frame_offsets[i]) { + differ = true; + } + } + + if (differ) { + tagged_frame_offset_count = count; + for (uint32_t i = 0; i < count; i++) { + tagged_frame_offsets[i] = offsets[i]; + } + } + + stream_preview_rect->update(); + } else { + if (tagged_frame_offset_count != 0) { + stream_preview_rect->update(); + } + tagged_frame_offset_count = 0; + } + } + } break; + } +} + +void EditorAudioStreamPicker::_update_resource() { + EditorResourcePicker::_update_resource(); + + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); + Ref<AudioStream> audio_stream = get_edited_resource(); + if (audio_stream.is_valid() && audio_stream->get_length() > 0.0) { + set_assign_button_min_size(Size2(1, font->get_height(font_size) * 3)); + } else { + set_assign_button_min_size(Size2(1, font->get_height(font_size) * 1.5)); + } + + stream_preview_rect->update(); +} + +void EditorAudioStreamPicker::_preview_draw() { + Ref<AudioStream> audio_stream = get_edited_resource(); + if (!audio_stream.is_valid()) { + get_assign_button()->set_text(TTR("[empty]")); + return; + } + + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); + + get_assign_button()->set_text(""); + + Size2i size = stream_preview_rect->get_size(); + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + + Rect2 rect(Point2(), size); + + if (audio_stream->get_length() > 0) { + rect.size.height *= 0.5; + + stream_preview_rect->draw_rect(rect, Color(0, 0, 0, 1)); + + Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(audio_stream); + float preview_len = preview->get_length(); + + Vector<Vector2> lines; + lines.resize(size.width * 2); + + for (int i = 0; i < size.width; i++) { + float ofs = i * preview_len / size.width; + float ofs_n = (i + 1) * preview_len / size.width; + float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5; + float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; + + int idx = i; + lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y); + lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y); + } + + Vector<Color> color; + color.push_back(get_theme_color(SNAME("contrast_color_2"), SNAME("Editor"))); + + RS::get_singleton()->canvas_item_add_multiline(stream_preview_rect->get_canvas_item(), lines, color); + + if (tagged_frame_offset_count) { + Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + + for (uint32_t i = 0; i < tagged_frame_offset_count; i++) { + int x = CLAMP(tagged_frame_offsets[i] * size.width / preview_len, 0, size.width); + if (x == 0) { + continue; // Because some may always return 0, ignore offset 0. + } + stream_preview_rect->draw_rect(Rect2i(x, 0, 2, rect.size.height), accent); + } + } + rect.position.y += rect.size.height; + } + + Ref<Texture2D> icon; + Color icon_modulate(1, 1, 1, 1); + + if (tagged_frame_offset_count > 0) { + icon = get_theme_icon(SNAME("Play"), SNAME("EditorIcons")); + if ((OS::get_singleton()->get_ticks_msec() % 500) > 250) { + icon_modulate = Color(1, 0.5, 0.5, 1); // get_theme_color(SNAME("accent_color"), SNAME("Editor")); + } + } else { + icon = EditorNode::get_singleton()->get_object_icon(audio_stream.operator->(), "Object"); + } + String text; + if (!audio_stream->get_name().is_empty()) { + text = audio_stream->get_name(); + } else if (audio_stream->get_path().is_resource_file()) { + text = audio_stream->get_path().get_file(); + } else { + text = audio_stream->get_class().replace_first("AudioStream", ""); + } + + stream_preview_rect->draw_texture(icon, Point2i(EDSCALE * 2, rect.position.y + (rect.size.height - icon->get_height()) / 2), icon_modulate); + stream_preview_rect->draw_string(font, Point2i(EDSCALE * 2 + icon->get_width(), rect.position.y + font->get_ascent(font_size) + (rect.size.height - font->get_height(font_size)) / 2), text, HORIZONTAL_ALIGNMENT_CENTER, size.width - 4 * EDSCALE - icon->get_width()); +} + +EditorAudioStreamPicker::EditorAudioStreamPicker() : + EditorResourcePicker(true) { + stream_preview_rect = memnew(Control); + + stream_preview_rect->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + stream_preview_rect->set_offset(SIDE_TOP, 1); + stream_preview_rect->set_offset(SIDE_BOTTOM, -1); + stream_preview_rect->set_offset(SIDE_RIGHT, -1); + stream_preview_rect->set_mouse_filter(MOUSE_FILTER_IGNORE); + stream_preview_rect->connect("draw", callable_mp(this, &EditorAudioStreamPicker::_preview_draw)); + + get_assign_button()->add_child(stream_preview_rect); + get_assign_button()->move_child(stream_preview_rect, 0); + set_process_internal(true); +} diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index 8e26e1f4c0..3a4d5985bd 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -58,12 +58,15 @@ class EditorResourcePicker : public HBoxContainer { EditorFileDialog *file_dialog = nullptr; EditorQuickOpen *quick_open = nullptr; + Size2i assign_button_min_size = Size2i(1, 1); + enum MenuOption { OBJ_MENU_LOAD, OBJ_MENU_QUICKLOAD, OBJ_MENU_EDIT, OBJ_MENU_CLEAR, OBJ_MENU_MAKE_UNIQUE, + OBJ_MENU_MAKE_UNIQUE_RECURSIVE, OBJ_MENU_SAVE, OBJ_MENU_COPY, OBJ_MENU_PASTE, @@ -75,7 +78,6 @@ class EditorResourcePicker : public HBoxContainer { PopupMenu *edit_menu = nullptr; - void _update_resource(); void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj); void _resource_selected(); @@ -100,9 +102,17 @@ class EditorResourcePicker : public HBoxContainer { void _ensure_resource_menu(); protected: + virtual void _update_resource(); + + Button *get_assign_button() { return assign_button; } static void _bind_methods(); void _notification(int p_what); + void set_assign_button_min_size(const Size2i &p_size) { + assign_button_min_size = p_size; + assign_button->set_custom_minimum_size(assign_button_min_size); + } + GDVIRTUAL1(_set_create_options, Object *) GDVIRTUAL1R(bool, _handle_menu_selected, int) @@ -126,7 +136,7 @@ public: virtual void set_create_options(Object *p_menu_node); virtual bool handle_menu_selected(int p_which); - EditorResourcePicker(); + EditorResourcePicker(bool p_hide_assign_button_controls = false); }; class EditorScriptPicker : public EditorResourcePicker { @@ -173,4 +183,26 @@ public: EditorShaderPicker(); }; +class EditorAudioStreamPicker : public EditorResourcePicker { + GDCLASS(EditorAudioStreamPicker, EditorResourcePicker); + + uint64_t last_preview_version = 0; + Control *stream_preview_rect = nullptr; + + enum { + MAX_TAGGED_FRAMES = 8 + }; + float tagged_frame_offsets[MAX_TAGGED_FRAMES]; + uint32_t tagged_frame_offset_count = 0; + + void _preview_draw(); + virtual void _update_resource() override; + +protected: + void _notification(int p_what); + +public: + EditorAudioStreamPicker(); +}; + #endif // EDITOR_RESOURCE_PICKER_H diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index b84e654d42..c0ea2b743e 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -195,9 +195,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< if (r_texture.is_valid()) { //wow it generated a preview... save cache bool has_small_texture = r_small_texture.is_valid(); - ResourceSaver::save(cache_base + ".png", r_texture); + ResourceSaver::save(r_texture, cache_base + ".png"); if (has_small_texture) { - ResourceSaver::save(cache_base + "_small.png", r_small_texture); + ResourceSaver::save(r_small_texture, cache_base + "_small.png"); } Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions."); diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 820e22bdc8..0413477d88 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORRESOURCEPREVIEW_H -#define EDITORRESOURCEPREVIEW_H +#ifndef EDITOR_RESOURCE_PREVIEW_H +#define EDITOR_RESOURCE_PREVIEW_H #include "core/os/semaphore.h" #include "core/os/thread.h" @@ -124,4 +124,4 @@ public: ~EditorResourcePreview(); }; -#endif // EDITORRESOURCEPREVIEW_H +#endif // EDITOR_RESOURCE_PREVIEW_H diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index ba49c6dc5f..6ce8625daa 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -55,7 +55,7 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) { args.push_back("--remote-debug"); args.push_back(EditorDebuggerNode::get_singleton()->get_server_uri()); - args.push_back("--allow_focus_steal_pid"); + args.push_back("--editor-pid"); args.push_back(itos(OS::get_singleton()->get_process_id())); bool debug_collisions = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false); diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 854885c707..d8b738be17 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -30,9 +30,10 @@ #include "editor_run_native.h" -#include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "editor/export/editor_export_platform.h" void EditorRunNative::_notification(int p_what) { switch (p_what) { @@ -51,8 +52,8 @@ void EditorRunNative::_notification(int p_what) { im->resize(16 * EDSCALE, 16 * EDSCALE); Ref<ImageTexture> small_icon = ImageTexture::create_from_image(im); MenuButton *mb = memnew(MenuButton); - mb->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native), varray(i)); - mb->connect("pressed", callable_mp(this, &EditorRunNative::run_native), varray(-1, i)); + mb->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native).bind(i)); + mb->connect("pressed", callable_mp(this, &EditorRunNative::run_native).bind(-1, i)); mb->set_icon(small_icon); add_child(mb); menus[i] = mb; diff --git a/editor/editor_scale.h b/editor/editor_scale.h index 918fde15fb..02e9b997f6 100644 --- a/editor/editor_scale.h +++ b/editor/editor_scale.h @@ -35,4 +35,5 @@ void editor_set_scale(float p_scale); float editor_get_scale(); #define EDSCALE (editor_get_scale()) + #endif // EDITOR_SCALE_H diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h index babd11eb69..758efae31e 100644 --- a/editor/editor_sectioned_inspector.h +++ b/editor/editor_sectioned_inspector.h @@ -76,4 +76,5 @@ public: SectionedInspector(); ~SectionedInspector(); }; + #endif // EDITOR_SECTIONED_INSPECTOR_H diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index fa8643af86..80e77a1125 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -414,7 +414,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_variations", ""); _initial_set("interface/editor/font_antialiased", true); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") #else EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (Light),None,Light,Normal") @@ -544,6 +544,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/behavior/navigation/smooth_scrolling", true); EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/navigation/v_scroll_speed", 80, "1,10000,1") _initial_set("text_editor/behavior/navigation/drag_and_drop_selection", true); + _initial_set("text_editor/behavior/navigation/stay_in_script_editor_on_node_selected", true); // Behavior: Indent EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/behavior/indent/type", 0, "Tabs,Spaces") @@ -684,7 +685,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Visual editors EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01") EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/lines_curvature", 0.5, "0.0,1.0,0.01") - EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visualshader/port_preview_size", 160, "100,400,0.01") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visual_shader/port_preview_size", 160, "100,400,0.01") /* Run */ @@ -866,7 +867,6 @@ void EditorSettings::create() { } singleton->save_changed_setting = true; - singleton->config_file_path = config_file_path; print_verbose("EditorSettings: Load OK!"); @@ -891,8 +891,8 @@ fail: } singleton = Ref<EditorSettings>(memnew(EditorSettings)); + singleton->set_path(config_file_path, true); singleton->save_changed_setting = true; - singleton->config_file_path = config_file_path; singleton->_load_defaults(extra_config); singleton->setup_language(); singleton->setup_network(); @@ -952,15 +952,10 @@ void EditorSettings::save() { return; } - if (singleton->config_file_path.is_empty()) { - ERR_PRINT("Cannot save EditorSettings config, no valid path"); - return; - } - - Error err = ResourceSaver::save(singleton->config_file_path, singleton); + Error err = ResourceSaver::save(singleton); if (err != OK) { - ERR_PRINT("Error saving editor settings to " + singleton->config_file_path); + ERR_PRINT("Error saving editor settings to " + singleton->get_path()); } else { singleton->changed_settings.clear(); print_verbose("EditorSettings: Save OK!"); @@ -1056,6 +1051,8 @@ void EditorSettings::set_initial_value(const StringName &p_setting, const Varian } Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_restart_if_changed) { + ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), p_default, "EditorSettings not instantiated yet."); + Variant ret = p_default; if (EditorSettings::get_singleton()->has_setting(p_setting)) { ret = EditorSettings::get_singleton()->get(p_setting); @@ -1072,7 +1069,7 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re } Variant _EDITOR_GET(const String &p_setting) { - ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant()); + ERR_FAIL_COND_V(!EditorSettings::get_singleton() || !EditorSettings::get_singleton()->has_setting(p_setting), Variant()); return EditorSettings::get_singleton()->get(p_setting); } @@ -1102,38 +1099,11 @@ void EditorSettings::add_property_hint(const PropertyInfo &p_hint) { hints[p_hint.name] = p_hint; } -// Editor data and config directories -// EditorPaths::create() is responsible for the creation of these directories. - -String EditorSettings::get_templates_dir() const { - return EditorPaths::get_singleton()->get_data_dir().plus_file("templates"); -} - -String EditorSettings::get_project_settings_dir() const { - return EditorPaths::get_singleton()->get_project_data_dir().plus_file("editor"); -} - -String EditorSettings::get_text_editor_themes_dir() const { - return EditorPaths::get_singleton()->get_config_dir().plus_file("text_editor_themes"); -} - -String EditorSettings::get_script_templates_dir() const { - return EditorPaths::get_singleton()->get_config_dir().plus_file("script_templates"); -} - -String EditorSettings::get_project_script_templates_dir() const { - return ProjectSettings::get_singleton()->get("editor/script/templates_search_path"); -} - -String EditorSettings::get_feature_profiles_dir() const { - return EditorPaths::get_singleton()->get_config_dir().plus_file("feature_profiles"); -} - // Metadata void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) { Ref<ConfigFile> cf = memnew(ConfigFile); - String path = get_project_settings_dir().plus_file("project_metadata.cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("project_metadata.cfg"); Error err; err = cf->load(path); ERR_FAIL_COND_MSG(err != OK && err != ERR_FILE_NOT_FOUND, "Cannot load editor settings from file '" + path + "'."); @@ -1144,7 +1114,7 @@ void EditorSettings::set_project_metadata(const String &p_section, const String Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const { Ref<ConfigFile> cf = memnew(ConfigFile); - String path = get_project_settings_dir().plus_file("project_metadata.cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("project_metadata.cfg"); Error err = cf->load(path); if (err != OK) { return p_default; @@ -1158,7 +1128,7 @@ void EditorSettings::set_favorites(const Vector<String> &p_favorites) { if (Engine::get_singleton()->is_project_manager_hint()) { favorites_file = EditorPaths::get_singleton()->get_config_dir().plus_file("favorite_dirs"); } else { - favorites_file = get_project_settings_dir().plus_file("favorites"); + favorites_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites"); } Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::WRITE); if (f.is_valid()) { @@ -1178,7 +1148,7 @@ void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) { if (Engine::get_singleton()->is_project_manager_hint()) { recent_dirs_file = EditorPaths::get_singleton()->get_config_dir().plus_file("recent_dirs"); } else { - recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs"); + recent_dirs_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("recent_dirs"); } Ref<FileAccess> f = FileAccess::open(recent_dirs_file, FileAccess::WRITE); if (f.is_valid()) { @@ -1199,8 +1169,8 @@ void EditorSettings::load_favorites_and_recent_dirs() { favorites_file = EditorPaths::get_singleton()->get_config_dir().plus_file("favorite_dirs"); recent_dirs_file = EditorPaths::get_singleton()->get_config_dir().plus_file("recent_dirs"); } else { - favorites_file = get_project_settings_dir().plus_file("favorites"); - recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs"); + favorites_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites"); + recent_dirs_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("recent_dirs"); } Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::READ); if (f.is_valid()) { @@ -1232,7 +1202,7 @@ bool EditorSettings::is_dark_theme() { void EditorSettings::list_text_editor_themes() { String themes = "Default,Godot 2,Custom"; - Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir()); + Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_text_editor_themes_dir()); if (d.is_valid()) { List<String> custom_themes; d->list_dir_begin(); @@ -1263,7 +1233,7 @@ void EditorSettings::load_text_editor_theme() { return; // sorry for "Settings changed" console spam } - String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet"); + String theme_path = EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file + ".tet"); Ref<ConfigFile> cf = memnew(ConfigFile); Error err = cf->load(theme_path); @@ -1298,9 +1268,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) { return false; } - Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir()); + Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_text_editor_themes_dir()); if (d.is_valid()) { - d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file())); + d->copy(p_file, EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file.get_file())); return true; } } @@ -1313,7 +1283,7 @@ bool EditorSettings::save_text_editor_theme() { if (_is_default_text_editor_theme(p_file.get_file().to_lower())) { return false; } - String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet"); + String theme_path = EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file + ".tet"); return _save_text_editor_theme(theme_path); } @@ -1330,7 +1300,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) { list_text_editor_themes(); String theme_name = p_file.substr(0, p_file.length() - 4).get_file(); - if (p_file.get_base_dir() == get_text_editor_themes_dir()) { + if (p_file.get_base_dir() == EditorPaths::get_singleton()->get_text_editor_themes_dir()) { _initial_set("text_editor/theme/color_theme", theme_name); load_text_editor_theme(); } @@ -1346,7 +1316,7 @@ bool EditorSettings::is_default_text_editor_theme() { Vector<String> EditorSettings::get_script_templates(const String &p_extension, const String &p_custom_path) { Vector<String> templates; - String template_dir = get_script_templates_dir(); + String template_dir = EditorPaths::get_singleton()->get_script_templates_dir(); if (!p_custom_path.is_empty()) { template_dir = p_custom_path; } @@ -1370,7 +1340,7 @@ String EditorSettings::get_editor_layouts_config() const { } float EditorSettings::get_auto_display_scale() const { -#if defined(OSX_ENABLED) || defined(ANDROID_ENABLED) +#if defined(MACOS_ENABLED) || defined(ANDROID_ENABLED) return DisplayServer::get_singleton()->screen_get_max_scale(); #else const int screen = DisplayServer::get_singleton()->window_get_current_screen(); @@ -1454,9 +1424,7 @@ void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) { } Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) { - if (!EditorSettings::get_singleton()) { - return nullptr; - } + ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), nullptr, "EditorSettings not instantiated yet."); Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); @@ -1466,6 +1434,8 @@ Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) { } void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode) { + ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet."); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + "."); @@ -1476,6 +1446,8 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k } void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes) { + ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet."); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + "."); @@ -1489,7 +1461,7 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c for (int i = 0; i < p_keycodes.size(); i++) { Key keycode = (Key)p_keycodes[i]; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS if (keycode == Key::KEY_DELETE) { keycode = KeyModifierMask::CMD | Key::BACKSPACE; @@ -1519,7 +1491,7 @@ Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, cons for (int i = 0; i < p_keycodes.size(); i++) { Key keycode = (Key)p_keycodes[i]; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS if (keycode == Key::KEY_DELETE) { keycode = KeyModifierMask::CMD | Key::BACKSPACE; @@ -1653,8 +1625,6 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert); ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind); - ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir); - ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata); ClassDB::bind_method(D_METHOD("get_project_metadata", "section", "key", "default"), &EditorSettings::get_project_metadata, DEFVAL(Variant())); diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 43f90f9258..5faeec88c8 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -88,8 +88,6 @@ private: mutable HashMap<String, Ref<Shortcut>> shortcuts; HashMap<String, List<Ref<InputEvent>>> builtin_action_overrides; - String config_file_path; - Vector<String> favorites; Vector<String> recent_dirs; @@ -150,14 +148,6 @@ public: void set_resource_clipboard(const Ref<Resource> &p_resource) { clipboard = p_resource; } Ref<Resource> get_resource_clipboard() const { return clipboard; } - String get_data_dir() const; - String get_templates_dir() const; - String get_project_settings_dir() const; - String get_text_editor_themes_dir() const; - String get_script_templates_dir() const; - String get_project_script_templates_dir() const; - String get_feature_profiles_dir() const; - void set_project_metadata(const String &p_section, const String &p_key, Variant p_data); Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const; diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index c651d6bf6e..20e9d7a3df 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -37,7 +37,7 @@ String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { if (grabber->is_visible()) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED Key key = Key::META; #else Key key = Key::CTRL; @@ -652,7 +652,7 @@ void EditorSpinSlider::_ensure_input_popup() { value_input = memnew(LineEdit); value_input_popup->add_child(value_input); value_input_popup->set_wrap_controls(true); - value_input->set_anchors_and_offsets_preset(PRESET_WIDE); + value_input->set_anchors_and_offsets_preset(PRESET_FULL_RECT); value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed)); value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted)); value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited)); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 13109478e4..a3086a2ccf 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -277,6 +277,14 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = exceptions.insert("StatusWarning"); exceptions.insert("OverbrightIndicator"); exceptions.insert("GuiMiniCheckerboard"); + + // Prevents Code Editor icons from changing + exceptions.insert("GuiTab"); + exceptions.insert("GuiSpace"); + exceptions.insert("CodeFoldedRightArrow"); + exceptions.insert("CodeFoldDownArrow"); + exceptions.insert("TextEditorPlay"); + exceptions.insert("Breakpoint"); } // These ones should be converted even if we are using a dark theme. @@ -633,6 +641,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Add a highlight line at the top of the selected tab. style_tab_selected->set_border_width_all(0); + style_tab_selected->set_default_margin(SIDE_LEFT, widget_default_margin.x - border_width); style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); // Make the highlight line prominent, but not too prominent as to not be distracting. Color tab_highlight = dark_color_2.lerp(accent_color, 0.75); @@ -645,6 +654,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // We can't prevent them with both rounded corners and non-zero border width, though style_tab_selected->set_expand_margin_size(SIDE_BOTTOM, corner_width > 0 ? corner_width : border_width); + // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. + style_tab_selected->set_expand_margin_size(SIDE_LEFT, -border_width); + style_tab_selected->set_default_margin(SIDE_LEFT, widget_default_margin.x + 2 * EDSCALE); style_tab_selected->set_default_margin(SIDE_RIGHT, widget_default_margin.x + 2 * EDSCALE); style_tab_selected->set_default_margin(SIDE_BOTTOM, widget_default_margin.y); @@ -822,6 +834,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("pressed", "CheckButton", style_menu); theme->set_stylebox("disabled", "CheckButton", style_menu); theme->set_stylebox("hover", "CheckButton", style_menu); + theme->set_stylebox("hover_pressed", "CheckButton", style_menu); theme->set_icon("on", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), SNAME("EditorIcons"))); theme->set_icon("on_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), SNAME("EditorIcons"))); @@ -859,6 +872,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("pressed", "CheckBox", sb_checkbox); theme->set_stylebox("disabled", "CheckBox", sb_checkbox); theme->set_stylebox("hover", "CheckBox", sb_checkbox); + theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox); theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), SNAME("EditorIcons"))); theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), SNAME("EditorIcons"))); theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), SNAME("EditorIcons"))); @@ -887,17 +901,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("panel", "PopupDialog", style_popup); // PopupMenu - const int popup_menu_margin_size = default_margin_size * 1.5 * EDSCALE; Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate(); // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, // and it looks weird. 1px solves this. - style_popup_menu->set_default_margin(SIDE_LEFT, 1 * EDSCALE); - style_popup_menu->set_default_margin(SIDE_TOP, popup_menu_margin_size); - style_popup_menu->set_default_margin(SIDE_RIGHT, 1 * EDSCALE); - style_popup_menu->set_default_margin(SIDE_BOTTOM, popup_menu_margin_size); + style_popup_menu->set_default_margin(SIDE_LEFT, EDSCALE); + style_popup_menu->set_default_margin(SIDE_TOP, 2 * EDSCALE); + style_popup_menu->set_default_margin(SIDE_RIGHT, EDSCALE); + style_popup_menu->set_default_margin(SIDE_BOTTOM, 2 * EDSCALE); // Always display a border for PopupMenus so they can be distinguished from their background. - style_popup_menu->set_border_width_all(1 * EDSCALE); + style_popup_menu->set_border_width_all(EDSCALE); style_popup_menu->set_border_color(dark_color_2); theme->set_stylebox("panel", "PopupMenu", style_popup_menu); @@ -931,12 +944,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Force the v_separation to be even so that the spacing on top and bottom is even. // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided. - // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example) - int vsep_base = extra_spacing + default_margin_size + 2; - int force_even_vsep = vsep_base + (vsep_base % 2); + // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example). + const int vsep_base = extra_spacing + default_margin_size + 6; + const int force_even_vsep = vsep_base + (vsep_base % 2); theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE); - theme->set_constant("item_start_padding", "PopupMenu", popup_menu_margin_size * EDSCALE); - theme->set_constant("item_end_padding", "PopupMenu", popup_menu_margin_size * EDSCALE); + theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); + theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); // Sub-inspectors for (int i = 0; i < 16; i++) { @@ -1652,6 +1665,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_dictionary_add_item->set_expand_margin_size(SIDE_RIGHT, 4 * EDSCALE); theme->set_stylebox("DictionaryAddItem", "EditorStyles", style_dictionary_add_item); + Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1); + theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style); + // adaptive script theme constants // for comments and elements with lower relevance const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5); @@ -1659,19 +1675,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const float mono_value = mono_color.r; const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); - const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.7); - - // editor main color - const Color main_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0.02, 0.5, 1.0); + const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); - const Color symbol_color = Color(0.34, 0.57, 1.0).lerp(mono_color, dark_theme ? 0.5 : 0.3); - const Color keyword_color = Color(1.0, 0.44, 0.52); - const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.8, 0.4, 0.6); - const Color basetype_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0.0, 0.76, 0.38); - const Color type_color = basetype_color.lerp(mono_color, dark_theme ? 0.4 : 0.3); - const Color usertype_color = basetype_color.lerp(mono_color, dark_theme ? 0.7 : 0.5); - const Color comment_color = dim_color; - const Color string_color = (dark_theme ? Color(1.0, 0.85, 0.26) : Color(1.0, 0.82, 0.09)).lerp(mono_color, dark_theme ? 0.5 : 0.3); + const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); + const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); + const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); + const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); + const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); + const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); + const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); + const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); // Use the brightest background color on a light theme (which generally uses a negative contrast rate). const Color te_background_color = dark_theme ? background_color : dark_color_3; @@ -1684,24 +1697,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color completion_font_color = font_color; const Color text_color = font_color; const Color line_number_color = dim_color; - const Color safe_line_number_color = dim_color * Color(1, 1.2, 1, 1.5); + const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); const Color caret_color = mono_color; const Color caret_background_color = mono_color.inverted(); const Color text_selected_color = dark_color_3; - const Color brace_mismatch_color = error_color; + const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1); const Color current_line_color = alpha1; const Color line_length_guideline_color = dark_theme ? base_color : background_color; const Color word_highlighted_color = alpha1; - const Color number_color = basetype_color.lerp(mono_color, dark_theme ? 0.5 : 0.3); - const Color function_color = main_color; - const Color member_variable_color = main_color.lerp(mono_color, 0.6); + const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); + const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); + const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1); 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 breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1); 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); + const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); EditorSettings *setting = EditorSettings::get_singleton(); String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); @@ -1709,9 +1722,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/base_type_color", basetype_color, true); - setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/user_type_color", usertype_color, true); + setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); @@ -1749,17 +1762,21 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Now theme is loaded, apply it to CodeEdit. theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), SNAME("EditorFonts"))); theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), SNAME("EditorFonts"))); + Ref<StyleBoxFlat> code_edit_stylebox = make_flat_stylebox(EDITOR_GET("text_editor/theme/highlighting/background_color"), widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y, corner_radius); theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox); theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox); theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), SNAME("EditorIcons"))); theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), SNAME("EditorIcons"))); - theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons"))); - theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons"))); - theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), SNAME("EditorIcons"))); + theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), SNAME("EditorIcons"))); + theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), SNAME("EditorIcons"))); theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), SNAME("EditorIcons"))); + theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing")); + theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color")); theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color")); diff --git a/editor/editor_themes.h b/editor/editor_themes.h index 642558d774..95184b9d4a 100644 --- a/editor/editor_themes.h +++ b/editor/editor_themes.h @@ -40,4 +40,4 @@ Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr); Ref<ImageTexture> create_unscaled_default_project_icon(); -#endif +#endif // EDITOR_THEMES_H diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 4986bccc35..050cde6069 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -356,7 +356,7 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_ break; } panel->set_modulate(Color(1, 1, 1, 0)); - panel->connect("draw", callable_bind(callable_mp(this, &EditorToaster::_draw_progress), panel)); + panel->connect("draw", callable_mp(this, &EditorToaster::_draw_progress).bind(panel)); // Horizontal container. HBoxContainer *hbox_container = memnew(HBoxContainer); @@ -372,8 +372,8 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_ Button *close_button = memnew(Button); close_button->set_flat(true); close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); - close_button->connect("pressed", callable_bind(callable_mp(this, &EditorToaster::close), panel)); - close_button->connect("theme_changed", callable_bind(callable_mp(this, &EditorToaster::_close_button_theme_changed), close_button)); + close_button->connect("pressed", callable_mp(this, &EditorToaster::close).bind(panel)); + close_button->connect("theme_changed", callable_mp(this, &EditorToaster::_close_button_theme_changed).bind(close_button)); hbox_container->add_child(close_button); } @@ -522,7 +522,7 @@ EditorToaster::EditorToaster() { main_button->set_modulate(Color(0.5, 0.5, 0.5)); main_button->set_disabled(true); main_button->set_flat(true); - main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(true)); + main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(true)); main_button->connect("pressed", callable_mp(this, &EditorToaster::_repop_old)); main_button->connect("draw", callable_mp(this, &EditorToaster::_draw_button)); add_child(main_button); @@ -536,7 +536,7 @@ EditorToaster::EditorToaster() { disable_notifications_button = memnew(Button); disable_notifications_button->set_tooltip(TTR("Silence the notifications.")); disable_notifications_button->set_flat(true); - disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(false)); + disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(false)); disable_notifications_panel->add_child(disable_notifications_button); // Other diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h index 487625e84c..6a6fca7eba 100644 --- a/editor/editor_vcs_interface.h +++ b/editor/editor_vcs_interface.h @@ -85,4 +85,4 @@ public: virtual ~EditorVCSInterface(); }; -#endif // !EDITOR_VCS_INTERFACE_H +#endif // EDITOR_VCS_INTERFACE_H diff --git a/editor/export/SCsub b/editor/export/SCsub new file mode 100644 index 0000000000..359d04e5df --- /dev/null +++ b/editor/export/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp new file mode 100644 index 0000000000..31f408eedb --- /dev/null +++ b/editor/export/editor_export.cpp @@ -0,0 +1,355 @@ +/*************************************************************************/ +/* editor_export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_export.h" + +#include "core/config/project_settings.h" +#include "core/io/config_file.h" + +EditorExport *EditorExport::singleton = nullptr; + +void EditorExport::_save() { + Ref<ConfigFile> config; + config.instantiate(); + for (int i = 0; i < export_presets.size(); i++) { + Ref<EditorExportPreset> preset = export_presets[i]; + String section = "preset." + itos(i); + + config->set_value(section, "name", preset->get_name()); + config->set_value(section, "platform", preset->get_platform()->get_name()); + config->set_value(section, "runnable", preset->is_runnable()); + config->set_value(section, "custom_features", preset->get_custom_features()); + + bool save_files = false; + switch (preset->get_export_filter()) { + case EditorExportPreset::EXPORT_ALL_RESOURCES: { + config->set_value(section, "export_filter", "all_resources"); + } break; + case EditorExportPreset::EXPORT_SELECTED_SCENES: { + config->set_value(section, "export_filter", "scenes"); + save_files = true; + } break; + case EditorExportPreset::EXPORT_SELECTED_RESOURCES: { + config->set_value(section, "export_filter", "resources"); + save_files = true; + } break; + case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: { + config->set_value(section, "export_filter", "exclude"); + save_files = true; + } break; + } + + if (save_files) { + Vector<String> export_files = preset->get_files_to_export(); + config->set_value(section, "export_files", export_files); + } + config->set_value(section, "include_filter", preset->get_include_filter()); + config->set_value(section, "exclude_filter", preset->get_exclude_filter()); + config->set_value(section, "export_path", preset->get_export_path()); + 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()); + + String option_section = "preset." + itos(i) + ".options"; + + for (const PropertyInfo &E : preset->get_properties()) { + config->set_value(option_section, E.name, preset->get(E.name)); + } + } + + config->save("res://export_presets.cfg"); +} + +void EditorExport::save_presets() { + if (block_save) { + return; + } + save_timer->start(); +} + +void EditorExport::_bind_methods() { + ADD_SIGNAL(MethodInfo("export_presets_updated")); +} + +void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) { + export_platforms.push_back(p_platform); +} + +int EditorExport::get_export_platform_count() { + return export_platforms.size(); +} + +Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>()); + + return export_platforms[p_idx]; +} + +void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) { + if (p_at_pos < 0) { + export_presets.push_back(p_preset); + } else { + export_presets.insert(p_at_pos, p_preset); + } +} + +String EditorExportPlatform::test_etc2() const { + const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2"); + + if (!etc2_supported) { + return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings."); + } + + return String(); +} + +int EditorExport::get_export_preset_count() const { + return export_presets.size(); +} + +Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>()); + return export_presets[p_idx]; +} + +void EditorExport::remove_export_preset(int p_idx) { + export_presets.remove_at(p_idx); + save_presets(); +} + +void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { + if (!export_plugins.has(p_plugin)) { + export_plugins.push_back(p_plugin); + } +} + +void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { + export_plugins.erase(p_plugin); +} + +Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() { + return export_plugins; +} + +void EditorExport::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + load_config(); + } break; + + case NOTIFICATION_PROCESS: { + update_export_presets(); + } break; + } +} + +void EditorExport::load_config() { + Ref<ConfigFile> config; + config.instantiate(); + Error err = config->load("res://export_presets.cfg"); + if (err != OK) { + return; + } + + block_save = true; + + int index = 0; + while (true) { + String section = "preset." + itos(index); + if (!config->has_section(section)) { + break; + } + + String platform = config->get_value(section, "platform"); + + Ref<EditorExportPreset> preset; + + for (int i = 0; i < export_platforms.size(); i++) { + if (export_platforms[i]->get_name() == platform) { + preset = export_platforms.write[i]->create_preset(); + break; + } + } + + if (!preset.is_valid()) { + index++; + ERR_CONTINUE(!preset.is_valid()); + } + + preset->set_name(config->get_value(section, "name")); + preset->set_runnable(config->get_value(section, "runnable")); + + if (config->has_section_key(section, "custom_features")) { + preset->set_custom_features(config->get_value(section, "custom_features")); + } + + String export_filter = config->get_value(section, "export_filter"); + + bool get_files = false; + + if (export_filter == "all_resources") { + preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES); + } else if (export_filter == "scenes") { + preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES); + get_files = true; + } else if (export_filter == "resources") { + preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES); + get_files = true; + } else if (export_filter == "exclude") { + preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES); + get_files = true; + } + + if (get_files) { + Vector<String> files = config->get_value(section, "export_files"); + + for (int i = 0; i < files.size(); i++) { + if (!FileAccess::exists(files[i])) { + preset->remove_export_file(files[i]); + } else { + preset->add_export_file(files[i]); + } + } + } + + preset->set_include_filter(config->get_value(section, "include_filter")); + preset->set_exclude_filter(config->get_value(section, "exclude_filter")); + preset->set_export_path(config->get_value(section, "export_path", "")); + + 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")); + } + if (config->has_section_key(section, "script_encryption_key")) { + preset->set_script_encryption_key(config->get_value(section, "script_encryption_key")); + } + + String option_section = "preset." + itos(index) + ".options"; + + List<String> options; + + config->get_section_keys(option_section, &options); + + for (const String &E : options) { + Variant value = config->get_value(option_section, E); + + preset->set(E, value); + } + + add_export_preset(preset); + index++; + } + + block_save = false; +} + +void EditorExport::update_export_presets() { + HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options; + + for (int i = 0; i < export_platforms.size(); i++) { + Ref<EditorExportPlatform> platform = export_platforms[i]; + + if (platform->should_update_export_options()) { + List<EditorExportPlatform::ExportOption> options; + platform->get_export_options(&options); + + platform_options[platform->get_name()] = options; + } + } + + bool export_presets_updated = false; + for (int i = 0; i < export_presets.size(); i++) { + Ref<EditorExportPreset> preset = export_presets[i]; + if (platform_options.has(preset->get_platform()->get_name())) { + export_presets_updated = true; + + List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()]; + + // Copy the previous preset values + HashMap<StringName, Variant> previous_values = preset->values; + + // Clear the preset properties and values prior to reloading + preset->properties.clear(); + preset->values.clear(); + + for (const EditorExportPlatform::ExportOption &E : options) { + preset->properties.push_back(E.option); + + StringName option_name = E.option.name; + preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value; + } + } + } + + if (export_presets_updated) { + emit_signal(_export_presets_updated); + } +} + +bool EditorExport::poll_export_platforms() { + bool changed = false; + for (int i = 0; i < export_platforms.size(); i++) { + if (export_platforms.write[i]->poll_export()) { + changed = true; + } + } + + return changed; +} + +EditorExport::EditorExport() { + save_timer = memnew(Timer); + add_child(save_timer); + save_timer->set_wait_time(0.8); + save_timer->set_one_shot(true); + save_timer->connect("timeout", callable_mp(this, &EditorExport::_save)); + + _export_presets_updated = "export_presets_updated"; + + singleton = this; + set_process(true); +} + +EditorExport::~EditorExport() { +} diff --git a/editor/export/editor_export.h b/editor/export/editor_export.h new file mode 100644 index 0000000000..13c3c34cea --- /dev/null +++ b/editor/export/editor_export.h @@ -0,0 +1,84 @@ +/*************************************************************************/ +/* editor_export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_H +#define EDITOR_EXPORT_H + +#include "editor_export_platform.h" +#include "editor_export_plugin.h" + +class EditorExport : public Node { + GDCLASS(EditorExport, Node); + + Vector<Ref<EditorExportPlatform>> export_platforms; + Vector<Ref<EditorExportPreset>> export_presets; + Vector<Ref<EditorExportPlugin>> export_plugins; + + StringName _export_presets_updated; + + Timer *save_timer = nullptr; + bool block_save = false; + + static EditorExport *singleton; + + void _save(); + +protected: + friend class EditorExportPreset; + void save_presets(); + + void _notification(int p_what); + static void _bind_methods(); + +public: + static EditorExport *get_singleton() { return singleton; } + + void add_export_platform(const Ref<EditorExportPlatform> &p_platform); + int get_export_platform_count(); + Ref<EditorExportPlatform> get_export_platform(int p_idx); + + void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1); + int get_export_preset_count() const; + Ref<EditorExportPreset> get_export_preset(int p_idx); + void remove_export_preset(int p_idx); + + void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin); + void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin); + Vector<Ref<EditorExportPlugin>> get_export_plugins(); + + void load_config(); + void update_export_presets(); + bool poll_export_platforms(); + + EditorExport(); + ~EditorExport(); +}; + +#endif // EDITOR_EXPORT_H diff --git a/editor/editor_export.cpp b/editor/export/editor_export_platform.cpp index bb9d930cf5..34b407779e 100644 --- a/editor/editor_export.cpp +++ b/editor/export/editor_export_platform.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* editor_export.cpp */ +/* editor_export_platform.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "editor_export.h" +#include "editor_export_platform.h" #include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/extension/native_extension.h" -#include "core/io/config_file.h" -#include "core/io/dir_access.h" -#include "core/io/file_access.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" #include "core/io/zip_io.h" -#include "core/object/script_language.h" #include "core/version.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" @@ -49,7 +43,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" -#include "scene/resources/resource_format_text.h" +#include "editor_export_plugin.h" static int _get_pad(int p_alignment, int p_n) { int rest = p_n % p_alignment; @@ -63,196 +57,6 @@ static int _get_pad(int p_alignment, int p_n) { #define PCK_PADDING 16 -bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) { - if (values.has(p_name)) { - values[p_name] = p_value; - EditorExport::singleton->save_presets(); - return true; - } - - return false; -} - -bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { - if (values.has(p_name)) { - r_ret = values[p_name]; - return true; - } - - return false; -} - -void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { - for (const PropertyInfo &E : properties) { - if (platform->get_export_option_visibility(E.name, values)) { - p_list->push_back(E); - } - } -} - -Ref<EditorExportPlatform> EditorExportPreset::get_platform() const { - return platform; -} - -void EditorExportPreset::update_files_to_export() { - Vector<String> to_remove; - for (const String &E : selected_files) { - if (!FileAccess::exists(E)) { - to_remove.push_back(E); - } - } - for (int i = 0; i < to_remove.size(); ++i) { - selected_files.erase(to_remove[i]); - } -} - -Vector<String> EditorExportPreset::get_files_to_export() const { - Vector<String> files; - for (const String &E : selected_files) { - files.push_back(E); - } - return files; -} - -void EditorExportPreset::set_name(const String &p_name) { - name = p_name; - EditorExport::singleton->save_presets(); -} - -String EditorExportPreset::get_name() const { - return name; -} - -void EditorExportPreset::set_runnable(bool p_enable) { - runnable = p_enable; - EditorExport::singleton->save_presets(); -} - -bool EditorExportPreset::is_runnable() const { - return runnable; -} - -void EditorExportPreset::set_export_filter(ExportFilter p_filter) { - export_filter = p_filter; - EditorExport::singleton->save_presets(); -} - -EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const { - return export_filter; -} - -void EditorExportPreset::set_include_filter(const String &p_include) { - include_filter = p_include; - EditorExport::singleton->save_presets(); -} - -String EditorExportPreset::get_include_filter() const { - return include_filter; -} - -void EditorExportPreset::set_export_path(const String &p_path) { - export_path = p_path; - /* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path, - * this should be removed. */ - if (export_path.is_absolute_path()) { - String res_path = OS::get_singleton()->get_resource_dir(); - export_path = res_path.path_to_file(export_path); - } - EditorExport::singleton->save_presets(); -} - -String EditorExportPreset::get_export_path() const { - return export_path; -} - -void EditorExportPreset::set_exclude_filter(const String &p_exclude) { - exclude_filter = p_exclude; - EditorExport::singleton->save_presets(); -} - -String EditorExportPreset::get_exclude_filter() const { - return exclude_filter; -} - -void EditorExportPreset::add_export_file(const String &p_path) { - selected_files.insert(p_path); - EditorExport::singleton->save_presets(); -} - -void EditorExportPreset::remove_export_file(const String &p_path) { - selected_files.erase(p_path); - EditorExport::singleton->save_presets(); -} - -bool EditorExportPreset::has_export_file(const String &p_path) { - return selected_files.has(p_path); -} - -void EditorExportPreset::set_custom_features(const String &p_custom_features) { - custom_features = p_custom_features; - EditorExport::singleton->save_presets(); -} - -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(); -} - -int EditorExportPreset::get_script_export_mode() const { - return script_mode; -} - -void EditorExportPreset::set_script_encryption_key(const String &p_key) { - script_key = p_key; - EditorExport::singleton->save_presets(); -} - -String EditorExportPreset::get_script_encryption_key() const { - return script_key; -} - -/////////////////////////////////// - bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) { bool has_messages = false; @@ -267,7 +71,7 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) if (get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) { p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")), 16 * EDSCALE, 16 * EDSCALE, Color(1.0, 1.0, 1.0), INLINE_ALIGNMENT_CENTER); p_log->add_text(" "); - p_log->add_text(TTR("Completed with errors.")); + p_log->add_text(TTR("Completed with warnings.")); has_messages = true; } else { p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")), 16 * EDSCALE, 16 * EDSCALE, Color(1.0, 1.0, 1.0), INLINE_ALIGNMENT_CENTER); @@ -491,7 +295,7 @@ Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const { String EditorExportPlatform::find_export_template(String template_file_name, String *err) const { String current_version = VERSION_FULL_CONFIG; - String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version).plus_file(template_file_name); + String template_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(current_version).plus_file(template_file_name); if (FileAccess::exists(template_path)) { return template_path; @@ -625,139 +429,7 @@ void EditorExportPlatform::_edit_filter_list(HashSet<String> &r_list, const Stri _edit_files_with_filter(da, filters, r_list, exclude); } -void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) { - if (p_preset.is_valid()) { - export_preset = p_preset; - } -} - -Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const { - return export_preset; -} - -void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) { - ExtraFile ef; - ef.data = p_file; - ef.path = p_path; - ef.remap = p_remap; - extra_files.push_back(ef); -} - -void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) { - shared_objects.push_back(SharedObject(p_path, p_tags, p_target)); -} - -void EditorExportPlugin::add_ios_framework(const String &p_path) { - ios_frameworks.push_back(p_path); -} - -void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) { - ios_embedded_frameworks.push_back(p_path); -} - -Vector<String> EditorExportPlugin::get_ios_frameworks() const { - return ios_frameworks; -} - -Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const { - return ios_embedded_frameworks; -} - -void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) { - ios_plist_content += p_plist_content + "\n"; -} - -String EditorExportPlugin::get_ios_plist_content() const { - return ios_plist_content; -} - -void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) { - if (ios_linker_flags.length() > 0) { - ios_linker_flags += ' '; - } - ios_linker_flags += p_flags; -} - -String EditorExportPlugin::get_ios_linker_flags() const { - return ios_linker_flags; -} - -void EditorExportPlugin::add_ios_bundle_file(const String &p_path) { - ios_bundle_files.push_back(p_path); -} - -Vector<String> EditorExportPlugin::get_ios_bundle_files() const { - return ios_bundle_files; -} - -void EditorExportPlugin::add_ios_cpp_code(const String &p_code) { - ios_cpp_code += p_code; -} - -String EditorExportPlugin::get_ios_cpp_code() const { - return ios_cpp_code; -} - -void EditorExportPlugin::add_osx_plugin_file(const String &p_path) { - osx_plugin_files.push_back(p_path); -} - -const Vector<String> &EditorExportPlugin::get_osx_plugin_files() const { - return osx_plugin_files; -} - -void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) { - ios_project_static_libs.push_back(p_path); -} - -Vector<String> EditorExportPlugin::get_ios_project_static_libs() const { - return ios_project_static_libs; -} - -void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) { - GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features); -} - -void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) { - GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags); -} - -void EditorExportPlugin::_export_end_script() { - GDVIRTUAL_CALL(_export_end); -} - -void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) { -} - -void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) { -} - -void EditorExportPlugin::skip() { - skipped = true; -} - -void EditorExportPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object); - ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib); - ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); - ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework); - ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework); - ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content); - ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags); - ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file); - ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code); - ClassDB::bind_method(D_METHOD("add_osx_plugin_file", "path"), &EditorExportPlugin::add_osx_plugin_file); - ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); - - GDVIRTUAL_BIND(_export_file, "path", "type", "features"); - GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags"); - GDVIRTUAL_BIND(_export_end); -} - -EditorExportPlugin::EditorExportPlugin() { -} - -EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) { +EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) const { Ref<EditorExportPlatform> platform = p_preset->get_platform(); List<String> feature_list; platform->get_platform_features(&feature_list); @@ -1504,573 +1176,3 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags EditorExportPlatform::EditorExportPlatform() { } - -//// - -EditorExport *EditorExport::singleton = nullptr; - -void EditorExport::_save() { - Ref<ConfigFile> config; - config.instantiate(); - for (int i = 0; i < export_presets.size(); i++) { - Ref<EditorExportPreset> preset = export_presets[i]; - String section = "preset." + itos(i); - - config->set_value(section, "name", preset->get_name()); - config->set_value(section, "platform", preset->get_platform()->get_name()); - config->set_value(section, "runnable", preset->is_runnable()); - config->set_value(section, "custom_features", preset->get_custom_features()); - - bool save_files = false; - switch (preset->get_export_filter()) { - case EditorExportPreset::EXPORT_ALL_RESOURCES: { - config->set_value(section, "export_filter", "all_resources"); - } break; - case EditorExportPreset::EXPORT_SELECTED_SCENES: { - config->set_value(section, "export_filter", "scenes"); - save_files = true; - } break; - case EditorExportPreset::EXPORT_SELECTED_RESOURCES: { - config->set_value(section, "export_filter", "resources"); - save_files = true; - } break; - case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: { - config->set_value(section, "export_filter", "exclude"); - save_files = true; - } break; - } - - if (save_files) { - Vector<String> export_files = preset->get_files_to_export(); - config->set_value(section, "export_files", export_files); - } - config->set_value(section, "include_filter", preset->get_include_filter()); - config->set_value(section, "exclude_filter", preset->get_exclude_filter()); - config->set_value(section, "export_path", preset->get_export_path()); - 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()); - - String option_section = "preset." + itos(i) + ".options"; - - for (const PropertyInfo &E : preset->get_properties()) { - config->set_value(option_section, E.name, preset->get(E.name)); - } - } - - config->save("res://export_presets.cfg"); -} - -void EditorExport::save_presets() { - if (block_save) { - return; - } - save_timer->start(); -} - -void EditorExport::_bind_methods() { - ADD_SIGNAL(MethodInfo("export_presets_updated")); -} - -void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) { - export_platforms.push_back(p_platform); -} - -int EditorExport::get_export_platform_count() { - return export_platforms.size(); -} - -Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>()); - - return export_platforms[p_idx]; -} - -void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) { - if (p_at_pos < 0) { - export_presets.push_back(p_preset); - } else { - export_presets.insert(p_at_pos, p_preset); - } -} - -String EditorExportPlatform::test_etc2() const { - const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2"); - - if (!etc2_supported) { - return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings."); - } - - return String(); -} - -int EditorExport::get_export_preset_count() const { - return export_presets.size(); -} - -Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>()); - return export_presets[p_idx]; -} - -void EditorExport::remove_export_preset(int p_idx) { - export_presets.remove_at(p_idx); - save_presets(); -} - -void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { - if (!export_plugins.has(p_plugin)) { - export_plugins.push_back(p_plugin); - } -} - -void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { - export_plugins.erase(p_plugin); -} - -Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() { - return export_plugins; -} - -void EditorExport::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - load_config(); - } break; - - case NOTIFICATION_PROCESS: { - update_export_presets(); - } break; - } -} - -void EditorExport::load_config() { - Ref<ConfigFile> config; - config.instantiate(); - Error err = config->load("res://export_presets.cfg"); - if (err != OK) { - return; - } - - block_save = true; - - int index = 0; - while (true) { - String section = "preset." + itos(index); - if (!config->has_section(section)) { - break; - } - - String platform = config->get_value(section, "platform"); - - Ref<EditorExportPreset> preset; - - for (int i = 0; i < export_platforms.size(); i++) { - if (export_platforms[i]->get_name() == platform) { - preset = export_platforms.write[i]->create_preset(); - break; - } - } - - if (!preset.is_valid()) { - index++; - ERR_CONTINUE(!preset.is_valid()); - } - - preset->set_name(config->get_value(section, "name")); - preset->set_runnable(config->get_value(section, "runnable")); - - if (config->has_section_key(section, "custom_features")) { - preset->set_custom_features(config->get_value(section, "custom_features")); - } - - String export_filter = config->get_value(section, "export_filter"); - - bool get_files = false; - - if (export_filter == "all_resources") { - preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES); - } else if (export_filter == "scenes") { - preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES); - get_files = true; - } else if (export_filter == "resources") { - preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES); - get_files = true; - } else if (export_filter == "exclude") { - preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES); - get_files = true; - } - - if (get_files) { - Vector<String> files = config->get_value(section, "export_files"); - - for (int i = 0; i < files.size(); i++) { - if (!FileAccess::exists(files[i])) { - preset->remove_export_file(files[i]); - } else { - preset->add_export_file(files[i]); - } - } - } - - preset->set_include_filter(config->get_value(section, "include_filter")); - preset->set_exclude_filter(config->get_value(section, "exclude_filter")); - preset->set_export_path(config->get_value(section, "export_path", "")); - - 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")); - } - if (config->has_section_key(section, "script_encryption_key")) { - preset->set_script_encryption_key(config->get_value(section, "script_encryption_key")); - } - - String option_section = "preset." + itos(index) + ".options"; - - List<String> options; - - config->get_section_keys(option_section, &options); - - for (const String &E : options) { - Variant value = config->get_value(option_section, E); - - preset->set(E, value); - } - - add_export_preset(preset); - index++; - } - - block_save = false; -} - -void EditorExport::update_export_presets() { - HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options; - - for (int i = 0; i < export_platforms.size(); i++) { - Ref<EditorExportPlatform> platform = export_platforms[i]; - - if (platform->should_update_export_options()) { - List<EditorExportPlatform::ExportOption> options; - platform->get_export_options(&options); - - platform_options[platform->get_name()] = options; - } - } - - bool export_presets_updated = false; - for (int i = 0; i < export_presets.size(); i++) { - Ref<EditorExportPreset> preset = export_presets[i]; - if (platform_options.has(preset->get_platform()->get_name())) { - export_presets_updated = true; - - List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()]; - - // Copy the previous preset values - HashMap<StringName, Variant> previous_values = preset->values; - - // Clear the preset properties and values prior to reloading - preset->properties.clear(); - preset->values.clear(); - - for (const EditorExportPlatform::ExportOption &E : options) { - preset->properties.push_back(E.option); - - StringName option_name = E.option.name; - preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value; - } - } - } - - if (export_presets_updated) { - emit_signal(_export_presets_updated); - } -} - -bool EditorExport::poll_export_platforms() { - bool changed = false; - for (int i = 0; i < export_platforms.size(); i++) { - if (export_platforms.write[i]->poll_export()) { - changed = true; - } - } - - return changed; -} - -EditorExport::EditorExport() { - save_timer = memnew(Timer); - add_child(save_timer); - save_timer->set_wait_time(0.8); - save_timer->set_one_shot(true); - save_timer->connect("timeout", callable_mp(this, &EditorExport::_save)); - - _export_presets_updated = "export_presets_updated"; - - singleton = this; - set_process(true); -} - -EditorExport::~EditorExport() { -} - -////////// - -void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - if (p_preset->get("texture_format/s3tc")) { - r_features->push_back("s3tc"); - } - if (p_preset->get("texture_format/etc")) { - r_features->push_back("etc"); - } - if (p_preset->get("texture_format/etc2")) { - r_features->push_back("etc2"); - } - - if (p_preset->get("binary_format/64_bits")) { - r_features->push_back("64"); - } else { - r_features->push_back("32"); - } -} - -void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) { - String ext_filter = (get_os_name() == "Windows") ? "*.exe" : ""; - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/64_bits"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true)); -} - -String EditorExportPlatformPC::get_name() const { - return name; -} - -String EditorExportPlatformPC::get_os_name() const { - return os_name; -} - -Ref<Texture2D> EditorExportPlatformPC::get_logo() const { - return logo; -} - -bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { - String err; - bool valid = false; - - // Look for export templates (first official, and if defined custom templates). - - bool use64 = p_preset->get("binary_format/64_bits"); - bool dvalid = exists_export_template(get_template_file_name("debug", use64 ? "64" : "32"), &err); - bool rvalid = exists_export_template(get_template_file_name("release", use64 ? "64" : "32"), &err); - - if (p_preset->get("custom_template/debug") != "") { - dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); - if (!dvalid) { - err += TTR("Custom debug template not found.") + "\n"; - } - } - if (p_preset->get("custom_template/release") != "") { - rvalid = FileAccess::exists(p_preset->get("custom_template/release")); - if (!rvalid) { - err += TTR("Custom release template not found.") + "\n"; - } - } - - valid = dvalid || rvalid; - r_missing_templates = !valid; - - if (!err.is_empty()) { - r_error = err; - } - return valid; -} - -Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - - Error err = prepare_template(p_preset, p_debug, p_path, p_flags); - if (err == OK) { - err = modify_template(p_preset, p_debug, p_path, p_flags); - } - if (err == OK) { - err = export_project_data(p_preset, p_debug, p_path, p_flags); - } - - return err; -} - -Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - if (!DirAccess::exists(p_path.get_base_dir())) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist.")); - return ERR_FILE_BAD_PATH; - } - - String custom_debug = p_preset->get("custom_template/debug"); - String custom_release = p_preset->get("custom_template/release"); - - String template_path = p_debug ? custom_debug : custom_release; - - template_path = template_path.strip_edges(); - - if (template_path.is_empty()) { - template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/64_bits") ? "64" : "32")); - } - - if (!template_path.is_empty() && !FileAccess::exists(template_path)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path)); - return ERR_FILE_NOT_FOUND; - } - - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->make_dir_recursive(p_path.get_base_dir()); - Error err = da->copy(template_path, p_path, get_chmod_flags()); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template.")); - } - - return err; -} - -Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - String pck_path; - if (p_preset->get("binary_format/embed_pck")) { - pck_path = p_path; - } else { - pck_path = p_path.get_basename() + ".pck"; - } - - Vector<SharedObject> so_files; - - int64_t embedded_pos; - int64_t embedded_size; - Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); - if (err == OK && p_preset->get("binary_format/embed_pck")) { - if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) { - add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); - return ERR_INVALID_PARAMETER; - } - - err = fixup_embedded_pck(p_path, embedded_pos, embedded_size); - } - - if (err == OK && !so_files.is_empty()) { - // If shared object files, copy them. - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - for (int i = 0; i < so_files.size() && err == OK; i++) { - String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); - String target_path; - if (so_files[i].target.is_empty()) { - target_path = p_path.get_base_dir().plus_file(src_path.get_file()); - } else { - target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file()); - } - - if (da->dir_exists(src_path)) { - err = da->make_dir_recursive(target_path); - if (err == OK) { - err = da->copy_dir(src_path, target_path, -1, true); - } - } else { - err = da->copy(src_path, target_path); - if (err == OK) { - err = sign_shared_object(p_preset, p_debug, target_path); - } - } - } - } - - return err; -} - -Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { - return OK; -} - -void EditorExportPlatformPC::set_name(const String &p_name) { - name = p_name; -} - -void EditorExportPlatformPC::set_os_name(const String &p_name) { - os_name = p_name; -} - -void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) { - logo = p_logo; -} - -void EditorExportPlatformPC::get_platform_features(List<String> *r_features) { - r_features->push_back("pc"); //all pcs support "pc" - r_features->push_back("s3tc"); //all pcs support "s3tc" compression - r_features->push_back(get_os_name().to_lower()); //OS name is a feature -} - -void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) { - if (p_features.has("bptc")) { - if (p_preset->has("texture_format/no_bptc_fallbacks")) { - p_features.erase("s3tc"); - } - } -} - -int EditorExportPlatformPC::get_chmod_flags() const { - return chmod_flags; -} - -void EditorExportPlatformPC::set_chmod_flags(int p_flags) { - chmod_flags = p_flags; -} - -/////////////////////// - -void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) { - String extension = p_path.get_extension().to_lower(); - if (extension != "tres" && extension != "tscn") { - return; - } - - bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary"); - if (!convert) { - return; - } - String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res"); - Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path); - if (err != OK) { - DirAccess::remove_file_or_error(tmp_path); - ERR_FAIL(); - } - Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path); - if (data.size() == 0) { - DirAccess::remove_file_or_error(tmp_path); - ERR_FAIL(); - } - DirAccess::remove_file_or_error(tmp_path); - add_file(p_path + ".converted.res", data, true); -} - -EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() { - GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false); -} diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h new file mode 100644 index 0000000000..832a0cf846 --- /dev/null +++ b/editor/export/editor_export_platform.h @@ -0,0 +1,221 @@ +/*************************************************************************/ +/* editor_export_platform.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_PLATFORM_H +#define EDITOR_EXPORT_PLATFORM_H + +class EditorFileSystemDirectory; +struct EditorProgress; + +#include "core/io/dir_access.h" +#include "editor_export_preset.h" +#include "editor_export_shared_object.h" +#include "scene/gui/rich_text_label.h" +#include "scene/main/node.h" + +class EditorExportPlatform : public RefCounted { + GDCLASS(EditorExportPlatform, RefCounted); + +public: + 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); + + enum ExportMessageType { + EXPORT_MESSAGE_NONE, + EXPORT_MESSAGE_INFO, + EXPORT_MESSAGE_WARNING, + EXPORT_MESSAGE_ERROR, + }; + + struct ExportMessage { + ExportMessageType msg_type; + String category; + String text; + }; + +private: + struct SavedData { + uint64_t ofs = 0; + uint64_t size = 0; + bool encrypted = false; + Vector<uint8_t> md5; + CharString path_utf8; + + bool operator<(const SavedData &p_data) const { + return path_utf8 < p_data.path_utf8; + } + }; + + struct PackData { + Ref<FileAccess> f; + Vector<SavedData> file_ofs; + EditorProgress *ep = nullptr; + Vector<SharedObject> *so_files = nullptr; + }; + + struct ZipData { + void *zip = nullptr; + EditorProgress *ep = nullptr; + }; + + struct FeatureContainers { + HashSet<String> features; + Vector<String> features_pv; + }; + + Vector<ExportMessage> messages; + + void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths); + void _export_find_dependencies(const String &p_path, HashSet<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, 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(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude); + void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude); + + static Error _add_shared_object(void *p_userdata, const SharedObject &p_so); + +protected: + struct ExportNotifier { + ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); + ~ExportNotifier(); + }; + + FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) const; + + bool exists_export_template(String template_file_name, String *err) const; + String find_export_template(String template_file_name, String *err = nullptr) const; + void gen_export_flags(Vector<String> &r_flags, int p_flags); + +public: + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0; + + struct ExportOption { + PropertyInfo option; + Variant default_value; + + ExportOption(const PropertyInfo &p_info, const Variant &p_default) : + option(p_info), + default_value(p_default) { + } + ExportOption() {} + }; + + virtual Ref<EditorExportPreset> create_preset(); + + virtual void clear_messages() { messages.clear(); } + virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) { + ExportMessage msg; + msg.category = p_category; + msg.text = p_message; + msg.msg_type = p_type; + messages.push_back(msg); + switch (p_type) { + case EXPORT_MESSAGE_INFO: { + print_line(vformat("%s: %s\n", msg.category, msg.text)); + } break; + case EXPORT_MESSAGE_WARNING: { + WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + } break; + case EXPORT_MESSAGE_ERROR: { + ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + } break; + default: + break; + } + } + + virtual int get_message_count() const { + return messages.size(); + } + + virtual ExportMessage get_message(int p_index) const { + ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage()); + return messages[p_index]; + } + + virtual ExportMessageType get_worst_message_type() const { + ExportMessageType worst_type = EXPORT_MESSAGE_NONE; + for (int i = 0; i < messages.size(); i++) { + worst_type = MAX(worst_type, messages[i].msg_type); + } + return worst_type; + } + + virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err); + + virtual void get_export_options(List<ExportOption> *r_options) = 0; + virtual bool should_update_export_options() { return false; } + virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } + + virtual String get_os_name() const = 0; + virtual String get_name() const = 0; + virtual Ref<Texture2D> get_logo() const = 0; + + Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); + + Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); + Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); + + virtual bool poll_export() { return false; } + virtual int get_options_count() const { return 0; } + virtual String get_options_tooltip() const { return ""; } + virtual Ref<ImageTexture> get_option_icon(int p_index) const; + virtual String get_option_label(int p_device) const { return ""; } + virtual String get_option_tooltip(int p_device) const { return ""; } + + enum DebugFlags { + DEBUG_FLAG_DUMB_CLIENT = 1, + DEBUG_FLAG_REMOTE_DEBUG = 2, + DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4, + DEBUG_FLAG_VIEW_COLLISONS = 8, + DEBUG_FLAG_VIEW_NAVIGATION = 16, + }; + + virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; } + virtual Ref<Texture2D> get_run_icon() const { return get_logo(); } + + String test_etc2() const; + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0; + + virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0; + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0; + virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + virtual void get_platform_features(List<String> *r_features) const = 0; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0; + virtual String get_debug_protocol() const { return "tcp://"; } + + EditorExportPlatform(); +}; + +#endif // EDITOR_EXPORT_PLATFORM_H diff --git a/editor/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp new file mode 100644 index 0000000000..5e0044f2ae --- /dev/null +++ b/editor/export/editor_export_platform_pc.cpp @@ -0,0 +1,242 @@ +/*************************************************************************/ +/* editor_export_platform_pc.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_export_platform_pc.h" + +#include "core/config/project_settings.h" + +void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { + if (p_preset->get("texture_format/s3tc")) { + r_features->push_back("s3tc"); + } + if (p_preset->get("texture_format/etc")) { + r_features->push_back("etc"); + } + if (p_preset->get("texture_format/etc2")) { + r_features->push_back("etc2"); + } + // PC platforms only have one architecture per export, since + // we export a single executable instead of a bundle. + r_features->push_back(p_preset->get("binary_format/architecture")); +} + +void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) { + String ext_filter = (get_os_name() == "Windows") ? "*.exe" : ""; + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1)); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false)); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true)); +} + +String EditorExportPlatformPC::get_name() const { + return name; +} + +String EditorExportPlatformPC::get_os_name() const { + return os_name; +} + +Ref<Texture2D> EditorExportPlatformPC::get_logo() const { + return logo; +} + +bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + String err; + bool valid = false; + + // Look for export templates (first official, and if defined custom templates). + String arch = p_preset->get("binary_format/architecture"); + bool dvalid = exists_export_template(get_template_file_name("debug", arch), &err); + bool rvalid = exists_export_template(get_template_file_name("release", arch), &err); + + if (p_preset->get("custom_template/debug") != "") { + dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); + if (!dvalid) { + err += TTR("Custom debug template not found.") + "\n"; + } + } + if (p_preset->get("custom_template/release") != "") { + rvalid = FileAccess::exists(p_preset->get("custom_template/release")); + if (!rvalid) { + err += TTR("Custom release template not found.") + "\n"; + } + } + + valid = dvalid || rvalid; + r_missing_templates = !valid; + + if (!err.is_empty()) { + r_error = err; + } + return valid; +} + +Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + + Error err = prepare_template(p_preset, p_debug, p_path, p_flags); + if (err == OK) { + err = modify_template(p_preset, p_debug, p_path, p_flags); + } + if (err == OK) { + err = export_project_data(p_preset, p_debug, p_path, p_flags); + } + + return err; +} + +Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + if (!DirAccess::exists(p_path.get_base_dir())) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist.")); + return ERR_FILE_BAD_PATH; + } + + String custom_debug = p_preset->get("custom_template/debug"); + String custom_release = p_preset->get("custom_template/release"); + + String template_path = p_debug ? custom_debug : custom_release; + + template_path = template_path.strip_edges(); + + if (template_path.is_empty()) { + template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/architecture"))); + } + + if (!template_path.is_empty() && !FileAccess::exists(template_path)) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path)); + return ERR_FILE_NOT_FOUND; + } + + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + da->make_dir_recursive(p_path.get_base_dir()); + Error err = da->copy(template_path, p_path, get_chmod_flags()); + if (err != OK) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template.")); + } + + return err; +} + +Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + String pck_path; + if (p_preset->get("binary_format/embed_pck")) { + pck_path = p_path; + } else { + pck_path = p_path.get_basename() + ".pck"; + } + + Vector<SharedObject> so_files; + + int64_t embedded_pos; + int64_t embedded_size; + Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); + if (err == OK && p_preset->get("binary_format/embed_pck")) { + if (embedded_size >= 0x100000000 && String(p_preset->get("binary_format/architecture")).contains("32")) { + add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); + return ERR_INVALID_PARAMETER; + } + + err = fixup_embedded_pck(p_path, embedded_pos, embedded_size); + } + + if (err == OK && !so_files.is_empty()) { + // If shared object files, copy them. + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + for (int i = 0; i < so_files.size() && err == OK; i++) { + String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); + String target_path; + if (so_files[i].target.is_empty()) { + target_path = p_path.get_base_dir().plus_file(src_path.get_file()); + } else { + target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file()); + } + + if (da->dir_exists(src_path)) { + err = da->make_dir_recursive(target_path); + if (err == OK) { + err = da->copy_dir(src_path, target_path, -1, true); + } + } else { + err = da->copy(src_path, target_path); + if (err == OK) { + err = sign_shared_object(p_preset, p_debug, target_path); + } + } + } + } + + return err; +} + +Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { + return OK; +} + +void EditorExportPlatformPC::set_name(const String &p_name) { + name = p_name; +} + +void EditorExportPlatformPC::set_os_name(const String &p_name) { + os_name = p_name; +} + +void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) { + logo = p_logo; +} + +void EditorExportPlatformPC::get_platform_features(List<String> *r_features) const { + r_features->push_back("pc"); //all pcs support "pc" + r_features->push_back("s3tc"); //all pcs support "s3tc" compression + r_features->push_back(get_os_name().to_lower()); //OS name is a feature +} + +void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) { + if (p_features.has("bptc")) { + if (p_preset->has("texture_format/no_bptc_fallbacks")) { + p_features.erase("s3tc"); + } + } +} + +int EditorExportPlatformPC::get_chmod_flags() const { + return chmod_flags; +} + +void EditorExportPlatformPC::set_chmod_flags(int p_flags) { + chmod_flags = p_flags; +} diff --git a/editor/export/editor_export_platform_pc.h b/editor/export/editor_export_platform_pc.h new file mode 100644 index 0000000000..bdb86e924a --- /dev/null +++ b/editor/export/editor_export_platform_pc.h @@ -0,0 +1,82 @@ +/*************************************************************************/ +/* editor_export_platform_pc.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_PLATFORM_PC_H +#define EDITOR_EXPORT_PLATFORM_PC_H + +#include "editor_export_platform.h" + +class EditorExportPlatformPC : public EditorExportPlatform { + GDCLASS(EditorExportPlatformPC, EditorExportPlatform); + +private: + Ref<ImageTexture> logo; + String name; + String os_name; + + int chmod_flags = -1; + +public: + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; + + virtual void get_export_options(List<ExportOption> *r_options) override; + + virtual String get_name() const override; + virtual String get_os_name() const override; + virtual Ref<Texture2D> get_logo() const override; + + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; + virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); + virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0; + + virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); + virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; }; + virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); + + void set_extension(const String &p_extension, const String &p_feature_key = "default"); + void set_name(const String &p_name); + void set_os_name(const String &p_name); + + void set_logo(const Ref<Texture2D> &p_logo); + + void add_platform_feature(const String &p_feature); + virtual void get_platform_features(List<String> *r_features) const override; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override; + + int get_chmod_flags() const; + void set_chmod_flags(int p_flags); + + virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { + return Error::OK; + } +}; + +#endif // EDITOR_EXPORT_PLATFORM_PC_H diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp new file mode 100644 index 0000000000..cf3a9b0810 --- /dev/null +++ b/editor/export/editor_export_plugin.cpp @@ -0,0 +1,201 @@ +/*************************************************************************/ +/* editor_export_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_export_plugin.h" + +#include "core/config/project_settings.h" +#include "core/io/dir_access.h" +#include "core/io/file_access.h" +#include "editor/editor_paths.h" +#include "editor/export/editor_export_platform.h" +#include "scene/resources/resource_format_text.h" + +void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) { + if (p_preset.is_valid()) { + export_preset = p_preset; + } +} + +Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const { + return export_preset; +} + +void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) { + ExtraFile ef; + ef.data = p_file; + ef.path = p_path; + ef.remap = p_remap; + extra_files.push_back(ef); +} + +void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) { + shared_objects.push_back(SharedObject(p_path, p_tags, p_target)); +} + +void EditorExportPlugin::add_ios_framework(const String &p_path) { + ios_frameworks.push_back(p_path); +} + +void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) { + ios_embedded_frameworks.push_back(p_path); +} + +Vector<String> EditorExportPlugin::get_ios_frameworks() const { + return ios_frameworks; +} + +Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const { + return ios_embedded_frameworks; +} + +void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) { + ios_plist_content += p_plist_content + "\n"; +} + +String EditorExportPlugin::get_ios_plist_content() const { + return ios_plist_content; +} + +void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) { + if (ios_linker_flags.length() > 0) { + ios_linker_flags += ' '; + } + ios_linker_flags += p_flags; +} + +String EditorExportPlugin::get_ios_linker_flags() const { + return ios_linker_flags; +} + +void EditorExportPlugin::add_ios_bundle_file(const String &p_path) { + ios_bundle_files.push_back(p_path); +} + +Vector<String> EditorExportPlugin::get_ios_bundle_files() const { + return ios_bundle_files; +} + +void EditorExportPlugin::add_ios_cpp_code(const String &p_code) { + ios_cpp_code += p_code; +} + +String EditorExportPlugin::get_ios_cpp_code() const { + return ios_cpp_code; +} + +void EditorExportPlugin::add_macos_plugin_file(const String &p_path) { + macos_plugin_files.push_back(p_path); +} + +const Vector<String> &EditorExportPlugin::get_macos_plugin_files() const { + return macos_plugin_files; +} + +void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) { + ios_project_static_libs.push_back(p_path); +} + +Vector<String> EditorExportPlugin::get_ios_project_static_libs() const { + return ios_project_static_libs; +} + +void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) { + GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features); +} + +void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) { + GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags); +} + +void EditorExportPlugin::_export_end_script() { + GDVIRTUAL_CALL(_export_end); +} + +void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) { +} + +void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) { +} + +void EditorExportPlugin::skip() { + skipped = true; +} + +void EditorExportPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object); + ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib); + ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); + ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework); + ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework); + ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content); + ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags); + ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file); + ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code); + ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file); + ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); + + GDVIRTUAL_BIND(_export_file, "path", "type", "features"); + GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags"); + GDVIRTUAL_BIND(_export_end); +} + +EditorExportPlugin::EditorExportPlugin() { +} + +/////////////////////// + +void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) { + String extension = p_path.get_extension().to_lower(); + if (extension != "tres" && extension != "tscn") { + return; + } + + bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary"); + if (!convert) { + return; + } + String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res"); + Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path); + if (err != OK) { + DirAccess::remove_file_or_error(tmp_path); + ERR_FAIL(); + } + Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path); + if (data.size() == 0) { + DirAccess::remove_file_or_error(tmp_path); + ERR_FAIL(); + } + DirAccess::remove_file_or_error(tmp_path); + add_file(p_path + ".converted.res", data, true); +} + +EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() { + GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false); +} diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h new file mode 100644 index 0000000000..04ebc1dfed --- /dev/null +++ b/editor/export/editor_export_plugin.h @@ -0,0 +1,132 @@ +/*************************************************************************/ +/* editor_export_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_PLUGIN_H +#define EDITOR_EXPORT_PLUGIN_H + +#include "core/extension/native_extension.h" +#include "editor_export_preset.h" +#include "editor_export_shared_object.h" + +class EditorExportPlugin : public RefCounted { + GDCLASS(EditorExportPlugin, RefCounted); + + friend class EditorExportPlatform; + + Ref<EditorExportPreset> export_preset; + + Vector<SharedObject> shared_objects; + struct ExtraFile { + String path; + Vector<uint8_t> data; + bool remap = false; + }; + Vector<ExtraFile> extra_files; + bool skipped = false; + + Vector<String> ios_frameworks; + Vector<String> ios_embedded_frameworks; + Vector<String> ios_project_static_libs; + String ios_plist_content; + String ios_linker_flags; + Vector<String> ios_bundle_files; + String ios_cpp_code; + + Vector<String> macos_plugin_files; + + _FORCE_INLINE_ void _clear() { + shared_objects.clear(); + extra_files.clear(); + skipped = false; + } + + _FORCE_INLINE_ void _export_end() { + ios_frameworks.clear(); + ios_embedded_frameworks.clear(); + ios_bundle_files.clear(); + ios_plist_content = ""; + ios_linker_flags = ""; + ios_cpp_code = ""; + macos_plugin_files.clear(); + } + + void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features); + void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags); + void _export_end_script(); + +protected: + void set_export_preset(const Ref<EditorExportPreset> &p_preset); + Ref<EditorExportPreset> get_export_preset() const; + + void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap); + void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String()); + + void add_ios_framework(const String &p_path); + void add_ios_embedded_framework(const String &p_path); + void add_ios_project_static_lib(const String &p_path); + void add_ios_plist_content(const String &p_plist_content); + void add_ios_linker_flags(const String &p_flags); + void add_ios_bundle_file(const String &p_path); + void add_ios_cpp_code(const String &p_code); + void add_macos_plugin_file(const String &p_path); + + void skip(); + + virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features); + virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags); + + static void _bind_methods(); + + GDVIRTUAL3(_export_file, String, String, Vector<String>) + GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t) + GDVIRTUAL0(_export_end) + +public: + Vector<String> get_ios_frameworks() const; + Vector<String> get_ios_embedded_frameworks() const; + Vector<String> get_ios_project_static_libs() const; + String get_ios_plist_content() const; + String get_ios_linker_flags() const; + Vector<String> get_ios_bundle_files() const; + String get_ios_cpp_code() const; + const Vector<String> &get_macos_plugin_files() const; + + EditorExportPlugin(); +}; + +class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin { + GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin); + +public: + virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override; + EditorExportTextSceneToBinaryPlugin(); +}; + +#endif // EDITOR_EXPORT_PLUGIN_H diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp new file mode 100644 index 0000000000..cdf69e727d --- /dev/null +++ b/editor/export/editor_export_preset.cpp @@ -0,0 +1,221 @@ +/*************************************************************************/ +/* editor_export_preset.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_export.h" + +bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) { + if (values.has(p_name)) { + values[p_name] = p_value; + EditorExport::singleton->save_presets(); + return true; + } + + return false; +} + +bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { + if (values.has(p_name)) { + r_ret = values[p_name]; + return true; + } + + return false; +} + +void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { + for (const PropertyInfo &E : properties) { + if (platform->get_export_option_visibility(E.name, values)) { + p_list->push_back(E); + } + } +} + +Ref<EditorExportPlatform> EditorExportPreset::get_platform() const { + return platform; +} + +void EditorExportPreset::update_files_to_export() { + Vector<String> to_remove; + for (const String &E : selected_files) { + if (!FileAccess::exists(E)) { + to_remove.push_back(E); + } + } + for (int i = 0; i < to_remove.size(); ++i) { + selected_files.erase(to_remove[i]); + } +} + +Vector<String> EditorExportPreset::get_files_to_export() const { + Vector<String> files; + for (const String &E : selected_files) { + files.push_back(E); + } + return files; +} + +void EditorExportPreset::set_name(const String &p_name) { + name = p_name; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_name() const { + return name; +} + +void EditorExportPreset::set_runnable(bool p_enable) { + runnable = p_enable; + EditorExport::singleton->save_presets(); +} + +bool EditorExportPreset::is_runnable() const { + return runnable; +} + +void EditorExportPreset::set_export_filter(ExportFilter p_filter) { + export_filter = p_filter; + EditorExport::singleton->save_presets(); +} + +EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const { + return export_filter; +} + +void EditorExportPreset::set_include_filter(const String &p_include) { + include_filter = p_include; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_include_filter() const { + return include_filter; +} + +void EditorExportPreset::set_export_path(const String &p_path) { + export_path = p_path; + /* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path, + * this should be removed. */ + if (export_path.is_absolute_path()) { + String res_path = OS::get_singleton()->get_resource_dir(); + export_path = res_path.path_to_file(export_path); + } + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_export_path() const { + return export_path; +} + +void EditorExportPreset::set_exclude_filter(const String &p_exclude) { + exclude_filter = p_exclude; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_exclude_filter() const { + return exclude_filter; +} + +void EditorExportPreset::add_export_file(const String &p_path) { + selected_files.insert(p_path); + EditorExport::singleton->save_presets(); +} + +void EditorExportPreset::remove_export_file(const String &p_path) { + selected_files.erase(p_path); + EditorExport::singleton->save_presets(); +} + +bool EditorExportPreset::has_export_file(const String &p_path) { + return selected_files.has(p_path); +} + +void EditorExportPreset::set_custom_features(const String &p_custom_features) { + custom_features = p_custom_features; + EditorExport::singleton->save_presets(); +} + +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(); +} + +int EditorExportPreset::get_script_export_mode() const { + return script_mode; +} + +void EditorExportPreset::set_script_encryption_key(const String &p_key) { + script_key = p_key; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_script_encryption_key() const { + return script_key; +} + +EditorExportPreset::EditorExportPreset() {} diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h new file mode 100644 index 0000000000..00109396b0 --- /dev/null +++ b/editor/export/editor_export_preset.h @@ -0,0 +1,145 @@ +/*************************************************************************/ +/* editor_export_preset.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_PRESET_H +#define EDITOR_EXPORT_PRESET_H + +class EditorExportPlatform; + +#include "core/object/ref_counted.h" + +class EditorExportPreset : public RefCounted { + GDCLASS(EditorExportPreset, RefCounted); + +public: + enum ExportFilter { + EXPORT_ALL_RESOURCES, + EXPORT_SELECTED_SCENES, + EXPORT_SELECTED_RESOURCES, + EXCLUDE_SELECTED_RESOURCES, + }; + + enum ScriptExportMode { + MODE_SCRIPT_TEXT, + MODE_SCRIPT_COMPILED, + }; + +private: + Ref<EditorExportPlatform> platform; + ExportFilter export_filter = EXPORT_ALL_RESOURCES; + String include_filter; + String exclude_filter; + String export_path; + + String exporter; + HashSet<String> selected_files; + bool runnable = false; + + friend class EditorExport; + friend class EditorExportPlatform; + + List<PropertyInfo> properties; + HashMap<StringName, Variant> values; + + String name; + + 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; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + +public: + Ref<EditorExportPlatform> get_platform() const; + + bool has(const StringName &p_property) const { return values.has(p_property); } + + void update_files_to_export(); + + Vector<String> get_files_to_export() const; + + void add_export_file(const String &p_path); + void remove_export_file(const String &p_path); + bool has_export_file(const String &p_path); + + void set_name(const String &p_name); + String get_name() const; + + void set_runnable(bool p_enable); + bool is_runnable() const; + + void set_export_filter(ExportFilter p_filter); + ExportFilter get_export_filter() const; + + void set_include_filter(const String &p_include); + String get_include_filter() const; + + void set_exclude_filter(const String &p_exclude); + String get_exclude_filter() const; + + void set_custom_features(const String &p_custom_features); + String get_custom_features() const; + + 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; + + void set_script_encryption_key(const String &p_key); + String get_script_encryption_key() const; + + const List<PropertyInfo> &get_properties() const { return properties; } + + EditorExportPreset(); +}; + +#endif // EDITOR_EXPORT_PRESET_H diff --git a/editor/export/editor_export_shared_object.h b/editor/export/editor_export_shared_object.h new file mode 100644 index 0000000000..558f403ca1 --- /dev/null +++ b/editor/export/editor_export_shared_object.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* editor_export_shared_object.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_EXPORT_SHARED_OBJECT_H +#define EDITOR_EXPORT_SHARED_OBJECT_H + +#include "core/string/ustring.h" +#include "core/templates/vector.h" + +struct SharedObject { + String path; + Vector<String> tags; + String target; + + SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) : + path(p_path), + tags(p_tags), + target(p_target) { + } + + SharedObject() {} +}; + +#endif // EDITOR_EXPORT_SHARED_OBJECT_H diff --git a/editor/export_template_manager.cpp b/editor/export/export_template_manager.cpp index af9c918360..a7d9d7f068 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -30,23 +30,24 @@ #include "export_template_manager.h" -#include "core/input/input.h" #include "core/io/dir_access.h" #include "core/io/json.h" #include "core/io/zip_io.h" -#include "core/os/keyboard.h" -#include "core/templates/rb_set.h" #include "core/version.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_scale.h" -#include "progress_dialog.h" -#include "scene/gui/link_button.h" +#include "editor/editor_settings.h" +#include "editor/progress_dialog.h" +#include "scene/gui/file_dialog.h" +#include "scene/gui/separator.h" +#include "scene/gui/tree.h" +#include "scene/main/http_request.h" void ExportTemplateManager::_update_template_status() { // Fetch installed templates from the file system. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir(); + const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir(); Error err = da->change_dir(templates_dir); ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'."); @@ -439,7 +440,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_ } Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version); + String template_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(version); Error err = d->make_dir_recursive(template_path); if (err != OK) { EditorNode::get_singleton()->show_warning(TTR("Error creating path for extracting templates:") + "\n" + template_path); @@ -538,7 +539,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) { void ExportTemplateManager::_uninstall_template_confirmed() { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir(); + const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir(); Error err = da->change_dir(templates_dir); ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'."); @@ -616,7 +617,7 @@ void ExportTemplateManager::_installed_table_button_cbk(Object *p_item, int p_co } void ExportTemplateManager::_open_template_folder(const String &p_version) { - const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir(); + const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir(); OS::get_singleton()->shell_open("file://" + templates_dir.plus_file(p_version)); } @@ -640,12 +641,12 @@ void ExportTemplateManager::_hide_dialog() { } bool ExportTemplateManager::can_install_android_template() { - const String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); + const String templates_dir = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG); return FileAccess::exists(templates_dir.plus_file("android_source.zip")); } Error ExportTemplateManager::install_android_template() { - const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); + const String &templates_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG); const String &source_zip = templates_path.plus_file("android_source.zip"); ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN); return install_android_template_from_file(source_zip); @@ -869,13 +870,13 @@ ExportTemplateManager::ExportTemplateManager() { current_open_button->set_text(TTR("Open Folder")); current_open_button->set_tooltip(TTR("Open the folder containing installed templates for the current version.")); current_installed_hb->add_child(current_open_button); - current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder), varray(VERSION_FULL_CONFIG)); + current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder).bind(VERSION_FULL_CONFIG)); current_uninstall_button = memnew(Button); current_uninstall_button->set_text(TTR("Uninstall")); current_uninstall_button->set_tooltip(TTR("Uninstall templates for the current version.")); current_installed_hb->add_child(current_uninstall_button); - current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(VERSION_FULL_CONFIG)); + current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template).bind(VERSION_FULL_CONFIG)); main_vb->add_child(memnew(HSeparator)); @@ -991,7 +992,7 @@ ExportTemplateManager::ExportTemplateManager() { install_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); install_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); install_file_dialog->add_filter("*.tpz", TTR("Godot Export Templates")); - install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected), varray(false)); + install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected).bind(false)); add_child(install_file_dialog); hide_dialog_accept = memnew(AcceptDialog); diff --git a/editor/export_template_manager.h b/editor/export/export_template_manager.h index 3494e11d5e..f01da15832 100644 --- a/editor/export_template_manager.h +++ b/editor/export/export_template_manager.h @@ -31,15 +31,15 @@ #ifndef EXPORT_TEMPLATE_MANAGER_H #define EXPORT_TEMPLATE_MANAGER_H -#include "editor/editor_settings.h" #include "scene/gui/dialogs.h" -#include "scene/gui/file_dialog.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/progress_bar.h" -#include "scene/gui/scroll_container.h" -#include "scene/main/http_request.h" class ExportTemplateVersion; +class FileDialog; +class HTTPRequest; +class MenuButton; +class OptionButton; +class ProgressBar; +class Tree; class ExportTemplateManager : public AcceptDialog { GDCLASS(ExportTemplateManager, AcceptDialog); diff --git a/editor/project_export.cpp b/editor/export/project_export.cpp index 209c997d58..cb82cefbbb 100644 --- a/editor/project_export.cpp +++ b/editor/export/project_export.cpp @@ -31,23 +31,16 @@ #include "project_export.h" #include "core/config/project_settings.h" -#include "core/io/dir_access.h" -#include "core/io/file_access.h" -#include "core/io/image_loader.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" -#include "core/os/os.h" -#include "core/string/optimized_translation.h" -#include "core/version_generated.gen.h" +#include "core/version.h" #include "editor/editor_file_dialog.h" +#include "editor/editor_file_system.h" #include "editor/editor_node.h" +#include "editor/editor_properties.h" #include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "scene/gui/box_container.h" -#include "scene/gui/margin_container.h" -#include "scene/gui/scroll_container.h" -#include "scene/gui/tab_container.h" -#include "servers/display_server.h" +#include "editor/export/editor_export.h" +#include "scene/gui/check_button.h" +#include "scene/gui/link_button.h" +#include "scene/gui/tree.h" void ProjectExportDialog::_theme_changed() { duplicate_preset->set_icon(presets->get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons"))); diff --git a/editor/project_export.h b/editor/export/project_export.h index 6b10642495..96dd765a2c 100644 --- a/editor/project_export.h +++ b/editor/export/project_export.h @@ -28,31 +28,25 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PROJECT_EXPORT_SETTINGS_H -#define PROJECT_EXPORT_SETTINGS_H - -#include "core/io/dir_access.h" -#include "core/os/thread.h" -#include "editor/editor_export.h" -#include "editor/editor_file_system.h" -#include "editor/editor_inspector.h" -#include "editor/editor_properties.h" -#include "scene/gui/button.h" -#include "scene/gui/check_button.h" -#include "scene/gui/control.h" +#ifndef PROJECT_EXPORT_H +#define PROJECT_EXPORT_H + #include "scene/gui/dialogs.h" -#include "scene/gui/file_dialog.h" -#include "scene/gui/label.h" -#include "scene/gui/link_button.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/option_button.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/slider.h" -#include "scene/gui/tab_container.h" -#include "scene/gui/tree.h" -#include "scene/main/timer.h" +class CheckBox; +class CheckButton; +class EditorExportPreset; class EditorFileDialog; +class EditorFileSystemDirectory; +class EditorInspector; +class EditorPropertyPath; +class ItemList; +class MenuButton; +class OptionButton; +class RichTextLabel; +class TabContainer; +class Tree; +class TreeItem; class ProjectExportDialog : public ConfirmationDialog { GDCLASS(ProjectExportDialog, ConfirmationDialog); @@ -183,4 +177,4 @@ public: ~ProjectExportDialog(); }; -#endif // PROJECT_EXPORT_SETTINGS_H +#endif // PROJECT_EXPORT_H diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index fe6e6044a4..b823db68f0 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -381,7 +381,7 @@ void FileSystemDock::_notification(int p_what) { file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option)); tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option)); - current_path->connect("text_submitted", callable_mp(this, &FileSystemDock::_navigate_to_path), make_binds(false)); + current_path->connect("text_submitted", callable_mp(this, &FileSystemDock::_navigate_to_path).bind(false)); always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders")); @@ -985,7 +985,9 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit } } - if (ResourceLoader::get_resource_type(fpath) == "PackedScene") { + String resource_type = ResourceLoader::get_resource_type(fpath); + + if (resource_type == "PackedScene") { bool is_imported = false; { @@ -1005,7 +1007,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit } else { EditorNode::get_singleton()->open_request(fpath); } - } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") { + } else if (resource_type == "AnimationLibrary") { bool is_imported = false; { @@ -1025,6 +1027,25 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit } else { EditorNode::get_singleton()->open_request(fpath); } + } else if (ResourceLoader::is_imported(fpath)) { + // If the importer has advanced settings, show them. + int order; + bool can_threads; + String name; + Error err = ResourceFormatImporter::get_singleton()->get_import_order_threads_and_importer(fpath, order, can_threads, name); + bool used_advanced_settings = false; + if (err == OK) { + Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name); + if (importer.is_valid() && importer->has_advanced_options()) { + importer->show_advanced_options(fpath); + used_advanced_settings = true; + } + } + + if (!used_advanced_settings) { + EditorNode::get_singleton()->load_resource(fpath); + } + } else { EditorNode::get_singleton()->load_resource(fpath); } @@ -1510,14 +1531,13 @@ void FileSystemDock::_folder_removed(String p_folder) { void FileSystemDock::_rename_operation_confirm() { String new_name = rename_dialog_text->get_text().strip_edges(); - String old_name = tree->get_selected()->get_text(0); if (new_name.length() == 0) { EditorNode::get_singleton()->show_warning(TTR("No name provided.")); return; } else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) { EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters.")); return; - } else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) { + } else if (to_rename.is_file && to_rename.path.get_extension() != new_name.get_extension()) { if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) { EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore.")); return; @@ -2034,6 +2054,10 @@ void FileSystemDock::_resource_created() { make_shader_dialog->config(fpath.plus_file("new_shader"), false, false, 1); make_shader_dialog->popup_centered(); return; + } else if (type_name == "ShaderInclude") { + make_shader_dialog->config(fpath.plus_file("new_shader_include"), false, false, 2); + make_shader_dialog->popup_centered(); + return; } Variant c = new_resource_dialog->instance_selected(); @@ -3054,7 +3078,7 @@ FileSystemDock::FileSystemDock() { tree_search_box = memnew(LineEdit); tree_search_box->set_h_size_flags(SIZE_EXPAND_FILL); tree_search_box->set_placeholder(TTR("Filter Files")); - tree_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed), varray(tree_search_box)); + tree_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed).bind(tree_search_box)); toolbar2_hbc->add_child(tree_search_box); tree_button_sort = _create_file_menu_button(); @@ -3099,7 +3123,7 @@ FileSystemDock::FileSystemDock() { file_list_search_box = memnew(LineEdit); file_list_search_box->set_h_size_flags(SIZE_EXPAND_FILL); file_list_search_box->set_placeholder(TTR("Filter Files")); - file_list_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed), varray(file_list_search_box)); + file_list_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed).bind(file_list_search_box)); path_hb->add_child(file_list_search_box); file_list_button_sort = _create_file_menu_button(); @@ -3147,7 +3171,7 @@ FileSystemDock::FileSystemDock() { move_dialog = memnew(EditorDirDialog); move_dialog->set_ok_button_text(TTR("Move")); add_child(move_dialog); - move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_operation_confirm), make_binds(false)); + move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_operation_confirm).bind(false)); rename_dialog = memnew(ConfirmationDialog); VBoxContainer *rename_dialog_vb = memnew(VBoxContainer); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index f73e076ac0..c38b3f8a47 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -342,4 +342,4 @@ public: ~FileSystemDock(); }; -#endif // SCENES_DOCK_H +#endif // FILESYSTEM_DOCK_H diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index bca8c95574..f16097f109 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -432,7 +432,7 @@ GroupDialog::GroupDialog() { VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); - vbc->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + vbc->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); HBoxContainer *hbc = memnew(HBoxContainer); vbc->add_child(hbc); @@ -473,7 +473,7 @@ GroupDialog::GroupDialog() { add_group_button = memnew(Button); add_group_button->set_text(TTR("Add")); chbc->add_child(add_group_button); - add_group_button->connect("pressed", callable_mp(this, &GroupDialog::_add_group_pressed), varray(String())); + add_group_button->connect("pressed", callable_mp(this, &GroupDialog::_add_group_pressed).bind(String())); VBoxContainer *vbc_add = memnew(VBoxContainer); hbc->add_child(vbc_add); @@ -562,7 +562,7 @@ GroupDialog::GroupDialog() { group_empty->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); nodes_to_remove->add_child(group_empty); - group_empty->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + group_empty->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); set_title(TTR("Group Editor")); @@ -737,7 +737,7 @@ GroupsEditor::GroupsEditor() { add = memnew(Button); add->set_text(TTR("Add")); hbc->add_child(add); - add->connect("pressed", callable_mp(this, &GroupsEditor::_add_group), varray(String())); + add->connect("pressed", callable_mp(this, &GroupsEditor::_add_group).bind(String())); tree = memnew(Tree); tree->set_hide_root(true); diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 75cbfd01a4..fec8913e31 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -144,4 +144,4 @@ public: ~GroupsEditor(); }; -#endif +#endif // GROUPS_EDITOR_H diff --git a/editor/icons/AudioStream.svg b/editor/icons/AudioStream.svg new file mode 100644 index 0000000000..5d92dc25a5 --- /dev/null +++ b/editor/icons/AudioStream.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m12 2a-1 1 0 0 1 1 1-1 1 0 0 1 -1 1c-4.4301 0-8 3.5699-8 8a-1 1 0 0 1 -1 1-1 1 0 0 1 -1-1c0-5.511 4.489-10 10-10zm0 4a-1 1 0 0 1 1 1-1 1 0 0 1 -1 1c-2.221 0-4 1.779-4 4a-1 1 0 0 1 -1 1-1 1 0 0 1 -1-1c0-3.3018 2.6981-6 6-6zm0 4a-2 2 0 0 1 2 2-2 2 0 0 1 -2 2-2 2 0 0 1 -2-2-2 2 0 0 1 2-2z" fill="url(#a)"/></svg> diff --git a/editor/icons/AudioStreamGenerator.svg b/editor/icons/AudioStreamGenerator.svg new file mode 100644 index 0000000000..55b0fb9d92 --- /dev/null +++ b/editor/icons/AudioStreamGenerator.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m14 9-3 5-3-12-3 7-3-2" fill="none" stroke="url(#a)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg> diff --git a/editor/icons/AudioStreamMicrophone.svg b/editor/icons/AudioStreamMicrophone.svg new file mode 100644 index 0000000000..51009e9d53 --- /dev/null +++ b/editor/icons/AudioStreamMicrophone.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m7 1c-1.108 0-2 .892-2 2h2v1h-2v2h2v1h-2c0 1.108.892 2 2 2v4l-2 2h6l-2-2v-4c1.108 0 2-.892 2-2h-2v-1h2v-2h-2v-1h2c0-1.108-.892-2-2-2z" fill="url(#a)"/></svg> diff --git a/editor/icons/AudioStreamOGGVorbis.svg b/editor/icons/AudioStreamOggVorbis.svg index 2e54de9faa..2e54de9faa 100644 --- a/editor/icons/AudioStreamOGGVorbis.svg +++ b/editor/icons/AudioStreamOggVorbis.svg diff --git a/editor/icons/AudioStreamRandomizer.svg b/editor/icons/AudioStreamRandomizer.svg new file mode 100644 index 0000000000..1696dff795 --- /dev/null +++ b/editor/icons/AudioStreamRandomizer.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m7.9999997 1c6.6837543 0 7.0000003.3165085 7.0000003 7.0057779 0 6.6877711-.286255 6.9755641-6.9367525 6.9938021-3.0191555.008313-4.4456225-.105997-5.1863245-.415726-1.570375-.65669-1.876923-1.727949-1.876923-6.5780761 0-6.6892694.316247-7.0057779 6.9999997-7.0057779zm3.5299143 1.7638478c-1.5662016 0-2.4379256 1.7724432-1.475213 2.9973439.738933.9401693 2.041543 1.025967 2.876923.1899002 1.183646-1.1846229.303279-3.1872441-1.40171-3.1872441zm-3.5760682 3.2710739c-1.5661974 0-2.4379268 1.7707341-1.4752138 2.9956331.7389365.9401892 2.0415435 1.0276772 2.8769233.191611 1.1836457-1.1846231.3032798-3.1872441-1.4017095-3.1872441zm-3.5538458 3.4729499c-.958537.031867-1.875214.7423284-1.875214 1.8493884 0 1.564955 2.248443 2.516522 3.249573 1.375494.7905175-.900982.8551191-1.664857.208547-2.487522-.416627-.5300879-1.007786-.7565128-1.582906-.7373604z" fill="url(#a)"/></svg> diff --git a/editor/icons/AudioStreamSample.svg b/editor/icons/AudioStreamWAV.svg index 2e54de9faa..2e54de9faa 100644 --- a/editor/icons/AudioStreamSample.svg +++ b/editor/icons/AudioStreamWAV.svg diff --git a/editor/icons/CodeFoldDownArrow.svg b/editor/icons/CodeFoldDownArrow.svg new file mode 100644 index 0000000000..0024a1256b --- /dev/null +++ b/editor/icons/CodeFoldDownArrow.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="m3 5 3 3 3-3" fill="none" stroke="#fff" stroke-width="2"/></svg> diff --git a/editor/icons/CodeFoldedRightArrow.svg b/editor/icons/CodeFoldedRightArrow.svg new file mode 100644 index 0000000000..f2a4bd44e0 --- /dev/null +++ b/editor/icons/CodeFoldedRightArrow.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="m4 9 3-3-3-3" fill="none" stroke="#fff" stroke-width="2"/></svg> diff --git a/editor/icons/ControlAlignWide.svg b/editor/icons/ControlAlignFullRect.svg index 0099e04896..0099e04896 100644 --- a/editor/icons/ControlAlignWide.svg +++ b/editor/icons/ControlAlignFullRect.svg diff --git a/editor/icons/FontFile.svg b/editor/icons/FontFile.svg index 4b94fd0d74..c014299783 100644 --- a/editor/icons/FontFile.svg +++ b/editor/icons/FontFile.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V3h2a1 1 0 0 1 1 1h1V1h-6Z" fill="#e0e0e0"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6Z" fill="#ff5f5f"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 7.5h-1a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5h-.5V9a1 1 0 0 1-1 1v1H8V9.854A1 1 0 0 1 7.5 9V7.5zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/FontVariation.svg b/editor/icons/FontVariation.svg index eaad049fce..39917bcba9 100644 --- a/editor/icons/FontVariation.svg +++ b/editor/icons/FontVariation.svg @@ -1 +1 @@ -<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M2.437 1 1.379 4h1A.84 1.192 50 0 1 3.73 3h2L3.615 9a.84 1.192 50 0 1-1.352 1l-.353 1h4l.353-1a.84 1.192 50 0 1-.648-1l2.116-6h2a.84 1.192 50 0 1 .648 1h1l1.058-3h-6Z" fill="#e0e0e0"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6Z" fill="#ff5f5f"/></svg> +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M5.975 11 7.21 7.5H5.916a.478.478 0 0 0-.113.016.837.837 0 0 0-.127.043c-.044.018-.089.04-.133.066l-.043.027V9a1 1 0 0 1-1 1v1h1.475zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/LabelSettings.svg b/editor/icons/LabelSettings.svg new file mode 100644 index 0000000000..4dc3b9e86e --- /dev/null +++ b/editor/icons/LabelSettings.svg @@ -0,0 +1 @@ +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h2.076a3.766 3.766 0 0 1-.058-.496c-.003-.058-.006-.115-.006-.174a2.606 2.606 0 0 1 .05-.508 3.212 3.212 0 0 1 .133-.496 5.104 5.104 0 0 1 .451-.982 8.303 8.303 0 0 1 .422-.656 14.41 14.41 0 0 1 .489-.667c.172-.223.351-.45.535-.68.163-.203.327-.408.492-.618a27.639 27.639 0 0 0 .732-.977 16.04 16.04 0 0 0 .465-.697c.075-.12.147-.242.219-.365a12.399 12.399 0 0 0 .684 1.062 27.555 27.555 0 0 0 .73.977c.165.21.331.415.494.619a43.298 43.298 0 0 1 .787 1.013c.082.111.16.222.237.332L15 9.79V4a1 1 0 0 0-1-1H6zM5 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" style="fill:#8eef97;fill-opacity:1"/><path d="M9.184 13A2.99 2.99 0 0 0 12 15a2.99 2.99 0 0 0 2.816-2z" fill="#ff4596"/><path d="M9.23 11c-.136.326-.23.656-.23 1 0 .352.072.686.184 1h5.632c.112-.314.184-.648.184-1 0-.344-.094-.674-.23-1H9.23z" fill="#8045ff"/><path d="M10.564 9c-.552.69-1.058 1.342-1.334 2h5.54c-.276-.658-.782-1.31-1.335-2Z" fill="#45d7ff"/><path d="M12 7c-.43.746-.945 1.387-1.435 2h2.87c-.49-.613-1.005-1.254-1.435-2Z" fill="#45ffa2"/></svg> diff --git a/editor/icons/NodeWarnings2.svg b/editor/icons/NodeWarnings2.svg new file mode 100644 index 0000000000..e0385c28d1 --- /dev/null +++ b/editor/icons/NodeWarnings2.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h12a1.0001 1.0001 0 0 0 .857422-1.513672l-2.326172-3.876953c-.89392-.5083134-1.507327-1.4610509-1.529297-2.5488281l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm0 6h2v2h-2z" fill="#ffdd65"/><g fill="#f95252"><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z"/><path d="m15.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/></g></svg> diff --git a/editor/icons/NodeWarnings3.svg b/editor/icons/NodeWarnings3.svg new file mode 100644 index 0000000000..53c0e70034 --- /dev/null +++ b/editor/icons/NodeWarnings3.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h12a1.0001 1.0001 0 0 0 .982422-1.171875c-.308689.108606-.638692.171875-.982422.171875-1.645008 0-3-1.354992-3-3a1.0001 1.0001 0 0 0 0-.0019531c.002071-.7569921.302544-1.4803618.818359-2.0332031-.464296-.5178712-.798903-1.1662278-.816406-1.9042969l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm6.095703 4.7636719c-.02286.0837076-.095296.1479891-.095703.2363281v.001953c.001004.551209.418791.97816.964844.996094l-.712891-1.1875001c-.051505-.0169949-.103183-.0337067-.15625-.046875zm-6.095703 1.2363281h2v2h-2z" fill="#ffdd65"/><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm1.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062zm0 4c-.430501.2402236-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z" fill="#f95252" stroke-dashoffset="16.5" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg> diff --git a/editor/icons/NodeWarnings4Plus.svg b/editor/icons/NodeWarnings4Plus.svg new file mode 100644 index 0000000000..64c0a0671d --- /dev/null +++ b/editor/icons/NodeWarnings4Plus.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h9a1.0001 1.0001 0 0 0 0-.001953c.002025-.740254.278882-1.453739.773438-2.001953-.478045-.532242-.773438-1.231924-.773438-1.996094a1.0001 1.0001 0 0 0 0-.0019531c.002071-.7569921.302544-1.4803618.818359-2.0332031-.464296-.5178713-.798903-1.1662278-.816406-1.9042969l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm6.095703 4.7636719c-.02286.0837076-.095296.1479891-.095703.2363281v.001953c.001004.551209.418791.97816.964844.996094l-.712891-1.1875001c-.051505-.0169949-.103183-.0337067-.15625-.046875zm-6.095703 1.2363281h2v2h-2zm6.095703 2.763672c-.02286.083707-.095296.147988-.095703.236328h1c-.326848 0-.598793-.160518-.904297-.236328z" fill="#ffdd65"/><g fill="#f95252" stroke-dashoffset="16.5" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z"/><path d="m15.447266 8.6210938c-.430501.2402236-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/><path d="m15.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/><path d="m15.447266 12.621094c-.430501.240224-.923653.378906-1.447266.378906-.522676 0-1.015355-.137527-1.445312-.376953a2 2 0 0 0 -.554688 1.376953 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.378906z"/></g></svg> diff --git a/editor/icons/ShapeCast3D.svg b/editor/icons/ShapeCast3D.svg new file mode 100644 index 0000000000..c9f24a59b4 --- /dev/null +++ b/editor/icons/ShapeCast3D.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m7 1v9h-3l4 5 4-5h-3v-9z"/><circle cx="7.990566" cy="4.8202" r="4.009434"/></g></svg> diff --git a/editor/icons/SystemFont.svg b/editor/icons/SystemFont.svg new file mode 100644 index 0000000000..a6f62d56d3 --- /dev/null +++ b/editor/icons/SystemFont.svg @@ -0,0 +1 @@ +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#e0e0e0;fill-opacity:1;stroke-width:.714755" d="m5.787 1-.402 1.613c-.352.265-.71.122-1.012-.111l-.904-.541L2.46 2.973l.853 1.425c-.058.438-.412.586-.79.635-.343.065-.674.216-1.024.213V6.72c.367 0 .715.157 1.074.224.371.032.716.243.727.65l-.84 1.4 1.008 1.01c.443-.266.895-.53 1.33-.802.349-.044.675.139.674.506l.314 1.258c.459-.059 1.099.115 1.45-.082.117-.475.242-.954.35-1.428A.67.67 0 0 1 8 9.195V7.5H6.5a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5H4v-4h5.75c-.005-.22.107-.434.254-.625l.543-.902L9.535 1.96l-1.426.853c-.437-.058-.588-.412-.636-.79L7.217 1h-1.43z"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/TextEditorPlay.svg b/editor/icons/TextEditorPlay.svg new file mode 100644 index 0000000000..5a1d195530 --- /dev/null +++ b/editor/icons/TextEditorPlay.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1048.4v-8l7 4z" fill="#e0e0e0" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/TorusMesh.svg b/editor/icons/TorusMesh.svg new file mode 100644 index 0000000000..2ed973d3cf --- /dev/null +++ b/editor/icons/TorusMesh.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="8" cy="7.5" fill="none" rx="6" ry="3.5" stroke="#ffca5f" stroke-linecap="square" stroke-linejoin="round" stroke-width="2"/></svg> diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp new file mode 100644 index 0000000000..f3709efab6 --- /dev/null +++ b/editor/import/audio_stream_import_settings.cpp @@ -0,0 +1,650 @@ +/*************************************************************************/ +/* audio_stream_import_settings.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "audio_stream_import_settings.h" +#include "editor/audio_stream_preview.h" +#include "editor/editor_file_system.h" +#include "editor/editor_scale.h" + +AudioStreamImportSettings *AudioStreamImportSettings::singleton = nullptr; + +void AudioStreamImportSettings::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AudioStreamImportSettings::_preview_changed)); + connect("confirmed", callable_mp(this, &AudioStreamImportSettings::_reimport)); + } break; + + case NOTIFICATION_THEME_CHANGED: + case NOTIFICATION_ENTER_TREE: { + _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); + _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor"))); + color_rect->set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor"))); + _current_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts"))); + _current_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts"))); + _duration_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts"))); + _duration_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts"))); + + zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); + zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); + zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons"))); + + _indicator->update(); + _preview->update(); + } break; + + case NOTIFICATION_PROCESS: { + _current = _player->get_playback_position(); + _indicator->update(); + } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + _stop(); + } + } break; + } +} + +void AudioStreamImportSettings::_draw_preview() { + Rect2 rect = _preview->get_rect(); + Size2 size = rect.size; + + Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream); + float preview_offset = zoom_bar->get_value(); + float preview_len = zoom_bar->get_page(); + + Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + Vector<Vector2> lines; + lines.resize(size.width * 2); + Color color_active = get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")); + Color color_inactive = color_active; + color_inactive.a *= 0.5; + Vector<Color> color; + color.resize(lines.size()); + + float inactive_from = 1e20; + float beat_size = 0; + int last_beat = 0; + if (stream->get_bpm() > 0) { + beat_size = 60 / float(stream->get_bpm()); + int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE; + rect.position.y += y_ofs; + rect.size.y -= y_ofs; + + if (stream->get_beat_count() > 0) { + last_beat = stream->get_beat_count(); + inactive_from = last_beat * beat_size; + } + } + + for (int i = 0; i < size.width; i++) { + float ofs = preview_offset + i * preview_len / size.width; + float ofs_n = preview_offset + (i + 1) * preview_len / size.width; + float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5; + float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; + + int idx = i; + lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y); + lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y); + + Color c = ofs > inactive_from ? color_inactive : color_active; + + color.write[idx * 2 + 0] = c; + color.write[idx * 2 + 1] = c; + } + + RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color); + + if (beat_size) { + Color beat_color = Color(1, 1, 1, 1); + Color final_beat_color = beat_color; + Color bar_color = beat_color; + beat_color.a *= 0.4; + bar_color.a *= 0.6; + + int prev_beat = 0; // Do not draw beat zero + Color color_bg = color_active; + color_bg.a *= 0.2; + _preview->draw_rect(Rect2(0, 0, rect.size.width, rect.position.y), color_bg); + int bar_beats = stream->get_bar_beats(); + + int last_text_end_x = 0; + for (int i = 0; i < size.width; i++) { + float ofs = preview_offset + i * preview_len / size.width; + int beat = int(ofs / beat_size); + if (beat != prev_beat) { + String text = itos(beat); + int text_w = beat_font->get_string_size(text).width; + if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE) { + int x_ofs = i - text_w / 2; + _preview->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color_active); + last_text_end_x = i + text_w / 2; + } + + if (beat == last_beat) { + _preview->draw_rect(Rect2i(i, rect.position.y, 2, rect.size.height), final_beat_color); + // Darken subsequent beats + beat_color.a *= 0.3; + color_active.a *= 0.3; + } else { + _preview->draw_rect(Rect2i(i, rect.position.y, 1, rect.size.height), (beat % bar_beats) == 0 ? bar_color : beat_color); + } + prev_beat = beat; + } + } + } +} + +void AudioStreamImportSettings::_preview_changed(ObjectID p_which) { + if (stream.is_valid() && stream->get_instance_id() == p_which) { + _preview->update(); + } +} + +void AudioStreamImportSettings::_preview_zoom_in() { + if (!stream.is_valid()) { + return; + } + float page_size = zoom_bar->get_page(); + zoom_bar->set_page(page_size * 0.5); + zoom_bar->set_value(zoom_bar->get_value() + page_size * 0.25); + + _preview->update(); + _indicator->update(); +} + +void AudioStreamImportSettings::_preview_zoom_out() { + if (!stream.is_valid()) { + return; + } + float page_size = zoom_bar->get_page(); + zoom_bar->set_page(MIN(zoom_bar->get_max(), page_size * 2.0)); + zoom_bar->set_value(zoom_bar->get_value() - page_size * 0.5); + + _preview->update(); + _indicator->update(); +} + +void AudioStreamImportSettings::_preview_zoom_reset() { + if (!stream.is_valid()) { + return; + } + zoom_bar->set_max(stream->get_length()); + zoom_bar->set_page(zoom_bar->get_max()); + zoom_bar->set_value(0); + _preview->update(); + _indicator->update(); +} + +void AudioStreamImportSettings::_preview_zoom_offset_changed(double) { + _preview->update(); + _indicator->update(); +} + +void AudioStreamImportSettings::_audio_changed() { + if (!is_visible()) { + return; + } + _preview->update(); + _indicator->update(); + color_rect->update(); +} + +void AudioStreamImportSettings::_play() { + if (_player->is_playing()) { + // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'. + _pausing = true; + _player->stop(); + _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + set_process(false); + } else { + _player->play(_current); + _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); + set_process(true); + } +} + +void AudioStreamImportSettings::_stop() { + _player->stop(); + _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + _current = 0; + _indicator->update(); + set_process(false); +} + +void AudioStreamImportSettings::_on_finished() { + _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + if (!_pausing) { + _current = 0; + _indicator->update(); + } else { + _pausing = false; + } + set_process(false); +} + +void AudioStreamImportSettings::_draw_indicator() { + if (!stream.is_valid()) { + return; + } + + Rect2 rect = _preview->get_rect(); + + Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + + if (stream->get_bpm() > 0) { + int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE; + rect.position.y += y_ofs; + rect.size.height -= y_ofs; + } + + float ofs_x = (_current - zoom_bar->get_value()) * rect.size.width / zoom_bar->get_page(); + if (ofs_x < 0 || ofs_x >= rect.size.width) { + return; + } + + const Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + _indicator->draw_line(Point2(ofs_x, rect.position.y), Point2(ofs_x, rect.position.y + rect.size.height), color, Math::round(2 * EDSCALE)); + _indicator->draw_texture( + get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")), + Point2(ofs_x - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, rect.position.y), + color); + + if (stream->get_bpm() > 0 && _hovering_beat != -1) { + // Draw hovered beat. + float preview_offset = zoom_bar->get_value(); + float preview_len = zoom_bar->get_page(); + float beat_size = 60 / float(stream->get_bpm()); + int prev_beat = 0; + int last_text_end_x = 0; + for (int i = 0; i < rect.size.width; i++) { + float ofs = preview_offset + i * preview_len / rect.size.width; + int beat = int(ofs / beat_size); + if (beat != prev_beat) { + String text = itos(beat); + int text_w = beat_font->get_string_size(text).width; + if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE && beat == _hovering_beat) { + int x_ofs = i - text_w / 2; + _indicator->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color); + last_text_end_x = i + text_w / 2; + break; + } + prev_beat = beat; + } + } + } + + _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /"); +} + +void AudioStreamImportSettings::_on_indicator_mouse_exited() { + _hovering_beat = -1; + _indicator->update(); +} + +void AudioStreamImportSettings::_on_input_indicator(Ref<InputEvent> p_event) { + const Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { + if (stream->get_bpm() > 0) { + int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE; + if ((!_dragging && mb->get_position().y < y_ofs) || _beat_len_dragging) { + if (mb->is_pressed()) { + _set_beat_len_to(mb->get_position().x); + _beat_len_dragging = true; + } else { + _beat_len_dragging = false; + } + return; + } + } + + if (mb->is_pressed()) { + _seek_to(mb->get_position().x); + } + _dragging = mb->is_pressed(); + } + + const Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + if (_dragging) { + _seek_to(mm->get_position().x); + } + if (_beat_len_dragging) { + _set_beat_len_to(mm->get_position().x); + } + if (stream->get_bpm() > 0) { + int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE; + if (mm->get_position().y < y_ofs) { + int new_hovering_beat = _get_beat_at_pos(mm->get_position().x); + if (new_hovering_beat != _hovering_beat) { + _hovering_beat = new_hovering_beat; + _indicator->update(); + } + } else if (_hovering_beat != -1) { + _hovering_beat = -1; + _indicator->update(); + } + } + } +} + +int AudioStreamImportSettings::_get_beat_at_pos(real_t p_x) { + float ofs_sec = zoom_bar->get_value() + p_x * zoom_bar->get_page() / _preview->get_size().width; + ofs_sec = CLAMP(ofs_sec, 0, stream->get_length()); + float beat_size = 60 / float(stream->get_bpm()); + int beat = int(ofs_sec / beat_size + 0.5); + + if (beat * beat_size > stream->get_length() + 0.001) { // Stream may end few audio frames before but may still want to use full loop. + beat--; + } + return beat; +} + +void AudioStreamImportSettings::_set_beat_len_to(real_t p_x) { + int beat = _get_beat_at_pos(p_x); + if (beat < 1) { + beat = 1; // Because 0 is disable. + } + updating_settings = true; + beats_enabled->set_pressed(true); + beats_edit->set_value(beat); + updating_settings = false; + _settings_changed(); +} + +void AudioStreamImportSettings::_seek_to(real_t p_x) { + _current = zoom_bar->get_value() + p_x / _preview->get_rect().size.x * zoom_bar->get_page(); + _current = CLAMP(_current, 0, stream->get_length()); + _player->seek(_current); + _indicator->update(); +} + +void AudioStreamImportSettings::edit(const String &p_path, const String &p_importer, const Ref<AudioStream> &p_stream) { + if (!stream.is_null()) { + stream->disconnect("changed", callable_mp(this, &AudioStreamImportSettings::_audio_changed)); + } + + importer = p_importer; + path = p_path; + + stream = p_stream; + _player->set_stream(stream); + _current = 0; + String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s"; + _duration_label->set_text(text); + + if (!stream.is_null()) { + stream->connect("changed", callable_mp(this, &AudioStreamImportSettings::_audio_changed)); + _preview->update(); + _indicator->update(); + color_rect->update(); + } else { + hide(); + } + params.clear(); + + if (stream.is_valid()) { + Ref<ConfigFile> config_file; + config_file.instantiate(); + Error err = config_file->load(p_path + ".import"); + updating_settings = true; + if (err == OK) { + double bpm = config_file->get_value("params", "bpm", 0); + int beats = config_file->get_value("params", "beat_count", 0); + bpm_edit->set_value(bpm > 0 ? bpm : 120); + bpm_enabled->set_pressed(bpm > 0); + beats_edit->set_value(beats); + beats_enabled->set_pressed(beats > 0); + loop->set_pressed(config_file->get_value("params", "loop", false)); + loop_offset->set_value(config_file->get_value("params", "loop_offset", 0)); + bar_beats_edit->set_value(config_file->get_value("params", "bar_beats", 4)); + + List<String> keys; + config_file->get_section_keys("params", &keys); + for (const String &K : keys) { + params[K] = config_file->get_value("params", K); + } + } else { + bpm_edit->set_value(false); + bpm_enabled->set_pressed(false); + beats_edit->set_value(0); + beats_enabled->set_pressed(false); + bar_beats_edit->set_value(4); + loop->set_pressed(false); + loop_offset->set_value(0); + } + + _preview_zoom_reset(); + updating_settings = false; + _settings_changed(); + + set_title(vformat(TTR("Audio Stream Importer: %s"), p_path.get_file())); + popup_centered(); + } +} + +void AudioStreamImportSettings::_settings_changed() { + if (updating_settings) { + return; + } + + updating_settings = true; + stream->call("set_loop", loop->is_pressed()); + stream->call("set_loop_offset", loop_offset->get_value()); + if (bpm_enabled->is_pressed()) { + stream->call("set_bpm", bpm_edit->get_value()); + beats_enabled->show(); + beats_edit->show(); + bar_beats_label->show(); + bar_beats_edit->show(); + double bpm = bpm_edit->get_value(); + if (bpm > 0) { + float beat_size = 60 / float(bpm); + int beat_max = int((stream->get_length() + 0.001) / beat_size); + int current_beat = beats_edit->get_value(); + beats_edit->set_max(beat_max); + if (current_beat > beat_max) { + beats_edit->set_value(beat_max); + stream->call("set_beat_count", beat_max); + } + } + stream->call("set_bar_beats", bar_beats_edit->get_value()); + } else { + stream->call("set_bpm", 0); + stream->call("set_bar_beats", 4); + beats_enabled->hide(); + beats_edit->hide(); + bar_beats_label->hide(); + bar_beats_edit->hide(); + } + if (bpm_enabled->is_pressed() && beats_enabled->is_pressed()) { + stream->call("set_beat_count", beats_edit->get_value()); + } else { + stream->call("set_beat_count", 0); + } + + updating_settings = false; + + _preview->update(); + _indicator->update(); + color_rect->update(); +} + +void AudioStreamImportSettings::_reimport() { + params["loop"] = loop->is_pressed(); + params["loop_offset"] = loop_offset->get_value(); + params["bpm"] = bpm_enabled->is_pressed() ? double(bpm_edit->get_value()) : double(0); + params["beat_count"] = (bpm_enabled->is_pressed() && beats_enabled->is_pressed()) ? int(beats_edit->get_value()) : int(0); + params["bar_beats"] = (bpm_enabled->is_pressed()) ? int(bar_beats_edit->get_value()) : int(4); + + EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(path, importer, params); +} + +AudioStreamImportSettings::AudioStreamImportSettings() { + get_ok_button()->set_text(TTR("Reimport")); + get_cancel_button()->set_text(TTR("Close")); + + VBoxContainer *main_vbox = memnew(VBoxContainer); + add_child(main_vbox); + + HBoxContainer *loop_hb = memnew(HBoxContainer); + loop_hb->add_theme_constant_override("separation", 4 * EDSCALE); + loop = memnew(CheckBox); + loop->set_text(TTR("Enable")); + loop->set_tooltip(TTR("Enable looping.")); + loop->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + loop_hb->add_child(loop); + loop_hb->add_spacer(); + loop_hb->add_child(memnew(Label(TTR("Offset:")))); + loop_offset = memnew(SpinBox); + loop_offset->set_max(10000); + loop_offset->set_step(0.001); + loop_offset->set_suffix("sec"); + loop_offset->set_tooltip(TTR("Loop offset (from beginning). Note that if BPM is set, this setting will be ignored.")); + loop_offset->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + loop_hb->add_child(loop_offset); + main_vbox->add_margin_child(TTR("Loop:"), loop_hb); + + HBoxContainer *interactive_hb = memnew(HBoxContainer); + interactive_hb->add_theme_constant_override("separation", 4 * EDSCALE); + bpm_enabled = memnew(CheckBox); + bpm_enabled->set_text((TTR("BPM:"))); + bpm_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + interactive_hb->add_child(bpm_enabled); + bpm_edit = memnew(SpinBox); + bpm_edit->set_max(400); + bpm_edit->set_step(0.01); + bpm_edit->set_tooltip(TTR("Configure the Beats Per Measure (tempo) used for the interactive streams.\nThis is required in order to configure beat information.")); + bpm_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + interactive_hb->add_child(bpm_edit); + interactive_hb->add_spacer(); + bar_beats_label = memnew(Label(TTR("Beats/Bar:"))); + interactive_hb->add_child(bar_beats_label); + bar_beats_edit = memnew(SpinBox); + bar_beats_edit->set_tooltip(TTR("Configure the Beats Per Bar. This used for music-aware transitions between AudioStreams.")); + bar_beats_edit->set_min(2); + bar_beats_edit->set_max(32); + bar_beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + interactive_hb->add_child(bar_beats_edit); + interactive_hb->add_spacer(); + beats_enabled = memnew(CheckBox); + beats_enabled->set_text(TTR("Length (in beats):")); + beats_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + interactive_hb->add_child(beats_enabled); + beats_edit = memnew(SpinBox); + beats_edit->set_tooltip(TTR("Configure the amount of Beats used for music-aware looping. If zero, it will be autodetected from the length.\nIt is recommended to set this value (either manually or by clicking on a beat number in the preview) to ensure looping works properly.")); + beats_edit->set_max(99999); + beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); + interactive_hb->add_child(beats_edit); + main_vbox->add_margin_child(TTR("Music Playback:"), interactive_hb); + + color_rect = memnew(ColorRect); + main_vbox->add_margin_child(TTR("Preview:"), color_rect); + + color_rect->set_custom_minimum_size(Size2(600, 200) * EDSCALE); + color_rect->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + _player = memnew(AudioStreamPlayer); + _player->connect("finished", callable_mp(this, &AudioStreamImportSettings::_on_finished)); + color_rect->add_child(_player); + + VBoxContainer *vbox = memnew(VBoxContainer); + vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 0); + color_rect->add_child(vbox); + vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + _preview = memnew(ColorRect); + _preview->set_v_size_flags(Control::SIZE_EXPAND_FILL); + _preview->connect("draw", callable_mp(this, &AudioStreamImportSettings::_draw_preview)); + _preview->set_v_size_flags(Control::SIZE_EXPAND_FILL); + vbox->add_child(_preview); + + HBoxContainer *zoom_hbox = memnew(HBoxContainer); + zoom_bar = memnew(HScrollBar); + zoom_in = memnew(Button); + zoom_in->set_flat(true); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); + zoom_out = memnew(Button); + zoom_out->set_flat(true); + zoom_hbox->add_child(zoom_bar); + zoom_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + zoom_bar->set_v_size_flags(Control::SIZE_EXPAND_FILL); + zoom_hbox->add_child(zoom_out); + zoom_hbox->add_child(zoom_reset); + zoom_hbox->add_child(zoom_in); + zoom_in->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_in)); + zoom_reset->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_reset)); + zoom_out->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_out)); + zoom_bar->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_offset_changed)); + vbox->add_child(zoom_hbox); + + _indicator = memnew(Control); + _indicator->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + _indicator->connect("draw", callable_mp(this, &AudioStreamImportSettings::_draw_indicator)); + _indicator->connect("gui_input", callable_mp(this, &AudioStreamImportSettings::_on_input_indicator)); + _indicator->connect("mouse_exited", callable_mp(this, &AudioStreamImportSettings::_on_indicator_mouse_exited)); + _preview->add_child(_indicator); + + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->add_theme_constant_override("separation", 0); + vbox->add_child(hbox); + + _play_button = memnew(Button); + _play_button->set_flat(true); + hbox->add_child(_play_button); + _play_button->set_focus_mode(Control::FOCUS_NONE); + _play_button->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_play)); + + _stop_button = memnew(Button); + _stop_button->set_flat(true); + hbox->add_child(_stop_button); + _stop_button->set_focus_mode(Control::FOCUS_NONE); + _stop_button->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_stop)); + + _current_label = memnew(Label); + _current_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); + _current_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + _current_label->set_modulate(Color(1, 1, 1, 0.5)); + hbox->add_child(_current_label); + + _duration_label = memnew(Label); + hbox->add_child(_duration_label); + + singleton = this; +} diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/import/audio_stream_import_settings.h index 0d927bddd5..5e399237ca 100644 --- a/editor/plugins/audio_stream_editor_plugin.h +++ b/editor/import/audio_stream_import_settings.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* audio_stream_editor_plugin.h */ +/* audio_stream_import_settings.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,27 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIO_STREAM_EDITOR_PLUGIN_H -#define AUDIO_STREAM_EDITOR_PLUGIN_H +#ifndef AUDIO_STREAM_IMPORT_SETTINGS_H +#define AUDIO_STREAM_IMPORT_SETTINGS_H #include "editor/editor_plugin.h" #include "scene/audio/audio_stream_player.h" #include "scene/gui/color_rect.h" +#include "scene/gui/spin_box.h" #include "scene/resources/texture.h" -class AudioStreamEditor : public ColorRect { - GDCLASS(AudioStreamEditor, ColorRect); +class AudioStreamImportSettings : public ConfirmationDialog { + GDCLASS(AudioStreamImportSettings, ConfirmationDialog); + CheckBox *bpm_enabled = nullptr; + SpinBox *bpm_edit = nullptr; + CheckBox *beats_enabled = nullptr; + SpinBox *beats_edit = nullptr; + Label *bar_beats_label = nullptr; + SpinBox *bar_beats_edit = nullptr; + CheckBox *loop = nullptr; + SpinBox *loop_offset = nullptr; + ColorRect *color_rect = nullptr; Ref<AudioStream> stream; AudioStreamPlayer *_player = nullptr; ColorRect *_preview = nullptr; @@ -46,18 +56,42 @@ class AudioStreamEditor : public ColorRect { Label *_current_label = nullptr; Label *_duration_label = nullptr; + HScrollBar *zoom_bar = nullptr; + Button *zoom_in = nullptr; + Button *zoom_reset = nullptr; + Button *zoom_out = nullptr; + Button *_play_button = nullptr; Button *_stop_button = nullptr; + bool updating_settings = false; + float _current = 0; bool _dragging = false; + bool _beat_len_dragging = false; bool _pausing = false; + int _hovering_beat = -1; + + HashMap<StringName, Variant> params; + String importer; + String path; void _audio_changed(); + static AudioStreamImportSettings *singleton; + + void _settings_changed(); + + void _reimport(); + protected: void _notification(int p_what); void _preview_changed(ObjectID p_which); + void _preview_zoom_in(); + void _preview_zoom_out(); + void _preview_zoom_reset(); + void _preview_zoom_offset_changed(double); + void _play(); void _stop(); void _on_finished(); @@ -65,27 +99,16 @@ protected: void _draw_indicator(); void _on_input_indicator(Ref<InputEvent> p_event); void _seek_to(real_t p_x); - static void _bind_methods(); + void _set_beat_len_to(real_t p_x); + void _on_indicator_mouse_exited(); + int _get_beat_at_pos(real_t p_x); public: - void edit(Ref<AudioStream> p_stream); - AudioStreamEditor(); -}; + void edit(const String &p_path, const String &p_importer, const Ref<AudioStream> &p_stream); -class AudioStreamEditorPlugin : public EditorPlugin { - GDCLASS(AudioStreamEditorPlugin, EditorPlugin); + static AudioStreamImportSettings *get_singleton() { return singleton; } - AudioStreamEditor *audio_editor = nullptr; - -public: - virtual String get_name() const override { return "Audio"; } - bool has_main_screen() const override { return false; } - virtual void edit(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual void make_visible(bool p_visible) override; - - AudioStreamEditorPlugin(); - ~AudioStreamEditorPlugin(); + AudioStreamImportSettings(); }; -#endif // AUDIO_STREAM_EDITOR_PLUGIN_H +#endif // AUDIO_STREAM_IMPORT_SETTINGS_H diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index ee13a1a9c1..043681aa87 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -971,6 +971,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { base_path = p_path; inspector_vars->edit(nullptr); + inspector_text->edit(nullptr); inspector_general->edit(nullptr); text_settings_data.instantiate(); diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index e45db47440..a75b0a903f 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -44,4 +44,4 @@ public: EditorSceneFormatImporterCollada(); }; -#endif +#endif // EDITOR_IMPORT_COLLADA_H diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 44fbd41962..4548513b6f 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -68,4 +68,4 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; }; -#endif //EDITOR_IMPORT_PLUGIN_H +#endif // EDITOR_IMPORT_PLUGIN_H diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp index b0c4bc8c30..69c0a047e4 100644 --- a/editor/import/post_import_plugin_skeleton_renamer.cpp +++ b/editor/import/post_import_plugin_skeleton_renamer.cpp @@ -39,6 +39,8 @@ void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones"), true)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/unique_node/make_unique"), true)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "retarget/bone_renamer/unique_node/skeleton_name"), "GeneralSkeleton")); } } @@ -137,6 +139,50 @@ void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_ nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce); } } + + // Make unique skeleton. + if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) { + String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]); + ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty."); + + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int track_len = anim->get_track_count(); + for (int i = 0; i < track_len; i++) { + String track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *orig_node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + while (node) { + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton && track_skeleton == skeleton) { + if (node == orig_node) { + if (anim->track_get_path(i).get_subname_count() > 0) { + anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + String(":") + anim->track_get_path(i).get_concatenated_subnames()); + } else { + anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name); + } + } else { + if (anim->track_get_path(i).get_subname_count() > 0) { + anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node) + String(":") + anim->track_get_path(i).get_concatenated_subnames()); + } else { + anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node)); + } + } + break; + } + node = node->get_parent(); + } + } + } + } + skeleton->set_name(unique_name); + skeleton->set_unique_name_in_owner(true); + } } } diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp new file mode 100644 index 0000000000..4f00bd120a --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp @@ -0,0 +1,489 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_rest_fixer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "post_import_plugin_skeleton_rest_fixer.h" + +#include "editor/import/scene_import_settings.h" +#include "scene/3d/importer_mesh_instance_3d.h" +#include "scene/3d/skeleton_3d.h" +#include "scene/animation/animation_player.h" +#include "scene/resources/bone_map.h" + +void PostImportPluginSkeletonRestFixer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/normalize_position_tracks"), true)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis"), true)); + + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/fix_silhouette/enable"), false)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "retarget/rest_fixer/fix_silhouette/threshold"), 15)); + + // TODO: PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options). + // get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values. + // r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "retarget/rest_fixer/filter", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::STRING_NAME, PROPERTY_HINT_ENUM, "Hips,Spine,Chest")), Array())); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "retarget/rest_fixer/fix_silhouette/filter", PROPERTY_HINT_ARRAY_TYPE, "StringName"), Array())); + } +} + +void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + // Prepare objects. + Object *map = p_options["retarget/bone_map"].get_validated_object(); + if (!map) { + return; + } + BoneMap *bone_map = Object::cast_to<BoneMap>(map); + Ref<SkeletonProfile> profile = bone_map->get_profile(); + if (!profile.is_valid()) { + return; + } + Skeleton3D *src_skeleton = Object::cast_to<Skeleton3D>(p_node); + if (!src_skeleton) { + return; + } + bool is_renamed = bool(p_options["retarget/bone_renamer/rename_bones"]); + Array filter = p_options["retarget/rest_fixer/fix_silhouette/filter"]; + bool is_rest_changed = false; + + // Build profile skeleton. + Skeleton3D *prof_skeleton = memnew(Skeleton3D); + { + int prof_bone_len = profile->get_bone_size(); + // Add single bones. + for (int i = 0; i < prof_bone_len; i++) { + prof_skeleton->add_bone(profile->get_bone_name(i)); + prof_skeleton->set_bone_rest(i, profile->get_reference_pose(i)); + } + // Set parents. + for (int i = 0; i < prof_bone_len; i++) { + int parent = profile->find_bone(profile->get_bone_parent(i)); + if (parent >= 0) { + prof_skeleton->set_bone_parent(i, parent); + } + } + } + + // Set motion scale to Skeleton if normalize position tracks. + if (bool(p_options["retarget/rest_fixer/normalize_position_tracks"])) { + int src_bone_idx = src_skeleton->find_bone(profile->get_scale_base_bone()); + if (src_bone_idx >= 0) { + real_t motion_scale = abs(src_skeleton->get_bone_global_rest(src_bone_idx).origin.y); + if (motion_scale > 0) { + src_skeleton->set_motion_scale(motion_scale); + } + } + + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int track_len = anim->get_track_count(); + for (int i = 0; i < track_len; i++) { + if (anim->track_get_path(i).get_subname_count() != 1 || anim->track_get_type(i) != Animation::TYPE_POSITION_3D) { + continue; + } + + if (anim->track_is_compressed(i)) { + continue; // Shouldn't occur in internal_process(). + } + + String track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + if (node) { + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton) { + if (track_skeleton && track_skeleton == src_skeleton) { + real_t mlt = 1 / src_skeleton->get_motion_scale(); + int key_len = anim->track_get_key_count(i); + for (int j = 0; j < key_len; j++) { + Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, pos * mlt); + } + } + } + } + } + } + } + } + + // Complement Rotation track for compatibility between different rests. + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int track_len = anim->get_track_count(); + + // Detect does the animation have skeleton's TRS track. + String track_path; + bool found_skeleton = false; + for (int i = 0; i < track_len; i++) { + if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) { + continue; + } + track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + if (node) { + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton && track_skeleton == src_skeleton) { + found_skeleton = true; + break; + } + } + } + + if (found_skeleton) { + // Search and insert rot track if it doesn't exist. + for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) { + String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx))); + if (bone_name == String()) { + continue; + } + int src_idx = src_skeleton->find_bone(bone_name); + if (src_idx == -1) { + continue; + } + String insert_path = track_path + ":" + bone_name; + int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D); + if (rot_track == -1) { + int track = anim->add_track(Animation::TYPE_ROTATION_3D); + anim->track_set_path(track, insert_path); + anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion()); + } + } + } + } + } + } + + // Fix silhouette. + Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis. + silhouette_diff.resize(src_skeleton->get_bone_count()); + Transform3D *silhouette_diff_w = silhouette_diff.ptrw(); + if (bool(p_options["retarget/rest_fixer/fix_silhouette/enable"])) { + LocalVector<Transform3D> old_skeleton_global_rest; + for (int i = 0; i < src_skeleton->get_bone_count(); i++) { + old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i)); + } + + Vector<int> bones_to_process = prof_skeleton->get_parentless_bones(); + while (bones_to_process.size() > 0) { + int prof_idx = bones_to_process[0]; + bones_to_process.erase(prof_idx); + Vector<int> prof_children = prof_skeleton->get_bone_children(prof_idx); + for (int i = 0; i < prof_children.size(); i++) { + bones_to_process.push_back(prof_children[i]); + } + + // Calc virtual/looking direction with origins. + bool is_filtered = false; + for (int i = 0; i < filter.size(); i++) { + if (String(filter[i]) == prof_skeleton->get_bone_name(prof_idx)) { + is_filtered = true; + break; + } + } + if (is_filtered) { + continue; + } + + int src_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)))); + if (src_idx < 0 || profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_END) { + continue; + } + Vector3 prof_tail; + Vector3 src_tail; + if (profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_AVERAGE_CHILDREN) { + PackedInt32Array prof_bone_children = prof_skeleton->get_bone_children(prof_idx); + int children_size = prof_bone_children.size(); + if (children_size == 0) { + continue; + } + bool exist_all_children = true; + for (int i = 0; i < children_size; i++) { + int prof_child_idx = prof_bone_children[i]; + int src_child_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_child_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_child_idx)))); + if (src_child_idx < 0) { + exist_all_children = false; + break; + } + prof_tail = prof_tail + prof_skeleton->get_bone_global_rest(prof_child_idx).origin; + src_tail = src_tail + src_skeleton->get_bone_global_rest(src_child_idx).origin; + } + if (!exist_all_children) { + continue; + } + prof_tail = prof_tail / children_size; + src_tail = src_tail / children_size; + } + if (profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_SPECIFIC_CHILD) { + int prof_tail_idx = prof_skeleton->find_bone(profile->get_bone_tail(prof_idx)); + if (prof_tail_idx < 0) { + continue; + } + int src_tail_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_tail_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_tail_idx)))); + if (src_tail_idx < 0) { + continue; + } + prof_tail = prof_skeleton->get_bone_global_rest(prof_tail_idx).origin; + src_tail = src_skeleton->get_bone_global_rest(src_tail_idx).origin; + } + + Vector3 prof_head = prof_skeleton->get_bone_global_rest(prof_idx).origin; + Vector3 src_head = src_skeleton->get_bone_global_rest(src_idx).origin; + + Vector3 prof_dir = prof_tail - prof_head; + Vector3 src_dir = src_tail - src_head; + + // Rotate rest. + if (Math::abs(Math::rad2deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { + // Get rotation difference. + Vector3 up_vec; // Need to rotate other than roll axis. + switch (Vector3(abs(src_dir.x), abs(src_dir.y), abs(src_dir.z)).min_axis_index()) { + case Vector3::AXIS_X: { + up_vec = Vector3(1, 0, 0); + } break; + case Vector3::AXIS_Y: { + up_vec = Vector3(0, 1, 0); + } break; + case Vector3::AXIS_Z: { + up_vec = Vector3(0, 0, 1); + } break; + } + Basis src_b; + src_b = src_b.looking_at(src_dir, up_vec); + Basis prof_b; + prof_b = src_b.looking_at(prof_dir, up_vec); + if (prof_b.is_equal_approx(Basis())) { + continue; // May not need to rotate. + } + Basis diff_b = prof_b * src_b.inverse(); + + // Apply rotation difference as global transform to skeleton. + Basis src_pg; + int src_parent = src_skeleton->get_bone_parent(src_idx); + if (src_parent >= 0) { + src_pg = src_skeleton->get_bone_global_rest(src_parent).basis; + } + Transform3D fixed_rest = Transform3D(src_pg.inverse() * diff_b * src_pg * src_skeleton->get_bone_rest(src_idx).basis, src_skeleton->get_bone_rest(src_idx).origin); + src_skeleton->set_bone_rest(src_idx, fixed_rest); + } + } + + // For skin modification in overwrite rest. + for (int i = 0; i < src_skeleton->get_bone_count(); i++) { + silhouette_diff_w[i] = old_skeleton_global_rest[i] * src_skeleton->get_bone_global_rest(i).inverse(); + } + + is_rest_changed = true; + } + + // Overwrite axis. + if (bool(p_options["retarget/rest_fixer/overwrite_axis"])) { + LocalVector<Transform3D> old_skeleton_rest; + LocalVector<Transform3D> old_skeleton_global_rest; + for (int i = 0; i < src_skeleton->get_bone_count(); i++) { + old_skeleton_rest.push_back(src_skeleton->get_bone_rest(i)); + old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i)); + } + + Vector<Basis> diffs; + diffs.resize(src_skeleton->get_bone_count()); + Basis *diffs_w = diffs.ptrw(); + + Vector<int> bones_to_process = src_skeleton->get_parentless_bones(); + while (bones_to_process.size() > 0) { + int src_idx = bones_to_process[0]; + bones_to_process.erase(src_idx); + Vector<int> src_children = src_skeleton->get_bone_children(src_idx); + for (int i = 0; i < src_children.size(); i++) { + bones_to_process.push_back(src_children[i]); + } + + Basis tgt_rot; + StringName src_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(src_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(src_idx)); + if (src_bone_name != StringName()) { + Basis src_pg; + int src_parent_idx = src_skeleton->get_bone_parent(src_idx); + if (src_parent_idx >= 0) { + src_pg = src_skeleton->get_bone_global_rest(src_parent_idx).basis; + } + + int prof_idx = profile->find_bone(src_bone_name); + if (prof_idx >= 0) { + tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis; // Mapped bone uses reference pose. + } + /* + // If there is rest-relative animation, this logic may be work fine, but currently not so... + } else { + // tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone keeps global rest. + } + */ + } + + if (src_skeleton->get_bone_parent(src_idx) >= 0) { + diffs_w[src_idx] = tgt_rot.inverse() * diffs[src_skeleton->get_bone_parent(src_idx)] * src_skeleton->get_bone_rest(src_idx).basis; + } else { + diffs_w[src_idx] = tgt_rot.inverse() * src_skeleton->get_bone_rest(src_idx).basis; + } + + Basis diff; + if (src_skeleton->get_bone_parent(src_idx) >= 0) { + diff = diffs[src_skeleton->get_bone_parent(src_idx)]; + } + src_skeleton->set_bone_rest(src_idx, Transform3D(tgt_rot, diff.xform(src_skeleton->get_bone_rest(src_idx).origin))); + } + + // Fix skin. + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D"); + while (nodes.size()) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back()); + Ref<Skin> skin = mi->get_skin(); + if (skin.is_valid()) { + Node *node = mi->get_node(mi->get_skeleton_path()); + if (node) { + Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node); + if (mesh_skeleton && node == src_skeleton) { + int skin_len = skin->get_bind_count(); + for (int i = 0; i < skin_len; i++) { + StringName bn = skin->get_bind_name(i); + int bone_idx = src_skeleton->find_bone(bn); + if (bone_idx >= 0) { + Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx); + skin->set_bind_pose(i, new_rest.inverse()); + } + } + } + } + } + } + } + + // Fix animation. + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int track_len = anim->get_track_count(); + for (int i = 0; i < track_len; i++) { + if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) { + continue; + } + + if (anim->track_is_compressed(i)) { + continue; // Shouldn't occur in internal_process(). + } + + String track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + if (node) { + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton && track_skeleton == src_skeleton) { + StringName bn = anim->track_get_path(i).get_subname(0); + if (bn) { + int bone_idx = src_skeleton->find_bone(bn); + + Transform3D old_rest = old_skeleton_rest[bone_idx]; + Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx); + Transform3D old_pg; + Transform3D new_pg; + int parent_idx = src_skeleton->get_bone_parent(bone_idx); + if (parent_idx >= 0) { + old_pg = old_skeleton_global_rest[parent_idx]; + new_pg = src_skeleton->get_bone_global_rest(parent_idx); + } + + int key_len = anim->track_get_key_count(i); + if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) { + Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion(); + Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion(); + Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); + Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); + for (int j = 0; j < key_len; j++) { + Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q); + } + } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) { + Basis old_rest_b = old_rest.basis; + Basis new_rest_b = new_rest.basis; + Basis old_pg_b = old_pg.basis; + Basis new_pg_b = new_pg.basis; + for (int j = 0; j < key_len; j++) { + Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j))); + anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale()); + } + } else { + Vector3 old_rest_o = old_rest.origin; + Vector3 new_rest_o = new_rest.origin; + Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); + Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); + for (int j = 0; j < key_len; j++) { + Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o); + } + } + } + } + } + } + } + } + } + + is_rest_changed = true; + } + + // Init skeleton pose to new rest. + if (is_rest_changed) { + for (int i = 0; i < src_skeleton->get_bone_count(); i++) { + Transform3D fixed_rest = src_skeleton->get_bone_rest(i); + src_skeleton->set_bone_pose_position(i, fixed_rest.origin); + src_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion()); + src_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale()); + } + } + + memdelete(prof_skeleton); + } +} + +PostImportPluginSkeletonRestFixer::PostImportPluginSkeletonRestFixer() { +} diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.h b/editor/import/post_import_plugin_skeleton_rest_fixer.h new file mode 100644 index 0000000000..11e9d08e88 --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_rest_fixer.h @@ -0,0 +1,46 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_rest_fixer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 POST_IMPORT_PLUGIN_SKELETON_REST_FIXER_H +#define POST_IMPORT_PLUGIN_SKELETON_REST_FIXER_H + +#include "resource_importer_scene.h" + +class PostImportPluginSkeletonRestFixer : public EditorScenePostImportPlugin { + GDCLASS(PostImportPluginSkeletonRestFixer, EditorScenePostImportPlugin); + +public: + virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override; + virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override; + + PostImportPluginSkeletonRestFixer(); +}; + +#endif // POST_IMPORT_PLUGIN_SKELETON_REST_FIXER_H diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.cpp b/editor/import/post_import_plugin_skeleton_track_organizer.cpp new file mode 100644 index 0000000000..01186f47fe --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_track_organizer.cpp @@ -0,0 +1,127 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_track_organizer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "post_import_plugin_skeleton_track_organizer.h" + +#include "editor/import/scene_import_settings.h" +#include "scene/3d/skeleton_3d.h" +#include "scene/animation/animation_player.h" +#include "scene/resources/bone_map.h" + +void PostImportPluginSkeletonTrackOrganizer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/except_bone_transform"), false)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unimportant_positions"), true)); + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unmapped_bones"), false)); + } +} + +void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) { + if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { + // Prepare objects. + Object *map = p_options["retarget/bone_map"].get_validated_object(); + if (!map) { + return; + } + BoneMap *bone_map = Object::cast_to<BoneMap>(map); + Ref<SkeletonProfile> profile = bone_map->get_profile(); + if (!profile.is_valid()) { + return; + } + Skeleton3D *src_skeleton = Object::cast_to<Skeleton3D>(p_node); + if (!src_skeleton) { + return; + } + bool remove_except_bone = bool(p_options["retarget/remove_tracks/except_bone_transform"]); + bool remove_positions = bool(p_options["retarget/remove_tracks/unimportant_positions"]); + bool remove_unmapped_bones = bool(p_options["retarget/remove_tracks/unmapped_bones"]); + + if (!remove_positions && !remove_unmapped_bones) { + return; + } + + TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); + while (nodes.size()) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + int track_len = anim->get_track_count(); + Vector<int> remove_indices; + for (int i = 0; i < track_len; i++) { + String track_path = String(anim->track_get_path(i).get_concatenated_names()); + Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); + if (!node) { + if (remove_except_bone) { + remove_indices.push_back(i); + } + continue; + } + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (track_skeleton && track_skeleton == src_skeleton) { + if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) { + if (remove_except_bone) { + remove_indices.push_back(i); + } + continue; + } + StringName bn = anim->track_get_path(i).get_subname(0); + if (bn) { + int prof_idx = profile->find_bone(bone_map->find_profile_bone_name(bn)); + if (remove_unmapped_bones && prof_idx < 0) { + remove_indices.push_back(i); + continue; + } + if (remove_positions && anim->track_get_type(i) == Animation::TYPE_POSITION_3D && prof_idx >= 0) { + StringName prof_bn = profile->get_bone_name(prof_idx); + if (prof_bn == profile->get_root_bone() || prof_bn == profile->get_scale_base_bone()) { + continue; + } + remove_indices.push_back(i); + } + } + } + if (remove_except_bone) { + remove_indices.push_back(i); + } + } + + remove_indices.reverse(); + for (int i = 0; i < remove_indices.size(); i++) { + anim->remove_track(remove_indices[i]); + } + } + } + } +} + +PostImportPluginSkeletonTrackOrganizer::PostImportPluginSkeletonTrackOrganizer() { +} diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.h b/editor/import/post_import_plugin_skeleton_track_organizer.h new file mode 100644 index 0000000000..1830861430 --- /dev/null +++ b/editor/import/post_import_plugin_skeleton_track_organizer.h @@ -0,0 +1,46 @@ +/*************************************************************************/ +/* post_import_plugin_skeleton_track_organizer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 POST_IMPORT_PLUGIN_SKELETON_TRACK_ORGANIZER_H +#define POST_IMPORT_PLUGIN_SKELETON_TRACK_ORGANIZER_H + +#include "resource_importer_scene.h" + +class PostImportPluginSkeletonTrackOrganizer : public EditorScenePostImportPlugin { + GDCLASS(PostImportPluginSkeletonTrackOrganizer, EditorScenePostImportPlugin); + +public: + virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override; + virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override; + + PostImportPluginSkeletonTrackOrganizer(); +}; + +#endif // POST_IMPORT_PLUGIN_SKELETON_TRACK_ORGANIZER_H diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index 966719dc48..c03962b8a4 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -103,7 +103,7 @@ Error ResourceImporterBitMap::import(const String &p_source_file, const String & } } - return ResourceSaver::save(p_save_path + ".res", bitmap); + return ResourceSaver::save(bitmap, p_save_path + ".res"); } ResourceImporterBitMap::ResourceImporterBitMap() { diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index 8682ab80a3..e791788d50 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -53,4 +53,5 @@ public: ResourceImporterBitMap(); ~ResourceImporterBitMap(); }; + #endif // RESOURCE_IMPORTER_BITMASK_H diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index 987ca4b911..14b5638755 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -84,7 +84,7 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & } print_verbose("Saving to: " + p_save_path + ".fontdata"); - err = ResourceSaver::save(p_save_path + ".fontdata", font, flg); + err = ResourceSaver::save(font, p_save_path + ".fontdata", flg); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\"."); print_verbose("Done saving to: " + p_save_path + ".fontdata"); return OK; diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 0b3622e3c0..8b429e74d1 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -131,7 +131,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const String save_path = p_source_file.get_basename() + "." + translations[i]->get_locale() + ".translation"; - ResourceSaver::save(save_path, xlt); + ResourceSaver::save(xlt, save_path); if (r_gen_files) { r_gen_files->push_back(save_path); } diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index 306aafa843..2ed121c5e8 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCEIMPORTERCSVTRANSLATION_H -#define RESOURCEIMPORTERCSVTRANSLATION_H +#ifndef RESOURCE_IMPORTER_CSV_TRANSLATION_H +#define RESOURCE_IMPORTER_CSV_TRANSLATION_H #include "core/io/resource_importer.h" @@ -54,4 +54,4 @@ public: ResourceImporterCSVTranslation(); }; -#endif // RESOURCEIMPORTERCSVTRANSLATION_H +#endif // RESOURCE_IMPORTER_CSV_TRANSLATION_H diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index f1a70ff30a..32fd94b093 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -219,7 +219,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str } print_verbose("Saving to: " + p_save_path + ".fontdata"); - Error err = ResourceSaver::save(p_save_path + ".fontdata", font, flg); + Error err = ResourceSaver::save(font, p_save_path + ".fontdata", flg); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\"."); print_verbose("Done saving to: " + p_save_path + ".fontdata"); return OK; diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index ea84d4c883..374cbe7ce2 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -159,7 +159,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin } print_verbose("Saving to: " + p_save_path + ".fontdata"); - err = ResourceSaver::save(p_save_path + ".fontdata", font, flg); + err = ResourceSaver::save(font, p_save_path + ".fontdata", flg); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\"."); print_verbose("Done saving to: " + p_save_path + ".fontdata"); return OK; diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h index f46bc8c19b..e163f873da 100644 --- a/editor/import/resource_importer_imagefont.h +++ b/editor/import/resource_importer_imagefont.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCE_IMPORTER_IMAGE_FONT_H -#define RESOURCE_IMPORTER_IMAGE_FONT_H +#ifndef RESOURCE_IMPORTER_IMAGEFONT_H +#define RESOURCE_IMPORTER_IMAGEFONT_H #include "core/io/resource_importer.h" #include "scene/resources/font.h" @@ -55,4 +55,4 @@ public: ResourceImporterImageFont(); }; -#endif // RESOURCE_IMPORTER_IMAGE_FONT_H +#endif // RESOURCE_IMPORTER_IMAGEFONT_H diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index bacd09592e..2e6de95a46 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -367,7 +367,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const for (int j = 0; j < hslices; j++) { int x = slice_w * j; int y = slice_h * i; - Ref<Image> slice = image->get_rect(Rect2(x, y, slice_w, slice_h)); + Ref<Image> slice = image->get_rect(Rect2i(x, y, slice_w, slice_h)); ERR_CONTINUE(slice.is_null() || slice->is_empty()); if (slice->get_width() != slice_w || slice->get_height() != slice_h) { slice->resize(slice_w, slice_h); @@ -391,7 +391,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const texture_import->bptc_ldr = bptc_ldr; texture_import->mipmaps = mipmaps; texture_import->used_channels = used_channels; - _check_compress_ctex(texture_import); + _check_compress_ctex(p_source_file, texture_import); if (r_metadata) { Dictionary metadata; metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED; @@ -472,7 +472,7 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() { ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() { } -void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImport> r_texture_import) { +void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source_file, Ref<LayeredTextureImport> r_texture_import) { String extension = get_save_extension(); ERR_FAIL_NULL(r_texture_import->csource); if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) { @@ -542,5 +542,5 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImpo } return; } - EditorNode::add_io_error(TTR("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC.")); + EditorNode::add_io_error(vformat(TTR("%s: No suitable PC VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file)); } diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 5a29010c3b..e292390fb3 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -87,7 +87,7 @@ protected: static ResourceImporterLayeredTexture *singleton; public: - void _check_compress_ctex(Ref<LayeredTextureImport> r_texture_import); + void _check_compress_ctex(const String &p_source_file, Ref<LayeredTextureImport> r_texture_import); static ResourceImporterLayeredTexture *get_singleton() { return singleton; } virtual String get_importer_name() const override; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 6fbfecfdfa..d1c4e1f8dd 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -519,7 +519,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s String save_path = p_save_path + ".mesh"; - err = ResourceSaver::save(save_path, meshes.front()->get()); + err = ResourceSaver::save(meshes.front()->get(), save_path); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Mesh to file '" + save_path + "'."); diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 3da9f02adb..4dfac90fa1 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCEIMPORTEROBJ_H -#define RESOURCEIMPORTEROBJ_H +#ifndef RESOURCE_IMPORTER_OBJ_H +#define RESOURCE_IMPORTER_OBJ_H #include "resource_importer_scene.h" @@ -69,4 +69,4 @@ public: ResourceImporterOBJ(); }; -#endif // RESOURCEIMPORTEROBJ_H +#endif // RESOURCE_IMPORTER_OBJ_H diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 860269bfcb..3c0de61d24 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -743,6 +743,163 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<R return p_node; } +Node *ResourceImporterScene::_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps) { + // children first + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *r = _pre_fix_animations(p_node->get_child(i), p_root, p_node_data, p_animation_data, p_animation_fps); + if (!r) { + i--; //was erased + } + } + + String import_id = p_node->get_meta("import_id", "PATH:" + p_root->get_path_to(p_node)); + + Dictionary node_settings; + if (p_node_data.has(import_id)) { + node_settings = p_node_data[import_id]; + } + + { + //make sure this is unique + node_settings = node_settings.duplicate(true); + //fill node settings for this node with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts); + for (const ImportOption &E : iopts) { + if (!node_settings.has(E.option.name)) { + node_settings[E.option.name] = E.default_value; + } + } + } + + if (Object::cast_to<AnimationPlayer>(p_node)) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); + + Array animation_clips; + { + int clip_count = node_settings["clips/amount"]; + + for (int i = 0; i < clip_count; i++) { + String name = node_settings["clip_" + itos(i + 1) + "/name"]; + int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"]; + int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"]; + Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]); + bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"]; + bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"]; + bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"]; + + animation_clips.push_back(name); + animation_clips.push_back(from_frame / p_animation_fps); + animation_clips.push_back(end_frame / p_animation_fps); + animation_clips.push_back(loop_mode); + animation_clips.push_back(save_to_file); + animation_clips.push_back(save_to_path); + animation_clips.push_back(save_to_file_keep_custom); + } + } + + if (animation_clips.size()) { + _create_clips(ap, animation_clips, true); + } else { + List<StringName> anims; + ap->get_animation_list(&anims); + AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = { + AnimationImportTracks(int(node_settings["import_tracks/position"])), + AnimationImportTracks(int(node_settings["import_tracks/rotation"])), + AnimationImportTracks(int(node_settings["import_tracks/scale"])) + }; + if (anims.size() > 1 && (import_tracks_mode[0] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[1] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[2] != ANIMATION_IMPORT_TRACKS_IF_PRESENT)) { + _optimize_track_usage(ap, import_tracks_mode); + } + } + } + + return p_node; +} + +Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps) { + // children first + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *r = _post_fix_animations(p_node->get_child(i), p_root, p_node_data, p_animation_data, p_animation_fps); + if (!r) { + i--; //was erased + } + } + + String import_id = p_node->get_meta("import_id", "PATH:" + p_root->get_path_to(p_node)); + + Dictionary node_settings; + if (p_node_data.has(import_id)) { + node_settings = p_node_data[import_id]; + } + + { + //make sure this is unique + node_settings = node_settings.duplicate(true); + //fill node settings for this node with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts); + for (const ImportOption &E : iopts) { + if (!node_settings.has(E.option.name)) { + node_settings[E.option.name] = E.default_value; + } + } + } + + if (Object::cast_to<AnimationPlayer>(p_node)) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); + + bool use_optimizer = node_settings["optimizer/enabled"]; + float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"]; + float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"]; + float anim_optimizer_maxang = node_settings["optimizer/max_angle"]; + + if (use_optimizer) { + _optimize_animations(ap, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang); + } + + bool use_compression = node_settings["compression/enabled"]; + int anim_compression_page_size = node_settings["compression/page_size"]; + + if (use_compression) { + _compress_animations(ap, anim_compression_page_size); + } + + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + Ref<Animation> anim = ap->get_animation(name); + if (p_animation_data.has(name)) { + Dictionary anim_settings = p_animation_data[name]; + { + //fill with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts); + for (const ImportOption &F : iopts) { + if (!anim_settings.has(F.option.name)) { + anim_settings[F.option.name] = F.default_value; + } + } + } + + anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"])); + bool save = anim_settings["save_to_file/enabled"]; + String path = anim_settings["save_to_file/path"]; + bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"]; + + Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom); + + if (saved_anim != anim) { + Ref<AnimationLibrary> al = ap->get_animation_library(ap->find_animation_library(anim)); + al->add_animation(name, saved_anim); //replace + } + } + } + } + + return p_node; +} + Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { @@ -1012,83 +1169,6 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, p_root, p_node, Ref<Resource>(), node_settings); } - bool use_optimizer = node_settings["optimizer/enabled"]; - float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"]; - float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"]; - float anim_optimizer_maxang = node_settings["optimizer/max_angle"]; - - if (use_optimizer) { - _optimize_animations(ap, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang); - } - - Array animation_clips; - { - int clip_count = node_settings["clips/amount"]; - - for (int i = 0; i < clip_count; i++) { - String name = node_settings["clip_" + itos(i + 1) + "/name"]; - int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"]; - int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"]; - Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]); - bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"]; - bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"]; - bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"]; - - animation_clips.push_back(name); - animation_clips.push_back(from_frame / p_animation_fps); - animation_clips.push_back(end_frame / p_animation_fps); - animation_clips.push_back(loop_mode); - animation_clips.push_back(save_to_file); - animation_clips.push_back(save_to_path); - animation_clips.push_back(save_to_file_keep_custom); - } - } - - if (animation_clips.size()) { - _create_clips(ap, animation_clips, true); - } else { - List<StringName> anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { - Ref<Animation> anim = ap->get_animation(name); - if (p_animation_data.has(name)) { - Dictionary anim_settings = p_animation_data[name]; - { - //fill with default values - List<ImportOption> iopts; - get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts); - for (const ImportOption &F : iopts) { - if (!anim_settings.has(F.option.name)) { - anim_settings[F.option.name] = F.default_value; - } - } - } - - anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"])); - bool save = anim_settings["save_to_file/enabled"]; - String path = anim_settings["save_to_file/path"]; - bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"]; - - Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom); - - if (saved_anim != anim) { - Ref<AnimationLibrary> al = ap->get_animation_library(ap->find_animation_library(anim)); - al->add_animation(name, saved_anim); //replace - } - } - } - - AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = { - AnimationImportTracks(int(node_settings["import_tracks/position"])), - AnimationImportTracks(int(node_settings["import_tracks/rotation"])), - AnimationImportTracks(int(node_settings["import_tracks/scale"])) - }; - - if (anims.size() > 1 && (import_tracks_mode[0] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[1] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[2] != ANIMATION_IMPORT_TRACKS_IF_PRESENT)) { - _optimize_track_usage(ap, import_tracks_mode); - } - } - if (post_importer_plugins.size()) { List<StringName> anims; ap->get_animation_list(&anims); @@ -1113,13 +1193,6 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } } } - - bool use_compression = node_settings["compression/enabled"]; - int anim_compression_page_size = node_settings["compression/page_size"]; - - if (use_compression) { - _compress_animations(ap, anim_compression_page_size); - } } return p_node; @@ -1151,7 +1224,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani } } anim->set_path(p_save_to_path, true); // Set path to save externally. - Error err = ResourceSaver::save(p_save_to_path, anim, ResourceSaver::FLAG_CHANGE_PATH); + Error err = ResourceSaver::save(anim, p_save_to_path, ResourceSaver::FLAG_CHANGE_PATH); ERR_FAIL_COND_V_MSG(err != OK, anim, "Saving of animation failed: " + p_save_to_path); return anim; } @@ -1769,7 +1842,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } mesh = src_mesh_node->get_mesh()->get_mesh(existing); - ResourceSaver::save(save_to_file, mesh); //override + ResourceSaver::save(mesh, save_to_file); //override mesh->set_path(save_to_file, true); //takeover existing, if needed @@ -2099,7 +2172,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p post_importer_plugins.write[i]->pre_process(scene, p_options); } + _pre_fix_animations(scene, scene, node_data, animation_data, fps); _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps); + _post_fix_animations(scene, scene, node_data, animation_data, fps); String root_type = p_options["nodes/root_type"]; root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class. @@ -2235,14 +2310,14 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } print_verbose("Saving animation to: " + p_save_path + ".scn"); - err = ResourceSaver::save(p_save_path + ".res", library); //do not take over, let the changed files reload themselves + err = ResourceSaver::save(library, p_save_path + ".res"); //do not take over, let the changed files reload themselves ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save animation to file '" + p_save_path + ".res'."); } else { Ref<PackedScene> packer = memnew(PackedScene); packer->pack(scene); print_verbose("Saving scene to: " + p_save_path + ".scn"); - err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves + err = ResourceSaver::save(packer, p_save_path + ".scn"); //do not take over, let the changed files reload themselves ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index b77c1dccb4..b336931476 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCEIMPORTERSCENE_H -#define RESOURCEIMPORTERSCENE_H +#ifndef RESOURCE_IMPORTER_SCENE_H +#define RESOURCE_IMPORTER_SCENE_H #include "core/error/error_macros.h" #include "core/io/resource_importer.h" @@ -274,7 +274,9 @@ public: virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } Node *_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames); + Node *_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps); Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); @@ -479,4 +481,4 @@ Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_opt return transform; } -#endif // RESOURCEIMPORTERSCENE_H +#endif // RESOURCE_IMPORTER_SCENE_H diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index 64839bf199..d3079141e0 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -109,7 +109,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri } } - ResourceSaver::save(p_save_path + ".res", shader_file); + ResourceSaver::save(shader_file, p_save_path + ".res"); return OK; } diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index deb3047864..0eed6184c0 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -597,7 +597,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } if (!ok_on_pc) { - EditorNode::add_io_error(TTR("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC.")); + EditorNode::add_io_error(vformat(TTR("%s: No suitable desktop VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file)); } } else { //import normally diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 7def2d4f77..496ad3bf70 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCEIMPORTTEXTURE_H -#define RESOURCEIMPORTTEXTURE_H +#ifndef RESOURCE_IMPORTER_TEXTURE_H +#define RESOURCE_IMPORTER_TEXTURE_H #include "core/io/file_access.h" #include "core/io/image.h" @@ -109,4 +109,4 @@ public: ~ResourceImporterTexture(); }; -#endif // RESOURCEIMPORTTEXTURE_H +#endif // RESOURCE_IMPORTER_TEXTURE_H diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index 28653dac3e..bae1b903c6 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -88,7 +88,7 @@ Error ResourceImporterTextureAtlas::import(const String &p_source_file, const St //use an xpm because it's size independent, the editor images are vector and size dependent //it's a simple hack Ref<Image> broken = memnew(Image((const char **)atlas_import_failed_xpm)); - ResourceSaver::save(p_save_path + ".tex", ImageTexture::create_from_image(broken)); + ResourceSaver::save(ImageTexture::create_from_image(broken), p_save_path + ".tex"); return OK; } @@ -212,7 +212,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file EditorAtlasPacker::Chart chart; - Rect2 used_rect = Rect2(Vector2(), image->get_size()); + Rect2i used_rect = Rect2i(Vector2i(), image->get_size()); if (trim_alpha_border_from_region) { // Clip a region from the image. used_rect = image->get_used_rect(); @@ -220,9 +220,9 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file pack_data.region = used_rect; chart.vertices.push_back(used_rect.position); - chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, 0)); - chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, used_rect.size.y)); - chart.vertices.push_back(used_rect.position + Vector2(0, used_rect.size.y)); + chart.vertices.push_back(used_rect.position + Vector2i(used_rect.size.x, 0)); + chart.vertices.push_back(used_rect.position + Vector2i(used_rect.size.x, used_rect.size.y)); + chart.vertices.push_back(used_rect.position + Vector2i(0, used_rect.size.y)); EditorAtlasPacker::Chart::Face f; f.vertex[0] = 0; f.vertex[1] = 1; @@ -386,7 +386,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file } String save_path = p_base_paths[E.key] + ".res"; - ResourceSaver::save(save_path, texture); + ResourceSaver::save(texture, save_path); idx++; } diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index f0ba1eb7a1..a1e00f7d30 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -33,7 +33,7 @@ #include "core/io/file_access.h" #include "core/io/marshalls.h" #include "core/io/resource_saver.h" -#include "scene/resources/audio_stream_sample.h" +#include "scene/resources/audio_stream_wav.h" const float TRIM_DB_LIMIT = -50; const int TRIM_FADE_OUT_FRAMES = 500; @@ -55,7 +55,7 @@ String ResourceImporterWAV::get_save_extension() const { } String ResourceImporterWAV::get_resource_type() const { - return "AudioStreamSample"; + return "AudioStreamWAV"; } bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { @@ -86,7 +86,7 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false)); - // Keep the `edit/loop_mode` enum in sync with AudioStreamSample::LoopMode (note: +1 offset due to "Detect From WAV"). + // Keep the `edit/loop_mode` enum in sync with AudioStreamWAV::LoopMode (note: +1 offset due to "Detect From WAV"). r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_mode", PROPERTY_HINT_ENUM, "Detect From WAV,Disabled,Forward,Ping-Pong,Backward", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_begin"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_end"), -1)); @@ -130,7 +130,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s int format_bits = 0; int format_channels = 0; - AudioStreamSample::LoopMode loop_mode = AudioStreamSample::LOOP_DISABLED; + AudioStreamWAV::LoopMode loop_mode = AudioStreamWAV::LOOP_DISABLED; uint16_t compression_code = 1; bool format_found = false; bool data_found = false; @@ -282,11 +282,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s int loop_type = file->get_32(); if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) { if (loop_type == 0x00) { - loop_mode = AudioStreamSample::LOOP_FORWARD; + loop_mode = AudioStreamWAV::LOOP_FORWARD; } else if (loop_type == 0x01) { - loop_mode = AudioStreamSample::LOOP_PINGPONG; + loop_mode = AudioStreamWAV::LOOP_PINGPONG; } else if (loop_type == 0x02) { - loop_mode = AudioStreamSample::LOOP_BACKWARD; + loop_mode = AudioStreamWAV::LOOP_BACKWARD; } loop_begin = file->get_32(); loop_end = file->get_32(); @@ -386,7 +386,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s bool trim = p_options["edit/trim"]; - if (trim && (loop_mode != AudioStreamSample::LOOP_DISABLED) && format_channels > 0) { + if (trim && (loop_mode != AudioStreamWAV::LOOP_DISABLED) && format_channels > 0) { int first = 0; int last = (frames / format_channels) - 1; bool found = false; @@ -431,7 +431,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } if (import_loop_mode >= 2) { - loop_mode = (AudioStreamSample::LoopMode)(import_loop_mode - 1); + loop_mode = (AudioStreamWAV::LoopMode)(import_loop_mode - 1); loop_begin = p_options["edit/loop_begin"]; loop_end = p_options["edit/loop_end"]; // Wrap around to max frames, so `-1` can be used to select the end, etc. @@ -463,10 +463,10 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } Vector<uint8_t> dst_data; - AudioStreamSample::Format dst_format; + AudioStreamWAV::Format dst_format; if (compression == 1) { - dst_format = AudioStreamSample::FORMAT_IMA_ADPCM; + dst_format = AudioStreamWAV::FORMAT_IMA_ADPCM; if (format_channels == 1) { _compress_ima_adpcm(data, dst_data); } else { @@ -503,7 +503,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } } else { - dst_format = is16 ? AudioStreamSample::FORMAT_16_BITS : AudioStreamSample::FORMAT_8_BITS; + dst_format = is16 ? AudioStreamWAV::FORMAT_16_BITS : AudioStreamWAV::FORMAT_8_BITS; dst_data.resize(data.size() * (is16 ? 2 : 1)); { uint8_t *w = dst_data.ptrw(); @@ -521,7 +521,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } } - Ref<AudioStreamSample> sample; + Ref<AudioStreamWAV> sample; sample.instantiate(); sample->set_data(dst_data); sample->set_format(dst_format); @@ -531,7 +531,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s sample->set_loop_end(loop_end); sample->set_stereo(format_channels == 2); - ResourceSaver::save(p_save_path + ".sample", sample); + ResourceSaver::save(sample, p_save_path + ".sample"); return OK; } diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 0e2967dc42..6c12464b5a 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -35,6 +35,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/importer_mesh.h" @@ -502,7 +503,7 @@ void SceneImportSettings::_update_camera() { Transform3D xf; xf.basis = Basis(Vector3(1, 0, 0), rot_x) * Basis(Vector3(0, 1, 0), rot_y); xf.origin = center; - xf.translate(0, 0, camera_size); + xf.translate_local(0, 0, camera_size); camera->set_transform(xf); } @@ -1184,7 +1185,7 @@ void SceneImportSettings::_save_dir_confirm() { ERR_CONTINUE(!material_map.has(id)); MaterialData &md = material_map[id]; - Error err = ResourceSaver::save(path, md.material); + Error err = ResourceSaver::save(md.material, path); if (err != OK) { EditorNode::get_singleton()->add_io_error(TTR("Can't make material external to file, write error:") + "\n\t" + path); continue; diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp index 9d96822aef..a70f5225e9 100644 --- a/editor/import_defaults_editor.cpp +++ b/editor/import_defaults_editor.cpp @@ -36,6 +36,7 @@ #include "editor/editor_autoload_settings.h" #include "editor/editor_plugin_settings.h" #include "editor/editor_sectioned_inspector.h" +#include "editor/editor_settings.h" #include "editor/localization_editor.h" #include "editor/shader_globals_editor.h" #include "scene/gui/center_container.h" diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index f9e5885f9d..087ef48b56 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -34,6 +34,7 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" class ImportDockParameters : public Object { GDCLASS(ImportDockParameters, Object); diff --git a/editor/import_dock.h b/editor/import_dock.h index 7f4aa1ddb3..3098c6e815 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IMPORTDOCK_H -#define IMPORTDOCK_H +#ifndef IMPORT_DOCK_H +#define IMPORT_DOCK_H #include "core/io/config_file.h" #include "core/io/resource_importer.h" @@ -105,4 +105,4 @@ public: ~ImportDock(); }; -#endif // IMPORTDOCK_H +#endif // IMPORT_DOCK_H diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index a509cf3d8f..79d94246ad 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -33,6 +33,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" InspectorDock *InspectorDock::singleton = nullptr; @@ -64,6 +65,9 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { case COLLAPSE_ALL: { _menu_collapseall(); } break; + case EXPAND_REVERTABLE: { + _menu_expand_revertable(); + } break; case RESOURCE_SAVE: { _save_resource(false); @@ -400,6 +404,10 @@ void InspectorDock::_menu_expandall() { inspector->expand_all_folding(); } +void InspectorDock::_menu_expand_revertable() { + inspector->expand_revertable(); +} + void InspectorDock::_warning_pressed() { warning_dialog->popup_centered(); } @@ -453,6 +461,9 @@ void InspectorDock::_bind_methods() { ClassDB::bind_method("edit_resource", &InspectorDock::edit_resource); + ClassDB::bind_method("store_script_properties", &InspectorDock::store_script_properties); + ClassDB::bind_method("apply_script_properties", &InspectorDock::apply_script_properties); + ADD_SIGNAL(MethodInfo("request_help")); } @@ -515,6 +526,8 @@ void InspectorDock::update(Object *p_object) { p->clear(); p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL); p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL); + // Calling it 'revertable' internally, because that's what the implementation is based on, but labeling it as 'non-default' because that's more user friendly, even if not 100% accurate. + p->add_shortcut(ED_SHORTCUT("property_editor/expand_revertable", TTR("Expand Non-Default")), EXPAND_REVERTABLE); p->add_separator(TTR("Property Name Style")); p->add_radio_check_item(TTR("Raw"), PROPERTY_NAME_STYLE_RAW); @@ -565,6 +578,31 @@ EditorPropertyNameProcessor::Style InspectorDock::get_property_name_style() cons return property_name_style; } +void InspectorDock::store_script_properties(Object *p_object) { + ERR_FAIL_NULL(p_object); + ScriptInstance *si = p_object->get_script_instance(); + if (!si) { + return; + } + si->get_property_state(stored_properties); +} + +void InspectorDock::apply_script_properties(Object *p_object) { + ERR_FAIL_NULL(p_object); + ScriptInstance *si = p_object->get_script_instance(); + if (!si) { + return; + } + + for (const Pair<StringName, Variant> &E : stored_properties) { + Variant current; + if (si->get(E.first, current) && current.get_type() == E.second.get_type()) { + si->set(E.first, E.second); + } + } + stored_properties.clear(); +} + InspectorDock::InspectorDock(EditorData &p_editor_data) { singleton = this; set_name("Inspector"); @@ -645,7 +683,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { open_docs_button->set_tooltip(TTR("Open documentation for this object.")); open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation"))); subresource_hb->add_child(open_docs_button); - open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP)); + open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option).bind(OBJECT_REQUEST_HELP)); new_resource_dialog = memnew(CreateDialog); EditorNode::get_singleton()->get_gui_base()->add_child(new_resource_dialog); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 1f2d8afb7d..e32410151f 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -61,6 +61,7 @@ class InspectorDock : public VBoxContainer { COLLAPSE_ALL, EXPAND_ALL, + EXPAND_REVERTABLE, // Matches `EditorPropertyNameProcessor::Style`. PROPERTY_NAME_STYLE_RAW, @@ -100,6 +101,7 @@ class InspectorDock : public VBoxContainer { Tree *unique_resources_list_tree = nullptr; EditorPropertyNameProcessor::Style property_name_style; + List<Pair<StringName, Variant>> stored_properties; void _prepare_menu(); void _menu_option(int p_option); @@ -123,6 +125,7 @@ class InspectorDock : public VBoxContainer { void _edit_back(); void _menu_collapseall(); void _menu_expandall(); + void _menu_expand_revertable(); void _select_history(int p_idx); void _prepare_history(); @@ -149,8 +152,11 @@ public: EditorPropertyNameProcessor::Style get_property_name_style() const; + void store_script_properties(Object *p_object); + void apply_script_properties(Object *p_object); + InspectorDock(EditorData &p_editor_data); ~InspectorDock(); }; -#endif +#endif // INSPECTOR_DOCK_H diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 0325f4bd5c..e8fb80eb57 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -36,6 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_translation_parser.h" +#include "editor/filesystem_dock.h" #include "editor/pot_generator.h" #include "scene/gui/control.h" @@ -379,6 +380,95 @@ void LocalizationEditor::_update_pot_file_extensions() { } } +void LocalizationEditor::connect_filesystem_dock_signals(FileSystemDock *p_fs_dock) { + p_fs_dock->connect("files_moved", callable_mp(this, &LocalizationEditor::_filesystem_files_moved)); + p_fs_dock->connect("file_removed", callable_mp(this, &LocalizationEditor::_filesystem_file_removed)); +} + +void LocalizationEditor::_filesystem_files_moved(const String &p_old_file, const String &p_new_file) { + // Update remaps if the moved file is a part of them. + Dictionary remaps; + bool remaps_changed = false; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { + remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); + } + + // Check for the keys. + if (remaps.has(p_old_file)) { + PackedStringArray remapped_files = remaps[p_old_file]; + remaps.erase(p_old_file); + remaps[p_new_file] = remapped_files; + remaps_changed = true; + print_verbose(vformat("Changed remap key \"%s\" to \"%s\" due to a moved file.", p_old_file, p_new_file)); + } + + // Check for the Array elements of the values. + Array remap_keys = remaps.keys(); + for (int i = 0; i < remap_keys.size(); i++) { + PackedStringArray remapped_files = remaps[remap_keys[i]]; + bool remapped_files_updated = false; + + for (int j = 0; j < remapped_files.size(); j++) { + int splitter_pos = remapped_files[j].rfind(":"); + String res_path = remapped_files[j].substr(0, splitter_pos); + + if (res_path == p_old_file) { + String locale_name = remapped_files[j].substr(splitter_pos + 1); + // Replace the element at that index. + remapped_files.insert(j, p_new_file + ":" + locale_name); + remapped_files.remove_at(j + 1); + remaps_changed = true; + remapped_files_updated = true; + print_verbose(vformat("Changed remap value \"%s\" to \"%s\" of key \"%s\" due to a moved file.", res_path + ":" + locale_name, remapped_files[j], remap_keys[i])); + } + } + + if (remapped_files_updated) { + remaps[remap_keys[i]] = remapped_files; + } + } + + if (remaps_changed) { + ProjectSettings::get_singleton()->set_setting("internationalization/locale/translation_remaps", remaps); + update_translations(); + emit_signal("localization_changed"); + } +} + +void LocalizationEditor::_filesystem_file_removed(const String &p_file) { + // Check if the remaps are affected. + Dictionary remaps; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { + remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); + } + + bool remaps_changed = remaps.has(p_file); + + if (!remaps_changed) { + Array remap_keys = remaps.keys(); + for (int i = 0; i < remap_keys.size() && !remaps_changed; i++) { + PackedStringArray remapped_files = remaps[remap_keys[i]]; + for (int j = 0; j < remapped_files.size() && !remaps_changed; j++) { + int splitter_pos = remapped_files[j].rfind(":"); + String res_path = remapped_files[j].substr(0, splitter_pos); + remaps_changed = p_file == res_path; + if (remaps_changed) { + print_verbose(vformat("Remap value \"%s\" of key \"%s\" has been removed from the file system.", remapped_files[j], remap_keys[i])); + } + } + } + } else { + print_verbose(vformat("Remap key \"%s\" has been removed from the file system.", p_file)); + } + + if (remaps_changed) { + update_translations(); + emit_signal("localization_changed"); + } +} + void LocalizationEditor::update_translations() { if (updating_translations) { return; @@ -432,6 +522,13 @@ void LocalizationEditor::update_translations() { t->set_tooltip(0, keys[i]); t->set_metadata(0, keys[i]); t->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove")); + + // Display that it has been removed if this is the case. + if (!FileAccess::exists(keys[i])) { + t->set_text(0, t->get_text(0) + vformat(" (%s)", TTR("Removed"))); + t->set_tooltip(0, vformat(TTR("%s cannot be found."), t->get_tooltip(0))); + } + if (keys[i] == remap_selected) { t->select(0); translation_res_option_add_button->set_disabled(false); @@ -454,6 +551,12 @@ void LocalizationEditor::update_translations() { t2->set_editable(1, true); t2->set_metadata(1, path); t2->set_tooltip(1, locale); + + // Display that it has been removed if this is the case. + if (!FileAccess::exists(path)) { + t2->set_text(0, t2->get_text(0) + vformat(" (%s)", TTR("Removed"))); + t2->set_tooltip(0, vformat(TTR("%s cannot be found."), t2->get_tooltip(0))); + } } } } diff --git a/editor/localization_editor.h b/editor/localization_editor.h index 4b41a90cc2..10ccdfdc13 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -36,6 +36,7 @@ #include "scene/gui/tree.h" class EditorFileDialog; +class FileSystemDock; class LocalizationEditor : public VBoxContainer { GDCLASS(LocalizationEditor, VBoxContainer); @@ -81,6 +82,9 @@ class LocalizationEditor : public VBoxContainer { void _pot_generate(const String &p_file); void _update_pot_file_extensions(); + void _filesystem_files_moved(const String &p_old_file, const String &p_new_file); + void _filesystem_file_removed(const String &p_file); + protected: void _notification(int p_what); static void _bind_methods(); @@ -88,6 +92,7 @@ protected: public: void add_translation(const String &p_translation); void update_translations(); + void connect_filesystem_dock_signals(FileSystemDock *p_fs_dock); LocalizationEditor(); }; diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 7061204832..6d323572e6 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -81,8 +81,8 @@ void PluginConfigDialog::_on_confirmed() { template_content = templates[0].content; } Ref<Script> script = ScriptServer::get_language(lang_idx)->make_template(template_content, class_name, "EditorPlugin"); - script->set_path(script_path); - ResourceSaver::save(script_path, script); + script->set_path(script_path, true); + ResourceSaver::save(script); emit_signal(SNAME("plugin_ready"), script.ptr(), active_edit->is_pressed() ? _to_absolute_plugin_path(_get_subfolder()) : ""); } else { diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index a5ca55f6df..a7d7c0145a 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -35,6 +35,8 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/separator.h" bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const { return polygon == p_vertex.polygon && vertex == p_vertex.vertex; @@ -292,9 +294,9 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) _commit_action(); return true; } else { - pre_move_edit = vertices; edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); vertices.insert(edited_point.vertex, edited_point.pos); + pre_move_edit = vertices; selected_point = Vertex(edited_point.polygon, edited_point.vertex); edge_point = PosVertex(); @@ -716,19 +718,19 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(bool p_wip_destructive) { button_create = memnew(Button); button_create->set_flat(true); add_child(button_create); - button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_CREATE)); + button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_CREATE)); button_create->set_toggle_mode(true); button_edit = memnew(Button); button_edit->set_flat(true); add_child(button_edit); - button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_EDIT)); + button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_EDIT)); button_edit->set_toggle_mode(true); button_delete = memnew(Button); button_delete->set_flat(true); add_child(button_delete); - button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_DELETE)); + button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_DELETE)); button_delete->set_toggle_mode(true); create_resource = memnew(ConfirmationDialog); diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 248ba021ce..32d97c65a9 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -34,6 +34,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const { @@ -314,6 +315,8 @@ void AnimationNodeBlendSpace1DEditor::_update_space() { max_value->set_value(blend_space->get_max_space()); min_value->set_value(blend_space->get_min_space()); + sync->set_pressed(blend_space->is_using_sync()); + label_value->set_text(blend_space->get_value_label()); snap_value->set_value(blend_space->get_snap()); @@ -329,13 +332,15 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) { } updating = true; - undo_redo->create_action(TTR("Change BlendSpace1D Limits")); + undo_redo->create_action(TTR("Change BlendSpace1D Config")); undo_redo->add_do_method(blend_space.ptr(), "set_max_space", max_value->get_value()); undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space()); undo_redo->add_do_method(blend_space.ptr(), "set_min_space", min_value->get_value()); undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space()); undo_redo->add_do_method(blend_space.ptr(), "set_snap", snap_value->get_value()); undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap()); + undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed()); + undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync()); undo_redo->add_do_method(this, "_update_space"); undo_redo->add_undo_method(this, "_update_space"); undo_redo->commit_action(); @@ -608,7 +613,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { top_hb->add_child(tool_blend); tool_blend->set_pressed(true); tool_blend->set_tooltip(TTR("Set the blending position within the space")); - tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(3)); + tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(3)); tool_select = memnew(Button); tool_select->set_flat(true); @@ -616,7 +621,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); - tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(0)); + tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(0)); tool_create = memnew(Button); tool_create->set_flat(true); @@ -624,7 +629,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_create->set_button_group(bg); top_hb->add_child(tool_create); tool_create->set_tooltip(TTR("Create points.")); - tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(1)); + tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(1)); tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); @@ -650,6 +655,12 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { snap_value->set_step(0.01); snap_value->set_max(1000); + top_hb->add_child(memnew(VSeparator)); + top_hb->add_child(memnew(Label(TTR("Sync:")))); + sync = memnew(CheckBox); + top_hb->add_child(sync); + sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed)); + edit_hb = memnew(HBoxContainer); top_hb->add_child(edit_hb); edit_hb->add_child(memnew(VSeparator)); @@ -665,7 +676,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { open_editor = memnew(Button); edit_hb->add_child(open_editor); open_editor->set_text(TTR("Open Editor")); - open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_open_editor), varray(), CONNECT_DEFERRED); + open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_open_editor), CONNECT_DEFERRED); edit_hb->hide(); open_editor->hide(); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 2f7dee65fc..9b06f3248f 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -33,11 +33,11 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_space_1d.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { @@ -61,6 +61,8 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { SpinBox *max_value = nullptr; SpinBox *min_value = nullptr; + CheckBox *sync = nullptr; + HBoxContainer *edit_hb = nullptr; SpinBox *edit_value = nullptr; Button *open_editor = nullptr; diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index dfde63ecb6..dc764725dd 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" @@ -595,6 +596,7 @@ void AnimationNodeBlendSpace2DEditor::_update_space() { auto_triangles->set_pressed(blend_space->get_auto_triangles()); + sync->set_pressed(blend_space->is_using_sync()); interpolation->select(blend_space->get_blend_mode()); max_x_value->set_value(blend_space->get_max_space().x); @@ -620,13 +622,15 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) { } updating = true; - undo_redo->create_action(TTR("Change BlendSpace2D Limits")); + undo_redo->create_action(TTR("Change BlendSpace2D Config")); undo_redo->add_do_method(blend_space.ptr(), "set_max_space", Vector2(max_x_value->get_value(), max_y_value->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space()); undo_redo->add_do_method(blend_space.ptr(), "set_min_space", Vector2(min_x_value->get_value(), min_y_value->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space()); undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap()); + undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed()); + undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync()); undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected()); undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode()); undo_redo->add_do_method(this, "_update_space"); @@ -829,7 +833,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(tool_blend); tool_blend->set_pressed(true); tool_blend->set_tooltip(TTR("Set the blending position within the space")); - tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(3)); + tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(3)); tool_select = memnew(Button); tool_select->set_flat(true); @@ -837,7 +841,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); - tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(0)); + tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(0)); tool_create = memnew(Button); tool_create->set_flat(true); @@ -845,7 +849,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_create->set_button_group(bg); top_hb->add_child(tool_create); tool_create->set_tooltip(TTR("Create points.")); - tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(1)); + tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(1)); tool_triangle = memnew(Button); tool_triangle->set_flat(true); @@ -853,7 +857,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_triangle->set_button_group(bg); top_hb->add_child(tool_triangle); tool_triangle->set_tooltip(TTR("Create triangles by connecting points.")); - tool_triangle->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(2)); + tool_triangle->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(2)); tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); @@ -899,6 +903,13 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(memnew(VSeparator)); + top_hb->add_child(memnew(Label(TTR("Sync:")))); + sync = memnew(CheckBox); + top_hb->add_child(sync); + sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_config_changed)); + + top_hb->add_child(memnew(VSeparator)); + top_hb->add_child(memnew(Label(TTR("Blend:")))); interpolation = memnew(OptionButton); top_hb->add_child(interpolation); @@ -923,7 +934,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { open_editor = memnew(Button); edit_hb->add_child(open_editor); open_editor->set_text(TTR("Open Editor")); - open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_open_editor), varray(), CONNECT_DEFERRED); + open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_open_editor), CONNECT_DEFERRED); edit_hb->hide(); open_editor->hide(); diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index db54e84254..26471df051 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -33,11 +33,11 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_space_2d.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { @@ -55,6 +55,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { Button *snap = nullptr; SpinBox *snap_x = nullptr; SpinBox *snap_y = nullptr; + CheckBox *sync = nullptr; OptionButton *interpolation = nullptr; Button *auto_triangles = nullptr; diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 5e703cf814..79be2d04b3 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -38,6 +38,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" @@ -147,11 +148,11 @@ void AnimationNodeBlendTreeEditor::_update_graph() { name->set_expand_to_text_length_enabled(true); node->add_child(name); node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label"))); - name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED); - name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED); + name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed).bind(agnode), CONNECT_DEFERRED); + name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(name, agnode), CONNECT_DEFERRED); base = 1; node->set_show_close_button(true); - node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request), varray(E), CONNECT_DEFERRED); + node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request).bind(E), CONNECT_DEFERRED); } for (int i = 0; i < agnode->get_input_count(); i++) { @@ -179,7 +180,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { } } - node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged), varray(E)); + node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged).bind(E)); if (AnimationTreeEditor::get_singleton()->can_edit(agnode)) { node->add_child(memnew(HSeparator)); @@ -187,7 +188,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { open_in_editor->set_text(TTR("Open Editor")); open_in_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); node->add_child(open_in_editor); - open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E), CONNECT_DEFERRED); + open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor).bind(E), CONNECT_DEFERRED); open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER); } @@ -197,7 +198,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { edit_filters->set_text(TTR("Edit Filters")); edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons"))); node->add_child(edit_filters); - edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E), CONNECT_DEFERRED); + edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters).bind(E), CONNECT_DEFERRED); edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER); } @@ -236,7 +237,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { animations[E] = pb; node->add_child(pb); - mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E), CONNECT_DEFERRED); + mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected).bind(options, E), CONNECT_DEFERRED); } Ref<StyleBoxFlat> sb = node->get_theme_stylebox(SNAME("frame"), SNAME("GraphNode")); @@ -961,8 +962,8 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { graph->add_valid_right_disconnect_type(0); graph->add_valid_left_disconnect_type(0); graph->set_v_size_flags(SIZE_EXPAND_FILL); - graph->connect("connection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_request), varray(), CONNECT_DEFERRED); - graph->connect("disconnection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_disconnection_request), varray(), CONNECT_DEFERRED); + graph->connect("connection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_request), CONNECT_DEFERRED); + graph->connect("disconnection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_disconnection_request), CONNECT_DEFERRED); graph->connect("node_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_selected)); graph->connect("scroll_offset_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_scroll_changed)); graph->connect("delete_nodes_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_nodes_request)); @@ -983,7 +984,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node)); - add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu), varray(false)); + add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu).bind(false)); add_options.push_back(AddOption("Animation", "AnimationNodeAnimation")); add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot", 2)); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index b5bf91a1da..18199676b8 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -33,7 +33,6 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_tree.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/animation_library_editor.h b/editor/plugins/animation_library_editor.h index bf89508321..6e214860b8 100644 --- a/editor/plugins/animation_library_editor.h +++ b/editor/plugins/animation_library_editor.h @@ -116,4 +116,4 @@ public: AnimationLibraryEditor(); }; -#endif // ANIMATIONPLAYERLIBRARYEDITOR_H +#endif // ANIMATION_LIBRARY_EDITOR_H diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 3d4701a54a..ebd7525bb8 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -132,8 +132,8 @@ void AnimationPlayerEditor::_notification(int p_what) { Size2 icon_size = autoplay_img->get_size(); autoplay_reset_img.instantiate(); autoplay_reset_img->create(icon_size.x * 2, icon_size.y, false, autoplay_img->get_format()); - autoplay_reset_img->blit_rect(autoplay_img, Rect2(Point2(), icon_size), Point2()); - autoplay_reset_img->blit_rect(reset_img, Rect2(Point2(), icon_size), Point2(icon_size.x, 0)); + autoplay_reset_img->blit_rect(autoplay_img, Rect2i(Point2i(), icon_size), Point2i()); + autoplay_reset_img->blit_rect(reset_img, Rect2i(Point2i(), icon_size), Point2i(icon_size.x, 0)); autoplay_reset_icon.instantiate(); autoplay_reset_icon->set_image(autoplay_reset_img); } @@ -1426,19 +1426,19 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { // Render every past/future step with the capture shader. RS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, onion.capture.material->get_rid()); - onion.capture.material->set_shader_param("bkg_color", GLOBAL_GET("rendering/environment/defaults/default_clear_color")); - onion.capture.material->set_shader_param("differences_only", onion.differences_only); - onion.capture.material->set_shader_param("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID()); + onion.capture.material->set_shader_uniform("bkg_color", GLOBAL_GET("rendering/environment/defaults/default_clear_color")); + onion.capture.material->set_shader_uniform("differences_only", onion.differences_only); + onion.capture.material->set_shader_uniform("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID()); int step_off_a = onion.past ? -onion.steps : 0; int step_off_b = onion.future ? onion.steps : 0; int cidx = 0; - onion.capture.material->set_shader_param("dir_color", onion.force_white_modulate ? Color(1, 1, 1) : Color(EDITOR_GET("editors/animation/onion_layers_past_color"))); + onion.capture.material->set_shader_uniform("dir_color", onion.force_white_modulate ? Color(1, 1, 1) : Color(EDITOR_GET("editors/animation/onion_layers_past_color"))); for (int step_off = step_off_a; step_off <= step_off_b; step_off++) { if (step_off == 0) { // Skip present step and switch to the color of future. if (!onion.force_white_modulate) { - onion.capture.material->set_shader_param("dir_color", EDITOR_GET("editors/animation/onion_layers_future_color")); + onion.capture.material->set_shader_uniform("dir_color", EDITOR_GET("editors/animation/onion_layers_future_color")); } continue; } @@ -1633,7 +1633,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug onion_toggle->set_flat(true); onion_toggle->set_toggle_mode(true); onion_toggle->set_tooltip(TTR("Enable Onion Skinning")); - onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu), varray(ONION_SKINNING_ENABLE)); + onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu).bind(ONION_SKINNING_ENABLE)); hb->add_child(onion_toggle); onion_skinning = memnew(MenuButton); @@ -1720,7 +1720,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug animation->connect("item_selected", callable_mp(this, &AnimationPlayerEditor::_animation_selected)); - frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false)); + frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed).bind(true, false)); scale->connect("text_submitted", callable_mp(this, &AnimationPlayerEditor::_scale_changed)); last_active = false; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 05d7a5f973..473450b292 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" @@ -1018,7 +1019,7 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) { anim->set_animation(animations_to_add[p_index]); - String base_name = animations_to_add[p_index]; + String base_name = animations_to_add[p_index].validate_node_name(); int base = 1; String name = base_name; while (state_machine->has_node(name)) { @@ -1899,7 +1900,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_select->set_button_group(bg); tool_select->set_pressed(true); tool_select->set_tooltip(TTR("Select and move nodes.\nRMB: Add node at position clicked.\nShift+LMB+Drag: Connects the selected node with another node or creates a new node if you select an area without nodes.")); - tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); + tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_create = memnew(Button); tool_create->set_flat(true); @@ -1907,7 +1908,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); tool_create->set_tooltip(TTR("Create new nodes.")); - tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); + tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_connect = memnew(Button); tool_connect->set_flat(true); @@ -1915,7 +1916,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_connect->set_toggle_mode(true); tool_connect->set_button_group(bg); tool_connect->set_tooltip(TTR("Connect nodes.")); - tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); + tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_erase_hb = memnew(HBoxContainer); top_hb->add_child(tool_erase_hb); @@ -1938,7 +1939,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_erase = memnew(Button); tool_erase->set_flat(true); tool_erase->set_tooltip(TTR("Remove selected node or transition.")); - tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected), varray(false)); + tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false)); tool_erase->set_disabled(true); tool_erase_hb->add_child(tool_erase); @@ -1969,7 +1970,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { state_machine_play_pos = memnew(Control); state_machine_draw->add_child(state_machine_play_pos); state_machine_play_pos->set_mouse_filter(MOUSE_FILTER_PASS); //pass all to parent - state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_WIDE); + state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_FULL_RECT); state_machine_play_pos->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_pos_draw)); v_scroll = memnew(VScrollBar); @@ -2022,7 +2023,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { add_child(name_edit_popup); name_edit = memnew(LineEdit); name_edit_popup->add_child(name_edit); - name_edit->set_anchors_and_offsets_preset(PRESET_WIDE); + name_edit->set_anchors_and_offsets_preset(PRESET_FULL_RECT); name_edit->connect("text_submitted", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited)); name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out)); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index ea16abd64c..165940e639 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -33,7 +33,6 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_node_state_machine.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index 7ea6906d72..bce4c9de8e 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -86,7 +86,7 @@ void AnimationTreeEditor::_update_path() { b->set_button_group(group); b->set_pressed(true); b->set_focus_mode(FOCUS_NONE); - b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed), varray(-1)); + b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed).bind(-1)); path_hb->add_child(b); for (int i = 0; i < button_path.size(); i++) { b = memnew(Button); @@ -96,7 +96,7 @@ void AnimationTreeEditor::_update_path() { path_hb->add_child(b); b->set_pressed(true); b->set_focus_mode(FOCUS_NONE); - b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed), varray(i)); + b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed).bind(i)); } } diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h index ab4ef5a001..a33d97f62f 100644 --- a/editor/plugins/animation_tree_editor_plugin.h +++ b/editor/plugins/animation_tree_editor_plugin.h @@ -32,7 +32,6 @@ #define ANIMATION_TREE_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_tree.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index bc95624dd5..8ee162d085 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -161,7 +161,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const Ref<Image> overlay = previews->get_theme_icon(SNAME("PlayOverlay"), SNAME("EditorIcons"))->get_image(); Ref<Image> thumbnail = p_image->get_image(); thumbnail = thumbnail->duplicate(); - Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2); + Point2i overlay_pos = Point2i((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2); // Overlay and thumbnail need the same format for `blend_rect` to work. thumbnail->convert(Image::FORMAT_RGBA8); @@ -253,7 +253,7 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons preview.button = memnew(Button); preview.button->set_icon(previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons"))); preview.button->set_toggle_mode(true); - preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click), varray(p_id)); + preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click).bind(p_id)); preview_hb->add_child(preview.button); if (!p_video) { preview.image = previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons")); @@ -887,7 +887,7 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, String p_image_url, Imag iq.queue_id = ++last_queue_id; iq.active = false; - iq.request->connect("request_completed", callable_mp(this, &EditorAssetLibrary::_image_request_completed), varray(iq.queue_id)); + iq.request->connect("request_completed", callable_mp(this, &EditorAssetLibrary::_image_request_completed).bind(iq.queue_id)); image_queue[iq.queue_id] = iq; @@ -1006,7 +1006,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int Button *first = memnew(Button); first->set_text(TTR("First", "Pagination")); if (p_page != 0) { - first->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(0)); + first->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(0)); } else { first->set_disabled(true); first->set_focus_mode(Control::FOCUS_NONE); @@ -1016,7 +1016,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int Button *prev = memnew(Button); prev->set_text(TTR("Previous", "Pagination")); if (p_page > 0) { - prev->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page - 1)); + prev->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page - 1)); } else { prev->set_disabled(true); prev->set_focus_mode(Control::FOCUS_NONE); @@ -1037,7 +1037,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int Button *current = memnew(Button); // Add padding to make page number buttons easier to click. current->set_text(vformat(" %d ", i + 1)); - current->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(i)); + current->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(i)); hbc->add_child(current); } @@ -1046,7 +1046,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int Button *next = memnew(Button); next->set_text(TTR("Next", "Pagination")); if (p_page < p_page_count - 1) { - next->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page + 1)); + next->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page + 1)); } else { next->set_disabled(true); next->set_focus_mode(Control::FOCUS_NONE); @@ -1057,7 +1057,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int Button *last = memnew(Button); last->set_text(TTR("Last", "Pagination")); if (p_page != p_page_count - 1) { - last->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page_count - 1)); + last->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page_count - 1)); } else { last->set_disabled(true); last->set_focus_mode(Control::FOCUS_NONE); @@ -1616,7 +1616,7 @@ AssetLibraryEditorPlugin::AssetLibraryEditorPlugin() { addon_library = memnew(EditorAssetLibrary); addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL); EditorNode::get_singleton()->get_main_control()->add_child(addon_library); - addon_library->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + addon_library->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); addon_library->hide(); } diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index e02662b8db..070d25e29f 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -338,4 +338,4 @@ public: ~AssetLibraryEditorPlugin(); }; -#endif // EDITORASSETLIBRARY_H +#endif // ASSET_LIBRARY_EDITOR_PLUGIN_H diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp deleted file mode 100644 index a60e49ca9d..0000000000 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/*************************************************************************/ -/* audio_stream_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "audio_stream_editor_plugin.h" - -#include "core/config/project_settings.h" -#include "core/io/resource_loader.h" -#include "core/os/keyboard.h" -#include "editor/audio_stream_preview.h" -#include "editor/editor_node.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" - -void AudioStreamEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AudioStreamEditor::_preview_changed)); - } break; - - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { - _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); - _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor"))); - set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor"))); - - _indicator->update(); - _preview->update(); - } break; - - case NOTIFICATION_PROCESS: { - _current = _player->get_playback_position(); - _indicator->update(); - } break; - - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible_in_tree()) { - _stop(); - } - } break; - } -} - -void AudioStreamEditor::_draw_preview() { - Rect2 rect = _preview->get_rect(); - Size2 size = get_size(); - - Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream); - float preview_len = preview->get_length(); - - Vector<Vector2> lines; - lines.resize(size.width * 2); - - for (int i = 0; i < size.width; i++) { - float ofs = i * preview_len / size.width; - float ofs_n = (i + 1) * preview_len / size.width; - float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5; - float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; - - int idx = i; - lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y); - lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y); - } - - Vector<Color> color; - color.push_back(get_theme_color(SNAME("contrast_color_2"), SNAME("Editor"))); - - RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color); -} - -void AudioStreamEditor::_preview_changed(ObjectID p_which) { - if (stream.is_valid() && stream->get_instance_id() == p_which) { - _preview->update(); - } -} - -void AudioStreamEditor::_audio_changed() { - if (!is_visible()) { - return; - } - update(); -} - -void AudioStreamEditor::_play() { - if (_player->is_playing()) { - // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'. - _pausing = true; - _player->stop(); - _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - set_process(false); - } else { - _player->play(_current); - _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); - set_process(true); - } -} - -void AudioStreamEditor::_stop() { - _player->stop(); - _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - _current = 0; - _indicator->update(); - set_process(false); -} - -void AudioStreamEditor::_on_finished() { - _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - if (!_pausing) { - _current = 0; - _indicator->update(); - } else { - _pausing = false; - } - set_process(false); -} - -void AudioStreamEditor::_draw_indicator() { - if (!stream.is_valid()) { - return; - } - - Rect2 rect = _preview->get_rect(); - float len = stream->get_length(); - float ofs_x = _current / len * rect.size.width; - const Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), color, Math::round(2 * EDSCALE)); - _indicator->draw_texture( - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")), - Point2(ofs_x - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, 0), - color); - - _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /"); -} - -void AudioStreamEditor::_on_input_indicator(Ref<InputEvent> p_event) { - const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { - if (mb->is_pressed()) { - _seek_to(mb->get_position().x); - } - _dragging = mb->is_pressed(); - } - - const Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid()) { - if (_dragging) { - _seek_to(mm->get_position().x); - } - } -} - -void AudioStreamEditor::_seek_to(real_t p_x) { - _current = p_x / _preview->get_rect().size.x * stream->get_length(); - _current = CLAMP(_current, 0, stream->get_length()); - _player->seek(_current); - _indicator->update(); -} - -void AudioStreamEditor::edit(Ref<AudioStream> p_stream) { - if (!stream.is_null()) { - stream->disconnect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed)); - } - - stream = p_stream; - _player->set_stream(stream); - _current = 0; - String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s"; - _duration_label->set_text(text); - - if (!stream.is_null()) { - stream->connect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed)); - update(); - } else { - hide(); - } -} - -void AudioStreamEditor::_bind_methods() { -} - -AudioStreamEditor::AudioStreamEditor() { - set_custom_minimum_size(Size2(1, 100) * EDSCALE); - - _player = memnew(AudioStreamPlayer); - _player->connect("finished", callable_mp(this, &AudioStreamEditor::_on_finished)); - add_child(_player); - - VBoxContainer *vbox = memnew(VBoxContainer); - vbox->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 0); - add_child(vbox); - - _preview = memnew(ColorRect); - _preview->set_v_size_flags(SIZE_EXPAND_FILL); - _preview->connect("draw", callable_mp(this, &AudioStreamEditor::_draw_preview)); - vbox->add_child(_preview); - - _indicator = memnew(Control); - _indicator->set_anchors_and_offsets_preset(PRESET_WIDE); - _indicator->connect("draw", callable_mp(this, &AudioStreamEditor::_draw_indicator)); - _indicator->connect("gui_input", callable_mp(this, &AudioStreamEditor::_on_input_indicator)); - _preview->add_child(_indicator); - - HBoxContainer *hbox = memnew(HBoxContainer); - hbox->add_theme_constant_override("separation", 0); - vbox->add_child(hbox); - - _play_button = memnew(Button); - _play_button->set_flat(true); - hbox->add_child(_play_button); - _play_button->set_focus_mode(Control::FOCUS_NONE); - _play_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_play)); - _play_button->set_shortcut(ED_SHORTCUT("inspector/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), Key::SPACE)); - - _stop_button = memnew(Button); - _stop_button->set_flat(true); - hbox->add_child(_stop_button); - _stop_button->set_focus_mode(Control::FOCUS_NONE); - _stop_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_stop)); - - _current_label = memnew(Label); - _current_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); - _current_label->set_h_size_flags(SIZE_EXPAND_FILL); - _current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts"))); - _current_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts"))); - _current_label->set_modulate(Color(1, 1, 1, 0.5)); - hbox->add_child(_current_label); - - _duration_label = memnew(Label); - _duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts"))); - _duration_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts"))); - hbox->add_child(_duration_label); -} - -void AudioStreamEditorPlugin::edit(Object *p_object) { - AudioStream *s = Object::cast_to<AudioStream>(p_object); - if (!s) { - return; - } - - audio_editor->edit(Ref<AudioStream>(s)); -} - -bool AudioStreamEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("AudioStream"); -} - -void AudioStreamEditorPlugin::make_visible(bool p_visible) { - audio_editor->set_visible(p_visible); -} - -AudioStreamEditorPlugin::AudioStreamEditorPlugin() { - audio_editor = memnew(AudioStreamEditor); - add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, audio_editor); - audio_editor->hide(); -} - -AudioStreamEditorPlugin::~AudioStreamEditorPlugin() { -} diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h index c883e5542f..b045f8c751 100644 --- a/editor/plugins/bit_map_editor_plugin.h +++ b/editor/plugins/bit_map_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BIT_MAP_PREVIEW_EDITOR_PLUGIN_H -#define BIT_MAP_PREVIEW_EDITOR_PLUGIN_H +#ifndef BIT_MAP_EDITOR_PLUGIN_H +#define BIT_MAP_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/resources/bit_map.h" @@ -61,4 +61,4 @@ public: BitMapEditorPlugin(); }; -#endif // BIT_MAP_PREVIEW_EDITOR_PLUGIN_H +#endif // BIT_MAP_EDITOR_PLUGIN_H diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index fffadae3eb..70775c1ee2 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -32,6 +32,8 @@ #include "editor/editor_scale.h" #include "editor/import/post_import_plugin_skeleton_renamer.h" +#include "editor/import/post_import_plugin_skeleton_rest_fixer.h" +#include "editor/import/post_import_plugin_skeleton_track_organizer.h" #include "editor/import/scene_import_settings.h" void BoneMapperButton::fetch_textures() { @@ -63,6 +65,9 @@ void BoneMapperButton::set_state(BoneMapState p_state) { case BONE_MAP_STATE_SET: { circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/set")); } break; + case BONE_MAP_STATE_MISSING: { + circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/missing")); + } break; case BONE_MAP_STATE_ERROR: { circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/error")); } break; @@ -71,6 +76,10 @@ void BoneMapperButton::set_state(BoneMapState p_state) { } } +bool BoneMapperButton::is_require() const { + return require; +} + void BoneMapperButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -79,8 +88,9 @@ void BoneMapperButton::_notification(int p_what) { } } -BoneMapperButton::BoneMapperButton(const StringName p_profile_bone_name, bool p_selected) { +BoneMapperButton::BoneMapperButton(const StringName p_profile_bone_name, bool p_require, bool p_selected) { profile_bone_name = p_profile_bone_name; + require = p_require; selected = p_selected; } @@ -89,7 +99,7 @@ BoneMapperButton::~BoneMapperButton() { void BoneMapperItem::create_editor() { skeleton_bone_selector = memnew(EditorPropertyTextEnum); - skeleton_bone_selector->setup(skeleton_bone_names); + skeleton_bone_selector->setup(skeleton_bone_names, false, true); skeleton_bone_selector->set_label(profile_bone_name); skeleton_bone_selector->set_selectable(false); skeleton_bone_selector->set_object_and_property(bone_map.ptr(), "bone_map/" + String(profile_bone_name)); @@ -251,8 +261,8 @@ void BoneMapper::recreate_editor() { for (int i = 0; i < len; i++) { if (profile->get_group(i) == profile->get_group_name(current_group_idx)) { - BoneMapperButton *mb = memnew(BoneMapperButton(profile->get_bone_name(i), current_bone_idx == i)); - mb->connect("pressed", callable_mp(this, &BoneMapper::set_current_bone_idx), varray(i), CONNECT_DEFERRED); + BoneMapperButton *mb = memnew(BoneMapperButton(profile->get_bone_name(i), profile->is_require(i), current_bone_idx == i)); + mb->connect("pressed", callable_mp(this, &BoneMapper::set_current_bone_idx).bind(i), CONNECT_DEFERRED); mb->set_h_grow_direction(GROW_DIRECTION_BOTH); mb->set_v_grow_direction(GROW_DIRECTION_BOTH); Vector2 vc = profile->get_handle_offset(i); @@ -284,8 +294,6 @@ void BoneMapper::recreate_items() { Ref<SkeletonProfile> profile = bone_map->get_profile(); if (profile.is_valid()) { PackedStringArray skeleton_bone_names; - skeleton_bone_names.push_back(String()); - int len = skeleton->get_bone_count(); for (int i = 0; i < len; i++) { skeleton_bone_names.push_back(skeleton->get_bone_name(i)); @@ -306,15 +314,51 @@ void BoneMapper::recreate_items() { void BoneMapper::_update_state() { int len = bone_mapper_buttons.size(); for (int i = 0; i < len; i++) { - StringName sbn = bone_map->get_skeleton_bone_name(bone_mapper_buttons[i]->get_profile_bone_name()); - if (skeleton->find_bone(sbn) >= 0) { + StringName pbn = bone_mapper_buttons[i]->get_profile_bone_name(); + StringName sbn = bone_map->get_skeleton_bone_name(pbn); + int bone_idx = skeleton->find_bone(sbn); + if (bone_idx >= 0) { if (bone_map->get_skeleton_bone_name_count(sbn) == 1) { - bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET); + Ref<SkeletonProfile> prof = bone_map->get_profile(); + + StringName parent_name = prof->get_bone_parent(prof->find_bone(pbn)); + Vector<int> prof_parent_bones; + while (parent_name != StringName()) { + prof_parent_bones.push_back(skeleton->find_bone(bone_map->get_skeleton_bone_name(parent_name))); + if (prof->find_bone(parent_name) == -1) { + break; + } + parent_name = prof->get_bone_parent(prof->find_bone(parent_name)); + } + + int parent_id = skeleton->get_bone_parent(bone_idx); + Vector<int> skel_parent_bones; + while (parent_id >= 0) { + skel_parent_bones.push_back(parent_id); + parent_id = skeleton->get_bone_parent(parent_id); + } + + bool is_broken = false; + for (int j = 0; j < prof_parent_bones.size(); j++) { + if (prof_parent_bones[j] != -1 && !skel_parent_bones.has(prof_parent_bones[j])) { + is_broken = true; + } + } + + if (is_broken) { + bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR); + } else { + bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET); + } } else { bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR); } } else { - bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_UNSET); + if (bone_mapper_buttons[i]->is_require()) { + bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_MISSING); + } else { + bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_UNSET); + } } } } @@ -371,11 +415,15 @@ void BoneMapEditor::create_editors() { } void BoneMapEditor::fetch_objects() { + skeleton = nullptr; // Hackey... but it may be the easist way to get a selected object from "ImporterScene". SceneImportSettings *si = SceneImportSettings::get_singleton(); if (!si) { return; } + if (!si->is_visible()) { + return; + } Node *selected = si->get_selected_node(); if (selected) { Skeleton3D *sk = Object::cast_to<Skeleton3D>(selected); @@ -396,9 +444,12 @@ void BoneMapEditor::_notification(int p_what) { create_editors(); } break; case NOTIFICATION_EXIT_TREE: { - remove_child(bone_mapper); - bone_mapper->queue_delete(); - } + if (bone_mapper) { + remove_child(bone_mapper); + bone_mapper->queue_delete(); + } + skeleton = nullptr; + } break; } } @@ -425,15 +476,24 @@ void EditorInspectorPluginBoneMap::parse_begin(Object *p_object) { BoneMapEditorPlugin::BoneMapEditorPlugin() { // Register properties in editor settings. + EDITOR_DEF("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3)); EDITOR_DEF("editors/bone_mapper/handle_colors/set", Color(0.1, 0.6, 0.25)); + EDITOR_DEF("editors/bone_mapper/handle_colors/missing", Color(0.8, 0.2, 0.8)); EDITOR_DEF("editors/bone_mapper/handle_colors/error", Color(0.8, 0.2, 0.2)); - EDITOR_DEF("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3)); Ref<EditorInspectorPluginBoneMap> inspector_plugin; inspector_plugin.instantiate(); add_inspector_plugin(inspector_plugin); + Ref<PostImportPluginSkeletonTrackOrganizer> post_import_plugin_track_organizer; + post_import_plugin_track_organizer.instantiate(); + add_scene_post_import_plugin(post_import_plugin_track_organizer); + Ref<PostImportPluginSkeletonRenamer> post_import_plugin_renamer; post_import_plugin_renamer.instantiate(); add_scene_post_import_plugin(post_import_plugin_renamer); + + Ref<PostImportPluginSkeletonRestFixer> post_import_plugin_rest_fixer; + post_import_plugin_rest_fixer.instantiate(); + add_scene_post_import_plugin(post_import_plugin_rest_fixer); } diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h index 0ec9f74373..339547ea10 100644 --- a/editor/plugins/bone_map_editor_plugin.h +++ b/editor/plugins/bone_map_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BONE_MAP_EDITOR_H -#define BONE_MAP_EDITOR_H +#ifndef BONE_MAP_EDITOR_PLUGIN_H +#define BONE_MAP_EDITOR_PLUGIN_H #include "editor/editor_node.h" #include "editor/editor_plugin.h" @@ -47,12 +47,14 @@ public: enum BoneMapState { BONE_MAP_STATE_UNSET, BONE_MAP_STATE_SET, + BONE_MAP_STATE_MISSING, BONE_MAP_STATE_ERROR }; private: StringName profile_bone_name; bool selected = false; + bool require = false; TextureRect *circle; @@ -65,7 +67,9 @@ public: StringName get_profile_bone_name() const; void set_state(BoneMapState p_state); - BoneMapperButton(const StringName p_profile_bone_name, bool p_selected); + bool is_require() const; + + BoneMapperButton(const StringName p_profile_bone_name, bool p_require, bool p_selected); ~BoneMapperButton(); }; @@ -173,4 +177,4 @@ public: BoneMapEditorPlugin(); }; -#endif // BONE_MAP_EDITOR_H +#endif // BONE_MAP_EDITOR_PLUGIN_H diff --git a/editor/plugins/camera_3d_editor_plugin.h b/editor/plugins/camera_3d_editor_plugin.h index a8164f9b85..a969b31976 100644 --- a/editor/plugins/camera_3d_editor_plugin.h +++ b/editor/plugins/camera_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERA_EDITOR_PLUGIN_H -#define CAMERA_EDITOR_PLUGIN_H +#ifndef CAMERA_3D_EDITOR_PLUGIN_H +#define CAMERA_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/camera_3d.h" @@ -68,4 +68,4 @@ public: ~Camera3DEditorPlugin(); }; -#endif // CAMERA_EDITOR_PLUGIN_H +#endif // CAMERA_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7e525a4698..ac85eb5e1b 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -50,8 +50,10 @@ #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite_2d.h" #include "scene/2d/touch_screen_button.h" +#include "scene/gui/flow_container.h" #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" +#include "scene/gui/separator.h" #include "scene/gui/subviewport_container.h" #include "scene/gui/view_panner.h" #include "scene/main/canvas_layer.h" @@ -1201,7 +1203,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1369,14 +1371,14 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { drag_selection[0]->get_name(), drag_selection[0]->_edit_get_pivot().x, drag_selection[0]->_edit_get_pivot().y)); - drag_type = DRAG_NONE; + _reset_drag(); return true; } // Cancel a drag if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1452,14 +1454,14 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { _insert_animation_keys(false, true, false, true); } - drag_type = DRAG_NONE; + _reset_drag(); return true; } // Cancel a drag if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1614,14 +1616,14 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { _commit_canvas_item_state( drag_selection, vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name())); - drag_type = DRAG_NONE; + _reset_drag(); return true; } // Cancel a drag if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1820,7 +1822,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1830,7 +1832,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { _restore_canvas_item_state(drag_selection); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1959,7 +1961,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { _insert_animation_keys(false, false, true, true); } - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -1967,7 +1969,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { // Cancel a drag if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -2092,7 +2094,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -2102,7 +2104,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { _restore_canvas_item_state(drag_selection, true); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -2209,7 +2211,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { drag_selection[0]->_edit_get_position().y), true); } - drag_type = DRAG_NONE; + _reset_drag(); } viewport->update(); return true; @@ -2281,7 +2283,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } selection_menu_additive_selection = b->is_shift_pressed(); - selection_menu->set_position(get_screen_position() + b->get_position()); + selection_menu->set_position(viewport->get_screen_transform().xform(b->get_position())); selection_menu->reset_size(); selection_menu->popup(); return true; @@ -2360,7 +2362,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_QUEUED) { if (b.is_valid() && !b->is_pressed()) { - drag_type = DRAG_NONE; + _reset_drag(); return true; } if (m.is_valid()) { @@ -2411,14 +2413,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::RIGHT) { // Cancel box selection - drag_type = DRAG_NONE; + _reset_drag(); viewport->update(); return true; } @@ -2792,10 +2794,10 @@ void CanvasItemEditor::_draw_rulers() { if (grid_snap_active || _is_grid_visible()) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (snap_relative && selection.size() > 0) { - ruler_transform.translate(_get_encompassing_rect_from_list(selection).position); + ruler_transform.translate_local(_get_encompassing_rect_from_list(selection).position); ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); } else { - ruler_transform.translate(grid_offset); + ruler_transform.translate_local(grid_offset); ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); } while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) { @@ -3645,7 +3647,7 @@ void CanvasItemEditor::_draw_hover() { } void CanvasItemEditor::_draw_transform_message() { - if (drag_selection.is_empty() || !drag_selection.front()->get()) { + if (drag_type == DRAG_NONE || drag_selection.is_empty() || !drag_selection.front()->get()) { return; } String transform_message; @@ -3861,7 +3863,7 @@ void CanvasItemEditor::_update_editor_settings() { key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55)); animation_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - context_menu_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); + context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/2d_editor_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); pan_speed = int(EditorSettings::get_singleton()->get("editors/panning/2d_editor_pan_speed")); @@ -3981,7 +3983,7 @@ void CanvasItemEditor::_notification(int p_what) { void CanvasItemEditor::_selection_changed() { if (!selected_from_canvas) { - drag_type = DRAG_NONE; + _reset_drag(); } selected_from_canvas = false; } @@ -3989,7 +3991,7 @@ void CanvasItemEditor::_selection_changed() { void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { Array selection = editor_selection->get_selected_nodes(); if (selection.size() != 1 || Object::cast_to<Node>(selection[0]) != p_canvas_item) { - drag_type = DRAG_NONE; + _reset_drag(); // Clear the selection editor_selection->clear(); //_clear_canvas_items(); @@ -4235,13 +4237,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, Control *ctrl = Object::cast_to<Control>(canvas_item); if (key_pos) { - te->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing); + te->insert_node_value_key(ctrl, "position", ctrl->get_position(), p_on_existing); } if (key_rot) { - te->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing); + te->insert_node_value_key(ctrl, "rotation", ctrl->get_rotation(), p_on_existing); } if (key_scale) { - te->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing); + te->insert_node_value_key(ctrl, "size", ctrl->get_size(), p_on_existing); } } } @@ -4701,6 +4703,11 @@ void CanvasItemEditor::_focus_selection(int p_op) { } } +void CanvasItemEditor::_reset_drag() { + drag_type = DRAG_NONE; + drag_selection.clear(); +} + void CanvasItemEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); @@ -4921,11 +4928,11 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { ERR_FAIL_COND(!p_control); - hbc_context_menu->add_child(p_control); + context_menu_hbox->add_child(p_control); } void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) { - hbc_context_menu->remove_child(p_control); + context_menu_hbox->remove_child(p_control); } void CanvasItemEditor::add_control_to_left_panel(Control *p_control) { @@ -4971,12 +4978,17 @@ CanvasItemEditor::CanvasItemEditor() { SceneTreeDock::get_singleton()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created)); SceneTreeDock::get_singleton()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position)); - EditorNode::get_singleton()->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true)); - EditorNode::get_singleton()->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false)); + EditorNode::get_singleton()->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button").bind(true)); + EditorNode::get_singleton()->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button").bind(false)); + + // A fluid container for all toolbars. + HFlowContainer *main_flow = memnew(HFlowContainer); + add_child(main_flow); - hb = memnew(HBoxContainer); - add_child(hb); - hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + // Main toolbars. + HBoxContainer *main_menu_hbox = memnew(HBoxContainer); + main_menu_hbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + main_flow->add_child(main_menu_hbox); bottom_split = memnew(VSplitContainer); add_child(bottom_split); @@ -5001,7 +5013,7 @@ CanvasItemEditor::CanvasItemEditor() { SubViewportContainer *scene_tree = memnew(SubViewportContainer); viewport_scrollable->add_child(scene_tree); scene_tree->set_stretch(true); - scene_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + scene_tree->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); scene_tree->add_child(EditorNode::get_singleton()->get_scene_root()); controls_vb = memnew(VBoxContainer); @@ -5031,7 +5043,7 @@ CanvasItemEditor::CanvasItemEditor() { viewport = memnew(CanvasItemEditorViewport(this)); viewport_scrollable->add_child(viewport); viewport->set_mouse_filter(MOUSE_FILTER_PASS); - viewport->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + viewport->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); viewport->set_clip_contents(true); viewport->set_focus_mode(FOCUS_ALL); viewport->connect("draw", callable_mp(this, &CanvasItemEditor::_draw_viewport)); @@ -5054,87 +5066,87 @@ CanvasItemEditor::CanvasItemEditor() { // This prevents the first button's hover/pressed effect from "touching" the panel's border, // which looks ugly. Control *margin_left = memnew(Control); - hb->add_child(margin_left); + main_menu_hbox->add_child(margin_left); margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE); select_button = memnew(Button); select_button->set_flat(true); - hb->add_child(select_button); + main_menu_hbox->add_child(select_button); select_button->set_toggle_mode(true); - select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SELECT)); + select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_SELECT)); select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q)); select_button->set_shortcut_context(this); select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); move_button = memnew(Button); move_button->set_flat(true); - hb->add_child(move_button); + main_menu_hbox->add_child(move_button); move_button->set_toggle_mode(true); - move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_MOVE)); + move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), Key::W)); move_button->set_shortcut_context(this); move_button->set_tooltip(TTR("Move Mode")); rotate_button = memnew(Button); rotate_button->set_flat(true); - hb->add_child(rotate_button); + main_menu_hbox->add_child(rotate_button); rotate_button->set_toggle_mode(true); - rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_ROTATE)); + rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), Key::E)); rotate_button->set_shortcut_context(this); rotate_button->set_tooltip(TTR("Rotate Mode")); scale_button = memnew(Button); scale_button->set_flat(true); - hb->add_child(scale_button); + main_menu_hbox->add_child(scale_button); scale_button->set_toggle_mode(true); - scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE)); + scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_SCALE)); scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), Key::S)); scale_button->set_shortcut_context(this); scale_button->set_tooltip(TTR("Shift: Scale proportionally.")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); list_select_button = memnew(Button); list_select_button->set_flat(true); - hb->add_child(list_select_button); + main_menu_hbox->add_child(list_select_button); list_select_button->set_toggle_mode(true); - list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_LIST_SELECT)); + list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show list of selectable nodes at position clicked.")); pivot_button = memnew(Button); pivot_button->set_flat(true); - hb->add_child(pivot_button); + main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); - pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_EDIT_PIVOT)); + pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); pan_button = memnew(Button); pan_button->set_flat(true); - hb->add_child(pan_button); + main_menu_hbox->add_child(pan_button); pan_button->set_toggle_mode(true); - pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_PAN)); + pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_PAN)); pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), Key::G)); pan_button->set_shortcut_context(this); pan_button->set_tooltip(TTR("You can also use Pan View shortcut (Space by default) to pan in any mode.")); ruler_button = memnew(Button); ruler_button->set_flat(true); - hb->add_child(ruler_button); + main_menu_hbox->add_child(ruler_button); ruler_button->set_toggle_mode(true); - ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_RULER)); + ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_RULER)); ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), Key::R)); ruler_button->set_shortcut_context(this); ruler_button->set_tooltip(TTR("Ruler Mode")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); smart_snap_button = memnew(Button); smart_snap_button->set_flat(true); - hb->add_child(smart_snap_button); + main_menu_hbox->add_child(smart_snap_button); smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap)); smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); @@ -5143,7 +5155,7 @@ CanvasItemEditor::CanvasItemEditor() { grid_snap_button = memnew(Button); grid_snap_button->set_flat(true); - hb->add_child(grid_snap_button); + main_menu_hbox->add_child(grid_snap_button); grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap)); grid_snap_button->set_tooltip(TTR("Toggle grid snapping.")); @@ -5152,7 +5164,7 @@ CanvasItemEditor::CanvasItemEditor() { snap_config_menu = memnew(MenuButton); snap_config_menu->set_shortcut_context(this); - hb->add_child(snap_config_menu); + main_menu_hbox->add_child(snap_config_menu); snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); snap_config_menu->set_tooltip(TTR("Snapping Options")); snap_config_menu->set_switch_on_hover(true); @@ -5181,46 +5193,46 @@ CanvasItemEditor::CanvasItemEditor() { smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to Other Nodes")), SNAP_USE_OTHER_NODES); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to Guides")), SNAP_USE_GUIDES); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); lock_button = memnew(Button); lock_button->set_flat(true); - hb->add_child(lock_button); + main_menu_hbox->add_child(lock_button); - lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED)); + lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); unlock_button = memnew(Button); unlock_button->set_flat(true); - hb->add_child(unlock_button); - unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED)); + main_menu_hbox->add_child(unlock_button); + unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); group_button = memnew(Button); group_button->set_flat(true); - hb->add_child(group_button); - group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED)); - group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); + main_menu_hbox->add_child(group_button); + group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(GROUP_SELECTED)); + group_button->set_tooltip(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); ungroup_button = memnew(Button); ungroup_button->set_flat(true); - hb->add_child(ungroup_button); - ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED)); - ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); + main_menu_hbox->add_child(ungroup_button); + ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNGROUP_SELECTED)); + ungroup_button->set_tooltip(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); skeleton_menu = memnew(MenuButton); skeleton_menu->set_shortcut_context(this); - hb->add_child(skeleton_menu); + main_menu_hbox->add_child(skeleton_menu); skeleton_menu->set_tooltip(TTR("Skeleton Options")); skeleton_menu->set_switch_on_hover(true); @@ -5231,24 +5243,24 @@ CanvasItemEditor::CanvasItemEditor() { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B), SKELETON_MAKE_BONES); p->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); override_camera_button = memnew(Button); override_camera_button->set_flat(true); - hb->add_child(override_camera_button); + main_menu_hbox->add_child(override_camera_button); override_camera_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_override_camera)); override_camera_button->set_toggle_mode(true); override_camera_button->set_disabled(true); _update_override_camera_button(false); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); view_menu = memnew(MenuButton); // TRANSLATORS: Noun, name of the 2D/3D View menus. view_menu->set_text(TTR("View")); view_menu->set_switch_on_hover(true); view_menu->set_shortcut_context(this); - hb->add_child(view_menu); + main_menu_hbox->add_child(view_menu); view_menu->get_popup()->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); p = view_menu->get_popup(); @@ -5281,16 +5293,17 @@ CanvasItemEditor::CanvasItemEditor() { p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::P), PREVIEW_CANVAS_SCALE); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); - context_menu_container = memnew(PanelContainer); - hbc_context_menu = memnew(HBoxContainer); - context_menu_container->add_child(hbc_context_menu); - hb->add_child(context_menu_container); + // Contextual toolbars. + context_menu_panel = memnew(PanelContainer); + context_menu_hbox = memnew(HBoxContainer); + context_menu_panel->add_child(context_menu_hbox); + main_flow->add_child(context_menu_panel); // Animation controls. animation_hb = memnew(HBoxContainer); - hbc_context_menu->add_child(animation_hb); + context_menu_hbox->add_child(animation_hb); animation_hb->add_child(memnew(VSeparator)); animation_hb->hide(); @@ -5299,7 +5312,7 @@ CanvasItemEditor::CanvasItemEditor() { key_loc_button->set_toggle_mode(true); key_loc_button->set_pressed(true); key_loc_button->set_focus_mode(FOCUS_NONE); - key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_POS)); + key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_POS)); key_loc_button->set_tooltip(TTR("Translation mask for inserting keys.")); animation_hb->add_child(key_loc_button); @@ -5308,7 +5321,7 @@ CanvasItemEditor::CanvasItemEditor() { key_rot_button->set_toggle_mode(true); key_rot_button->set_pressed(true); key_rot_button->set_focus_mode(FOCUS_NONE); - key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_ROT)); + key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_ROT)); key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys.")); animation_hb->add_child(key_rot_button); @@ -5316,14 +5329,14 @@ CanvasItemEditor::CanvasItemEditor() { key_scale_button->set_flat(true); key_scale_button->set_toggle_mode(true); key_scale_button->set_focus_mode(FOCUS_NONE); - key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_SCALE)); + key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_SCALE)); key_scale_button->set_tooltip(TTR("Scale mask for inserting keys.")); animation_hb->add_child(key_scale_button); key_insert_button = memnew(Button); key_insert_button->set_flat(true); key_insert_button->set_focus_mode(FOCUS_NONE); - key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_KEY)); + key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_KEY)); key_insert_button->set_tooltip(TTR("Insert keys (based on mask).")); key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), Key::INSERT)); key_insert_button->set_shortcut_context(this); @@ -5364,7 +5377,7 @@ CanvasItemEditor::CanvasItemEditor() { add_child(selection_menu); selection_menu->set_min_size(Vector2(100, 0)); selection_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_selection_result_pressed)); - selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide)); + selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide), CONNECT_DEFERRED); add_node_menu = memnew(PopupMenu); add_child(add_node_menu); @@ -5420,7 +5433,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin() { canvas_item_editor = memnew(CanvasItemEditor); canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); EditorNode::get_singleton()->get_main_control()->add_child(canvas_item_editor); - canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); canvas_item_editor->hide(); } @@ -5903,7 +5916,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it CheckBox *check = memnew(CheckBox); btn_group->add_child(check); check->set_text(texture_node_types[i]); - check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_type), varray(check)); + check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_type).bind(check)); check->set_button_group(button_group); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 5f50882dba..04fd819dec 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -188,11 +188,10 @@ private: HScrollBar *h_scroll = nullptr; VScrollBar *v_scroll = nullptr; - HBoxContainer *hb = nullptr; // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). - PanelContainer *context_menu_container = nullptr; - HBoxContainer *hbc_context_menu = nullptr; + PanelContainer *context_menu_panel = nullptr; + HBoxContainer *context_menu_hbox = nullptr; Transform2D transform; GridVisibility grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING; @@ -215,8 +214,8 @@ private: int primary_grid_steps = 8; int grid_step_multiplier = 0; - real_t snap_rotation_step = 0.0; - real_t snap_rotation_offset = Math::deg2rad(15.0); + real_t snap_rotation_step = Math::deg2rad(15.0); + real_t snap_rotation_offset = 0.0; real_t snap_scale_step = 0.1f; bool smart_snap_active = false; bool grid_snap_active = false; @@ -455,8 +454,8 @@ private: void _update_cursor(); void _selection_changed(); - void _focus_selection(int p_op); + void _reset_drag(); SnapTarget snap_target[2]; Transform2D snap_transform; @@ -503,8 +502,6 @@ protected: static void _bind_methods(); - HBoxContainer *get_panel_hb() { return hb; } - static CanvasItemEditor *singleton; public: @@ -633,4 +630,4 @@ public: ~CanvasItemEditorViewport(); }; -#endif //CANVAS_ITEM_EDITOR_PLUGIN_H +#endif // CANVAS_ITEM_EDITOR_PLUGIN_H diff --git a/editor/plugins/ray_cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp index 6f247a37ef..18c38e7ab8 100644 --- a/editor/plugins/ray_cast_2d_editor_plugin.cpp +++ b/editor/plugins/cast_2d_editor_plugin.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_cast_2d_editor_plugin.cpp */ +/* cast_2d_editor_plugin.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,30 +28,32 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "ray_cast_2d_editor_plugin.h" +#include "cast_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" #include "editor/editor_node.h" +#include "scene/2d/ray_cast_2d.h" +#include "scene/2d/shape_cast_2d.h" -void RayCast2DEditor::_notification(int p_what) { +void Cast2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + get_tree()->connect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed)); } break; case NOTIFICATION_EXIT_TREE: { - get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + get_tree()->disconnect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed)); } break; } } -void RayCast2DEditor::_node_removed(Node *p_node) { +void Cast2DEditor::_node_removed(Node *p_node) { if (p_node == node) { node = nullptr; } } -bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { +bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { if (!node || !node->is_visible_in_tree()) { return false; } @@ -60,10 +62,12 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { + Vector2 target_position = node->get("target_position"); + if (mb->is_pressed()) { - if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) { + if (xform.xform(target_position).distance_to(mb->get_position()) < 8) { pressed = true; - original_target_position = node->get_target_position(); + original_target_position = target_position; return true; } else { @@ -73,9 +77,9 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { } } else if (pressed) { undo_redo->create_action(TTR("Set target_position")); - undo_redo->add_do_method(node, "set_target_position", node->get_target_position()); + undo_redo->add_do_property(node, "target_position", target_position); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(node, "set_target_position", original_target_position); + undo_redo->add_undo_property(node, "target_position", original_target_position); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); @@ -90,7 +94,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())); point = node->get_global_transform().affine_inverse().xform(point); - node->set_target_position(point); + node->set("target_position", point); canvas_item_editor->update_viewport(); node->notify_property_list_changed(); @@ -100,7 +104,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; } -void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { +void Cast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node || !node->is_visible_in_tree()) { return; } @@ -108,16 +112,16 @@ void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons")); - p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2); + p_overlay->draw_texture(handle, gt.xform((Vector2)node->get("target_position")) - handle->get_size() / 2); } -void RayCast2DEditor::edit(Node *p_node) { +void Cast2DEditor::edit(Node2D *p_node) { if (!canvas_item_editor) { canvas_item_editor = CanvasItemEditor::get_singleton(); } - if (p_node) { - node = Object::cast_to<RayCast2D>(p_node); + if (Object::cast_to<RayCast2D>(p_node) || Object::cast_to<ShapeCast2D>(p_node)) { + node = p_node; } else { node = nullptr; } @@ -125,27 +129,27 @@ void RayCast2DEditor::edit(Node *p_node) { canvas_item_editor->update_viewport(); } -RayCast2DEditor::RayCast2DEditor() { +Cast2DEditor::Cast2DEditor() { undo_redo = EditorNode::get_singleton()->get_undo_redo(); } /////////////////////// -void RayCast2DEditorPlugin::edit(Object *p_object) { - ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object)); +void Cast2DEditorPlugin::edit(Object *p_object) { + cast_2d_editor->edit(Object::cast_to<Node2D>(p_object)); } -bool RayCast2DEditorPlugin::handles(Object *p_object) const { - return Object::cast_to<RayCast2D>(p_object) != nullptr; +bool Cast2DEditorPlugin::handles(Object *p_object) const { + return Object::cast_to<RayCast2D>(p_object) != nullptr || Object::cast_to<ShapeCast2D>(p_object) != nullptr; } -void RayCast2DEditorPlugin::make_visible(bool p_visible) { +void Cast2DEditorPlugin::make_visible(bool p_visible) { if (!p_visible) { edit(nullptr); } } -RayCast2DEditorPlugin::RayCast2DEditorPlugin() { - ray_cast_2d_editor = memnew(RayCast2DEditor); - EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor); +Cast2DEditorPlugin::Cast2DEditorPlugin() { + cast_2d_editor = memnew(Cast2DEditor); + EditorNode::get_singleton()->get_gui_base()->add_child(cast_2d_editor); } diff --git a/editor/plugins/ray_cast_2d_editor_plugin.h b/editor/plugins/cast_2d_editor_plugin.h index 74628da0e4..d9c0cc4a06 100644 --- a/editor/plugins/ray_cast_2d_editor_plugin.h +++ b/editor/plugins/cast_2d_editor_plugin.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_cast_2d_editor_plugin.h */ +/* cast_2d_editor_plugin.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H -#define RAY_CAST_2D_EDITOR_PLUGIN_H +#ifndef CAST_2D_EDITOR_PLUGIN_H +#define CAST_2D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "scene/2d/ray_cast_2d.h" +#include "scene/2d/node_2d.h" class CanvasItemEditor; -class RayCast2DEditor : public Control { - GDCLASS(RayCast2DEditor, Control); +class Cast2DEditor : public Control { + GDCLASS(Cast2DEditor, Control); UndoRedo *undo_redo = nullptr; CanvasItemEditor *canvas_item_editor = nullptr; - RayCast2D *node; + Node2D *node; bool pressed = false; Point2 original_target_position; @@ -53,27 +53,27 @@ protected: public: bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); void forward_canvas_draw_over_viewport(Control *p_overlay); - void edit(Node *p_node); + void edit(Node2D *p_node); - RayCast2DEditor(); + Cast2DEditor(); }; -class RayCast2DEditorPlugin : public EditorPlugin { - GDCLASS(RayCast2DEditorPlugin, EditorPlugin); +class Cast2DEditorPlugin : public EditorPlugin { + GDCLASS(Cast2DEditorPlugin, EditorPlugin); - RayCast2DEditor *ray_cast_2d_editor = nullptr; + Cast2DEditor *cast_2d_editor = nullptr; public: - virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); } - virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return cast_2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } - virtual String get_name() const override { return "RayCast2D"; } + virtual String get_name() const override { return "Cast2D"; } bool has_main_screen() const override { return false; } virtual void edit(Object *p_object) override; virtual bool handles(Object *p_object) const override; virtual void make_visible(bool visible) override; - RayCast2DEditorPlugin(); + Cast2DEditorPlugin(); }; -#endif // RAY_CAST_2D_EDITOR_PLUGIN_H +#endif // CAST_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index da9e9f339f..f7de05ddd1 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -112,4 +112,4 @@ public: ~CollisionShape2DEditorPlugin(); }; -#endif //COLLISION_SHAPE_2D_EDITOR_PLUGIN_H +#endif // COLLISION_SHAPE_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index 3adaf8f601..2756e45cf4 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -31,7 +31,9 @@ #include "control_editor_plugin.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "scene/gui/separator.h" void ControlPositioningWarning::_update_warning() { if (!control_node) { @@ -173,7 +175,7 @@ void EditorPropertyAnchorsPreset::setup(const Vector<String> &p_options) { Vector<String> split_after; split_after.append("Custom"); - split_after.append("PresetWide"); + split_after.append("PresetFullRect"); split_after.append("PresetBottomLeft"); split_after.append("PresetCenter"); @@ -181,24 +183,18 @@ void EditorPropertyAnchorsPreset::setup(const Vector<String> &p_options) { Vector<String> text_split = p_options[i].split(":"); int64_t current_val = text_split[1].to_int(); - String humanized_name = text_split[0]; - if (humanized_name.begins_with("Preset")) { - if (humanized_name == "PresetWide") { - humanized_name = "Full Rect"; - } else { - humanized_name = humanized_name.trim_prefix("Preset"); - humanized_name = humanized_name.capitalize(); - } - - String icon_name = text_split[0].trim_prefix("Preset"); - icon_name = "ControlAlign" + icon_name; + String option_name = text_split[0]; + if (option_name.begins_with("Preset")) { + String preset_name = option_name.trim_prefix("Preset"); + String humanized_name = preset_name.capitalize(); + String icon_name = "ControlAlign" + preset_name; options->add_icon_item(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(icon_name, "EditorIcons"), humanized_name); } else { - options->add_item(humanized_name); + options->add_item(option_name); } options->set_item_metadata(j, current_val); - if (split_after.has(text_split[0])) { + if (split_after.has(option_name)) { options->add_separator(); j++; } @@ -479,7 +475,7 @@ void ControlEditorToolbar::_set_anchors_and_offsets_preset(Control::LayoutPreset case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_MINSIZE); break; } @@ -689,8 +685,8 @@ void ControlEditorToolbar::_popup_callback(int p_op) { case ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE: { _set_anchors_and_offsets_preset(PRESET_HCENTER_WIDE); } break; - case ANCHORS_AND_OFFSETS_PRESET_WIDE: { - _set_anchors_and_offsets_preset(Control::PRESET_WIDE); + case ANCHORS_AND_OFFSETS_PRESET_FULL_RECT: { + _set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); } break; case ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO: { _set_anchors_and_offsets_to_keep_ratio(); @@ -741,8 +737,8 @@ void ControlEditorToolbar::_popup_callback(int p_op) { case ANCHORS_PRESET_HCENTER_WIDE: { _set_anchors_preset(PRESET_HCENTER_WIDE); } break; - case ANCHORS_PRESET_WIDE: { - _set_anchors_preset(Control::PRESET_WIDE); + case ANCHORS_PRESET_FULL_RECT: { + _set_anchors_preset(Control::PRESET_FULL_RECT); } break; case CONTAINERS_H_PRESET_FILL: { @@ -840,7 +836,7 @@ void ControlEditorToolbar::_notification(int p_what) { p->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE); p->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE); p->add_separator(); - p->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_WIDE); + p->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_FULL_RECT); p->add_icon_item(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")), TTR("Keep Current Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO); p->set_item_tooltip(19, TTR("Adjust anchors and offsets to match the current rect size.")); @@ -867,7 +863,7 @@ void ControlEditorToolbar::_notification(int p_what) { anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE); anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE); anchors_popup->add_separator(); - anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE); + anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_FULL_RECT); anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons"))); diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 96451f7dcf..11389bc095 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -147,7 +147,7 @@ class ControlEditorToolbar : public HBoxContainer { ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE, ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE, ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE, - ANCHORS_AND_OFFSETS_PRESET_WIDE, + ANCHORS_AND_OFFSETS_PRESET_FULL_RECT, ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO, @@ -166,7 +166,7 @@ class ControlEditorToolbar : public HBoxContainer { ANCHORS_PRESET_BOTTOM_WIDE, ANCHORS_PRESET_VCENTER_WIDE, ANCHORS_PRESET_HCENTER_WIDE, - ANCHORS_PRESET_WIDE, + ANCHORS_PRESET_FULL_RECT, // Offsets Presets are not currently in use. OFFSETS_PRESET_TOP_LEFT, @@ -184,7 +184,7 @@ class ControlEditorToolbar : public HBoxContainer { OFFSETS_PRESET_BOTTOM_WIDE, OFFSETS_PRESET_VCENTER_WIDE, OFFSETS_PRESET_HCENTER_WIDE, - OFFSETS_PRESET_WIDE, + OFFSETS_PRESET_FULL_RECT, CONTAINERS_H_PRESET_FILL, CONTAINERS_H_PRESET_FILL_EXPAND, @@ -247,4 +247,4 @@ public: ControlEditorPlugin(); }; -#endif //CONTROL_EDITOR_PLUGIN_H +#endif // CONTROL_EDITOR_PLUGIN_H diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.h b/editor/plugins/cpu_particles_3d_editor_plugin.h index 70f2da4b2d..f38349985c 100644 --- a/editor/plugins/cpu_particles_3d_editor_plugin.h +++ b/editor/plugins/cpu_particles_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CPU_PARTICLES_EDITOR_PLUGIN_H -#define CPU_PARTICLES_EDITOR_PLUGIN_H +#ifndef CPU_PARTICLES_3D_EDITOR_PLUGIN_H +#define CPU_PARTICLES_3D_EDITOR_PLUGIN_H #include "editor/plugins/gpu_particles_3d_editor_plugin.h" #include "scene/3d/cpu_particles_3d.h" @@ -78,4 +78,4 @@ public: ~CPUParticles3DEditorPlugin(); }; -#endif // CPU_PARTICLES_EDITOR_PLUGIN_H +#endif // CPU_PARTICLES_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 66e58339ed..8aeab684e3 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" CurveEditor::CurveEditor() { _selected_point = -1; @@ -542,11 +543,11 @@ void CurveEditor::update_view_transform() { const Vector2 scale = view_size / world_rect.size; Transform2D world_trans; - world_trans.translate(-world_rect.position - Vector2(0, world_rect.size.y)); + world_trans.translate_local(-world_rect.position - Vector2(0, world_rect.size.y)); world_trans.scale(Vector2(scale.x, -scale.y)); Transform2D view_trans; - view_trans.translate(view_margin); + view_trans.translate_local(view_margin); _world_to_view = view_trans * world_trans; } diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 5c90d70982..c572b5b7fe 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -35,6 +35,7 @@ #include "editor/debugger/editor_debugger_server.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/fileserver/editor_file_server.h" #include "editor/plugins/script_editor_plugin.h" #include "scene/gui/menu_button.h" diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 478f4264e5..0196214ceb 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -307,7 +307,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from if (material->get_shader_mode() == Shader::MODE_SPATIAL) { RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); preview_done.wait(); @@ -599,7 +599,7 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const Ref<Resource> &p_f uint8_t *imgdata = img.ptrw(); uint8_t *imgw = imgdata; - Ref<AudioStreamPlayback> playback = stream->instance_playback(); + Ref<AudioStreamPlayback> playback = stream->instantiate_playback(); ERR_FAIL_COND_V(playback.is_null(), Ref<Texture2D>()); real_t len_s = stream->get_length(); @@ -702,7 +702,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co xform.origin.z -= rot_aabb.size.z * 2; RS::get_singleton()->instance_set_transform(mesh_instance, xform); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); preview_done.wait(); @@ -812,7 +812,7 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0; sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg)); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); preview_done.wait(); diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index f548683b70..163cfe79f9 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITORPREVIEWPLUGINS_H -#define EDITORPREVIEWPLUGINS_H +#ifndef EDITOR_PREVIEW_PLUGINS_H +#define EDITOR_PREVIEW_PLUGINS_H #include "core/templates/safe_refcount.h" #include "editor/editor_resource_preview.h" @@ -193,4 +193,5 @@ public: EditorGradientPreviewPlugin(); }; -#endif // EDITORPREVIEWPLUGINS_H + +#endif // EDITOR_PREVIEW_PLUGINS_H diff --git a/editor/plugins/editor_resource_conversion_plugin.cpp b/editor/plugins/editor_resource_conversion_plugin.cpp new file mode 100644 index 0000000000..91394dbac7 --- /dev/null +++ b/editor/plugins/editor_resource_conversion_plugin.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* editor_resource_conversion_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_resource_conversion_plugin.h" + +void EditorResourceConversionPlugin::_bind_methods() { + GDVIRTUAL_BIND(_converts_to); + GDVIRTUAL_BIND(_handles, "resource"); + GDVIRTUAL_BIND(_convert, "resource"); +} + +String EditorResourceConversionPlugin::converts_to() const { + String ret; + if (GDVIRTUAL_CALL(_converts_to, ret)) { + return ret; + } + + return ""; +} + +bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const { + bool ret; + if (GDVIRTUAL_CALL(_handles, p_resource, ret)) { + return ret; + } + + return false; +} + +Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const { + Ref<Resource> ret; + if (GDVIRTUAL_CALL(_convert, p_resource, ret)) { + return ret; + } + + return Ref<Resource>(); +} diff --git a/editor/plugins/editor_resource_conversion_plugin.h b/editor/plugins/editor_resource_conversion_plugin.h new file mode 100644 index 0000000000..34b0837383 --- /dev/null +++ b/editor/plugins/editor_resource_conversion_plugin.h @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* editor_resource_conversion_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_RESOURCE_CONVERSION_PLUGIN_H +#define EDITOR_RESOURCE_CONVERSION_PLUGIN_H + +#include "core/io/resource.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" + +class EditorResourceConversionPlugin : public RefCounted { + GDCLASS(EditorResourceConversionPlugin, RefCounted); + +protected: + static void _bind_methods(); + + GDVIRTUAL0RC(String, _converts_to) + GDVIRTUAL1RC(bool, _handles, Ref<Resource>) + GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>) + +public: + virtual String converts_to() const; + virtual bool handles(const Ref<Resource> &p_resource) const; + virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; +}; + +#endif // EDITOR_RESOURCE_CONVERSION_PLUGIN_H diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp index 848fb5887d..cadb974345 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -307,7 +307,7 @@ void EditorPropertyFontMetaOverride::update_property() { Button *remove = memnew(Button); remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); hbox->add_child(remove); - remove->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_remove), varray(remove, name)); + remove->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_remove).bind(remove, name)); prop->update_property(); } @@ -783,7 +783,7 @@ void EditorPropertyOTFeatures::update_property() { Button *remove = memnew(Button); remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); hbox->add_child(remove); - remove->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_remove), varray(remove, name_tag)); + remove->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_remove).bind(remove, name_tag)); prop->update_property(); } @@ -895,17 +895,45 @@ void FontPreview::_notification(int p_what) { Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label")); - font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color); // Draw font preview. - Vector2 pos = Vector2(0, font->get_height(font_size)) + (get_size() - Vector2(0, font->get_height(font_size)) - line->get_size()) / 2; - line->draw(get_canvas_item(), pos, text_color); - - // Draw font baseline. - Color line_color = text_color; - line_color.a *= 0.6; - draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color); - draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color); + bool prev_ok = true; + if (prev_font.is_valid()) { + if (prev_font->get_font_name().is_empty()) { + prev_ok = false; + } else { + String name; + if (prev_font->get_font_style_name().is_empty()) { + name = prev_font->get_font_name(); + } else { + name = vformat("%s (%s)", prev_font->get_font_name(), prev_font->get_font_style_name()); + } + if (prev_font->is_class("FontVariation")) { + name += " " + TTR(" - Variation"); + } + font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color); + + String sample; + static const String sample_base = U"12æ¼¢å—ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš ᜀᜠá€á កá á¤á¥Ab😀"; + for (int i = 0; i < sample_base.length(); i++) { + if (prev_font->has_char(sample_base[i])) { + sample += sample_base[i]; + } + } + if (sample.is_empty()) { + sample = prev_font->get_supported_chars().substr(0, 6); + } + if (sample.is_empty()) { + prev_ok = false; + } else { + prev_font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + prev_font->get_height(25 * EDSCALE)), sample, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, 25 * EDSCALE, text_color); + } + } + } + if (!prev_ok) { + text_color.a *= 0.5; + font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), TTR("Unable to preview font"), HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color); + } } break; } } @@ -917,30 +945,11 @@ Size2 FontPreview::get_minimum_size() const { } void FontPreview::set_data(const Ref<Font> &p_f) { - line->clear(); - if (p_f.is_valid()) { - name = vformat("%s (%s)", p_f->get_font_name(), p_f->get_font_style_name()); - if (p_f->is_class("FontVariation")) { - name += " " + TTR(" - Variation"); - } - String sample; - static const String sample_base = U"12æ¼¢å—ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš ᜀᜠá€á កá á¤á¥Ab😀"; - for (int i = 0; i < sample_base.length(); i++) { - if (p_f->has_char(sample_base[i])) { - sample += sample_base[i]; - } - } - if (sample.is_empty()) { - sample = p_f->get_supported_chars().substr(0, 6); - } - line->add_string(sample, p_f, 50); - } - + prev_font = p_f; update(); } FontPreview::FontPreview() { - line.instantiate(); } /*************************************************************************/ @@ -965,6 +974,71 @@ bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Va } /*************************************************************************/ +/* EditorPropertyFontNamesArray */ +/*************************************************************************/ + +void EditorPropertyFontNamesArray::_add_element() { + Size2 size = get_size(); + menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); + menu->reset_size(); + menu->popup(); +} + +void EditorPropertyFontNamesArray::_add_font(int p_option) { + if (updating) { + return; + } + + Variant array = object->get_array(); + int previous_size = array.call("size"); + + array.call("resize", previous_size + 1); + array.set(previous_size, menu->get_item_text(p_option)); + + emit_changed(get_edited_property(), array, "", false); + object->set_array(array); + update_property(); +} + +EditorPropertyFontNamesArray::EditorPropertyFontNamesArray() { + menu = memnew(PopupMenu); + menu->add_item("Sans-Serif", 0); + menu->add_item("Serif", 1); + menu->add_item("Monospace", 2); + menu->add_item("Fantasy", 3); + menu->add_item("Cursive", 4); + + menu->add_separator(); + + if (OS::get_singleton()) { + Vector<String> fonts = OS::get_singleton()->get_system_fonts(); + for (int i = 0; i < fonts.size(); i++) { + menu->add_item(fonts[i], i + 6); + } + } + add_child(menu); + menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontNamesArray::_add_font)); +} + +/*************************************************************************/ +/* EditorInspectorPluginSystemFont */ +/*************************************************************************/ + +bool EditorInspectorPluginSystemFont::can_handle(Object *p_object) { + return Object::cast_to<SystemFont>(p_object) != nullptr; +} + +bool EditorInspectorPluginSystemFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { + if (p_path == "font_names") { + EditorPropertyFontNamesArray *editor = memnew(EditorPropertyFontNamesArray); + editor->setup(p_type, p_hint_text); + add_property_editor(p_path, editor); + return true; + } + return false; +} + +/*************************************************************************/ /* FontEditorPlugin */ /*************************************************************************/ @@ -973,6 +1047,10 @@ FontEditorPlugin::FontEditorPlugin() { fc_plugin.instantiate(); EditorInspector::add_inspector_plugin(fc_plugin); + Ref<EditorInspectorPluginSystemFont> fs_plugin; + fs_plugin.instantiate(); + EditorInspector::add_inspector_plugin(fs_plugin); + Ref<EditorInspectorPluginFontPreview> fp_plugin; fp_plugin.instantiate(); EditorInspector::add_inspector_plugin(fp_plugin); diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h index 9b7ee55870..3eaa2fdc17 100644 --- a/editor/plugins/font_config_plugin.h +++ b/editor/plugins/font_config_plugin.h @@ -28,12 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OT_FEATURES_PLUGIN_H -#define OT_FEATURES_PLUGIN_H +#ifndef FONT_CONFIG_PLUGIN_H +#define FONT_CONFIG_PLUGIN_H #include "core/io/marshalls.h" #include "editor/editor_plugin.h" #include "editor/editor_properties.h" +#include "editor/editor_properties_array_dict.h" /*************************************************************************/ @@ -225,8 +226,7 @@ protected: void _notification(int p_what); static void _bind_methods(); - String name; - Ref<TextLine> line; + Ref<Font> prev_font; public: virtual Size2 get_minimum_size() const override; @@ -249,6 +249,33 @@ public: /*************************************************************************/ +class EditorPropertyFontNamesArray : public EditorPropertyArray { + GDCLASS(EditorPropertyFontNamesArray, EditorPropertyArray); + + PopupMenu *menu = nullptr; + +protected: + virtual void _add_element() override; + + void _add_font(int p_option); + static void _bind_methods(){}; + +public: + EditorPropertyFontNamesArray(); +}; + +/*************************************************************************/ + +class EditorInspectorPluginSystemFont : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginSystemFont, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; +}; + +/*************************************************************************/ + class FontEditorPlugin : public EditorPlugin { GDCLASS(FontEditorPlugin, EditorPlugin); @@ -258,4 +285,4 @@ public: virtual String get_name() const override { return "Font"; } }; -#endif // OT_FEATURES_PLUGIN_H +#endif // FONT_CONFIG_PLUGIN_H diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index b91a17d9e5..b5eca46ad3 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -31,7 +31,7 @@ #ifndef GDEXTENSION_EXPORT_PLUGIN_H #define GDEXTENSION_EXPORT_PLUGIN_H -#include "editor/editor_export.h" +#include "editor/export/editor_export.h" class GDExtensionExportPlugin : public EditorExportPlugin { protected: diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h index 75f68617d1..bf49a82166 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.h +++ b/editor/plugins/gpu_particles_2d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PARTICLES_2D_EDITOR_PLUGIN_H -#define PARTICLES_2D_EDITOR_PLUGIN_H +#ifndef GPU_PARTICLES_2D_EDITOR_PLUGIN_H +#define GPU_PARTICLES_2D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/2d/collision_polygon_2d.h" @@ -97,4 +97,4 @@ public: ~GPUParticles2DEditorPlugin(); }; -#endif // PARTICLES_2D_EDITOR_PLUGIN_H +#endif // GPU_PARTICLES_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h index 6ba6d102ef..17bdfa6e3f 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.h +++ b/editor/plugins/gpu_particles_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PARTICLES_EDITOR_PLUGIN_H -#define PARTICLES_EDITOR_PLUGIN_H +#ifndef GPU_PARTICLES_3D_EDITOR_PLUGIN_H +#define GPU_PARTICLES_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/gpu_particles_3d.h" @@ -114,4 +114,4 @@ public: ~GPUParticles3DEditorPlugin(); }; -#endif // PARTICLES_EDITOR_PLUGIN_H +#endif // GPU_PARTICLES_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp index 643a470425..b54cb515e4 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp @@ -140,7 +140,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake(const Strin if (col_sdf) { Ref<Image> bake_img = col_sdf->bake(); if (bake_img.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("Bake Error.")); + EditorNode::get_singleton()->show_warning(TTR("No faces detected during GPUParticlesCollisionSDF3D bake.\nCheck whether there are visible meshes matching the bake mask within its extents.")); return; } diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 1386f03662..542aee879b 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -33,6 +33,7 @@ #include "canvas_item_editor_plugin.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "node_3d_editor_plugin.h" Size2 GradientEditor::get_minimum_size() const { @@ -85,6 +86,7 @@ void GradientEditor::reverse_gradient() { } GradientEditor::GradientEditor() { + GradientEdit::get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(GradientEdit::get_picker())); editing = false; } diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h index 4ce64ce1dc..93c49b1e6f 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.h +++ b/editor/plugins/gradient_texture_2d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GRADIENT_TEXTURE_2D_EDITOR -#define GRADIENT_TEXTURE_2D_EDITOR +#ifndef GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H +#define GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "editor/editor_spin_slider.h" @@ -109,4 +109,4 @@ public: GradientTexture2DEditorPlugin(); }; -#endif +#endif // GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/lightmap_gi_editor_plugin.h b/editor/plugins/lightmap_gi_editor_plugin.h index 1202efe8fc..a06f97fc94 100644 --- a/editor/plugins/lightmap_gi_editor_plugin.h +++ b/editor/plugins/lightmap_gi_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H -#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H +#ifndef LIGHTMAP_GI_EDITOR_PLUGIN_H +#define LIGHTMAP_GI_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/lightmap_gi.h" @@ -67,4 +67,4 @@ public: ~LightmapGIEditorPlugin(); }; -#endif +#endif // LIGHTMAP_GI_EDITOR_PLUGIN_H diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index eb004568d0..1b4d98fc3f 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/subviewport_container.h" #include "scene/resources/fog_material.h" #include "scene/resources/particles_material.h" @@ -130,7 +131,7 @@ MaterialEditor::MaterialEditor() { layout_2d = memnew(HBoxContainer); layout_2d->set_alignment(BoxContainer::ALIGNMENT_CENTER); add_child(layout_2d); - layout_2d->set_anchors_and_offsets_preset(PRESET_WIDE); + layout_2d->set_anchors_and_offsets_preset(PRESET_FULL_RECT); rect_instance = memnew(ColorRect); layout_2d->add_child(rect_instance); @@ -143,7 +144,7 @@ MaterialEditor::MaterialEditor() { vc = memnew(SubViewportContainer); vc->set_stretch(true); add_child(vc); - vc->set_anchors_and_offsets_preset(PRESET_WIDE); + vc->set_anchors_and_offsets_preset(PRESET_FULL_RECT); viewport = memnew(SubViewport); Ref<World3D> world_3d; world_3d.instantiate(); @@ -155,7 +156,9 @@ MaterialEditor::MaterialEditor() { camera = memnew(Camera3D); camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 3))); - camera->set_perspective(45, 0.1, 10); + // Use low field of view so the sphere/box is fully encompassed within the preview, + // without much distortion. + camera->set_perspective(20, 0.1, 10); camera->make_current(); viewport->add_child(camera); @@ -177,8 +180,8 @@ MaterialEditor::MaterialEditor() { Transform3D box_xform; box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(25.0)); box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg2rad(-25.0)); - box_xform.basis.scale(Vector3(0.8, 0.8, 0.8)); - box_xform.origin.y = 0.2; + box_xform.basis.scale(Vector3(0.7, 0.7, 0.7)); + box_xform.origin.y = 0.05; box_instance->set_transform(box_xform); sphere_mesh.instantiate(); @@ -190,7 +193,7 @@ MaterialEditor::MaterialEditor() { layout_3d = memnew(HBoxContainer); add_child(layout_3d); - layout_3d->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2); + layout_3d->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 2); VBoxContainer *vb_shape = memnew(VBoxContainer); layout_3d->add_child(vb_shape); @@ -199,13 +202,13 @@ MaterialEditor::MaterialEditor() { sphere_switch->set_toggle_mode(true); sphere_switch->set_pressed(true); vb_shape->add_child(sphere_switch); - sphere_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(sphere_switch)); + sphere_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(sphere_switch)); box_switch = memnew(TextureButton); box_switch->set_toggle_mode(true); box_switch->set_pressed(false); vb_shape->add_child(box_switch); - box_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(box_switch)); + box_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(box_switch)); layout_3d->add_spacer(); @@ -215,12 +218,12 @@ MaterialEditor::MaterialEditor() { light_1_switch = memnew(TextureButton); light_1_switch->set_toggle_mode(true); vb_light->add_child(light_1_switch); - light_1_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(light_1_switch)); + light_1_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(light_1_switch)); light_2_switch = memnew(TextureButton); light_2_switch->set_toggle_mode(true); vb_light->add_child(light_2_switch); - light_2_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(light_2_switch)); + light_2_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(light_2_switch)); first_enter = true; @@ -337,17 +340,17 @@ Ref<Resource> StandardMaterial3DConversionPlugin::convert(const Ref<Resource> &p smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { // Texture parameter has to be treated specially since StandardMaterial3D saved it // as RID but ShaderMaterial needs Texture itself Ref<Texture2D> texture = mat->get_texture_by_name(E.name); if (texture.is_valid()) { - smat->set_shader_param(E.name, texture); + smat->set_shader_uniform(E.name, texture); } else { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } } @@ -383,17 +386,17 @@ Ref<Resource> ORMMaterial3DConversionPlugin::convert(const Ref<Resource> &p_reso smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { // Texture parameter has to be treated specially since ORMMaterial3D saved it // as RID but ShaderMaterial needs Texture itself Ref<Texture2D> texture = mat->get_texture_by_name(E.name); if (texture.is_valid()) { - smat->set_shader_param(E.name, texture); + smat->set_shader_uniform(E.name, texture); } else { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } } @@ -429,11 +432,11 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_ smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); @@ -468,11 +471,11 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); @@ -507,11 +510,11 @@ Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource> smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); @@ -546,11 +549,11 @@ Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> & smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); @@ -585,11 +588,11 @@ Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> & smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); @@ -624,11 +627,11 @@ Ref<Resource> FogMaterialConversionPlugin::convert(const Ref<Resource> &p_resour smat->set_shader(shader); List<PropertyInfo> params; - RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), ¶ms); for (const PropertyInfo &E : params) { Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name); - smat->set_shader_param(E.name, value); + smat->set_shader_uniform(E.name, value); } smat->set_render_priority(mat->get_render_priority()); diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 9c6247d59b..fc3da5fd9f 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -32,7 +32,7 @@ #define MATERIAL_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/property_editor.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 7029768479..31c9f1e387 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -137,7 +137,7 @@ MeshEditor::MeshEditor() { HBoxContainer *hb = memnew(HBoxContainer); add_child(hb); - hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2); + hb->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 2); hb->add_spacer(); @@ -147,12 +147,12 @@ MeshEditor::MeshEditor() { light_1_switch = memnew(TextureButton); light_1_switch->set_toggle_mode(true); vb_light->add_child(light_1_switch); - light_1_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed), varray(light_1_switch)); + light_1_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed).bind(light_1_switch)); light_2_switch = memnew(TextureButton); light_2_switch->set_toggle_mode(true); vb_light->add_child(light_2_switch); - light_2_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed), varray(light_2_switch)); + light_2_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed).bind(light_2_switch)); first_enter = true; diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h index 3554b3c1e9..fb61f03485 100644 --- a/editor/plugins/mesh_editor_plugin.h +++ b/editor/plugins/mesh_editor_plugin.h @@ -87,4 +87,4 @@ public: MeshEditorPlugin(); }; -#endif +#endif // MESH_EDITOR_PLUGIN_H diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h index 36d8eacd98..7968176744 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.h +++ b/editor/plugins/mesh_instance_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef MESH_INSTANCE_EDITOR_PLUGIN_H -#define MESH_INSTANCE_EDITOR_PLUGIN_H +#ifndef MESH_INSTANCE_3D_EDITOR_PLUGIN_H +#define MESH_INSTANCE_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/mesh_instance_3d.h" @@ -97,4 +97,4 @@ public: ~MeshInstance3DEditorPlugin(); }; -#endif // MESH_EDITOR_PLUGIN_H +#endif // MESH_INSTANCE_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 72bfc05270..319f6ee9de 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -289,8 +289,8 @@ MeshLibraryEditor::MeshLibraryEditor() { cd_update = memnew(ConfirmationDialog); add_child(cd_update); cd_update->set_ok_button_text(TTR("Apply without Transforms")); - cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(false)); - cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(true)); + cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm).bind(false)); + cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm).bind(true)); } void MeshLibraryEditorPlugin::edit(Object *p_node) { diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index 7207390922..fc4dc5bc2f 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -291,7 +291,7 @@ MultiMeshEditor::MultiMeshEditor() { Button *b = memnew(Button); hbc->add_child(b); b->set_text(".."); - b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse), make_binds(false)); + b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse).bind(false)); vbc->add_margin_child(TTR("Target Surface:"), hbc); @@ -303,7 +303,7 @@ MultiMeshEditor::MultiMeshEditor() { hbc->add_child(b); b->set_text(".."); vbc->add_margin_child(TTR("Source Mesh:"), hbc); - b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse), make_binds(true)); + b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse).bind(true)); populate_axis = memnew(OptionButton); populate_axis->add_item(TTR("X-Axis")); diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h index 7550b75fa3..239da88ba2 100644 --- a/editor/plugins/navigation_polygon_editor_plugin.h +++ b/editor/plugins/navigation_polygon_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H -#define NAVIGATIONPOLYGONEDITORPLUGIN_H +#ifndef NAVIGATION_POLYGON_EDITOR_PLUGIN_H +#define NAVIGATION_POLYGON_EDITOR_PLUGIN_H #include "editor/plugins/abstract_polygon_2d_editor.h" #include "scene/2d/navigation_region_2d.h" @@ -67,4 +67,4 @@ public: NavigationPolygonEditorPlugin(); }; -#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H +#endif // NAVIGATION_POLYGON_EDITOR_PLUGIN_H diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 77cf1f0064..0070226d40 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -57,6 +57,7 @@ #include "scene/3d/position_3d.h" #include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" +#include "scene/3d/shape_cast_3d.h" #include "scene/3d/soft_dynamic_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" @@ -74,6 +75,7 @@ #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/world_boundary_shape_3d.h" +#include "servers/navigation_server_3d.h" #define HANDLE_HALF_SIZE 9.5 @@ -2540,6 +2542,44 @@ void RayCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { ///// +ShapeCast3DGizmoPlugin::ShapeCast3DGizmoPlugin() { + const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); + create_material("shape_material", gizmo_color); + const float gizmo_value = gizmo_color.get_v(); + const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65); + create_material("shape_material_disabled", gizmo_color_disabled); +} + +bool ShapeCast3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<ShapeCast3D>(p_spatial) != nullptr; +} + +String ShapeCast3DGizmoPlugin::get_gizmo_name() const { + return "ShapeCast3D"; +} + +int ShapeCast3DGizmoPlugin::get_priority() const { + return -1; +} + +void ShapeCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + ShapeCast3D *shapecast = Object::cast_to<ShapeCast3D>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + const Ref<StandardMaterial3D> material = shapecast->is_enabled() ? shapecast->get_debug_material() : get_material("shape_material_disabled"); + + p_gizmo->add_lines(shapecast->get_debug_line_vertices(), material); + + if (shapecast->get_shape().is_valid()) { + p_gizmo->add_lines(shapecast->get_debug_shape_vertices(), material); + } + + p_gizmo->add_collision_segments(shapecast->get_debug_line_vertices()); +} + +///// + void SpringArm3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { SpringArm3D *spring_arm = Object::cast_to<SpringArm3D>(p_gizmo->get_spatial_node()); @@ -4799,10 +4839,6 @@ void CollisionPolygon3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { //// NavigationRegion3DGizmoPlugin::NavigationRegion3DGizmoPlugin() { - create_material("navigation_edge_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1))); - create_material("navigation_edge_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7))); - create_material("navigation_solid_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4))); - create_material("navigation_solid_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4))); } bool NavigationRegion3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { @@ -4818,24 +4854,19 @@ int NavigationRegion3DGizmoPlugin::get_priority() const { } void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - NavigationRegion3D *navmesh = Object::cast_to<NavigationRegion3D>(p_gizmo->get_spatial_node()); - - Ref<Material> edge_material = get_material("navigation_edge_material", p_gizmo); - Ref<Material> edge_material_disabled = get_material("navigation_edge_material_disabled", p_gizmo); - Ref<Material> solid_material = get_material("navigation_solid_material", p_gizmo); - Ref<Material> solid_material_disabled = get_material("navigation_solid_material_disabled", p_gizmo); + NavigationRegion3D *navigationregion = Object::cast_to<NavigationRegion3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); - Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh(); - if (navmeshie.is_null()) { + Ref<NavigationMesh> navigationmesh = navigationregion->get_navigation_mesh(); + if (navigationmesh.is_null()) { return; } - Vector<Vector3> vertices = navmeshie->get_vertices(); + Vector<Vector3> vertices = navigationmesh->get_vertices(); const Vector3 *vr = vertices.ptr(); List<Face3> faces; - for (int i = 0; i < navmeshie->get_polygon_count(); i++) { - Vector<int> p = navmeshie->get_polygon(i); + for (int i = 0; i < navigationmesh->get_polygon_count(); i++) { + Vector<int> p = navigationmesh->get_polygon(i); for (int j = 2; j < p.size(); j++) { Face3 f; @@ -4892,17 +4923,90 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref<TriangleMesh> tmesh = memnew(TriangleMesh); tmesh->create(tmeshfaces); - if (lines.size()) { - p_gizmo->add_lines(lines, navmesh->is_enabled() ? edge_material : edge_material_disabled); - } p_gizmo->add_collision_triangles(tmesh); - Ref<ArrayMesh> m = memnew(ArrayMesh); - Array a; - a.resize(Mesh::ARRAY_MAX); - a[0] = tmeshfaces; - m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a); - m->surface_set_material(0, navmesh->is_enabled() ? solid_material : solid_material_disabled); - p_gizmo->add_mesh(m); + + Ref<ArrayMesh> debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + int polygon_count = navigationmesh->get_polygon_count(); + + // build geometry face surface + Vector<Vector3> face_vertex_array; + face_vertex_array.resize(polygon_count * 3); + + for (int i = 0; i < polygon_count; i++) { + Vector<int> polygon = navigationmesh->get_polygon(i); + + face_vertex_array.push_back(vertices[polygon[0]]); + face_vertex_array.push_back(vertices[polygon[1]]); + face_vertex_array.push_back(vertices[polygon[2]]); + } + + Array face_mesh_array; + face_mesh_array.resize(Mesh::ARRAY_MAX); + face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array; + + // if enabled add vertex colors to colorize each face individually + bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color(); + if (enabled_geometry_face_random_color) { + Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); + Color polygon_color = debug_navigation_geometry_face_color; + + Vector<Color> face_color_array; + face_color_array.resize(polygon_count * 3); + + for (int i = 0; i < polygon_count; i++) { + polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf())); + + Vector<int> polygon = navigationmesh->get_polygon(i); + + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + } + face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array; + } + + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); + Ref<StandardMaterial3D> debug_geometry_face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material(); + debug_mesh->surface_set_material(0, debug_geometry_face_material); + + // if enabled build geometry edge line surface + bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines(); + + if (enabled_edge_lines) { + Vector<Vector3> line_vertex_array; + line_vertex_array.resize(polygon_count * 6); + + for (int i = 0; i < polygon_count; i++) { + Vector<int> polygon = navigationmesh->get_polygon(i); + + line_vertex_array.push_back(vertices[polygon[0]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[0]]); + } + + Array line_mesh_array; + line_mesh_array.resize(Mesh::ARRAY_MAX); + line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array; + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array); + Ref<StandardMaterial3D> debug_geometry_edge_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material(); + debug_mesh->surface_set_material(1, debug_geometry_edge_material); + } + + if (!navigationregion->is_enabled()) { + if (debug_mesh.is_valid()) { + if (debug_mesh->get_surface_count() > 0) { + debug_mesh->surface_set_material(0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material()); + } + if (debug_mesh->get_surface_count() > 1) { + debug_mesh->surface_set_material(1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material()); + } + } + } + + p_gizmo->add_mesh(debug_mesh); p_gizmo->add_collision_segments(lines); } @@ -5044,8 +5148,8 @@ Basis JointGizmosDrawer::look_body_toward_z(const Transform3D &p_joint_transform void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform3D &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) { if (p_limit_lower == p_limit_upper) { - r_points.push_back(p_offset.translated(Vector3()).origin); - r_points.push_back(p_offset.translated(p_base.xform(Vector3(0.5, 0, 0))).origin); + r_points.push_back(p_offset.translated_local(Vector3()).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(0.5, 0, 0))).origin); } else { if (p_limit_lower > p_limit_upper) { @@ -5087,20 +5191,20 @@ void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const } if (i == points - 1) { - r_points.push_back(p_offset.translated(to).origin); - r_points.push_back(p_offset.translated(Vector3()).origin); + r_points.push_back(p_offset.translated_local(to).origin); + r_points.push_back(p_offset.translated_local(Vector3()).origin); } if (i == 0) { - r_points.push_back(p_offset.translated(from).origin); - r_points.push_back(p_offset.translated(Vector3()).origin); + r_points.push_back(p_offset.translated_local(from).origin); + r_points.push_back(p_offset.translated_local(Vector3()).origin); } - r_points.push_back(p_offset.translated(from).origin); - r_points.push_back(p_offset.translated(to).origin); + r_points.push_back(p_offset.translated_local(from).origin); + r_points.push_back(p_offset.translated_local(to).origin); } - r_points.push_back(p_offset.translated(Vector3(0, p_radius * 1.5, 0)).origin); - r_points.push_back(p_offset.translated(Vector3()).origin); + r_points.push_back(p_offset.translated_local(Vector3(0, p_radius * 1.5, 0)).origin); + r_points.push_back(p_offset.translated_local(Vector3()).origin); } } @@ -5116,17 +5220,17 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w; - r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin); - r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, b.x, b.y))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, b.x, b.y))).origin); if (i % 90 == 0) { - r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin); - r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin); } } - r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin); - r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 0))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(1, 0, 0))).origin); /// Twist float ts = Math::rad2deg(p_twist); @@ -5140,8 +5244,8 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w * cn; - r_points.push_back(p_offset.translated(p_base.xform(Vector3(c, a.x, a.y))).origin); - r_points.push_back(p_offset.translated(p_base.xform(Vector3(cn, b.x, b.y))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(c, a.x, a.y))).origin); + r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(cn, b.x, b.y))).origin); } } @@ -5325,17 +5429,17 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform3D &p_offset, Vector<Vector3> &r_cursor_points) { float cs = 0.25; - r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(+cs, 0, 0)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(-cs, 0, 0)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(0, +cs, 0)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(0, -cs, 0)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, +cs)).origin); + r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, -cs)).origin); } void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { - r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin); - r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin); + r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin); + r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin); if (!p_use_limit) { p_limit_upper = -1; @@ -5368,34 +5472,34 @@ void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform3D &p_offset, con p_linear_limit_upper = -p_linear_limit_upper; float cs = 0.25; - r_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin); - r_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin); + r_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin); + r_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin); if (p_linear_limit_lower >= p_linear_limit_upper) { - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, 0, 0)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, 0, 0)).origin); - - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin); - - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin); - r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, 0, 0)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, 0, 0)).origin); + + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin); + + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin); + r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin); } else { - r_points.push_back(p_offset.translated(Vector3(+cs * 2, 0, 0)).origin); - r_points.push_back(p_offset.translated(Vector3(-cs * 2, 0, 0)).origin); + r_points.push_back(p_offset.translated_local(Vector3(+cs * 2, 0, 0)).origin); + r_points.push_back(p_offset.translated_local(Vector3(-cs * 2, 0, 0)).origin); } if (r_body_a_points) { @@ -5518,13 +5622,13 @@ void Joint3DGizmoPlugin::CreateGeneric6DOFJointGizmo( break; } -#define ADD_VTX(x, y, z) \ - { \ - Vector3 v; \ - v[a1] = (x); \ - v[a2] = (y); \ - v[a3] = (z); \ - r_points.push_back(p_offset.translated(v).origin); \ +#define ADD_VTX(x, y, z) \ + { \ + Vector3 v; \ + v[a1] = (x); \ + v[a2] = (y); \ + v[a3] = (z); \ + r_points.push_back(p_offset.translated_local(v).origin); \ } if (enable_lin && lll >= lul) { diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index a0d7715347..739bf1b929 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -373,6 +373,18 @@ public: RayCast3DGizmoPlugin(); }; +class ShapeCast3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(ShapeCast3DGizmoPlugin, EditorNode3DGizmoPlugin); + +public: + bool has_gizmo(Node3D *p_spatial) override; + String get_gizmo_name() const override; + int get_priority() const override; + void redraw(EditorNode3DGizmo *p_gizmo) override; + + ShapeCast3DGizmoPlugin(); +}; + class SpringArm3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(SpringArm3DGizmoPlugin, EditorNode3DGizmoPlugin); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 99c492379d..6afc6798d0 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -33,8 +33,8 @@ #include "core/config/project_settings.h" #include "core/input/input.h" #include "core/input/input_map.h" -#include "core/math/camera_matrix.h" #include "core/math/math_funcs.h" +#include "core/math/projection.h" #include "core/os/keyboard.h" #include "core/templates/sort_array.h" #include "editor/debugger/editor_debugger_node.h" @@ -52,6 +52,7 @@ #include "scene/3d/visual_instance_3d.h" #include "scene/3d/world_environment.h" #include "scene/gui/center_container.h" +#include "scene/gui/flow_container.h" #include "scene/gui/subviewport_container.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" @@ -355,14 +356,14 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) { Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const { Transform3D camera_transform; - camera_transform.translate(p_cursor.pos); + camera_transform.translate_local(p_cursor.pos); camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot); camera_transform.basis.rotate(Vector3(0, 1, 0), -p_cursor.y_rot); if (orthogonal) { - camera_transform.translate(0, 0, (get_zfar() - get_znear()) / 2.0); + camera_transform.translate_local(0, 0, (get_zfar() - get_znear()) / 2.0); } else { - camera_transform.translate(0, 0, p_cursor.distance); + camera_transform.translate_local(0, 0, p_cursor.distance); } return camera_transform; @@ -514,7 +515,7 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) { } } -ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) { +ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const { Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink(); @@ -641,7 +642,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe } Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { - CameraMatrix cm; + Projection cm; if (orthogonal) { cm.set_orthogonal(camera->get_size(), get_size().aspect(), get_znear() + p_vector3.z, get_zfar()); } else { @@ -650,10 +651,10 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { Vector2 screen_he = cm.get_viewport_half_extents(); Transform3D camera_transform; - camera_transform.translate(cursor.pos); + camera_transform.translate_local(cursor.pos); camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot); camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot); - camera_transform.translate(0, 0, cursor.distance); + camera_transform.translate_local(0, 0, cursor.distance); return camera_transform.xform(Vector3(((p_vector3.x / get_size().width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / get_size().height)) * 2.0 - 1.0) * screen_he.y, -(get_znear() + p_vector3.z))); } @@ -1259,7 +1260,9 @@ void Node3DEditorViewport::_surface_mouse_enter() { } void Node3DEditorViewport::_surface_mouse_exit() { - _remove_preview(); + _remove_preview_node(); + _reset_preview_material(); + _remove_preview_material(); } void Node3DEditorViewport::_surface_focus_enter() { @@ -1383,25 +1386,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { const real_t zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { case MouseButton::WHEEL_UP: { - if (b->is_alt_pressed()) { - scale_fov(-0.05); + if (is_freelook_active()) { + scale_freelook_speed(zoom_factor); } else { - if (is_freelook_active()) { - scale_freelook_speed(zoom_factor); - } else { - scale_cursor_distance(1.0 / zoom_factor); - } + scale_cursor_distance(1.0 / zoom_factor); } } break; case MouseButton::WHEEL_DOWN: { - if (b->is_alt_pressed()) { - scale_fov(0.05); + if (is_freelook_active()) { + scale_freelook_speed(1.0 / zoom_factor); } else { - if (is_freelook_active()) { - scale_freelook_speed(1.0 / zoom_factor); - } else { - scale_cursor_distance(zoom_factor); - } + scale_cursor_distance(zoom_factor); } } break; case MouseButton::RIGHT: { @@ -2099,7 +2094,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const Transform3D camera_transform; - camera_transform.translate(cursor.pos); + camera_transform.translate_local(cursor.pos); camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot); camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot); const bool invert_x_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_x_axis"); @@ -2109,7 +2104,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const (invert_y_axis ? -1 : 1) * p_relative.y * pan_speed, 0); translation *= cursor.distance / DISTANCE_DEFAULT; - camera_transform.translate(translation); + camera_transform.translate_local(translation); cursor.pos = camera_transform.origin; } @@ -2379,19 +2374,19 @@ void Node3DEditorPlugin::edited_scene_changed() { void Node3DEditorViewport::_project_settings_changed() { //update shadow atlas if changed - int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/size"); - bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/16_bits"); - int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_0_subdiv"); - int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_1_subdiv"); - int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_2_subdiv"); - int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_3_subdiv"); - - viewport->set_shadow_atlas_size(shadowmap_size); - viewport->set_shadow_atlas_16_bits(shadowmap_16_bits); - viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0)); - viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1)); - viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2)); - viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3)); + int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_size"); + bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_16_bits"); + int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv"); + int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv"); + int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv"); + int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv"); + + viewport->set_positional_shadow_atlas_size(shadowmap_size); + viewport->set_positional_shadow_atlas_16_bits(shadowmap_16_bits); + viewport->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0)); + viewport->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1)); + viewport->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2)); + viewport->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3)); _update_shrink(); @@ -2422,8 +2417,8 @@ void Node3DEditorViewport::_project_settings_changed() { const float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness"); viewport->set_fsr_sharpness(fsr_sharpness); - const float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias"); - viewport->set_fsr_mipmap_bias(fsr_mipmap_bias); + const float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias"); + viewport->set_texture_mipmap_bias(texture_mipmap_bias); } void Node3DEditorViewport::_notification(int p_what) { @@ -2519,14 +2514,14 @@ void Node3DEditorViewport::_notification(int p_what) { const Vector3 offset(0.005, 0.005, 0.005); Basis aabb_s; aabb_s.scale(se->aabb.size + offset); - t.translate(se->aabb.position - offset / 2); + t.translate_local(se->aabb.position - offset / 2); t.basis = t.basis * aabb_s; } { const Vector3 offset(0.01, 0.01, 0.01); Basis aabb_s; aabb_s.scale(se->aabb.size + offset); - t_offset.translate(se->aabb.position - offset / 2); + t_offset.translate_local(se->aabb.position - offset / 2); t_offset.basis = t_offset.basis * aabb_s; } @@ -2702,6 +2697,13 @@ void Node3DEditorViewport::_notification(int p_what) { cinema_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles"))); locked_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles"))); } break; + + case NOTIFICATION_DRAG_END: { + // Clear preview material when dropped outside applicable object. + if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) { + _remove_preview_material(); + } + } break; } } @@ -3793,7 +3795,7 @@ Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const { return p_node; } -void Node3DEditorViewport::_create_preview(const Vector<String> &files) const { +void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const { for (int i = 0; i < files.size(); i++) { String path = files[i]; Ref<Resource> res = ResourceLoader::load(path); @@ -3820,7 +3822,7 @@ void Node3DEditorViewport::_create_preview(const Vector<String> &files) const { *preview_bounds = _calculate_spatial_bounds(preview_node); } -void Node3DEditorViewport::_remove_preview() { +void Node3DEditorViewport::_remove_preview_node() { if (preview_node->get_parent()) { for (int i = preview_node->get_child_count() - 1; i >= 0; i--) { Node *node = preview_node->get_child(i); @@ -3831,6 +3833,106 @@ void Node3DEditorViewport::_remove_preview() { } } +bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Point2 &p_point) const { + _reset_preview_material(); + + if (p_target.is_null()) { + return false; + } + + spatial_editor->set_preview_material_target(p_target); + + Object *target_inst = ObjectDB::get_instance(p_target); + + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); + + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(target_inst); + if (is_ctrl && mesh_instance) { + Ref<Mesh> mesh = mesh_instance->get_mesh(); + int surface_count = mesh->get_surface_count(); + + Vector3 world_ray = _get_ray(p_point); + Vector3 world_pos = _get_ray_pos(p_point); + + int closest_surface = -1; + float closest_dist = 1e20; + + Transform3D gt = mesh_instance->get_global_transform(); + + Transform3D ai = gt.affine_inverse(); + Vector3 xform_ray = ai.basis.xform(world_ray).normalized(); + Vector3 xform_pos = ai.xform(world_pos); + + for (int surface = 0; surface < surface_count; surface++) { + Ref<TriangleMesh> surface_mesh = mesh->generate_surface_triangle_mesh(surface); + + Vector3 rpos, rnorm; + if (surface_mesh->intersect_ray(xform_pos, xform_ray, rpos, rnorm)) { + Vector3 hitpos = gt.xform(rpos); + + const real_t dist = world_pos.distance_to(hitpos); + + if (dist < 0) { + continue; + } + + if (dist < closest_dist) { + closest_surface = surface; + closest_dist = dist; + } + } + } + + if (closest_surface == -1) { + return false; + } + + if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) { + spatial_editor->set_preview_material_surface(closest_surface); + spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface)); + mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material()); + } + + return true; + } + + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst); + if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) { + spatial_editor->set_preview_reset_material(geometry_instance->get_material_override()); + geometry_instance->set_material_override(spatial_editor->get_preview_material()); + return true; + } + + return false; +} + +void Node3DEditorViewport::_reset_preview_material() const { + ObjectID last_target = spatial_editor->get_preview_material_target(); + if (last_target.is_null()) { + return; + } + Object *last_target_inst = ObjectDB::get_instance(last_target); + + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(last_target_inst); + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst); + if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { + mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); + spatial_editor->set_preview_material_surface(-1); + } else if (geometry_instance) { + geometry_instance->set_material_override(spatial_editor->get_preview_reset_material()); + } +} + +void Node3DEditorViewport::_remove_preview_material() { + preview_material_label->hide(); + preview_material_label_desc->hide(); + + spatial_editor->set_preview_material(Ref<Material>()); + spatial_editor->set_preview_reset_material(Ref<Material>()); + spatial_editor->set_preview_material_target(ObjectID()); + spatial_editor->set_preview_material_surface(-1); +} + bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) { if (p_desired_node->get_scene_file_path() == p_target_scene_path) { return true; @@ -3929,7 +4031,26 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po } void Node3DEditorViewport::_perform_drop_data() { - _remove_preview(); + if (spatial_editor->get_preview_material_target().is_valid()) { + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); + if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { + editor_data->get_undo_redo().create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface())); + editor_data->get_undo_redo().add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material()); + editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); + editor_data->get_undo_redo().commit_action(); + } else if (geometry_instance) { + editor_data->get_undo_redo().create_action(TTR("Set Material Override")); + editor_data->get_undo_redo().add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material()); + editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material()); + editor_data->get_undo_redo().commit_action(); + } + + _remove_preview_material(); + return; + } + + _remove_preview_node(); Vector<String> error_files; @@ -3967,7 +4088,7 @@ void Node3DEditorViewport::_perform_drop_data() { bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { bool can_instantiate = false; - if (!preview_node->is_inside_tree()) { + if (!preview_node->is_inside_tree() && spatial_editor->get_preview_material().is_null()) { Dictionary d = p_data; if (d.has("type") && (String(d["type"]) == "files")) { Vector<String> files = d["files"]; @@ -3976,40 +4097,78 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); List<String> mesh_extensions; ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions); + List<String> material_extensions; + ResourceLoader::get_recognized_extensions_for_type("Material", &material_extensions); + List<String> texture_extensions; + ResourceLoader::get_recognized_extensions_for_type("Texture", &texture_extensions); for (int i = 0; i < files.size(); i++) { // Check if dragged files with mesh or scene extension can be created at least once. - if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) { + if (mesh_extensions.find(files[i].get_extension()) || + scene_extensions.find(files[i].get_extension()) || + material_extensions.find(files[i].get_extension()) || + texture_extensions.find(files[i].get_extension())) { Ref<Resource> res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; } Ref<PackedScene> scn = res; + Ref<Material> mat = res; + Ref<Texture2D> tex = res; if (scn.is_valid()) { Node *instantiated_scene = scn->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instantiated_scene) { continue; } memdelete(instantiated_scene); + } else if (mat.is_valid()) { + Ref<BaseMaterial3D> base_mat = res; + Ref<ShaderMaterial> shader_mat = res; + + if (base_mat.is_null() && !shader_mat.is_null()) { + break; + } + + spatial_editor->set_preview_material(mat); + break; + } else if (tex.is_valid()) { + Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D); + new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex); + + spatial_editor->set_preview_material(new_mat); + break; + } else { + continue; } can_instantiate = true; break; } } if (can_instantiate) { - _create_preview(files); + _create_preview_node(files); } } } else { - can_instantiate = true; + if (preview_node->is_inside_tree()) { + can_instantiate = true; + } } if (can_instantiate) { Transform3D global_transform = Transform3D(Basis(), _get_instance_position(p_point)); preview_node->set_global_transform(global_transform); + return true; } - return can_instantiate; + if (spatial_editor->get_preview_material().is_valid()) { + preview_material_label->show(); + preview_material_label_desc->show(); + + ObjectID new_preview_material_target = _select_ray(p_point); + return _apply_preview_material(new_preview_material_target, p_point); + } + + return false; } void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { @@ -4047,7 +4206,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_ } else { accept->set_text(TTR("Cannot drag and drop into multiple selected nodes.")); accept->popup_centered(); - _remove_preview(); + _remove_preview_node(); return; } @@ -4449,7 +4608,7 @@ void Node3DEditorViewport::register_shortcut_action(const String &p_path, const Ref<Shortcut> sc = ED_SHORTCUT(p_path, p_name, p_keycode); shortcut_changed_callback(sc, p_path); // Connect to the change event on the shortcut so the input binding can be updated. - sc->connect("changed", callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback), varray(sc, p_path)); + sc->connect("changed", callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path)); } // Update the action in the InputMap to the provided shortcut events. @@ -4494,7 +4653,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p subviewport_container = c; c->set_stretch(true); add_child(c); - c->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + c->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); viewport = memnew(SubViewport); viewport->set_disable_input(true); @@ -4502,7 +4661,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p surface = memnew(Control); surface->set_drag_forwarding(this); add_child(surface); - surface->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + surface->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); surface->set_clip_contents(true); camera = memnew(Camera3D); camera->set_disable_gizmos(true); @@ -4698,6 +4857,23 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p zoom_limit_label->hide(); surface->add_child(zoom_limit_label); + preview_material_label = memnew(Label); + preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); + preview_material_label->set_offset(Side::SIDE_TOP, -70 * EDSCALE); + preview_material_label->set_text(TTR("Overriding material...")); + preview_material_label->add_theme_color_override("font_color", Color(1, 1, 1, 1)); + preview_material_label->hide(); + surface->add_child(preview_material_label); + + preview_material_label_desc = memnew(Label); + preview_material_label_desc->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); + preview_material_label_desc->set_offset(Side::SIDE_TOP, -50 * EDSCALE); + preview_material_label_desc->set_text(TTR("Drag and drop to override the material of any geometry node.\nHold Ctrl when dropping to override a specific surface.")); + preview_material_label_desc->add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1)); + preview_material_label_desc->add_theme_constant_override("line_spacing", 0); + preview_material_label_desc->hide(); + surface->add_child(preview_material_label_desc); + frame_time_gradient = memnew(Gradient); // The color is set when the theme changes. frame_time_gradient->add_point(0.5, Color()); @@ -6224,7 +6400,7 @@ void fragment() { Ref<ShaderMaterial> rotate_mat = memnew(ShaderMaterial); rotate_mat->set_render_priority(Material::RENDER_PRIORITY_MAX); rotate_mat->set_shader(rotate_shader); - rotate_mat->set_shader_param("albedo", col); + rotate_mat->set_shader_uniform("albedo", col); rotate_gizmo_color[i] = rotate_mat; Array arrays = surftool->commit_to_arrays(); @@ -6232,7 +6408,7 @@ void fragment() { rotate_gizmo[i]->surface_set_material(0, rotate_mat); Ref<ShaderMaterial> rotate_mat_hl = rotate_mat->duplicate(); - rotate_mat_hl->set_shader_param("albedo", albedo); + rotate_mat_hl->set_shader_uniform("albedo", albedo); rotate_gizmo_color_hl[i] = rotate_mat_hl; if (i == 2) { // Rotation white outline @@ -6273,7 +6449,7 @@ void fragment() { )"); border_mat->set_shader(border_shader); - border_mat->set_shader_param("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0)); + border_mat->set_shader_uniform("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0)); rotate_gizmo[3] = Ref<ArrayMesh>(memnew(ArrayMesh)); rotate_gizmo[3]->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays); @@ -6526,8 +6702,8 @@ void Node3DEditor::_init_grid() { fade_size = CLAMP(fade_size, min_fade_size, max_fade_size); real_t grid_fade_size = (grid_size - primary_grid_steps) * fade_size; - grid_mat[c]->set_shader_param("grid_size", grid_fade_size); - grid_mat[c]->set_shader_param("orthogonal", orthogonal); + grid_mat[c]->set_shader_uniform("grid_size", grid_fade_size); + grid_mat[c]->set_shader_uniform("orthogonal", orthogonal); // Cache these so we don't have to re-access memory. Vector<Vector3> &ref_grid = grid_points[c]; @@ -6638,7 +6814,7 @@ void Node3DEditor::_finish_grid() { } void Node3DEditor::update_grid() { - const Camera3D::Projection current_projection = viewports[0]->camera->get_projection(); + const Camera3D::ProjectionType current_projection = viewports[0]->camera->get_projection(); if (current_projection != grid_camera_last_update_perspective) { grid_init_draw = false; // redraw @@ -6983,7 +7159,7 @@ void Node3DEditor::_update_theme() { environ_sky_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); environ_ground_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); - context_menu_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); + context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); } void Node3DEditor::_notification(int p_what) { @@ -6998,8 +7174,8 @@ void Node3DEditor::_notification(int p_what) { SceneTreeDock::get_singleton()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed)); - EditorNode::get_singleton()->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false)); - EditorNode::get_singleton()->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true)); + EditorNode::get_singleton()->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(false)); + EditorNode::get_singleton()->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(true)); _update_preview_environment(); @@ -7072,11 +7248,11 @@ Vector<int> Node3DEditor::get_subgizmo_selection() { } void Node3DEditor::add_control_to_menu_panel(Control *p_control) { - hbc_context_menu->add_child(p_control); + context_menu_hbox->add_child(p_control); } void Node3DEditor::remove_control_from_menu_panel(Control *p_control) { - hbc_context_menu->remove_child(p_control); + context_menu_hbox->remove_child(p_control); } void Node3DEditor::set_can_preview(Camera3D *p_preview) { @@ -7233,7 +7409,7 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) { if (!maximized) { for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { if (i == (uint32_t)index) { - viewports[i]->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + viewports[i]->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); } else { viewports[i]->hide(); } @@ -7313,6 +7489,7 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin))); add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin))); add_gizmo_plugin(Ref<RayCast3DGizmoPlugin>(memnew(RayCast3DGizmoPlugin))); + add_gizmo_plugin(Ref<ShapeCast3DGizmoPlugin>(memnew(ShapeCast3DGizmoPlugin))); add_gizmo_plugin(Ref<SpringArm3DGizmoPlugin>(memnew(SpringArm3DGizmoPlugin))); add_gizmo_plugin(Ref<VehicleWheel3DGizmoPlugin>(memnew(VehicleWheel3DGizmoPlugin))); add_gizmo_plugin(Ref<VisibleOnScreenNotifier3DGizmoPlugin>(memnew(VisibleOnScreenNotifier3DGizmoPlugin))); @@ -7374,9 +7551,9 @@ void Node3DEditor::_sun_direction_draw() { sun_direction->draw_rect(Rect2(Vector2(), sun_direction->get_size()), Color(1, 1, 1, 1)); Vector3 z_axis = preview_sun->get_transform().basis.get_column(Vector3::AXIS_Z); z_axis = get_editor_viewport(0)->camera->get_camera_transform().basis.xform_inv(z_axis); - sun_direction_material->set_shader_param("sun_direction", Vector3(z_axis.x, -z_axis.y, z_axis.z)); + sun_direction_material->set_shader_uniform("sun_direction", Vector3(z_axis.x, -z_axis.y, z_axis.z)); Color color = sun_color->get_pick_color() * sun_energy->get_value(); - sun_direction_material->set_shader_param("sun_color", Vector3(color.r, color.g, color.b)); + sun_direction_material->set_shader_uniform("sun_color", Vector3(color.r, color.g, color.b)); } void Node3DEditor::_preview_settings_changed() { @@ -7529,163 +7706,155 @@ Node3DEditor::Node3DEditor() { camera_override_viewport_id = 0; - hbc_menu = memnew(HBoxContainer); - vbc->add_child(hbc_menu); + // A fluid container for all toolbars. + HFlowContainer *main_flow = memnew(HFlowContainer); + vbc->add_child(main_flow); + + // Main toolbars. + HBoxContainer *main_menu_hbox = memnew(HBoxContainer); + main_flow->add_child(main_menu_hbox); - Vector<Variant> button_binds; - button_binds.resize(1); String sct; // Add some margin to the left for better aesthetics. // This prevents the first button's hover/pressed effect from "touching" the panel's border, // which looks ugly. Control *margin_left = memnew(Control); - hbc_menu->add_child(margin_left); + main_menu_hbox->add_child(margin_left); margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE); tool_button[TOOL_MODE_SELECT] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_SELECT]->set_flat(true); tool_button[TOOL_MODE_SELECT]->set_pressed(true); - button_binds.write[0] = MENU_TOOL_SELECT; - tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT)); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q)); tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this); tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); - button_binds.write[0] = MENU_TOOL_MOVE; - tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + + tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_MOVE)); tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), Key::W)); tool_button[TOOL_MODE_MOVE]->set_shortcut_context(this); tool_button[TOOL_MODE_ROTATE] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); - button_binds.write[0] = MENU_TOOL_ROTATE; - tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_ROTATE)); tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), Key::E)); tool_button[TOOL_MODE_ROTATE]->set_shortcut_context(this); tool_button[TOOL_MODE_SCALE] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); - button_binds.write[0] = MENU_TOOL_SCALE; - tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SCALE)); tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), Key::R)); tool_button[TOOL_MODE_SCALE]->set_shortcut_context(this); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_LIST_SELECT] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); - button_binds.write[0] = MENU_TOOL_LIST_SELECT; - tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_LIST_SELECT)); tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show list of selectable nodes at position clicked.")); tool_button[TOOL_LOCK_SELECTED] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_LOCK_SELECTED]); tool_button[TOOL_LOCK_SELECTED]->set_flat(true); - button_binds.write[0] = MENU_LOCK_SELECTED; - tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED)); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]); tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true); - button_binds.write[0] = MENU_UNLOCK_SELECTED; - tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED)); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); tool_button[TOOL_GROUP_SELECTED] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]); tool_button[TOOL_GROUP_SELECTED]->set_flat(true); - button_binds.write[0] = MENU_GROUP_SELECTED; - tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); + tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED)); + tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); - hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]); tool_button[TOOL_UNGROUP_SELECTED]->set_flat(true); - button_binds.write[0] = MENU_UNGROUP_SELECTED; - tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); + tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED)); + tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(Button); - hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); - button_binds.write[0] = MENU_TOOL_LOCAL_COORDS; - tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_LOCAL_COORDS)); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), Key::T)); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut_context(this); tool_option_button[TOOL_OPT_USE_SNAP] = memnew(Button); - hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); - button_binds.write[0] = MENU_TOOL_USE_SNAP; - tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_USE_SNAP)); tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), Key::Y)); tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut_context(this); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(Button); - hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true); - button_binds.write[0] = MENU_TOOL_OVERRIDE_CAMERA; - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_OVERRIDE_CAMERA)); _update_camera_override_button(false); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); sun_button = memnew(Button); sun_button->set_tooltip(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); sun_button->set_toggle_mode(true); sun_button->set_flat(true); - sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED); + sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); sun_button->set_disabled(true); - hbc_menu->add_child(sun_button); + main_menu_hbox->add_child(sun_button); environ_button = memnew(Button); environ_button->set_tooltip(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled.")); environ_button->set_toggle_mode(true); environ_button->set_flat(true); - environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED); + environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); environ_button->set_disabled(true); - hbc_menu->add_child(environ_button); + main_menu_hbox->add_child(environ_button); sun_environ_settings = memnew(Button); sun_environ_settings->set_tooltip(TTR("Edit Sun and Environment settings.")); sun_environ_settings->set_flat(true); sun_environ_settings->connect("pressed", callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed)); - hbc_menu->add_child(sun_environ_settings); + main_menu_hbox->add_child(sun_environ_settings); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); // Drag and drop support; preview_node = memnew(Node3D); @@ -7719,7 +7888,7 @@ Node3DEditor::Node3DEditor() { transform_menu->set_text(TTR("Transform")); transform_menu->set_switch_on_hover(true); transform_menu->set_shortcut_context(this); - hbc_menu->add_child(transform_menu); + main_menu_hbox->add_child(transform_menu); p = transform_menu->get_popup(); p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap Object to Floor"), Key::PAGEDOWN), MENU_SNAP_TO_FLOOR); @@ -7735,14 +7904,14 @@ Node3DEditor::Node3DEditor() { view_menu->set_text(TTR("View")); view_menu->set_switch_on_hover(true); view_menu->set_shortcut_context(this); - hbc_menu->add_child(view_menu); + main_menu_hbox->add_child(view_menu); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); - context_menu_container = memnew(PanelContainer); - hbc_context_menu = memnew(HBoxContainer); - context_menu_container->add_child(hbc_context_menu); - hbc_menu->add_child(context_menu_container); + context_menu_panel = memnew(PanelContainer); + context_menu_hbox = memnew(HBoxContainer); + context_menu_panel->add_child(context_menu_hbox); + main_flow->add_child(context_menu_panel); // Get the view menu popup and have it stay open when a checkable item is selected p = view_menu->get_popup(); @@ -7860,7 +8029,7 @@ Node3DEditor::Node3DEditor() { settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar); for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) { - settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed), varray(0.0)); + settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed).bind(0.0)); } /* XFORM DIALOG */ @@ -7985,8 +8154,8 @@ void fragment() { )"); sun_direction_material.instantiate(); sun_direction_material->set_shader(sun_direction_shader); - sun_direction_material->set_shader_param("sun_direction", Vector3(0, 0, 1)); - sun_direction_material->set_shader_param("sun_color", Vector3(1, 1, 1)); + sun_direction_material->set_shader_uniform("sun_direction", Vector3(0, 0, 1)); + sun_direction_material->set_shader_uniform("sun_color", Vector3(1, 1, 1)); sun_direction->set_material(sun_direction_material); HBoxContainer *sun_angle_hbox = memnew(HBoxContainer); @@ -8022,6 +8191,7 @@ void fragment() { sun_color->set_edit_alpha(false); sun_vb->add_margin_child(TTR("Sun Color"), sun_color); sun_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1)); + sun_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(sun_color->get_picker())); sun_energy = memnew(EditorSpinSlider); sun_vb->add_margin_child(TTR("Sun Energy"), sun_energy); @@ -8037,7 +8207,7 @@ void fragment() { sun_add_to_scene = memnew(Button); sun_add_to_scene->set_text(TTR("Add Sun to Scene")); sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); - sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene), varray(false)); + sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene).bind(false)); sun_vb->add_spacer(); sun_vb->add_child(sun_add_to_scene); @@ -8067,10 +8237,12 @@ void fragment() { environ_sky_color = memnew(ColorPickerButton); environ_sky_color->set_edit_alpha(false); environ_sky_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1)); + environ_sky_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_sky_color->get_picker())); environ_vb->add_margin_child(TTR("Sky Color"), environ_sky_color); environ_ground_color = memnew(ColorPickerButton); environ_ground_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1)); environ_ground_color->set_edit_alpha(false); + environ_ground_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_ground_color->get_picker())); environ_vb->add_margin_child(TTR("Ground Color"), environ_ground_color); environ_energy = memnew(EditorSpinSlider); environ_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1)); @@ -8082,29 +8254,29 @@ void fragment() { environ_ao_button = memnew(Button); environ_ao_button->set_text(TTR("AO")); environ_ao_button->set_toggle_mode(true); - environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED); + environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED); fx_vb->add_child(environ_ao_button); environ_glow_button = memnew(Button); environ_glow_button->set_text(TTR("Glow")); environ_glow_button->set_toggle_mode(true); - environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED); + environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED); fx_vb->add_child(environ_glow_button); environ_tonemap_button = memnew(Button); environ_tonemap_button->set_text(TTR("Tonemap")); environ_tonemap_button->set_toggle_mode(true); - environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED); + environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED); fx_vb->add_child(environ_tonemap_button); environ_gi_button = memnew(Button); environ_gi_button->set_text(TTR("GI")); environ_gi_button->set_toggle_mode(true); - environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED); + environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED); fx_vb->add_child(environ_gi_button); environ_vb->add_margin_child(TTR("Post Process"), fx_vb); environ_add_to_scene = memnew(Button); environ_add_to_scene->set_text(TTR("Add Environment to Scene")); environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); - environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene), varray(false)); + environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene).bind(false)); environ_vb->add_spacer(); environ_vb->add_child(environ_add_to_scene); @@ -8131,7 +8303,6 @@ void fragment() { _preview_settings_changed(); } } - Node3DEditor::~Node3DEditor() { memdelete(preview_node); } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 8a602be08b..4469271a38 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -227,6 +227,9 @@ private: Label *locked_label = nullptr; Label *zoom_limit_label = nullptr; + Label *preview_material_label = nullptr; + Label *preview_material_label_desc = nullptr; + VBoxContainer *top_right_vbox = nullptr; ViewportRotationControl *rotation_control = nullptr; Gradient *frame_time_gradient = nullptr; @@ -244,7 +247,7 @@ private: void _compute_edit(const Point2 &p_point); void _clear_selected(); void _select_clicked(bool p_allow_locked); - ObjectID _select_ray(const Point2 &p_pos); + ObjectID _select_ray(const Point2 &p_pos) const; void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked); Vector3 _get_ray_pos(const Vector2 &p_pos) const; Vector3 _get_ray(const Vector2 &p_pos) const; @@ -272,6 +275,7 @@ private: float get_fov() const; ObjectID clicked; + ObjectID material_target; Vector<_RayResult> selection_results; bool clicked_wants_append = false; bool selection_in_progress = false; @@ -399,8 +403,11 @@ private: Node *_sanitize_preview_node(Node *p_node) const; - void _create_preview(const Vector<String> &files) const; - void _remove_preview(); + void _create_preview_node(const Vector<String> &files) const; + void _remove_preview_node(); + bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const; + void _reset_preview_material() const; + void _remove_preview_material(); bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node); bool _create_instance(Node *parent, String &path, const Point2 &p_point); void _perform_drop_data(); @@ -560,7 +567,7 @@ private: bool grid_enable[3]; //should be always visible if true bool grid_enabled = false; bool grid_init_draw = false; - Camera3D::Projection grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE; + Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE; Vector3 grid_camera_last_update_position = Vector3(); Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3]; @@ -593,6 +600,11 @@ private: Node3D *preview_node = nullptr; AABB preview_bounds; + Ref<Material> preview_material; + Ref<Material> preview_reset_material; + ObjectID preview_material_target; + int preview_material_surface = -1; + struct Gizmo { bool visible = false; real_t scale = 0; @@ -664,11 +676,10 @@ private: void _menu_gizmo_toggled(int p_option); void _update_camera_override_button(bool p_game_running); void _update_camera_override_viewport(Object *p_viewport); - HBoxContainer *hbc_menu = nullptr; // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). - PanelContainer *context_menu_container = nullptr; - HBoxContainer *hbc_context_menu = nullptr; + PanelContainer *context_menu_panel = nullptr; + HBoxContainer *context_menu_hbox = nullptr; void _generate_selection_boxes(); UndoRedo *undo_redo = nullptr; @@ -851,6 +862,15 @@ public: void set_can_preview(Camera3D *p_preview); + void set_preview_material(Ref<Material> p_material) { preview_material = p_material; } + Ref<Material> get_preview_material() { return preview_material; } + void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; } + Ref<Material> get_preview_reset_material() const { return preview_reset_material; } + void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; } + ObjectID get_preview_material_target() const { return preview_material_target; } + void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; } + int get_preview_material_surface() const { return preview_material_surface; } + Node3DEditorViewport *get_editor_viewport(int p_idx) { ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr); return viewports[p_idx]; diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.h b/editor/plugins/occluder_instance_3d_editor_plugin.h index 360b7297cf..e8d98927f4 100644 --- a/editor/plugins/occluder_instance_3d_editor_plugin.h +++ b/editor/plugins/occluder_instance_3d_editor_plugin.h @@ -63,4 +63,4 @@ public: ~OccluderInstance3DEditorPlugin(); }; -#endif +#endif // OCCLUDER_INSTANCE_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 9e666ef70a..fd331c4127 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -537,7 +537,7 @@ Path2DEditor::Path2DEditor() { curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); - curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT)); + curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT)); base_hb->add_child(curve_edit); curve_edit_curve = memnew(Button); @@ -545,7 +545,7 @@ Path2DEditor::Path2DEditor() { curve_edit_curve->set_toggle_mode(true); curve_edit_curve->set_focus_mode(Control::FOCUS_NONE); curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)")); - curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT_CURVE)); + curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT_CURVE)); base_hb->add_child(curve_edit_curve); curve_create = memnew(Button); @@ -553,7 +553,7 @@ Path2DEditor::Path2DEditor() { curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)")); - curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_CREATE)); + curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CREATE)); base_hb->add_child(curve_create); curve_del = memnew(Button); @@ -561,14 +561,14 @@ Path2DEditor::Path2DEditor() { curve_del->set_toggle_mode(true); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); - curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_DELETE)); + curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_DELETE)); base_hb->add_child(curve_del); curve_close = memnew(Button); curve_close->set_flat(true); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); - curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(ACTION_CLOSE)); + curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(ACTION_CLOSE)); base_hb->add_child(curve_close); PopupMenu *menu; diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 36f559b2ae..65b15a6001 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -34,6 +34,7 @@ #include "core/math/geometry_3d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "node_3d_editor_plugin.h" #include "scene/resources/curve.h" @@ -557,9 +558,9 @@ void Path3DEditorPlugin::_update_theme() { void Path3DEditorPlugin::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - curve_create->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(0)); - curve_edit->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(1)); - curve_del->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(2)); + curve_create->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(0)); + curve_edit->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(1)); + curve_del->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(2)); curve_close->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_close_curve)); _update_theme(); diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index ee31fcf43d..53e4e2efa8 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PATH_EDITOR_PLUGIN_H -#define PATH_EDITOR_PLUGIN_H +#ifndef PATH_3D_EDITOR_PLUGIN_H +#define PATH_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "editor/plugins/node_3d_editor_gizmos.h" @@ -118,4 +118,4 @@ public: ~Path3DEditorPlugin(); }; -#endif // PATH_EDITOR_PLUGIN_H +#endif // PATH_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h index 93e722a432..f15eab7991 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.h +++ b/editor/plugins/physical_bone_3d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICAL_BONE_PLUGIN_H -#define PHYSICAL_BONE_PLUGIN_H +#ifndef PHYSICAL_BONE_3D_EDITOR_PLUGIN_H +#define PHYSICAL_BONE_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/physics_body_3d.h" @@ -76,4 +76,4 @@ public: PhysicalBone3DEditorPlugin(); }; -#endif +#endif // PHYSICAL_BONE_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index a682bb455c..4f46c99a04 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -192,7 +192,7 @@ void Polygon2DEditor::_update_bone_list() { cb->set_pressed(true); } - cb->connect("pressed", callable_mp(this, &Polygon2DEditor::_bone_paint_selected), varray(i)); + cb->connect("pressed", callable_mp(this, &Polygon2DEditor::_bone_paint_selected).bind(i)); } uv_edit_draw->update(); @@ -1238,7 +1238,7 @@ Polygon2DEditor::Polygon2DEditor() { button_uv->set_flat(true); add_child(button_uv); button_uv->set_tooltip(TTR("Open Polygon 2D UV editor.")); - button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option), varray(MODE_EDIT_UV)); + button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option).bind(MODE_EDIT_UV)); uv_mode = UV_MODE_EDIT_POINT; uv_edit = memnew(AcceptDialog); @@ -1276,10 +1276,10 @@ Polygon2DEditor::Polygon2DEditor() { uv_edit_mode[2]->set_button_group(uv_edit_group); uv_edit_mode[3]->set_button_group(uv_edit_group); - uv_edit_mode[0]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(0)); - uv_edit_mode[1]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(1)); - uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(2)); - uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(3)); + uv_edit_mode[0]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(0)); + uv_edit_mode[1]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(1)); + uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(2)); + uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(3)); uv_mode_hb->add_child(memnew(VSeparator)); @@ -1289,7 +1289,7 @@ Polygon2DEditor::Polygon2DEditor() { uv_button[i]->set_flat(true); uv_button[i]->set_toggle_mode(true); uv_mode_hb->add_child(uv_button[i]); - uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode), varray(i)); + uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode).bind(i)); uv_button[i]->set_focus_mode(FOCUS_NONE); } diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp index 1c69e0d635..83092f990f 100644 --- a/editor/plugins/polygon_3d_editor_plugin.cpp +++ b/editor/plugins/polygon_3d_editor_plugin.cpp @@ -532,13 +532,13 @@ Polygon3DEditor::Polygon3DEditor() { button_create = memnew(Button); button_create->set_flat(true); add_child(button_create); - button_create->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option), varray(MODE_CREATE)); + button_create->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_CREATE)); button_create->set_toggle_mode(true); button_edit = memnew(Button); button_edit->set_flat(true); add_child(button_edit); - button_edit->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option), varray(MODE_EDIT)); + button_edit->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_EDIT)); button_edit->set_toggle_mode(true); mode = MODE_EDIT; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index f4d42ff456..c53ac59c11 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "editor/debugger/script_editor_debugger.h" #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_run_script.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -590,7 +591,7 @@ void ScriptEditor::_go_to_tab(int p_idx) { } } - Control *c = Object::cast_to<Control>(tab_container->get_tab_control(p_idx)); + Control *c = tab_container->get_tab_control(p_idx); if (!c) { return; } @@ -812,7 +813,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { if (history_pos >= 0) { idx = tab_container->get_tab_idx_from_control(history[history_pos].control); } - tab_container->set_current_tab(idx); + _go_to_tab(idx); } else { _update_selected_editor_menu(); } @@ -882,7 +883,7 @@ void ScriptEditor::_queue_close_tabs() { // Maybe there are unsaved changes. if (se->is_unsaved()) { _ask_close_current_unsaved_tab(se); - erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), varray(), CONNECT_ONESHOT); + erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONESHOT); break; } } @@ -1447,20 +1448,20 @@ void ScriptEditor::_menu_option(int p_option) { case WINDOW_MOVE_UP: { if (tab_container->get_current_tab() > 0) { tab_container->move_child(current, tab_container->get_current_tab() - 1); - tab_container->set_current_tab(tab_container->get_current_tab() - 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; case WINDOW_MOVE_DOWN: { if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) { tab_container->move_child(current, tab_container->get_current_tab() + 1); - tab_container->set_current_tab(tab_container->get_current_tab() + 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; default: { if (p_option >= WINDOW_SELECT_BASE) { - tab_container->set_current_tab(p_option - WINDOW_SELECT_BASE); + _go_to_tab(p_option - WINDOW_SELECT_BASE); _update_script_names(); } } @@ -1493,14 +1494,14 @@ void ScriptEditor::_menu_option(int p_option) { case WINDOW_MOVE_UP: { if (tab_container->get_current_tab() > 0) { tab_container->move_child(help, tab_container->get_current_tab() - 1); - tab_container->set_current_tab(tab_container->get_current_tab() - 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; case WINDOW_MOVE_DOWN: { if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) { tab_container->move_child(help, tab_container->get_current_tab() + 1); - tab_container->set_current_tab(tab_container->get_current_tab() + 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; @@ -1542,7 +1543,7 @@ void ScriptEditor::_show_save_theme_as_dialog() { file_dialog_option = THEME_SAVE_AS; file_dialog->clear_filters(); file_dialog->add_filter("*.tet"); - file_dialog->set_current_path(EditorSettings::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme"))); + file_dialog->set_current_path(EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme"))); file_dialog->popup_file_dialog(); file_dialog->set_title(TTR("Save Theme As...")); } @@ -1852,10 +1853,12 @@ void ScriptEditor::_update_members_overview_visibility() { if (members_overview_enabled && se->show_members_overview()) { members_overview_alphabeta_sort_button->set_visible(true); + filter_methods->set_visible(true); members_overview->set_visible(true); overview_vbox->set_visible(true); } else { members_overview_alphabeta_sort_button->set_visible(false); + filter_methods->set_visible(false); members_overview->set_visible(false); overview_vbox->set_visible(false); } @@ -1910,6 +1913,7 @@ void ScriptEditor::_update_help_overview_visibility() { if (help_overview_enabled) { members_overview_alphabeta_sort_button->set_visible(false); + filter_methods->set_visible(false); help_overview->set_visible(true); overview_vbox->set_visible(true); filename->set_text(se->get_name()); @@ -2124,8 +2128,8 @@ void ScriptEditor::_update_script_names() { sd.index = i; sedata.set(i, sd); } - tab_container->set_current_tab(new_prev_tab); - tab_container->set_current_tab(new_cur_tab); + _go_to_tab(new_prev_tab); + _go_to_tab(new_cur_tab); _sort_list_on_update = false; } @@ -2153,8 +2157,10 @@ void ScriptEditor::_update_script_names() { } if (tab_container->get_current_tab() == sedata_filtered[i].index) { script_list->select(index); + script_name_label->set_text(sedata_filtered[i].name); script_icon->set_texture(sedata_filtered[i].icon); + ScriptEditorBase *se = _get_current_editor(); if (se) { se->enable_editor(); @@ -3264,7 +3270,7 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) { p_layout->set_value("ScriptEditor", "list_split_offset", list_split->get_split_offset()); // Save the cache. - script_editor_cache->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg")); + script_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg")); } void ScriptEditor::_help_class_open(const String &p_class) { @@ -3645,7 +3651,7 @@ ScriptEditor::ScriptEditor() { current_theme = ""; script_editor_cache.instantiate(); - script_editor_cache->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg")); + script_editor_cache->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg")); completion_cache = memnew(EditorScriptCodeCompletionCache); restoring_layout = false; @@ -3685,7 +3691,7 @@ ScriptEditor::ScriptEditor() { script_list->set_v_size_flags(SIZE_EXPAND_FILL); script_split->set_split_offset(70 * EDSCALE); _sort_list_on_update = true; - script_list->connect("gui_input", callable_mp(this, &ScriptEditor::_script_list_gui_input), varray(), CONNECT_DEFERRED); + script_list->connect("gui_input", callable_mp(this, &ScriptEditor::_script_list_gui_input), CONNECT_DEFERRED); script_list->set_allow_rmb_select(true); script_list->set_drag_forwarding(this); @@ -3853,14 +3859,14 @@ ScriptEditor::ScriptEditor() { site_search = memnew(Button); site_search->set_flat(true); site_search->set_text(TTR("Online Docs")); - site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_WEBSITE)); + site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_WEBSITE)); menu_hb->add_child(site_search); site_search->set_tooltip(TTR("Open Godot online documentation.")); help_search = memnew(Button); help_search->set_flat(true); help_search->set_text(TTR("Search Help")); - help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_HELP)); + help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_HELP)); menu_hb->add_child(help_search); help_search->set_tooltip(TTR("Search the reference documentation.")); @@ -3885,7 +3891,7 @@ ScriptEditor::ScriptEditor() { erase_tab_confirm = memnew(ConfirmationDialog); erase_tab_confirm->set_ok_button_text(TTR("Save")); erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "discard"); - erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab), varray(true)); + erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab).bind(true)); erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab)); add_child(erase_tab_confirm); @@ -3939,8 +3945,8 @@ ScriptEditor::ScriptEditor() { help_search_dialog->connect("go_to_help", callable_mp(this, &ScriptEditor::_help_class_goto)); find_in_files_dialog = memnew(FindInFilesDialog); - find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files), varray(false)); - find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files), varray(true)); + find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files).bind(false)); + find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files).bind(true)); add_child(find_in_files_dialog); find_in_files = memnew(FindInFilesPanel); find_in_files_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Search Results"), find_in_files); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 66cd85a26a..5d5f452390 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1420,7 +1420,9 @@ Control *ScriptTextEditor::get_edit_menu() { } void ScriptTextEditor::clear_edit_menu() { - memdelete(edit_hb); + if (editor_enabled) { + memdelete(edit_hb); + } } void ScriptTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) { @@ -1454,7 +1456,7 @@ void ScriptTextEditor::clear_breakpoints() { void ScriptTextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) { Variant args[1] = { this }; const Variant *argp[] = { &args[0] }; - code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1)); + code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bindp(argp, 1)); } void ScriptTextEditor::set_debugger_active(bool p_active) { @@ -1821,7 +1823,7 @@ void ScriptTextEditor::_enable_code_editor() { VSplitContainer *editor_box = memnew(VSplitContainer); add_child(editor_box); - editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); editor_box->set_v_size_flags(SIZE_EXPAND_FILL); editor_box->add_child(code_editor); @@ -1860,16 +1862,10 @@ void ScriptTextEditor::_enable_code_editor() { color_picker = memnew(ColorPicker); color_picker->set_deferred_mode(true); color_picker->connect("color_changed", callable_mp(this, &ScriptTextEditor::_color_changed)); + color_panel->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(color_picker)); color_panel->add_child(color_picker); - // get default color picker mode from editor settings - int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode"); - color_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode); - - int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); - color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); - quick_open = memnew(ScriptEditorQuickOpen); quick_open->connect("goto_line", callable_mp(this, &ScriptTextEditor::_goto_line)); add_child(quick_open); @@ -1958,7 +1954,7 @@ void ScriptTextEditor::_enable_code_editor() { ScriptTextEditor::ScriptTextEditor() { code_editor = memnew(CodeTextEditor); code_editor->add_theme_constant_override("separation", 2); - code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); code_editor->set_code_complete_func(_code_complete_scripts, this); code_editor->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 85a39b1c9c..e700412188 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -41,10 +41,10 @@ #include "editor/filesystem_dock.h" #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/project_settings_editor.h" -#include "editor/property_editor.h" #include "editor/shader_create_dialog.h" #include "scene/gui/split_container.h" #include "servers/display_server.h" +#include "servers/rendering/shader_preprocessor.h" #include "servers/rendering/shader_types.h" /*** SHADER SCRIPT EDITOR ****/ @@ -72,15 +72,65 @@ Ref<Shader> ShaderTextEditor::get_edited_shader() const { return shader; } +Ref<ShaderInclude> ShaderTextEditor::get_edited_shader_include() const { + return shader_inc; +} + void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { + set_edited_shader(p_shader, p_shader->get_code()); +} + +void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader, const String &p_code) { if (shader == p_shader) { return; } + if (shader.is_valid()) { + shader->disconnect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed)); + } shader = p_shader; + shader_inc = Ref<ShaderInclude>(); + + set_edited_code(p_code); + + if (shader.is_valid()) { + shader->connect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed)); + } +} + +void ShaderTextEditor::set_edited_shader_include(const Ref<ShaderInclude> &p_shader_inc) { + set_edited_shader_include(p_shader_inc, p_shader_inc->get_code()); +} + +void ShaderTextEditor::_shader_changed() { + // This function is used for dependencies (include changing changes main shader and forces it to revalidate) + if (block_shader_changed) { + return; + } + dependencies_version++; + _validate_script(); +} + +void ShaderTextEditor::set_edited_shader_include(const Ref<ShaderInclude> &p_shader_inc, const String &p_code) { + if (shader_inc == p_shader_inc) { + return; + } + if (shader_inc.is_valid()) { + shader_inc->disconnect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed)); + } + shader_inc = p_shader_inc; + shader = Ref<Shader>(); + + set_edited_code(p_code); + + if (shader_inc.is_valid()) { + shader_inc->connect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed)); + } +} +void ShaderTextEditor::set_edited_code(const String &p_code) { _load_theme_settings(); - get_text_editor()->set_text(p_shader->get_code()); + get_text_editor()->set_text(p_code); get_text_editor()->clear_undo_history(); get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0); get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0); @@ -132,11 +182,12 @@ void ShaderTextEditor::_load_theme_settings() { syntax_highlighter->clear_keyword_colors(); - List<String> keywords; - ShaderLanguage::get_keyword_list(&keywords); const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); + List<String> keywords; + ShaderLanguage::get_keyword_list(&keywords); + for (const String &E : keywords) { if (ShaderLanguage::is_control_flow_keyword(E)) { syntax_highlighter->add_keyword_color(E, control_flow_keyword_color); @@ -145,11 +196,41 @@ void ShaderTextEditor::_load_theme_settings() { } } + List<String> pp_keywords; + ShaderPreprocessor::get_keyword_list(&pp_keywords, false); + + for (const String &E : pp_keywords) { + syntax_highlighter->add_keyword_color(E, keyword_color); + } + // Colorize built-ins like `COLOR` differently to make them easier // to distinguish from keywords at a quick glance. List<String> built_ins; - if (shader.is_valid()) { + + if (shader_inc.is_valid()) { + for (int i = 0; i < RenderingServer::SHADER_MAX; i++) { + for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) { + for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) { + built_ins.push_back(F.key); + } + } + + const Vector<ShaderLanguage::ModeInfo> &modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i)); + + for (int j = 0; j < modes.size(); j++) { + const ShaderLanguage::ModeInfo &info = modes[j]; + + if (!info.options.is_empty()) { + for (int k = 0; k < info.options.size(); k++) { + built_ins.push_back(String(info.name) + "_" + String(info.options[k])); + } + } else { + built_ins.push_back(String(info.name)); + } + } + } + } else if (shader.is_valid()) { for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()))) { for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) { built_ins.push_back(F.key); @@ -191,8 +272,12 @@ void ShaderTextEditor::_load_theme_settings() { text_editor->add_auto_brace_completion_pair("/*", "*/"); } + // Colorize preprocessor include strings. + const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color"); + syntax_highlighter->add_color_region("\"", "\"", string_color, false); + if (warnings_panel) { - // Warnings panel + // Warnings panel. warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts"))); warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"))); } @@ -216,82 +301,204 @@ void ShaderTextEditor::_check_shader_mode() { } if (shader->get_mode() != mode) { + set_block_shader_changed(true); shader->set_code(get_text_editor()->get_text()); + set_block_shader_changed(false); _load_theme_settings(); } } -static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) { - RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable); - return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt); +static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) { + RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable); + return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); +} + +static String complete_from_path; + +static void _complete_include_paths_search(EditorFileSystemDirectory *p_efsd, List<ScriptLanguage::CodeCompletionOption> *r_options) { + if (!p_efsd) { + return; + } + for (int i = 0; i < p_efsd->get_file_count(); i++) { + if (p_efsd->get_file_type(i) == SNAME("ShaderInclude")) { + String path = p_efsd->get_file_path(i); + if (path.begins_with(complete_from_path)) { + path = path.replace_first(complete_from_path, ""); + } + r_options->push_back(ScriptLanguage::CodeCompletionOption(path, ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH)); + } + } + for (int j = 0; j < p_efsd->get_subdir_count(); j++) { + _complete_include_paths_search(p_efsd->get_subdir(j), r_options); + } +} + +static void _complete_include_paths(List<ScriptLanguage::CodeCompletionOption> *r_options) { + _complete_include_paths_search(EditorFileSystem::get_singleton()->get_filesystem(), r_options); } void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLanguage::CodeCompletionOption> *r_options) { - _check_shader_mode(); + List<ScriptLanguage::CodeCompletionOption> pp_options; + ShaderPreprocessor preprocessor; + String code; + complete_from_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path()).get_base_dir(); + if (!complete_from_path.ends_with("/")) { + complete_from_path += "/"; + } + preprocessor.preprocess(p_code, code, nullptr, nullptr, nullptr, &pp_options, _complete_include_paths); + complete_from_path = String(); + if (pp_options.size()) { + for (const ScriptLanguage::CodeCompletionOption &E : pp_options) { + r_options->push_back(E); + } + return; + } ShaderLanguage sl; String calltip; - ShaderLanguage::ShaderCompileInfo info; + info.global_shader_uniform_type_func = _get_global_shader_uniform_type; + + if (shader.is_null()) { + info.is_include = true; + + sl.complete(code, info, r_options, calltip); + get_text_editor()->set_code_hint(calltip); + return; + } + _check_shader_mode(); info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())); info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())); info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_variable_type_func = _get_global_variable_type; - - sl.complete(p_code, info, r_options, calltip); + sl.complete(code, info, r_options, calltip); get_text_editor()->set_code_hint(calltip); } void ShaderTextEditor::_validate_script() { - _check_shader_mode(); + emit_signal(SNAME("script_changed")); // Ensure to notify that it changed, so it is applied - String code = get_text_editor()->get_text(); - //List<StringName> params; - //shader->get_param_list(¶ms); + String code; - ShaderLanguage::ShaderCompileInfo info; - info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())); - info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())); - info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_variable_type_func = _get_global_variable_type; - - ShaderLanguage sl; + if (shader.is_valid()) { + _check_shader_mode(); + code = shader->get_code(); + } else { + code = shader_inc->get_code(); + } - sl.enable_warning_checking(saved_warnings_enabled); - sl.set_warning_flags(saved_warning_flags); + ShaderPreprocessor preprocessor; + String code_pp; + String error_pp; + List<ShaderPreprocessor::FilePosition> err_positions; + last_compile_result = preprocessor.preprocess(code, code_pp, &error_pp, &err_positions); - last_compile_result = sl.compile(code, info); + for (int i = 0; i < get_text_editor()->get_line_count(); i++) { + get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0)); + } + set_error(""); + set_error_count(0); if (last_compile_result != OK) { - String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); + //preprocessor error + ERR_FAIL_COND(err_positions.size() == 0); + + String error_text = error_pp; + int error_line = err_positions.front()->get().line; + if (err_positions.size() == 1) { + // Error in main file + error_text = "error(" + itos(error_line) + "): " + error_text; + } else { + error_text = "error(" + itos(error_line) + ") in include " + err_positions.back()->get().file.get_file() + ":" + itos(err_positions.back()->get().line) + ": " + error_text; + set_error_count(err_positions.size() - 1); + } + set_error(error_text); - set_error_pos(sl.get_error_line() - 1, 0); + set_error_pos(error_line - 1, 0); for (int i = 0; i < get_text_editor()->get_line_count(); i++) { get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0)); } - get_text_editor()->set_line_background_color(sl.get_error_line() - 1, marked_line_color); + get_text_editor()->set_line_background_color(error_line - 1, marked_line_color); + + set_warning_count(0); + } else { - for (int i = 0; i < get_text_editor()->get_line_count(); i++) { - get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0)); + ShaderLanguage sl; + + sl.enable_warning_checking(saved_warnings_enabled); + uint32_t flags = saved_warning_flags; + if (shader.is_null()) { + if (flags & ShaderWarning::UNUSED_CONSTANT) { + flags &= ~(ShaderWarning::UNUSED_CONSTANT); + } + if (flags & ShaderWarning::UNUSED_FUNCTION) { + flags &= ~(ShaderWarning::UNUSED_FUNCTION); + } + if (flags & ShaderWarning::UNUSED_STRUCT) { + flags &= ~(ShaderWarning::UNUSED_STRUCT); + } + if (flags & ShaderWarning::UNUSED_UNIFORM) { + flags &= ~(ShaderWarning::UNUSED_UNIFORM); + } + if (flags & ShaderWarning::UNUSED_VARYING) { + flags &= ~(ShaderWarning::UNUSED_VARYING); + } } - set_error(""); - } + sl.set_warning_flags(flags); - if (warnings.size() > 0 || last_compile_result != OK) { - warnings_panel->clear(); - } - warnings.clear(); - for (List<ShaderWarning>::Element *E = sl.get_warnings_ptr(); E; E = E->next()) { - warnings.push_back(E->get()); - } - if (warnings.size() > 0 && last_compile_result == OK) { - warnings.sort_custom<WarningsComparator>(); - _update_warning_panel(); - } else { - set_warning_count(0); + ShaderLanguage::ShaderCompileInfo info; + info.global_shader_uniform_type_func = _get_global_shader_uniform_type; + + if (shader.is_null()) { + info.is_include = true; + } else { + Shader::Mode mode = shader->get_mode(); + info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(mode)); + info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(mode)); + info.shader_types = ShaderTypes::get_singleton()->get_types(); + } + + code = code_pp; + //compiler error + last_compile_result = sl.compile(code, info); + + if (last_compile_result != OK) { + String error_text; + int error_line; + Vector<ShaderLanguage::FilePosition> include_positions = sl.get_include_positions(); + if (include_positions.size() > 1) { + //error is in an include + error_line = include_positions[0].line; + error_text = "error(" + itos(error_line) + ") in include " + include_positions[include_positions.size() - 1].file + ":" + itos(include_positions[include_positions.size() - 1].line) + ": " + sl.get_error_text(); + set_error_count(include_positions.size() - 1); + } else { + error_line = sl.get_error_line(); + error_text = "error(" + itos(error_line) + "): " + sl.get_error_text(); + set_error_count(0); + } + set_error(error_text); + set_error_pos(error_line - 1, 0); + get_text_editor()->set_line_background_color(error_line - 1, marked_line_color); + } else { + set_error(""); + } + + if (warnings.size() > 0 || last_compile_result != OK) { + warnings_panel->clear(); + } + warnings.clear(); + for (List<ShaderWarning>::Element *E = sl.get_warnings_ptr(); E; E = E->next()) { + warnings.push_back(E->get()); + } + if (warnings.size() > 0 && last_compile_result == OK) { + warnings.sort_custom<WarningsComparator>(); + _update_warning_panel(); + } else { + set_warning_count(0); + } } - emit_signal(SNAME("script_changed")); + + emit_signal(SNAME("script_validated"), last_compile_result == OK); // Notify that validation finished, to update the list of scripts } void ShaderTextEditor::_update_warning_panel() { @@ -338,6 +545,7 @@ void ShaderTextEditor::_update_warning_panel() { } void ShaderTextEditor::_bind_methods() { + ADD_SIGNAL(MethodInfo("script_validated", PropertyInfo(Variant::BOOL, "valid"))); } ShaderTextEditor::ShaderTextEditor() { @@ -473,6 +681,8 @@ void ShaderEditor::_warning_clicked(Variant p_line) { void ShaderEditor::_bind_methods() { ClassDB::bind_method("_show_warnings_panel", &ShaderEditor::_show_warnings_panel); ClassDB::bind_method("_warning_clicked", &ShaderEditor::_warning_clicked); + + ADD_SIGNAL(MethodInfo("validation_changed")); } void ShaderEditor::ensure_select_current() { @@ -524,15 +734,23 @@ void ShaderEditor::_update_warnings(bool p_validate) { } void ShaderEditor::_check_for_external_edit() { - if (shader.is_null() || !shader.is_valid()) { + bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change")); + + if (shader_inc.is_valid()) { + if (shader_inc->get_last_modified_time() != FileAccess::get_modified_time(shader_inc->get_path())) { + if (use_autoreload) { + _reload_shader_include_from_disk(); + } else { + disk_changed->call_deferred(SNAME("popup_centered")); + } + } return; } - if (shader->is_built_in()) { + if (shader.is_null() || shader->is_built_in()) { return; } - bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change")); if (shader->get_last_modified_time() != FileAccess::get_modified_time(shader->get_path())) { if (use_autoreload) { _reload_shader_from_disk(); @@ -546,11 +764,32 @@ void ShaderEditor::_reload_shader_from_disk() { Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE); ERR_FAIL_COND(!rel_shader.is_valid()); + shader_editor->set_block_shader_changed(true); shader->set_code(rel_shader->get_code()); + shader_editor->set_block_shader_changed(false); shader->set_last_modified_time(rel_shader->get_last_modified_time()); shader_editor->reload_text(); } +void ShaderEditor::_reload_shader_include_from_disk() { + Ref<ShaderInclude> rel_shader_include = ResourceLoader::load(shader_inc->get_path(), shader_inc->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE); + ERR_FAIL_COND(!rel_shader_include.is_valid()); + + shader_editor->set_block_shader_changed(true); + shader_inc->set_code(rel_shader_include->get_code()); + shader_editor->set_block_shader_changed(false); + shader_inc->set_last_modified_time(rel_shader_include->get_last_modified_time()); + shader_editor->reload_text(); +} + +void ShaderEditor::_reload() { + if (shader.is_valid()) { + _reload_shader_from_disk(); + } else if (shader_inc.is_valid()) { + _reload_shader_include_from_disk(); + } +} + void ShaderEditor::edit(const Ref<Shader> &p_shader) { if (p_shader.is_null() || !p_shader->is_text_shader()) { return; @@ -561,37 +800,79 @@ void ShaderEditor::edit(const Ref<Shader> &p_shader) { } shader = p_shader; + shader_inc = Ref<ShaderInclude>(); + + shader_editor->set_edited_shader(shader); +} + +void ShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) { + if (p_shader_inc.is_null()) { + return; + } + + if (shader_inc == p_shader_inc) { + return; + } - shader_editor->set_edited_shader(p_shader); + shader_inc = p_shader_inc; + shader = Ref<Shader>(); - //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); - // see if already has it + shader_editor->set_edited_shader_include(p_shader_inc); } void ShaderEditor::save_external_data(const String &p_str) { - if (shader.is_null()) { + if (shader.is_null() && shader_inc.is_null()) { disk_changed->hide(); return; } apply_shaders(); - if (!shader->is_built_in()) { - //external shader, save it - ResourceSaver::save(shader->get_path(), shader); + + Ref<Shader> edited_shader = shader_editor->get_edited_shader(); + if (edited_shader.is_valid()) { + ResourceSaver::save(edited_shader); + } + if (shader.is_valid() && shader != edited_shader) { + ResourceSaver::save(shader); + } + + Ref<ShaderInclude> edited_shader_inc = shader_editor->get_edited_shader_include(); + if (edited_shader_inc.is_valid()) { + ResourceSaver::save(edited_shader_inc); + } + if (shader_inc.is_valid() && shader_inc != edited_shader_inc) { + ResourceSaver::save(shader_inc); } disk_changed->hide(); } +void ShaderEditor::validate_script() { + shader_editor->_validate_script(); +} + void ShaderEditor::apply_shaders() { + String editor_code = shader_editor->get_text_editor()->get_text(); if (shader.is_valid()) { String shader_code = shader->get_code(); - String editor_code = shader_editor->get_text_editor()->get_text(); - if (shader_code != editor_code) { + if (shader_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) { + shader_editor->set_block_shader_changed(true); shader->set_code(editor_code); + shader_editor->set_block_shader_changed(false); shader->set_edited(true); } } + if (shader_inc.is_valid()) { + String shader_inc_code = shader_inc->get_code(); + if (shader_inc_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) { + shader_editor->set_block_shader_changed(true); + shader_inc->set_code(editor_code); + shader_editor->set_block_shader_changed(false); + shader_inc->set_edited(true); + } + } + + dependencies_version = shader_editor->get_dependencies_version(); } void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { @@ -704,9 +985,12 @@ ShaderEditor::ShaderEditor() { _update_warnings(false); shader_editor = memnew(ShaderTextEditor); + + shader_editor->connect("script_validated", callable_mp(this, &ShaderEditor::_script_validated)); + shader_editor->set_v_size_flags(SIZE_EXPAND_FILL); shader_editor->add_theme_constant_override("separation", 0); - shader_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + shader_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); shader_editor->connect("show_warnings_panel", callable_mp(this, &ShaderEditor::_show_warnings_panel)); shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders)); @@ -797,7 +1081,7 @@ ShaderEditor::ShaderEditor() { VSplitContainer *editor_box = memnew(VSplitContainer); main_container->add_child(editor_box); - editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); editor_box->set_v_size_flags(SIZE_EXPAND_FILL); editor_box->add_child(shader_editor); @@ -829,7 +1113,7 @@ ShaderEditor::ShaderEditor() { dl->set_text(TTR("This shader has been modified on disk.\nWhat action should be taken?")); vbc->add_child(dl); - disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk)); + disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload)); disk_changed->set_ok_button_text(TTR("Reload")); disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); @@ -844,19 +1128,37 @@ void ShaderEditorPlugin::_update_shader_list() { shader_list->clear(); for (uint32_t i = 0; i < edited_shaders.size(); i++) { String text; - String path = edited_shaders[i].shader->get_path(); - String _class = edited_shaders[i].shader->get_class(); + String path; + String _class; + String shader_name; + if (edited_shaders[i].shader.is_valid()) { + Ref<Shader> shader = edited_shaders[i].shader; + + path = shader->get_path(); + _class = shader->get_class(); + shader_name = shader->get_name(); + } else { + Ref<ShaderInclude> shader_inc = edited_shaders[i].shader_inc; + + path = shader_inc->get_path(); + _class = shader_inc->get_class(); + shader_name = shader_inc->get_name(); + } if (path.is_resource_file()) { text = path.get_file(); - } else if (edited_shaders[i].shader->get_name() != "") { - text = edited_shaders[i].shader->get_name(); + } else if (shader_name != "") { + text = shader_name; } else { - text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id()); + if (edited_shaders[i].shader.is_valid()) { + text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id()); + } else { + text = _class + ":" + itos(edited_shaders[i].shader_inc->get_instance_id()); + } } if (!shader_list->has_theme_icon(_class, SNAME("EditorIcons"))) { - _class = "Resource"; + _class = "TextFile"; } Ref<Texture2D> icon = shader_list->get_theme_icon(_class, SNAME("EditorIcons")); @@ -871,38 +1173,70 @@ void ShaderEditorPlugin::_update_shader_list() { for (int i = 1; i < FILE_MAX; i++) { file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.size() == 0); } + + _update_shader_list_status(); } -void ShaderEditorPlugin::edit(Object *p_object) { - Shader *s = Object::cast_to<Shader>(p_object); - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader.ptr() == s) { - // Exists, select. - shader_tabs->set_current_tab(i); - shader_list->select(i); - return; +void ShaderEditorPlugin::_update_shader_list_status() { + for (int i = 0; i < shader_list->get_item_count(); i++) { + ShaderEditor *se = Object::cast_to<ShaderEditor>(shader_tabs->get_tab_control(i)); + if (se) { + if (se->was_compilation_successful()) { + shader_list->set_item_tag_icon(i, Ref<Texture2D>()); + } else { + shader_list->set_item_tag_icon(i, shader_list->get_theme_icon(SNAME("Error"), SNAME("EditorIcons"))); + } } } - // Add. +} + +void ShaderEditorPlugin::edit(Object *p_object) { EditedShader es; - es.shader = Ref<Shader>(s); - Ref<VisualShader> vs = es.shader; - if (vs.is_valid()) { - es.visual_shader_editor = memnew(VisualShaderEditor); - es.visual_shader_editor->edit(vs.ptr()); - shader_tabs->add_child(es.visual_shader_editor); - } else { + + ShaderInclude *si = Object::cast_to<ShaderInclude>(p_object); + if (si != nullptr) { + for (uint32_t i = 0; i < edited_shaders.size(); i++) { + if (edited_shaders[i].shader_inc.ptr() == si) { + shader_tabs->set_current_tab(i); + shader_list->select(i); + return; + } + } + es.shader_inc = Ref<ShaderInclude>(si); es.shader_editor = memnew(ShaderEditor); - es.shader_editor->edit(s); + es.shader_editor->edit(si); shader_tabs->add_child(es.shader_editor); + es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status)); + } else { + Shader *s = Object::cast_to<Shader>(p_object); + for (uint32_t i = 0; i < edited_shaders.size(); i++) { + if (edited_shaders[i].shader.ptr() == s) { + shader_tabs->set_current_tab(i); + shader_list->select(i); + return; + } + } + es.shader = Ref<Shader>(s); + Ref<VisualShader> vs = es.shader; + if (vs.is_valid()) { + es.visual_shader_editor = memnew(VisualShaderEditor); + shader_tabs->add_child(es.visual_shader_editor); + es.visual_shader_editor->edit(vs.ptr()); + } else { + es.shader_editor = memnew(ShaderEditor); + shader_tabs->add_child(es.shader_editor); + es.shader_editor->edit(s); + es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status)); + } } + shader_tabs->set_current_tab(shader_tabs->get_tab_count() - 1); edited_shaders.push_back(es); _update_shader_list(); } bool ShaderEditorPlugin::handles(Object *p_object) const { - return Object::cast_to<Shader>(p_object) != nullptr; + return Object::cast_to<Shader>(p_object) != nullptr || Object::cast_to<ShaderInclude>(p_object) != nullptr; } void ShaderEditorPlugin::make_visible(bool p_visible) { @@ -923,6 +1257,15 @@ ShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_sha return nullptr; } +VisualShaderEditor *ShaderEditorPlugin::get_visual_shader_editor(const Ref<Shader> &p_for_shader) { + for (uint32_t i = 0; i < edited_shaders.size(); i++) { + if (edited_shaders[i].shader == p_for_shader) { + return edited_shaders[i].visual_shader_editor; + } + } + return nullptr; +} + void ShaderEditorPlugin::save_external_data() { for (uint32_t i = 0; i < edited_shaders.size(); i++) { if (edited_shaders[i].shader_editor) { @@ -940,6 +1283,9 @@ void ShaderEditorPlugin::apply_changes() { } void ShaderEditorPlugin::_shader_selected(int p_index) { + if (edited_shaders[p_index].shader_editor) { + edited_shaders[p_index].shader_editor->validate_script(); + } shader_tabs->set_current_tab(p_index); } @@ -950,6 +1296,7 @@ void ShaderEditorPlugin::_close_shader(int p_index) { memdelete(c); edited_shaders.remove_at(index); _update_shader_list(); + EditorNode::get_singleton()->get_undo_redo()->clear_history(); // To prevent undo on deleted graphs. } void ShaderEditorPlugin::_resource_saved(Object *obj) { @@ -965,31 +1312,56 @@ void ShaderEditorPlugin::_resource_saved(Object *obj) { void ShaderEditorPlugin::_menu_item_pressed(int p_index) { switch (p_index) { case FILE_NEW: { - String base_path = FileSystemDock::get_singleton()->get_current_path(); + String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir(); shader_create_dialog->config(base_path.plus_file("new_shader"), false, false, 0); shader_create_dialog->popup_centered(); } break; + case FILE_NEW_INCLUDE: { + String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir(); + shader_create_dialog->config(base_path.plus_file("new_shader"), false, false, 2); + shader_create_dialog->popup_centered(); + } break; case FILE_OPEN: { InspectorDock::get_singleton()->open_resource("Shader"); } break; + case FILE_OPEN_INCLUDE: { + InspectorDock::get_singleton()->open_resource("ShaderInclude"); + } break; case FILE_SAVE: { int index = shader_tabs->get_current_tab(); ERR_FAIL_INDEX(index, shader_tabs->get_tab_count()); - EditorNode::get_singleton()->save_resource(edited_shaders[index].shader); + if (edited_shaders[index].shader.is_valid()) { + EditorNode::get_singleton()->save_resource(edited_shaders[index].shader); + } else { + EditorNode::get_singleton()->save_resource(edited_shaders[index].shader_inc); + } } break; case FILE_SAVE_AS: { int index = shader_tabs->get_current_tab(); ERR_FAIL_INDEX(index, shader_tabs->get_tab_count()); - String path = edited_shaders[index].shader->get_path(); - if (!path.is_resource_file()) { - path = ""; + String path; + if (edited_shaders[index].shader.is_valid()) { + path = edited_shaders[index].shader->get_path(); + if (!path.is_resource_file()) { + path = ""; + } + EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader, path); + } else { + path = edited_shaders[index].shader_inc->get_path(); + if (!path.is_resource_file()) { + path = ""; + } + EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader_inc, path); } - EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader, path); } break; case FILE_INSPECT: { int index = shader_tabs->get_current_tab(); ERR_FAIL_INDEX(index, shader_tabs->get_tab_count()); - EditorNode::get_singleton()->push_item(edited_shaders[index].shader.ptr()); + if (edited_shaders[index].shader.is_valid()) { + EditorNode::get_singleton()->push_item(edited_shaders[index].shader.ptr()); + } else { + EditorNode::get_singleton()->push_item(edited_shaders[index].shader_inc.ptr()); + } } break; case FILE_CLOSE: { _close_shader(shader_tabs->get_current_tab()); @@ -1001,6 +1373,10 @@ void ShaderEditorPlugin::_shader_created(Ref<Shader> p_shader) { EditorNode::get_singleton()->push_item(p_shader.ptr()); } +void ShaderEditorPlugin::_shader_include_created(Ref<ShaderInclude> p_shader_inc) { + EditorNode::get_singleton()->push_item(p_shader_inc.ptr()); +} + ShaderEditorPlugin::ShaderEditorPlugin() { main_split = memnew(HSplitContainer); @@ -1011,18 +1387,20 @@ ShaderEditorPlugin::ShaderEditorPlugin() { file_menu = memnew(MenuButton); file_menu->set_text(TTR("File")); file_menu->get_popup()->add_item(TTR("New Shader"), FILE_NEW); + file_menu->get_popup()->add_item(TTR("New Shader Include"), FILE_NEW_INCLUDE); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_item(TTR("Load Shader"), FILE_OPEN); - file_menu->get_popup()->add_item(TTR("Save Shader"), FILE_SAVE); - file_menu->get_popup()->add_item(TTR("Save Shader As"), FILE_SAVE_AS); + file_menu->get_popup()->add_item(TTR("Load Shader File"), FILE_OPEN); + file_menu->get_popup()->add_item(TTR("Load Shader Include File"), FILE_OPEN_INCLUDE); + file_menu->get_popup()->add_item(TTR("Save File"), FILE_SAVE); + file_menu->get_popup()->add_item(TTR("Save File As"), FILE_SAVE_AS); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_item(TTR("Open Shader in Inspector"), FILE_INSPECT); + file_menu->get_popup()->add_item(TTR("Open File in Inspector"), FILE_INSPECT); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_item(TTR("Close Shader"), FILE_CLOSE); + file_menu->get_popup()->add_item(TTR("Close File"), FILE_CLOSE); file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed)); file_hb->add_child(file_menu); - for (int i = 1; i < FILE_MAX; i++) { + for (int i = 2; i < FILE_MAX; i++) { file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), true); } @@ -1045,11 +1423,12 @@ ShaderEditorPlugin::ShaderEditorPlugin() { button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Shader Editor"), main_split); // Defer connect because Editor class is not in the binding system yet. - EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), varray(), CONNECT_DEFERRED); + EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), CONNECT_DEFERRED); shader_create_dialog = memnew(ShaderCreateDialog); vb->add_child(shader_create_dialog); shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created)); + shader_create_dialog->connect("shader_include_created", callable_mp(this, &ShaderEditorPlugin::_shader_include_created)); } ShaderEditorPlugin::~ShaderEditorPlugin() { diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index e1e815f939..907de6ea87 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -40,6 +40,7 @@ #include "scene/gui/text_edit.h" #include "scene/main/timer.h" #include "scene/resources/shader.h" +#include "scene/resources/shader_include.h" #include "servers/rendering/shader_warnings.h" class ItemList; @@ -59,12 +60,18 @@ class ShaderTextEditor : public CodeTextEditor { Ref<CodeHighlighter> syntax_highlighter; RichTextLabel *warnings_panel = nullptr; Ref<Shader> shader; + Ref<ShaderInclude> shader_inc; List<ShaderWarning> warnings; Error last_compile_result = Error::OK; void _check_shader_mode(); void _update_warning_panel(); + bool block_shader_changed = false; + void _shader_changed(); + + uint32_t dependencies_version = 0; // Incremented if deps changed + protected: void _notification(int p_what); static void _bind_methods(); @@ -73,13 +80,23 @@ protected: virtual void _code_complete_script(const String &p_code, List<ScriptLanguage::CodeCompletionOption> *r_options) override; public: + void set_block_shader_changed(bool p_block) { block_shader_changed = p_block; } + uint32_t get_dependencies_version() const { return dependencies_version; } + virtual void _validate_script() override; void reload_text(); void set_warnings_panel(RichTextLabel *p_warnings_panel); Ref<Shader> get_edited_shader() const; + Ref<ShaderInclude> get_edited_shader_include() const; + void set_edited_shader(const Ref<Shader> &p_shader); + void set_edited_shader(const Ref<Shader> &p_shader, const String &p_code); + void set_edited_shader_include(const Ref<ShaderInclude> &p_include); + void set_edited_shader_include(const Ref<ShaderInclude> &p_include, const String &p_code); + void set_edited_code(const String &p_code); + ShaderTextEditor(); }; @@ -126,38 +143,50 @@ class ShaderEditor : public PanelContainer { ConfirmationDialog *disk_changed = nullptr; ShaderTextEditor *shader_editor = nullptr; + bool compilation_success = true; void _menu_option(int p_option); mutable Ref<Shader> shader; + mutable Ref<ShaderInclude> shader_inc; void _editor_settings_changed(); void _project_settings_changed(); void _check_for_external_edit(); void _reload_shader_from_disk(); + void _reload_shader_include_from_disk(); + void _reload(); void _show_warnings_panel(bool p_show); void _warning_clicked(Variant p_line); void _update_warnings(bool p_validate); + void _script_validated(bool p_valid) { + compilation_success = p_valid; + emit_signal(SNAME("validation_changed")); + } + + uint32_t dependencies_version = 0xFFFFFFFF; + protected: void _notification(int p_what); static void _bind_methods(); void _make_context_menu(bool p_selection, Vector2 p_position); - void _text_edit_gui_input(const Ref<InputEvent> &ev); + void _text_edit_gui_input(const Ref<InputEvent> &p_ev); void _update_bookmark_list(); void _bookmark_item_pressed(int p_idx); public: + bool was_compilation_successful() const { return compilation_success; } void apply_shaders(); - void ensure_select_current(); void edit(const Ref<Shader> &p_shader); - + void edit(const Ref<ShaderInclude> &p_shader_inc); void goto_line_selection(int p_line, int p_begin, int p_end); + void save_external_data(const String &p_str = ""); + void validate_script(); virtual Size2 get_minimum_size() const override { return Size2(0, 200); } - void save_external_data(const String &p_str = ""); ShaderEditor(); }; @@ -167,6 +196,7 @@ class ShaderEditorPlugin : public EditorPlugin { struct EditedShader { Ref<Shader> shader; + Ref<ShaderInclude> shader_inc; ShaderEditor *shader_editor = nullptr; VisualShaderEditor *visual_shader_editor = nullptr; }; @@ -175,7 +205,9 @@ class ShaderEditorPlugin : public EditorPlugin { enum { FILE_NEW, + FILE_NEW_INCLUDE, FILE_OPEN, + FILE_OPEN_INCLUDE, FILE_SAVE, FILE_SAVE_AS, FILE_INSPECT, @@ -199,6 +231,8 @@ class ShaderEditorPlugin : public EditorPlugin { void _close_shader(int p_index); void _shader_created(Ref<Shader> p_shader); + void _shader_include_created(Ref<ShaderInclude> p_shader_inc); + void _update_shader_list_status(); public: virtual String get_name() const override { return "Shader"; } @@ -209,6 +243,7 @@ public: virtual void selected_notify() override; ShaderEditor *get_shader_editor(const Ref<Shader> &p_for_shader); + VisualShaderEditor *get_visual_shader_editor(const Ref<Shader> &p_for_shader); virtual void save_external_data() override; virtual void apply_changes() override; @@ -217,4 +252,4 @@ public: ~ShaderEditorPlugin(); }; -#endif +#endif // SHADER_EDITOR_PLUGIN_H diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 4458555de2..4874944d33 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -37,7 +37,6 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "editor/property_editor.h" #include "servers/display_server.h" #include "servers/rendering/shader_types.h" @@ -282,7 +281,7 @@ ShaderFileEditor::ShaderFileEditor() { stage_hb->add_child(button); stages[i] = button; button->set_button_group(bg); - button->connect("pressed", callable_mp(this, &ShaderFileEditor::_version_selected), varray(i)); + button->connect("pressed", callable_mp(this, &ShaderFileEditor::_version_selected).bind(i)); } error_text = memnew(RichTextLabel); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 8845fe9eca..c453ed26aa 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -42,6 +42,7 @@ #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/skeleton_profile.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" @@ -156,7 +157,7 @@ void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) if (split.size() == 3 && split[0] == "bones") { int bone_idx = split[1].to_int(); if (split[2] == "position") { - te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, skeleton->get(p_path)); + te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, (Vector3)skeleton->get(p_path) / skeleton->get_motion_scale()); } if (split[2] == "rotation") { te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_ROTATION_3D, skeleton->get(p_path)); @@ -250,6 +251,10 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) { create_physical_skeleton(); break; } + case SKELETON_OPTION_EXPORT_SKELETON_PROFILE: { + export_skeleton_profile(); + break; + } } } @@ -314,7 +319,7 @@ void Skeleton3DEditor::insert_keys(const bool p_all_bones) { } if (pos_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_POSITION_3D))) { - te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i)); + te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i) / skeleton->get_motion_scale()); } if (rot_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_ROTATION_3D))) { te->insert_transform_key(skeleton, name, Animation::TYPE_ROTATION_3D, skeleton->get_bone_pose_rotation(i)); @@ -451,6 +456,73 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi return physical_bone; } +void Skeleton3DEditor::export_skeleton_profile() { + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + file_dialog->set_title(TTR("Export Skeleton Profile As...")); + + List<String> exts; + ResourceLoader::get_recognized_extensions_for_type("SkeletonProfile", &exts); + file_dialog->clear_filters(); + for (const String &K : exts) { + file_dialog->add_filter("*." + K); + } + + file_dialog->popup_file_dialog(); +} + +void Skeleton3DEditor::_file_selected(const String &p_file) { + // Export SkeletonProfile. + Ref<SkeletonProfile> sp(memnew(SkeletonProfile)); + + // Build SkeletonProfile. + sp->set_group_size(1); + + Vector<Vector2> handle_positions; + Vector2 position_max; + Vector2 position_min; + + int len = skeleton->get_bone_count(); + sp->set_bone_size(len); + for (int i = 0; i < len; i++) { + sp->set_bone_name(i, skeleton->get_bone_name(i)); + int parent = skeleton->get_bone_parent(i); + if (parent >= 0) { + sp->set_bone_parent(i, skeleton->get_bone_name(parent)); + } + sp->set_reference_pose(i, skeleton->get_bone_rest(i)); + + Transform3D grest = skeleton->get_bone_global_rest(i); + handle_positions.append(Vector2(grest.origin.x, grest.origin.y)); + if (i == 0) { + position_max = Vector2(grest.origin.x, grest.origin.y); + position_min = Vector2(grest.origin.x, grest.origin.y); + } else { + position_max.x = MAX(grest.origin.x, position_max.x); + position_max.y = MAX(grest.origin.y, position_max.y); + position_min.x = MIN(grest.origin.x, position_min.x); + position_min.y = MIN(grest.origin.y, position_min.y); + } + } + + // Layout handles provisionaly. + Vector2 bound = Vector2(position_max.x - position_min.x, position_max.y - position_min.y); + Vector2 center = Vector2((position_max.x + position_min.x) * 0.5, (position_max.y + position_min.y) * 0.5); + float nrm = MAX(bound.x, bound.y); + if (nrm > 0) { + for (int i = 0; i < len; i++) { + handle_positions.write[i] = (handle_positions[i] - center) / nrm * 0.9; + sp->set_handle_offset(i, Vector2(0.5 + handle_positions[i].x, 0.5 - handle_positions[i].y)); + } + } + + Error err = ResourceSaver::save(sp, p_file); + + if (err != OK) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_file)); + return; + } +} + Variant Skeleton3DEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { TreeItem *selected = joint_tree->get_selected(); @@ -631,6 +703,11 @@ void Skeleton3DEditor::create_editors() { Node3DEditor *ne = Node3DEditor::get_singleton(); AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor(); + // Create File dialog. + file_dialog = memnew(EditorFileDialog); + file_dialog->connect("file_selected", callable_mp(this, &Skeleton3DEditor::_file_selected)); + add_child(file_dialog); + // Create Top Menu Bar. separator = memnew(VSeparator); ne->add_control_to_menu_panel(separator); @@ -649,6 +726,7 @@ void Skeleton3DEditor::create_editors() { p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS); p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS); p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON); + p->add_item(TTR("Export skeleton profile"), SKELETON_OPTION_EXPORT_SKELETON_PROFILE); p->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option)); set_bone_options_enabled(false); @@ -704,7 +782,7 @@ void Skeleton3DEditor::create_editors() { key_insert_button = memnew(Button); key_insert_button->set_flat(true); key_insert_button->set_focus_mode(FOCUS_NONE); - key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(false)); + key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false)); key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track.")); key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), Key::INSERT)); animation_hb->add_child(key_insert_button); @@ -712,7 +790,7 @@ void Skeleton3DEditor::create_editors() { key_insert_all_button = memnew(Button); key_insert_all_button->set_flat(true); key_insert_all_button->set_focus_mode(FOCUS_NONE); - key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(true)); + key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true)); key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses.")); key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD + Key::INSERT)); animation_hb->add_child(key_insert_all_button); @@ -758,7 +836,7 @@ void Skeleton3DEditor::_notification(int p_what) { key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons"))); key_insert_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons"))); key_insert_all_button->set_icon(get_theme_icon(SNAME("NewKey"), SNAME("EditorIcons"))); - get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT); + get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONESHOT); break; } case NOTIFICATION_ENTER_TREE: { @@ -843,8 +921,8 @@ void fragment() { )"); handle_material->set_shader(handle_shader); Ref<Texture2D> handle = EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("EditorBoneHandle"), SNAME("EditorIcons")); - handle_material->set_shader_param("point_size", handle->get_width()); - handle_material->set_shader_param("texture_albedo", handle); + handle_material->set_shader_uniform("point_size", handle->get_width()); + handle_material->set_shader_uniform("texture_albedo", handle); handles_mesh_instance = memnew(MeshInstance3D); handles_mesh_instance->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF); diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 8f03e7c8db..975b54fa77 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -101,6 +101,7 @@ class Skeleton3DEditor : public VBoxContainer { SKELETON_OPTION_ALL_POSES_TO_RESTS, SKELETON_OPTION_SELECTED_POSES_TO_RESTS, SKELETON_OPTION_CREATE_PHYSICAL_SKELETON, + SKELETON_OPTION_EXPORT_SKELETON_PROFILE, }; struct BoneInfo { @@ -155,6 +156,8 @@ class Skeleton3DEditor : public VBoxContainer { void create_physical_skeleton(); PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos); + void export_skeleton_profile(); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h index 8e3dc19c7e..b87f108bd2 100644 --- a/editor/plugins/sprite_2d_editor_plugin.h +++ b/editor/plugins/sprite_2d_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPRITE_EDITOR_PLUGIN_H -#define SPRITE_EDITOR_PLUGIN_H +#ifndef SPRITE_2D_EDITOR_PLUGIN_H +#define SPRITE_2D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/2d/sprite_2d.h" @@ -111,4 +111,4 @@ public: ~Sprite2DEditorPlugin(); }; -#endif // SPRITE_EDITOR_PLUGIN_H +#endif // SPRITE_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index edd900f7d8..a39d24a167 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -423,6 +423,7 @@ void SpriteFramesEditor::_notification(int p_what) { zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); new_anim->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons"))); remove_anim->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + anim_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); split_sheet_zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons"))); split_sheet_zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); @@ -750,7 +751,7 @@ void SpriteFramesEditor::_animation_name_edited() { undo_redo->add_do_method(this, "_update_library"); undo_redo->add_undo_method(this, "_update_library"); - edited_anim = new_name; + edited_anim = name; undo_redo->commit_action(); } @@ -816,6 +817,10 @@ void SpriteFramesEditor::_animation_remove_confirmed() { undo_redo->commit_action(); } +void SpriteFramesEditor::_animation_search_text_changed(const String &p_text) { + _update_library(); +} + void SpriteFramesEditor::_animation_loop_changed() { if (updating) { return; @@ -900,14 +905,19 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { TreeItem *anim_root = animations->create_item(); List<StringName> anim_names; - frames->get_animation_list(&anim_names); - anim_names.sort_custom<StringName::AlphCompare>(); + bool searching = anim_search_box->get_text().size(); + String searched_string = searching ? anim_search_box->get_text().to_lower() : String(); + for (const StringName &E : anim_names) { String name = E; + if (searching && name.to_lower().find(searched_string) < 0) { + continue; + } + TreeItem *it = animations->create_item(anim_root); it->set_metadata(0, name); @@ -970,7 +980,6 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { anim_loop->set_pressed(frames->get_animation_loop(edited_anim)); updating = false; - //player->add_resource("default",resource); } void SpriteFramesEditor::edit(SpriteFrames *p_frames) { @@ -1157,6 +1166,13 @@ SpriteFramesEditor::SpriteFramesEditor() { hbc_animlist->add_child(remove_anim); remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove)); + anim_search_box = memnew(LineEdit); + hbc_animlist->add_child(anim_search_box); + anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL); + anim_search_box->set_placeholder(TTR("Filter Animations")); + anim_search_box->set_clear_button_enabled(true); + anim_search_box->connect("text_changed", callable_mp(this, &SpriteFramesEditor::_animation_search_text_changed)); + animations = memnew(Tree); sub_vb->add_child(animations); animations->set_v_size_flags(SIZE_EXPAND_FILL); @@ -1290,7 +1306,7 @@ SpriteFramesEditor::SpriteFramesEditor() { empty2->connect("pressed", callable_mp(this, &SpriteFramesEditor::_empty2_pressed)); move_up->connect("pressed", callable_mp(this, &SpriteFramesEditor::_up_pressed)); move_down->connect("pressed", callable_mp(this, &SpriteFramesEditor::_down_pressed)); - file->connect("files_selected", callable_mp(this, &SpriteFramesEditor::_file_load_request), make_binds(-1)); + file->connect("files_selected", callable_mp(this, &SpriteFramesEditor::_file_load_request).bind(-1)); loading_scene = false; sel = -1; @@ -1317,7 +1333,7 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_h->set_max(128); split_sheet_h->set_step(1); split_sheet_hb->add_child(split_sheet_h); - split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT)); + split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT)); split_sheet_hb->add_child(memnew(Label(TTR("Vertical:")))); split_sheet_v = memnew(SpinBox); @@ -1325,7 +1341,7 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_v->set_max(128); split_sheet_v->set_step(1); split_sheet_hb->add_child(split_sheet_v); - split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT)); + split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT)); split_sheet_hb->add_child(memnew(VSeparator)); split_sheet_hb->add_child(memnew(Label(TTR("Size:")))); @@ -1333,13 +1349,13 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_size_x->set_min(1); split_sheet_size_x->set_step(1); split_sheet_size_x->set_suffix("px"); - split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE)); + split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE)); split_sheet_hb->add_child(split_sheet_size_x); split_sheet_size_y = memnew(SpinBox); split_sheet_size_y->set_min(1); split_sheet_size_y->set_step(1); split_sheet_size_y->set_suffix("px"); - split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE)); + split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE)); split_sheet_hb->add_child(split_sheet_size_y); split_sheet_hb->add_child(memnew(VSeparator)); @@ -1348,13 +1364,13 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_sep_x->set_min(0); split_sheet_sep_x->set_step(1); split_sheet_sep_x->set_suffix("px"); - split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT)); + split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT)); split_sheet_hb->add_child(split_sheet_sep_x); split_sheet_sep_y = memnew(SpinBox); split_sheet_sep_y->set_min(0); split_sheet_sep_y->set_step(1); split_sheet_sep_y->set_suffix("px"); - split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT)); + split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT)); split_sheet_hb->add_child(split_sheet_sep_y); split_sheet_hb->add_child(memnew(VSeparator)); @@ -1363,13 +1379,13 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_offset_x->set_min(0); split_sheet_offset_x->set_step(1); split_sheet_offset_x->set_suffix("px"); - split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT)); + split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT)); split_sheet_hb->add_child(split_sheet_offset_x); split_sheet_offset_y = memnew(SpinBox); split_sheet_offset_y->set_min(0); split_sheet_offset_y->set_step(1); split_sheet_offset_y->set_suffix("px"); - split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT)); + split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT)); split_sheet_hb->add_child(split_sheet_offset_y); split_sheet_hb->add_spacer(); @@ -1448,6 +1464,10 @@ SpriteFramesEditor::SpriteFramesEditor() { max_sheet_zoom = 16.0f * MAX(1.0f, EDSCALE); min_sheet_zoom = 0.01f * MAX(1.0f, EDSCALE); _zoom_reset(); + + // Ensure the anim search box is wide enough by default. + // Not by setting its minimum size so it can still be shrinked if desired. + set_split_offset(56 * EDSCALE); } void SpriteFramesEditorPlugin::edit(Object *p_object) { diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 3c8c5ef19d..6352259b73 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -37,6 +37,7 @@ #include "scene/gui/check_button.h" #include "scene/gui/dialogs.h" #include "scene/gui/item_list.h" +#include "scene/gui/line_edit.h" #include "scene/gui/scroll_container.h" #include "scene/gui/spin_box.h" #include "scene/gui/split_container.h" @@ -73,6 +74,7 @@ class SpriteFramesEditor : public HSplitContainer { Button *new_anim = nullptr; Button *remove_anim = nullptr; + LineEdit *anim_search_box = nullptr; Tree *animations = nullptr; SpinBox *anim_speed = nullptr; @@ -137,6 +139,7 @@ class SpriteFramesEditor : public HSplitContainer { void _animation_add(); void _animation_remove(); void _animation_remove_confirmed(); + void _animation_search_text_changed(const String &p_text); void _animation_loop_changed(); void _animation_fps_changed(double p_value); diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index 1281ce0cfd..d4baff34e2 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -132,7 +132,7 @@ StyleBoxPreview::StyleBoxPreview() { preview->set_clip_contents(true); preview->connect("draw", callable_mp(this, &StyleBoxPreview::_redraw)); checkerboard->add_child(preview); - preview->set_anchors_and_offsets_preset(PRESET_WIDE); + preview->set_anchors_and_offsets_preset(PRESET_FULL_RECT); add_margin_child(TTR("Preview:"), checkerboard); grid_preview = memnew(TextureButton); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 7ca65c073d..196d87da36 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -32,6 +32,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { ERR_FAIL_COND(p_highlighter.is_null()); @@ -275,7 +276,7 @@ void TextEditor::update_settings() { void TextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) { Variant args[1] = { this }; const Variant *argp[] = { &args[0] }; - code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1)); + code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bindp(argp, 1)); } Control *TextEditor::get_edit_menu() { @@ -524,7 +525,7 @@ TextEditor::TextEditor() { code_editor->add_theme_constant_override("separation", 0); code_editor->connect("load_theme_settings", callable_mp(this, &TextEditor::_load_theme_settings)); code_editor->connect("validate_script", callable_mp(this, &TextEditor::_validate_script)); - code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); code_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); code_editor->show_toggle_scripts_button(); diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp index 0fc7079a24..64cafa17f3 100644 --- a/editor/plugins/texture_3d_editor_plugin.cpp +++ b/editor/plugins/texture_3d_editor_plugin.cpp @@ -57,8 +57,8 @@ void Texture3DEditor::_texture_changed() { } 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()); + material->set_shader_uniform("layer", (layer->get_value() + 0.5) / texture->get_depth()); + material->set_shader_uniform("tex", texture->get_rid()); String format = Image::get_format_name(texture->get_format()); diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h index 2f7f6f83bb..357bdb0845 100644 --- a/editor/plugins/texture_3d_editor_plugin.h +++ b/editor/plugins/texture_3d_editor_plugin.h @@ -91,4 +91,4 @@ public: Texture3DEditorPlugin(); }; -#endif // TEXTURE_EDITOR_PLUGIN_H +#endif // TEXTURE_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index 98e80c5513..f6b02d5f80 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -124,7 +124,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { texture_display = memnew(TextureRect); texture_display->set_texture(p_texture); - texture_display->set_anchors_preset(TextureRect::PRESET_WIDE); + texture_display->set_anchors_preset(TextureRect::PRESET_FULL_RECT); texture_display->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); texture_display->set_ignore_texture_size(true); add_child(texture_display); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index cb146fd342..2c6f70463d 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -68,9 +68,9 @@ void TextureLayeredEditor::_texture_changed() { } void TextureLayeredEditor::_update_material() { - materials[0]->set_shader_param("layer", layer->get_value()); - materials[2]->set_shader_param("layer", layer->get_value()); - materials[texture->get_layered_type()]->set_shader_param("tex", texture->get_rid()); + materials[0]->set_shader_uniform("layer", layer->get_value()); + materials[2]->set_shader_uniform("layer", layer->get_value()); + materials[texture->get_layered_type()]->set_shader_uniform("tex", texture->get_rid()); Vector3 v(1, 1, 1); v.normalize(); @@ -79,10 +79,10 @@ void TextureLayeredEditor::_update_material() { b.rotate(Vector3(1, 0, 0), x_rot); b.rotate(Vector3(0, 1, 0), y_rot); - materials[1]->set_shader_param("normal", v); - materials[1]->set_shader_param("rot", b); - materials[2]->set_shader_param("normal", v); - materials[2]->set_shader_param("rot", b); + materials[1]->set_shader_uniform("normal", v); + materials[1]->set_shader_uniform("rot", b); + materials[2]->set_shader_uniform("normal", v); + materials[2]->set_shader_uniform("rot", b); String format = Image::get_format_name(texture->get_format()); diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h index 830916e954..f49aa83eb2 100644 --- a/editor/plugins/texture_layered_editor_plugin.h +++ b/editor/plugins/texture_layered_editor_plugin.h @@ -93,4 +93,4 @@ public: TextureLayeredEditorPlugin(); }; -#endif // TEXTURE_EDITOR_PLUGIN_H +#endif // TEXTURE_LAYERED_EDITOR_PLUGIN_H diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index dd98247428..0bd8a8a484 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -35,7 +35,9 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/check_box.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/resources/texture.h" @@ -239,7 +241,7 @@ void TextureRegionEditor::_region_draw() { hscroll->set_value((hscroll->get_min() + hscroll->get_max() - hscroll->get_page()) / 2); vscroll->set_value((vscroll->get_min() + vscroll->get_max() - vscroll->get_page()) / 2); // This ensures that the view is updated correctly. - callable_bind(callable_mp(this, &TextureRegionEditor::_pan_callback), Vector2(1, 0)).call_deferred(nullptr, 0); + callable_mp(this, &TextureRegionEditor::_pan_callback).bind(Vector2(1, 0)).call_deferredp(nullptr, 0); request_center = false; } @@ -1153,7 +1155,7 @@ bool EditorInspectorPluginTextureRegion::parse_property(Object *p_object, const if (((Object::cast_to<Sprite2D>(p_object) || Object::cast_to<Sprite3D>(p_object) || Object::cast_to<NinePatchRect>(p_object) || Object::cast_to<StyleBoxTexture>(p_object)) && p_path == "region_rect") || (Object::cast_to<AtlasTexture>(p_object) && p_path == "region")) { Button *button = EditorInspector::create_inspector_action_button(TTR("Edit Region")); button->set_icon(texture_region_editor->get_theme_icon(SNAME("RegionEdit"), SNAME("EditorIcons"))); - button->connect("pressed", callable_mp(this, &EditorInspectorPluginTextureRegion::_region_edit), varray(p_object)); + button->connect("pressed", callable_mp(this, &EditorInspectorPluginTextureRegion::_region_edit).bind(p_object)); add_property_editor(p_path, button, true); } } diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 129af1bb1d..bbc22c8622 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "editor/editor_resource_picker.h" #include "editor/editor_scale.h" #include "editor/progress_dialog.h" +#include "scene/gui/color_picker.h" void ThemeItemImportTree::_update_items_tree() { import_items_tree->clear(); @@ -70,9 +71,17 @@ void ThemeItemImportTree::_update_items_tree() { for (const StringName &E : types) { String type_name = (String)E; + Ref<Texture2D> type_icon; + if (E == "") { + type_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons")); + } else { + type_icon = EditorNode::get_singleton()->get_class_icon(E, "NodeDisabled"); + } + TreeItem *type_node = import_items_tree->create_item(root); type_node->set_meta("_can_be_imported", false); type_node->set_collapsed(true); + type_node->set_icon(0, type_icon); type_node->set_text(0, type_name); type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK); type_node->set_checked(IMPORT_ITEM, false); @@ -214,7 +223,7 @@ void ThemeItemImportTree::_update_items_tree() { if (color_amount > 0) { Array arr; arr.push_back(color_amount); - select_colors_label->set_text(TTRN("One color", "{num} colors", color_amount).format(arr, "{num}")); + select_colors_label->set_text(TTRN("1 color", "{num} colors", color_amount).format(arr, "{num}")); select_all_colors_button->set_visible(true); select_full_colors_button->set_visible(true); deselect_all_colors_button->set_visible(true); @@ -228,7 +237,7 @@ void ThemeItemImportTree::_update_items_tree() { if (constant_amount > 0) { Array arr; arr.push_back(constant_amount); - select_constants_label->set_text(TTRN("One constant", "{num} constants", constant_amount).format(arr, "{num}")); + select_constants_label->set_text(TTRN("1 constant", "{num} constants", constant_amount).format(arr, "{num}")); select_all_constants_button->set_visible(true); select_full_constants_button->set_visible(true); deselect_all_constants_button->set_visible(true); @@ -242,7 +251,7 @@ void ThemeItemImportTree::_update_items_tree() { if (font_amount > 0) { Array arr; arr.push_back(font_amount); - select_fonts_label->set_text(TTRN("One font", "{num} fonts", font_amount).format(arr, "{num}")); + select_fonts_label->set_text(TTRN("1 font", "{num} fonts", font_amount).format(arr, "{num}")); select_all_fonts_button->set_visible(true); select_full_fonts_button->set_visible(true); deselect_all_fonts_button->set_visible(true); @@ -256,7 +265,7 @@ void ThemeItemImportTree::_update_items_tree() { if (font_size_amount > 0) { Array arr; arr.push_back(font_size_amount); - select_font_sizes_label->set_text(TTRN("One font size", "{num} font sizes", font_size_amount).format(arr, "{num}")); + select_font_sizes_label->set_text(TTRN("1 font size", "{num} font sizes", font_size_amount).format(arr, "{num}")); select_all_font_sizes_button->set_visible(true); select_full_font_sizes_button->set_visible(true); deselect_all_font_sizes_button->set_visible(true); @@ -270,7 +279,7 @@ void ThemeItemImportTree::_update_items_tree() { if (icon_amount > 0) { Array arr; arr.push_back(icon_amount); - select_icons_label->set_text(TTRN("One icon", "{num} icons", icon_amount).format(arr, "{num}")); + select_icons_label->set_text(TTRN("1 icon", "{num} icons", icon_amount).format(arr, "{num}")); select_all_icons_button->set_visible(true); select_full_icons_button->set_visible(true); deselect_all_icons_button->set_visible(true); @@ -286,7 +295,7 @@ void ThemeItemImportTree::_update_items_tree() { if (stylebox_amount > 0) { Array arr; arr.push_back(stylebox_amount); - select_styleboxes_label->set_text(TTRN("One stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}")); + select_styleboxes_label->set_text(TTRN("1 stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}")); select_all_styleboxes_button->set_visible(true); select_full_styleboxes_button->set_visible(true); deselect_all_styleboxes_button->set_visible(true); @@ -1095,15 +1104,15 @@ ThemeItemImportTree::ThemeItemImportTree() { select_all_items_button->set_flat(true); select_all_items_button->set_tooltip(select_all_items_tooltip); button_set->add_child(select_all_items_button); - select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed), varray(i)); + select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed).bind(i)); select_full_items_button->set_flat(true); select_full_items_button->set_tooltip(select_full_items_tooltip); button_set->add_child(select_full_items_button); - select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed), varray(i)); + select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed).bind(i)); deselect_all_items_button->set_flat(true); deselect_all_items_button->set_tooltip(deselect_all_items_tooltip); button_set->add_child(deselect_all_items_button); - deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed), varray(i)); + deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed).bind(i)); total_selected_items_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); total_selected_items_label->hide(); @@ -1134,12 +1143,12 @@ ThemeItemImportTree::ThemeItemImportTree() { import_collapse_types_button->set_flat(true); import_collapse_types_button->set_tooltip(TTR("Collapse types.")); import_buttons->add_child(import_collapse_types_button); - import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(true)); + import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(true)); import_expand_types_button = memnew(Button); import_expand_types_button->set_flat(true); import_expand_types_button->set_tooltip(TTR("Expand types.")); import_buttons->add_child(import_expand_types_button); - import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(false)); + import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(false)); import_buttons->add_child(memnew(VSeparator)); @@ -1170,6 +1179,8 @@ ThemeItemImportTree::ThemeItemImportTree() { import_add_selected_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_import_selected)); } +/////////////////////// + void ThemeItemEditorDialog::ok_pressed() { if (import_default_theme_items->has_selected_items() || import_editor_theme_items->has_selected_items() || import_other_theme_items->has_selected_items()) { confirm_closing_dialog->set_text(TTR("Import Items tab has some items selected. Selection will be lost upon closing this window.\nClose anyway?")); @@ -1867,6 +1878,8 @@ void ThemeItemEditorDialog::_notification(int p_what) { edit_items_remove_custom->set_icon(get_theme_icon(SNAME("ThemeRemoveCustomItems"), SNAME("EditorIcons"))); edit_items_remove_all->set_icon(get_theme_icon(SNAME("ThemeRemoveAllItems"), SNAME("EditorIcons"))); + edit_add_type_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + import_another_theme_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; } @@ -1924,10 +1937,9 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); edit_add_type_value->connect("text_submitted", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type)); edit_add_type_hb->add_child(edit_add_type_value); - Button *edit_add_type_button = memnew(Button); - edit_add_type_button->set_text(TTR("Add")); + edit_add_type_button = memnew(Button); edit_add_type_hb->add_child(edit_add_type_button); - edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type), varray("")); + edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type).bind("")); VBoxContainer *edit_items_vb = memnew(VBoxContainer); edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -1945,42 +1957,42 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_items_add_color->set_flat(true); edit_items_add_color->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_color); - edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_COLOR)); + edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_COLOR)); edit_items_add_constant = memnew(Button); edit_items_add_constant->set_tooltip(TTR("Add Constant Item")); edit_items_add_constant->set_flat(true); edit_items_add_constant->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_constant); - edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_CONSTANT)); + edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_CONSTANT)); edit_items_add_font = memnew(Button); edit_items_add_font->set_tooltip(TTR("Add Font Item")); edit_items_add_font->set_flat(true); edit_items_add_font->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_font); - edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT)); + edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT)); edit_items_add_font_size = memnew(Button); edit_items_add_font_size->set_tooltip(TTR("Add Font Size Item")); edit_items_add_font_size->set_flat(true); edit_items_add_font_size->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_font_size); - edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT_SIZE)); + edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT_SIZE)); edit_items_add_icon = memnew(Button); edit_items_add_icon->set_tooltip(TTR("Add Icon Item")); edit_items_add_icon->set_flat(true); edit_items_add_icon->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_icon); - edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_ICON)); + edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_ICON)); edit_items_add_stylebox = memnew(Button); edit_items_add_stylebox->set_tooltip(TTR("Add StyleBox Item")); edit_items_add_stylebox->set_flat(true); edit_items_add_stylebox->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_stylebox); - edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_STYLEBOX)); + edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_STYLEBOX)); edit_items_toolbar->add_child(memnew(VSeparator)); @@ -2017,7 +2029,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_items_tree->connect("button_clicked", callable_mp(this, &ThemeItemEditorDialog::_item_tree_button_pressed)); edit_items_message = memnew(Label); - edit_items_message->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + edit_items_message->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); edit_items_message->set_mouse_filter(Control::MOUSE_FILTER_STOP); edit_items_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); edit_items_message->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); @@ -2099,6 +2111,8 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog)); } +/////////////////////// + void ThemeTypeDialog::_dialog_about_to_show() { add_type_filter->set_text(""); add_type_filter->grab_focus(); @@ -2237,6 +2251,8 @@ ThemeTypeDialog::ThemeTypeDialog() { add_child(add_type_confirmation); } +/////////////////////// + VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) { VBoxContainer *items_tab = memnew(VBoxContainer); items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE); @@ -2256,11 +2272,11 @@ VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) { LineEdit *item_add_edit = memnew(LineEdit); item_add_edit->set_h_size_flags(SIZE_EXPAND_FILL); item_add_hb->add_child(item_add_edit); - item_add_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_add_lineedit_cbk), varray(p_data_type, item_add_edit)); + item_add_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_add_lineedit_cbk).bind(p_data_type, item_add_edit)); Button *item_add_button = memnew(Button); item_add_button->set_text(TTR("Add")); item_add_hb->add_child(item_add_button); - item_add_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_add_cbk), varray(p_data_type, item_add_edit)); + item_add_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_add_cbk).bind(p_data_type, item_add_edit)); return items_list; } @@ -2403,7 +2419,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_name_edit->set_h_size_flags(SIZE_EXPAND_FILL); item_name_edit->set_text(p_item_name); item_name_container->add_child(item_name_edit); - item_name_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_rename_entered), varray(p_data_type, p_item_name, item_name_container)); + item_name_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_rename_entered).bind(p_data_type, p_item_name, item_name_container)); item_name_edit->hide(); Button *item_rename_button = memnew(Button); @@ -2411,21 +2427,21 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_rename_button->set_tooltip(TTR("Rename Item")); item_rename_button->set_flat(true); item_name_container->add_child(item_rename_button); - item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk), varray(p_data_type, p_item_name, item_name_container)); + item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk).bind(p_data_type, p_item_name, item_name_container)); Button *item_remove_button = memnew(Button); item_remove_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); item_remove_button->set_tooltip(TTR("Remove Item")); item_remove_button->set_flat(true); item_name_container->add_child(item_remove_button); - item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk), varray(p_data_type, p_item_name)); + item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk).bind(p_data_type, p_item_name)); Button *item_rename_confirm_button = memnew(Button); item_rename_confirm_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"))); item_rename_confirm_button->set_tooltip(TTR("Confirm Item Rename")); item_rename_confirm_button->set_flat(true); item_name_container->add_child(item_rename_confirm_button); - item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed), varray(p_data_type, p_item_name, item_name_container)); + item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed).bind(p_data_type, p_item_name, item_name_container)); item_rename_confirm_button->hide(); Button *item_rename_cancel_button = memnew(Button); @@ -2433,7 +2449,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_rename_cancel_button->set_tooltip(TTR("Cancel Item Rename")); item_rename_cancel_button->set_flat(true); item_name_container->add_child(item_rename_cancel_button); - item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled), varray(p_data_type, p_item_name, item_name_container)); + item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container)); item_rename_cancel_button->hide(); } else { item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); @@ -2443,7 +2459,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_override_button->set_tooltip(TTR("Override Item")); item_override_button->set_flat(true); item_name_container->add_child(item_override_button); - item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk), varray(p_data_type, p_item_name)); + item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk).bind(p_data_type, p_item_name)); } return item_control; @@ -2476,7 +2492,8 @@ void ThemeTypeEditor::_update_type_items() { if (E.value) { item_editor->set_pick_color(edited_theme->get_color(E.key, edited_type)); - item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key)); + item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed).bind(E.key)); + item_editor->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(item_editor->get_picker())); } else { item_editor->set_pick_color(Theme::get_default()->get_color(E.key, edited_type)); item_editor->set_disabled(true); @@ -2509,7 +2526,7 @@ void ThemeTypeEditor::_update_type_items() { if (E.value) { item_editor->set_value(edited_theme->get_constant(E.key, edited_type)); - item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key)); + item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed).bind(E.key)); } else { item_editor->set_value(Theme::get_default()->get_constant(E.key, edited_type)); item_editor->set_editable(false); @@ -2543,7 +2560,7 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key)); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed).bind(E.key)); } else { if (Theme::get_default()->has_font(E.key, edited_type)) { item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type)); @@ -2580,7 +2597,7 @@ void ThemeTypeEditor::_update_type_items() { if (E.value) { item_editor->set_value(edited_theme->get_font_size(E.key, edited_type)); - item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key)); + item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed).bind(E.key)); } else { item_editor->set_value(Theme::get_default()->get_font_size(E.key, edited_type)); item_editor->set_editable(false); @@ -2614,7 +2631,7 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key)); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed).bind(E.key)); } else { if (Theme::get_default()->has_icon(E.key, edited_type)) { item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type)); @@ -2661,7 +2678,7 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(leading_stylebox.item_name)); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed).bind(leading_stylebox.item_name)); stylebox_items_list->add_child(item_control); stylebox_items_list->add_child(memnew(HSeparator)); @@ -2686,7 +2703,7 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key)); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed).bind(E.key)); Button *pin_leader_button = memnew(Button); pin_leader_button->set_flat(true); @@ -2694,7 +2711,7 @@ void ThemeTypeEditor::_update_type_items() { pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type.")); item_control->add_child(pin_leader_button); - pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key)); + pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key)); } else { if (Theme::get_default()->has_stylebox(E.key, edited_type)) { item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type)); @@ -3364,6 +3381,7 @@ ThemeTypeEditor::ThemeTypeEditor() { theme_type_list = memnew(OptionButton); theme_type_list->set_h_size_flags(SIZE_EXPAND_FILL); + theme_type_list->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); type_list_hb->add_child(theme_type_list); theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected)); @@ -3454,6 +3472,8 @@ ThemeTypeEditor::ThemeTypeEditor() { add_child(update_debounce_timer); } +/////////////////////// + void ThemeEditor::edit(const Ref<Theme> &p_theme) { if (theme == p_theme) { return; @@ -3504,8 +3524,8 @@ void ThemeEditor::_preview_scene_dialog_cbk(const String &p_path) { } _add_preview_tab(preview_tab, p_path.get_file(), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"))); - preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid), varray(preview_tab)); - preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab), varray(preview_tab)); + preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid).bind(preview_tab)); + preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab).bind(preview_tab)); } void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon) { @@ -3599,13 +3619,13 @@ ThemeEditor::ThemeEditor() { Button *theme_save_button = memnew(Button); theme_save_button->set_text(TTR("Save")); theme_save_button->set_flat(true); - theme_save_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(false)); + theme_save_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk).bind(false)); top_menu->add_child(theme_save_button); Button *theme_save_as_button = memnew(Button); theme_save_as_button->set_text(TTR("Save As...")); theme_save_as_button->set_flat(true); - theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(true)); + theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk).bind(true)); top_menu->add_child(theme_save_as_button); top_menu->add_child(memnew(VSeparator)); @@ -3672,6 +3692,8 @@ ThemeEditor::ThemeEditor() { theme_type_editor->set_custom_minimum_size(Size2(280, 0) * EDSCALE); } +/////////////////////// + void ThemeEditorPlugin::edit(Object *p_node) { if (Object::cast_to<Theme>(p_node)) { theme_editor->edit(Object::cast_to<Theme>(p_node)); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 543113a5eb..9f89a047cb 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -198,6 +198,7 @@ class ThemeItemEditorDialog : public AcceptDialog { Tree *edit_type_list = nullptr; LineEdit *edit_add_type_value = nullptr; + Button *edit_add_type_button = nullptr; String edited_item_type; Button *edit_items_add_color = nullptr; diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index 826631d750..b5c6c6d651 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -36,6 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "scene/gui/button.h" +#include "scene/gui/check_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/progress_bar.h" #include "scene/resources/packed_scene.h" @@ -246,7 +247,7 @@ ThemeEditorPreview::ThemeEditorPreview() { preview_root->set_h_size_flags(SIZE_EXPAND_FILL); preview_bg = memnew(ColorRect); - preview_bg->set_anchors_and_offsets_preset(PRESET_WIDE); + preview_bg->set_anchors_and_offsets_preset(PRESET_FULL_RECT); preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color")); preview_root->add_child(preview_bg); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 3073c8a7f2..f119ada810 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -544,7 +544,7 @@ TileAtlasView::TileAtlasView() { Panel *panel = memnew(Panel); panel->set_clip_contents(true); panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); panel->set_h_size_flags(SIZE_EXPAND_FILL); panel->set_v_size_flags(SIZE_EXPAND_FILL); add_child(panel); @@ -613,32 +613,32 @@ TileAtlasView::TileAtlasView() { background_left = memnew(Control); background_left->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - background_left->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + background_left->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); background_left->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); background_left->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_left)); base_tiles_root_control->add_child(background_left); base_tiles_drawing_root = memnew(Control); base_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - base_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); base_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST); base_tiles_root_control->add_child(base_tiles_drawing_root); base_tiles_draw = memnew(Control); base_tiles_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - base_tiles_draw->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_tiles_draw->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); base_tiles_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles)); base_tiles_drawing_root->add_child(base_tiles_draw); base_tiles_texture_grid = memnew(Control); base_tiles_texture_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - base_tiles_texture_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_tiles_texture_grid->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); base_tiles_texture_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_texture_grid)); base_tiles_drawing_root->add_child(base_tiles_texture_grid); base_tiles_shape_grid = memnew(Control); base_tiles_shape_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - base_tiles_shape_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_tiles_shape_grid->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); base_tiles_shape_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_shape_grid)); base_tiles_drawing_root->add_child(base_tiles_shape_grid); diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index ff46b7871f..196a642283 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -158,4 +158,4 @@ public: TileAtlasView(); }; -#endif // TILE_ATLAS_VIEW +#endif // TILE_ATLAS_VIEW_H diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 1263ee5758..a00e1ed9e8 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -803,13 +803,13 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { add_child(root); panel = memnew(Panel); - panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); root->add_child(panel); base_control = memnew(Control); base_control->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); - base_control->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); base_control->connect("draw", callable_mp(this, &GenericTilePolygonEditor::_base_control_draw)); base_control->connect("gui_input", callable_mp(this, &GenericTilePolygonEditor::_base_control_gui_input)); base_control->set_clip_contents(true); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index d914b9c363..1bf24a7393 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -2198,7 +2198,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1)); sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1)); sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current)); - sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list, source_sort_button)); + sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button)); sources_list->add_user_signal(MethodInfo("sort_request")); sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list)); split_container_left_side->add_child(sources_list); @@ -3212,7 +3212,7 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() { terrains_tile_list->set_item_metadata(item_index, list_metadata_dict); item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainPath"), SNAME("EditorIcons"))); - terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted withing the same stroke.")); + terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted within the same stroke.")); list_metadata_dict = Dictionary(); list_metadata_dict["type"] = SELECTED_TYPE_PATH; terrains_tile_list->set_item_metadata(item_index, list_metadata_dict); diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index ff586ebbfe..605fbe4823 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -377,4 +377,4 @@ public: static Vector<Vector2i> get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell); }; -#endif // TILE_MAP_EDITOR_PLUGIN_H +#endif // TILE_MAP_EDITOR_H diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp index 3fe13fd341..12e1615484 100644 --- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp +++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp @@ -340,7 +340,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); source_level_list->set_select_mode(ItemList::SELECT_MULTI); source_level_list->set_allow_rmb_select(true); - source_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(source_level_list)); + source_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(source_level_list)); vbox_container->add_child(source_level_list); Label *coords_level_label = memnew(Label); @@ -351,7 +351,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); coords_level_list->set_select_mode(ItemList::SELECT_MULTI); coords_level_list->set_allow_rmb_select(true); - coords_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(coords_level_list)); + coords_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(coords_level_list)); vbox_container->add_child(coords_level_list); Label *alternative_level_label = memnew(Label); @@ -362,7 +362,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); alternative_level_list->set_select_mode(ItemList::SELECT_MULTI); alternative_level_list->set_allow_rmb_select(true); - alternative_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(alternative_level_list)); + alternative_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(alternative_level_list)); vbox_container->add_child(alternative_level_list); popup_menu = memnew(PopupMenu); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index deffa48615..6950f57a00 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -735,15 +735,15 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { // --- Custom Data --- ADD_TILE_DATA_EDITOR_GROUP("Custom Data"); for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) { - if (tile_set->get_custom_data_name(i).is_empty()) { + if (tile_set->get_custom_data_layer_name(i).is_empty()) { ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i)); } else { - ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_name(i), vformat("custom_data_%d", i)); + ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_layer_name(i), vformat("custom_data_%d", i)); } if (!tile_data_editors.has(vformat("custom_data_%d", i))) { TileDataDefaultEditor *tile_data_custom_data_editor = memnew(TileDataDefaultEditor()); tile_data_custom_data_editor->hide(); - tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_name(i)); + tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_layer_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_layer_name(i)); tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update)); tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update)); tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor; @@ -913,7 +913,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() { button->add_theme_style_override("hover", memnew(StyleBoxEmpty)); button->add_theme_style_override("focus", memnew(StyleBoxEmpty)); button->add_theme_style_override("pressed", memnew(StyleBoxEmpty)); - button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE)); + button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile).bind(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE)); button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min))); button->set_expand_icon(true); @@ -1822,7 +1822,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); - xform.translate(position); + xform.translate_local(position); if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, 0 })) { continue; @@ -1845,7 +1845,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, 0); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); - xform.translate(position); + xform.translate_local(position); TileMapCell cell; cell.source_id = tile_set_atlas_source_id; @@ -1886,6 +1886,12 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In tile_atlas_control_unscaled->update(); alternative_tiles_control->update(); alternative_tiles_control_unscaled->update(); + + if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { + if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) { + drag_type = DRAG_TYPE_NONE; + } + } } Ref<InputEventMouseButton> mb = p_event; @@ -1911,7 +1917,10 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In } } else if (mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { - // Right click pressed + drag_type = DRAG_TYPE_MAY_POPUP_MENU; + drag_start_mouse_pos = alternative_tiles_control->get_local_mouse_position(); + } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { + // Right click released and wasn't dragged too far Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); selection.clear(); @@ -1989,7 +1998,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { Vector2 position = rect.get_center(); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); - xform.translate(position); + xform.translate_local(position); if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, alternative_tile })) { continue; @@ -2013,7 +2022,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { Vector2 position = rect.get_center(); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); - xform.translate(position); + xform.translate_local(position); TileMapCell cell; cell.source_id = tile_set_atlas_source_id; @@ -2370,7 +2379,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_data_editors_tree = memnew(Tree); tile_data_editors_tree->set_hide_root(true); - tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); tile_data_editors_tree->set_h_scroll_enabled(false); tile_data_editors_tree->set_v_scroll_enabled(false); tile_data_editors_tree->connect("item_selected", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editors_tree_selected)); @@ -2509,7 +2518,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control); tile_atlas_control_unscaled = memnew(Control); - tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); tile_atlas_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw)); tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control_unscaled, false); tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -2526,7 +2535,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control); alternative_tiles_control_unscaled = memnew(Control); - alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); alternative_tiles_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw)); tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false); alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index de373e121b..81804710b4 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -710,9 +710,9 @@ TileSetEditor::TileSetEditor() { sources_list->set_v_size_flags(SIZE_EXPAND_FILL); sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected)); sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current)); - sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list, source_sort_button)); + sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button)); sources_list->add_user_signal(MethodInfo("sort_request")); - sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list), varray(-1)); + sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1)); sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->set_drag_forwarding(this); split_container_left_side->add_child(sources_list); diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h index e633de37b0..c45240043e 100644 --- a/editor/plugins/tiles/tile_set_editor.h +++ b/editor/plugins/tiles/tile_set_editor.h @@ -108,4 +108,4 @@ public: ~TileSetEditor(); }; -#endif // TILE_SET_EDITOR_PLUGIN_H +#endif // TILE_SET_EDITOR_H diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h index 657bfca032..77a583e522 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h @@ -142,4 +142,4 @@ public: ~TileSetScenesCollectionSourceEditor(); }; -#endif +#endif // TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index 419d0ffcfc..b5134f6893 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -116,7 +116,7 @@ void TilesEditorPlugin::_thread() { // Add the viewport at the last moment to avoid rendering too early. EditorNode::get_singleton()->add_child(viewport); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONESHOT); pattern_preview_done.wait(); @@ -127,7 +127,7 @@ void TilesEditorPlugin::_thread() { const Variant *args_ptr[] = { &args[0], &args[1] }; Variant r; Callable::CallError error; - item.callback.call(args_ptr, 2, r, error); + item.callback.callp(args_ptr, 2, r, error); viewport->queue_delete(); } else { @@ -155,6 +155,9 @@ void TilesEditorPlugin::_update_editors() { // Update the viewport. CanvasItemEditor::get_singleton()->update_viewport(); + // Make sure the tile set editor is visible if we have one assigned. + tileset_editor_button->set_visible(is_visible && tile_set.is_valid()); + // Update visibility of bottom panel buttons. if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) { if (tile_map) { @@ -181,12 +184,14 @@ void TilesEditorPlugin::_notification(int p_what) { } void TilesEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { + is_visible = p_visible; + + if (is_visible) { // Disable and hide invalid editors. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); tileset_editor_button->set_visible(tile_set.is_valid()); tilemap_editor_button->set_visible(tile_map); - if (tile_map) { + if (tile_map && !is_editing_tile_set) { EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor); } else { EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor); @@ -226,14 +231,14 @@ void TilesEditorPlugin::synchronize_sources_list(Object *p_current_list, Object } if (item_list->is_visible_in_tree()) { + // Make sure the selection is not overwritten after sorting. + int atlas_sources_lists_current_mem = atlas_sources_lists_current; + item_list->emit_signal(SNAME("sort_request")); + atlas_sources_lists_current = atlas_sources_lists_current_mem; + if (atlas_sources_lists_current < 0 || atlas_sources_lists_current >= item_list->get_item_count()) { item_list->deselect_all(); } else { - // Make sure the selection is not overwritten after sorting. - int atlas_sources_lists_current_mem = atlas_sources_lists_current; - item_list->emit_signal(SNAME("sort_request")); - atlas_sources_lists_current = atlas_sources_lists_current_mem; - item_list->set_current(atlas_sources_lists_current); item_list->ensure_current_is_visible(); item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current); @@ -345,6 +350,8 @@ void TilesEditorPlugin::edit(Object *p_object) { // Update edited objects. tile_set = Ref<TileSet>(); + is_editing_tile_set = false; + if (p_object) { if (p_object->is_class("TileMap")) { tile_map_id = p_object->get_instance_id(); @@ -359,6 +366,7 @@ void TilesEditorPlugin::edit(Object *p_object) { tile_map_id = ObjectID(); } } + is_editing_tile_set = true; EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor); } } diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index a22e782b34..b1fe6f8df6 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -53,9 +53,12 @@ public: }; private: + bool is_visible = false; + bool tile_map_changed_needs_update = false; ObjectID tile_map_id; Ref<TileSet> tile_set; + bool is_editing_tile_set = false; Button *tilemap_editor_button = nullptr; TileMapEditor *tilemap_editor = nullptr; diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 443d5975cd..cf55465417 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -35,6 +35,8 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/separator.h" VersionControlEditorPlugin *VersionControlEditorPlugin::singleton = nullptr; diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h index 39a56de772..fa721268ba 100644 --- a/editor/plugins/version_control_editor_plugin.h +++ b/editor/plugins/version_control_editor_plugin.h @@ -148,4 +148,4 @@ public: VARIANT_ENUM_CAST(VersionControlEditorPlugin::ChangeType); -#endif // !VERSION_CONTROL_EDITOR_PLUGIN_H +#endif // VERSION_CONTROL_EDITOR_PLUGIN_H diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 94073daeda..4a144bc391 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -40,9 +40,17 @@ #include "editor/editor_node.h" #include "editor/editor_properties.h" #include "editor/editor_scale.h" +#include "editor/plugins/curve_editor_plugin.h" +#include "editor/plugins/shader_editor_plugin.h" #include "scene/animation/animation_player.h" +#include "scene/gui/button.h" +#include "scene/gui/code_edit.h" +#include "scene/gui/graph_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "scene/gui/popup.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/resources/visual_shader_nodes.h" @@ -72,6 +80,10 @@ const int MAX_FLOAT_CONST_DEFS = sizeof(float_constant_defs) / sizeof(FloatConst /////////////////// +void VisualShaderNodePlugin::set_editor(VisualShaderEditor *p_editor) { + vseditor = p_editor; +} + Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) { Object *ret; if (GDVIRTUAL_CALL(_create_editor, p_parent_resource, p_node, ret)) { @@ -86,17 +98,6 @@ 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(SIDE_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE); - return style; -} - -/////////////////// - VisualShaderGraphPlugin::VisualShaderGraphPlugin() { } @@ -115,6 +116,10 @@ void VisualShaderGraphPlugin::_bind_methods() { ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz); } +void VisualShaderGraphPlugin::set_editor(VisualShaderEditor *p_editor) { + editor = p_editor; +} + void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { visual_shader = Ref<VisualShader>(p_shader); } @@ -186,15 +191,11 @@ void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_ switch (p_value.get_type()) { case Variant::COLOR: { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { - break; - } button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); Callable ce = callable_mp(editor, &VisualShaderEditor::_draw_color_over_button); if (!button->is_connected("draw", ce)) { - button->connect("draw", ce, varray(button, p_value)); + button->connect("draw", ce.bind(button, p_value)); } } break; case Variant::BOOL: { @@ -337,10 +338,6 @@ void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_u } void VisualShaderGraphPlugin::update_theme() { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { - return; - } vector_expanded_color[0] = editor->get_theme_color(SNAME("axis_x_color"), SNAME("Editor")); // red vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), SNAME("Editor")); // green vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), SNAME("Editor")); // blue @@ -351,10 +348,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (!visual_shader.is_valid() || p_type != visual_shader->get_shader_type()) { return; } - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { - return; - } GraphEdit *graph = editor->graph; if (!graph) { return; @@ -367,8 +360,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Control *offset; - static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - static const Color type_color[] = { Color(0.38, 0.85, 0.96), // scalar (float) Color(0.49, 0.78, 0.94), // scalar (int) @@ -426,7 +417,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { size = resizable_node->get_size(); node->set_resizable(true); - node->connect("resize_request", callable_mp(editor, &VisualShaderEditor::_node_resized), varray((int)p_type, p_id)); + node->connect("resize_request", callable_mp(editor, &VisualShaderEditor::_node_resized).bind((int)p_type, p_id)); } if (is_expression) { expression = expression_node->get_expression(); @@ -438,10 +429,10 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (p_id >= 2) { node->set_show_close_button(true); - node->connect("close_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request), varray(p_type, p_id), CONNECT_DEFERRED); + node->connect("close_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED); } - node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged), varray(p_id)); + node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged).bind(p_id)); Control *custom_editor = nullptr; int port_offset = 1; @@ -474,6 +465,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { node->set_custom_minimum_size(Size2(200 * EDSCALE, 0)); } + Ref<VisualShaderNodeUniformRef> uniform_ref = vsnode; + if (uniform_ref.is_valid()) { + uniform_ref->set_shader_rid(visual_shader->get_rid()); + uniform_ref->update_uniform_type(); + } + Ref<VisualShaderNodeUniform> uniform = vsnode; HBoxContainer *hb = nullptr; @@ -482,8 +479,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { register_uniform_name(p_id, uniform_name); uniform_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); uniform_name->set_text(uniform->get_uniform_name()); - uniform_name->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_changed), varray(p_id)); - uniform_name->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_focus_out), varray(uniform_name, p_id)); + uniform_name->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_changed).bind(p_id)); + uniform_name->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_focus_out).bind(uniform_name, p_id)); if (vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { hb = memnew(HBoxContainer); @@ -523,7 +520,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Callable ce = callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve); if (curve->get_texture().is_valid() && !curve->get_texture()->is_connected("changed", ce)) { - curve->get_texture()->connect("changed", ce, varray(p_id)); + curve->get_texture()->connect("changed", ce.bind(p_id)); } CurveEditor *curve_editor = memnew(CurveEditor); @@ -541,7 +538,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Callable ce = callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve_xyz); if (curve_xyz->get_texture().is_valid() && !curve_xyz->get_texture()->is_connected("changed", ce)) { - curve_xyz->get_texture()->connect("changed", ce, varray(p_id)); + curve_xyz->get_texture()->connect("changed", ce.bind(p_id)); } CurveEditor *curve_editor_x = memnew(CurveEditor); @@ -604,14 +601,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Button *add_input_btn = memnew(Button); add_input_btn->set_text(TTR("Add Input")); - add_input_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_input_port), varray(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, input_port_name), CONNECT_DEFERRED); + add_input_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_input_port).bind(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, input_port_name), 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(editor, &VisualShaderEditor::_add_output_port), varray(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, output_port_name), CONNECT_DEFERRED); + add_output_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_output_port).bind(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, output_port_name), CONNECT_DEFERRED); hb2->add_child(add_output_btn); node->add_child(hb2); @@ -719,7 +716,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Button *button = memnew(Button); hb->add_child(button); register_default_input_button(p_id, i, button); - button->connect("pressed", callable_mp(editor, &VisualShaderEditor::_edit_port_default_input), varray(button, p_id, i)); + button->connect("pressed", callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(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 { @@ -744,32 +741,32 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { 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(editor, &VisualShaderEditor::_change_input_port_type), varray(p_id, i), CONNECT_DEFERRED); + type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_input_port_type).bind(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_submitted", callable_mp(editor, &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED); - name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false), CONNECT_DEFERRED); + name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_input_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED); + name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, false), CONNECT_DEFERRED); Button *remove_btn = memnew(Button); remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED); + remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(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 + label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact hb->add_child(label); if (vsnode->is_input_port_default(i, mode) && !port_left_used) { Label *hint_label = memnew(Label); hint_label->set_text(TTR("[default]")); hint_label->add_theme_color_override("font_color", editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit"))); - hint_label->add_theme_style_override("normal", label_style); + hint_label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); hb->add_child(hint_label); } } @@ -784,7 +781,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Button *remove_btn = memnew(Button); remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED); + remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED); hb->add_child(remove_btn); LineEdit *name_box = memnew(LineEdit); @@ -792,8 +789,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { 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_submitted", callable_mp(editor, &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED); - name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true), CONNECT_DEFERRED); + name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_output_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED); + name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, true), CONNECT_DEFERRED); OptionButton *type_box = memnew(OptionButton); hb->add_child(type_box); @@ -806,11 +803,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { 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(editor, &VisualShaderEditor::_change_output_port_type), varray(p_id, i), CONNECT_DEFERRED); + type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_output_port_type).bind(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 + label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact hb->add_child(label); } } @@ -824,7 +821,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { expand->set_pressed_texture(editor->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons"))); expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER); expand->set_pressed(vsnode->_is_output_port_expanded(i)); - expand->connect("pressed", callable_mp(editor, &VisualShaderEditor::_expand_output_port), varray(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED); + expand->connect("pressed", callable_mp(editor, &VisualShaderEditor::_expand_output_port).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED); hb->add_child(expand); } if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { @@ -836,7 +833,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { register_output_port(p_id, j, preview); - preview->connect("pressed", callable_mp(editor, &VisualShaderEditor::_preview_select_port), varray(p_id, j), CONNECT_DEFERRED); + preview->connect("pressed", callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED); hb->add_child(preview); } } @@ -1018,7 +1015,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { expression_box->set_context_menu_enabled(false); expression_box->set_draw_line_numbers(true); - expression_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_expression_focus_out), varray(expression_box, p_id)); + expression_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_expression_focus_out).bind(expression_box, p_id)); } if (is_comment) { @@ -1035,10 +1032,6 @@ void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int 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) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { - return; - } GraphEdit *graph = editor->graph; if (!graph) { return; @@ -1055,10 +1048,6 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro } void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { - return; - } GraphEdit *graph = editor->graph; if (!graph) { return; @@ -1085,6 +1074,27 @@ VisualShaderGraphPlugin::~VisualShaderGraphPlugin() { ///////////////// +void VisualShaderEditedProperty::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualShaderEditedProperty::set_edited_property); + ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualShaderEditedProperty::get_edited_property); + + ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property"); +} + +void VisualShaderEditedProperty::set_edited_property(Variant p_variant) { + edited_property = p_variant; +} + +Variant VisualShaderEditedProperty::get_edited_property() const { + return edited_property; +} + +///////////////// + +Vector2 VisualShaderEditor::selection_center; +List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer; +List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer; + void VisualShaderEditor::edit(VisualShader *p_visual_shader) { bool changed = false; if (p_visual_shader) { @@ -1602,7 +1612,7 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { } void VisualShaderEditor::_update_uniforms(bool p_update_refs) { - VisualShaderNodeUniformRef::clear_uniforms(); + VisualShaderNodeUniformRef::clear_uniforms(visual_shader->get_rid()); for (int t = 0; t < VisualShader::TYPE_MAX; t++) { Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t); @@ -1640,7 +1650,7 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) { } else { uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_SAMPLER; } - VisualShaderNodeUniformRef::add_uniform(uniform->get_uniform_name(), uniform_type); + VisualShaderNodeUniformRef::add_uniform(visual_shader->get_rid(), uniform->get_uniform_name(), uniform_type); } } } @@ -2288,10 +2298,8 @@ void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, } } -void VisualShaderEditor::_port_edited() { +void VisualShaderEditor::_port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) { VisualShader::Type type = get_current_shader_type(); - - Variant value = property_editor->get_variant(); Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node); ERR_FAIL_COND(!vsn.is_valid()); @@ -2299,30 +2307,51 @@ void VisualShaderEditor::_port_edited() { Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr()); if (custom.is_valid()) { - undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, value); + undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, p_value); undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); } else { - undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); + undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, p_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(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); + undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, p_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 = get_current_shader_type(); + Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, p_node); + Variant value = vs_node->get_input_port_default_value(p_port); + + edited_property_holder->set_edited_property(value); + + if (property_editor) { + property_editor->disconnect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + property_editor_popup->remove_child(property_editor); + } + + // TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget. + property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE); + if (property_editor) { + property_editor->set_object_and_property(edited_property_holder.ptr(), "edited_property"); + property_editor->update_property(); + property_editor->set_name_split_ratio(0); + property_editor_popup->add_child(property_editor); - Ref<VisualShaderNode> vsn = visual_shader->get_node(type, p_node); + property_editor->connect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + + Button *button = Object::cast_to<Button>(p_button); + if (button) { + property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom()); + } + property_editor_popup->reset_size(); + if (button) { + property_editor_popup->popup(); + } else { + property_editor_popup->popup_centered_ratio(); + } + } - Button *button = Object::cast_to<Button>(p_button); - ERR_FAIL_COND(!button); - Variant value = vsn->get_input_port_default_value(p_port); - property_editor->set_position(button->get_screen_position() + Vector2(0, button->get_size().height)); - property_editor->edit(nullptr, "", value.get_type(), value, 0, ""); - property_editor->popup(); editing_node = p_node; editing_port = p_port; } @@ -2645,7 +2674,6 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri _setup_node(vsn, p_ops); } VisualShaderNodeUniformRef *uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn); - if (uniform_ref && to_node != -1 && to_slot != -1) { VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot); bool success = false; @@ -4565,9 +4593,9 @@ void VisualShaderEditor::_preview_size_changed() { preview_vbox->set_custom_minimum_size(preview_window->get_size()); } -static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) { - RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable); - return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt); +static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) { + RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable); + return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); } void VisualShaderEditor::_update_preview() { @@ -4584,7 +4612,7 @@ void VisualShaderEditor::_update_preview() { info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())); info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())); info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_variable_type_func = _get_global_variable_type; + info.global_shader_uniform_type_func = _get_global_shader_uniform_type; ShaderLanguage sl; @@ -4644,10 +4672,7 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available); } -VisualShaderEditor *VisualShaderEditor::singleton = nullptr; - VisualShaderEditor::VisualShaderEditor() { - singleton = this; ShaderLanguage::get_keyword_list(&keyword_list); graph = memnew(GraphEdit); @@ -4671,13 +4696,13 @@ VisualShaderEditor::VisualShaderEditor() { graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER); //graph->add_valid_left_disconnect_type(0); graph->set_v_size_flags(SIZE_EXPAND_FILL); - graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), varray(), CONNECT_DEFERRED); - graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), varray(), CONNECT_DEFERRED); + graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), CONNECT_DEFERRED); + graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), CONNECT_DEFERRED); graph->connect("node_selected", callable_mp(this, &VisualShaderEditor::_node_selected)); graph->connect("scroll_offset_changed", callable_mp(this, &VisualShaderEditor::_scroll_changed)); graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes)); - graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes), varray(false)); - graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes), varray(false, Point2())); + graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(false)); + graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes).bind(false, Point2())); graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request)); graph->connect("gui_input", callable_mp(this, &VisualShaderEditor::_graph_gui_input)); graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty)); @@ -4780,7 +4805,7 @@ VisualShaderEditor::VisualShaderEditor() { add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->add_child(add_node); graph->get_zoom_hbox()->move_child(add_node, 0); - add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX)); + add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX)); varying_button = memnew(Button); varying_button->set_flat(true); @@ -5152,6 +5177,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("NodePositionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("CameraPositionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("CameraDirectionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("NodePositionView", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, 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"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -5167,6 +5196,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("NodePositionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("CameraPositionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("CameraDirectionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("NodePositionView", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo", "ALBEDO"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -5544,8 +5577,12 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D)); + add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D)); + add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D)); @@ -5635,19 +5672,23 @@ VisualShaderEditor::VisualShaderEditor() { Ref<VisualShaderNodePluginDefault> default_plugin; default_plugin.instantiate(); + default_plugin->set_editor(this); add_plugin(default_plugin); graph_plugin.instantiate(); + graph_plugin->set_editor(this); - property_editor = memnew(CustomPropertyEditor); - add_child(property_editor); + property_editor_popup = memnew(PopupPanel); + property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE); + add_child(property_editor_popup); - property_editor->connect("variant_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + edited_property_holder.instantiate(); } class VisualShaderNodePluginInputEditor : public OptionButton { GDCLASS(VisualShaderNodePluginInputEditor, OptionButton); + VisualShaderEditor *editor = nullptr; Ref<VisualShaderNodeInput> input; public: @@ -5660,13 +5701,11 @@ public: } void _item_selected(int p_item) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (editor) { - editor->call_deferred(SNAME("_input_select_item"), input, get_item_text(p_item)); - } + editor->call_deferred(SNAME("_input_select_item"), input, get_item_text(p_item)); } - void setup(const Ref<VisualShaderNodeInput> &p_input) { + void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeInput> &p_input) { + editor = p_editor; input = p_input; Ref<Texture2D> type_icon[] = { EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")), @@ -5699,6 +5738,7 @@ public: class VisualShaderNodePluginVaryingEditor : public OptionButton { GDCLASS(VisualShaderNodePluginVaryingEditor, OptionButton); + VisualShaderEditor *editor = nullptr; Ref<VisualShaderNodeVarying> varying; public: @@ -5709,13 +5749,11 @@ public: } void _item_selected(int p_item) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (editor) { - editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_text(p_item)); - } + editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_text(p_item)); } - void setup(const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) { + void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) { + editor = p_editor; varying = p_varying; Ref<Texture2D> type_icon[] = { @@ -5776,6 +5814,7 @@ public: class VisualShaderNodePluginUniformRefEditor : public OptionButton { GDCLASS(VisualShaderNodePluginUniformRefEditor, OptionButton); + VisualShaderEditor *editor = nullptr; Ref<VisualShaderNodeUniformRef> uniform_ref; public: @@ -5788,13 +5827,11 @@ public: } void _item_selected(int p_item) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (editor) { - editor->call_deferred(SNAME("_uniform_select_item"), uniform_ref, get_item_text(p_item)); - } + editor->call_deferred(SNAME("_uniform_select_item"), uniform_ref, get_item_text(p_item)); } - void setup(const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) { + void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) { + editor = p_editor; uniform_ref = p_uniform_ref; Ref<Texture2D> type_icon[] = { @@ -5828,6 +5865,7 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer); + VisualShaderEditor *editor = nullptr; Ref<Resource> parent_resource; int node_id = 0; VisualShader::Type shader_type; @@ -5861,13 +5899,10 @@ public: } } if (p_property != "constant") { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (editor) { - VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin(); - if (graph_plugin) { - undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id); - undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id); - } + VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin(); + if (graph_plugin) { + undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id); + undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id); } } undo_redo->commit_action(); @@ -5903,7 +5938,8 @@ public: } } - void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) { + void setup(VisualShaderEditor *p_editor, Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) { + editor = p_editor; parent_resource = p_parent_resource; updating = false; node = p_node; @@ -5956,19 +5992,19 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par if (p_shader.is_valid() && (p_node->is_class("VisualShaderNodeVaryingGetter") || p_node->is_class("VisualShaderNodeVaryingSetter"))) { VisualShaderNodePluginVaryingEditor *editor = memnew(VisualShaderNodePluginVaryingEditor); - editor->setup(p_node, p_shader->get_shader_type()); + editor->setup(vseditor, p_node, p_shader->get_shader_type()); return editor; } if (p_node->is_class("VisualShaderNodeUniformRef")) { VisualShaderNodePluginUniformRefEditor *editor = memnew(VisualShaderNodePluginUniformRefEditor); - editor->setup(p_node); + editor->setup(vseditor, p_node); return editor; } if (p_node->is_class("VisualShaderNodeInput")) { VisualShaderNodePluginInputEditor *editor = memnew(VisualShaderNodePluginInputEditor); - editor->setup(p_node); + editor->setup(vseditor, p_node); return editor; } @@ -6023,22 +6059,22 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par properties.push_back(pinfo[i].name); } VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor); - editor->setup(p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node); + editor->setup(vseditor, p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node); return editor; } void EditorPropertyShaderMode::_option_selected(int p_which) { - VisualShaderEditor *editor = VisualShaderEditor::get_singleton(); - if (!editor) { + Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object())); + if (visual_shader->get_mode() == p_which) { return; } - //will not use this, instead will do all the logic setting manually - //emit_signal(SNAME("property_changed"), get_edited_property(), p_which); - - Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object())); - - if (visual_shader->get_mode() == p_which) { + ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader")); + if (!shader_editor) { + return; + } + VisualShaderEditor *editor = shader_editor->get_visual_shader_editor(visual_shader); + if (!editor) { return; } @@ -6145,10 +6181,10 @@ bool EditorInspectorShaderModePlugin::can_handle(Object *p_object) { bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) { - EditorPropertyShaderMode *editor = memnew(EditorPropertyShaderMode); + EditorPropertyShaderMode *mode_editor = memnew(EditorPropertyShaderMode); Vector<String> options = p_hint_text.split(","); - editor->setup(options); - add_property_editor(p_path, editor); + mode_editor->setup(options); + add_property_editor(p_path, mode_editor); return true; } @@ -6196,7 +6232,7 @@ void VisualShaderNodePortPreview::_shader_changed() { } if (src_mat && src_mat->get_shader().is_valid()) { List<PropertyInfo> params; - src_mat->get_shader()->get_param_list(¶ms); + src_mat->get_shader()->get_shader_uniform_list(¶ms); for (const PropertyInfo &E : params) { material->set(E.name, src_mat->get(E.name)); } @@ -6217,7 +6253,7 @@ void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Visua } Size2 VisualShaderNodePortPreview::get_minimum_size() const { - int port_preview_size = EditorSettings::get_singleton()->get("editors/visual_editors/visualshader/port_preview_size"); + int port_preview_size = EditorSettings::get_singleton()->get("editors/visual_editors/visual_shader/port_preview_size"); return Size2(port_preview_size, port_preview_size) * EDSCALE; } diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index b8da266ed7..b846c34f9e 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -32,25 +32,36 @@ #define VISUAL_SHADER_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/plugins/curve_editor_plugin.h" -#include "editor/property_editor.h" -#include "scene/gui/button.h" -#include "scene/gui/code_edit.h" -#include "scene/gui/graph_edit.h" -#include "scene/gui/popup.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/tree.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/resources/visual_shader.h" +class Button; +class CodeEdit; +class CodeHighlighter; +class CurveEditor; +class GraphEdit; +class GraphNode; +class PopupMenu; +class PopupPanel; +class RichTextLabel; +class TextEdit; +class Tree; + +class VisualShaderEditor; + class VisualShaderNodePlugin : public RefCounted { GDCLASS(VisualShaderNodePlugin, RefCounted); protected: + VisualShaderEditor *vseditor = nullptr; + +protected: static void _bind_methods(); GDVIRTUAL2RC(Object *, _create_editor, Ref<Resource>, Ref<VisualShaderNode>) public: + void set_editor(VisualShaderEditor *p_editor); virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node); }; @@ -58,6 +69,8 @@ class VisualShaderGraphPlugin : public RefCounted { GDCLASS(VisualShaderGraphPlugin, RefCounted); private: + VisualShaderEditor *editor = nullptr; + struct InputPort { Button *default_input_button = nullptr; }; @@ -91,6 +104,7 @@ protected: static void _bind_methods(); public: + void set_editor(VisualShaderEditor *p_editor); void register_shader(VisualShader *p_visual_shader); void set_connections(const List<VisualShader::Connection> &p_connections); void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node); @@ -128,13 +142,31 @@ public: ~VisualShaderGraphPlugin(); }; +class VisualShaderEditedProperty : public RefCounted { + GDCLASS(VisualShaderEditedProperty, RefCounted); + +private: + Variant edited_property; + +protected: + static void _bind_methods(); + +public: + void set_edited_property(Variant p_variant); + Variant get_edited_property() const; + + VisualShaderEditedProperty() {} +}; + class VisualShaderEditor : public VBoxContainer { GDCLASS(VisualShaderEditor, VBoxContainer); friend class VisualShaderGraphPlugin; - CustomPropertyEditor *property_editor = nullptr; + PopupPanel *property_editor_popup = nullptr; + EditorProperty *property_editor = nullptr; int editing_node = -1; int editing_port = -1; + Ref<VisualShaderEditedProperty> edited_property_holder; Ref<VisualShader> visual_shader; GraphEdit *graph = nullptr; @@ -324,8 +356,6 @@ class VisualShaderEditor : public VBoxContainer { void _update_preview(); String _get_description(int p_idx); - static VisualShaderEditor *singleton; - struct DragOp { VisualShader::Type type = VisualShader::Type::TYPE_MAX; int node = 0; @@ -351,7 +381,7 @@ class VisualShaderEditor : public VBoxContainer { void _node_changed(int p_id); void _edit_port_default_input(Object *p_button, int p_node, int p_port); - void _port_edited(); + void _port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing); int to_node = -1; int to_slot = -1; @@ -403,9 +433,9 @@ class VisualShaderEditor : public VBoxContainer { void _duplicate_nodes(); - Vector2 selection_center; - List<CopyItem> copy_items_buffer; - List<VisualShader::Connection> copy_connections_buffer; + static Vector2 selection_center; + static List<CopyItem> copy_items_buffer; + static List<VisualShader::Connection> copy_connections_buffer; void _clear_copy_buffer(); void _copy_nodes(bool p_cut); @@ -482,7 +512,6 @@ public: void add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin); 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(); diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp index 6fc6c1ad39..e3b2be33df 100644 --- a/editor/plugins/voxel_gi_editor_plugin.cpp +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -139,7 +139,7 @@ void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) { if (voxel_gi) { voxel_gi->bake(); ERR_FAIL_COND(voxel_gi->get_probe_data().is_null()); - ResourceSaver::save(p_path, voxel_gi->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH); + ResourceSaver::save(voxel_gi->get_probe_data(), p_path, ResourceSaver::FLAG_CHANGE_PATH); } } diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h index 621e98beef..43d6f71e26 100644 --- a/editor/plugins/voxel_gi_editor_plugin.h +++ b/editor/plugins/voxel_gi_editor_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VOXEL_GIEDITORPLUGIN_H -#define VOXEL_GIEDITORPLUGIN_H +#ifndef VOXEL_GI_EDITOR_PLUGIN_H +#define VOXEL_GI_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" #include "scene/3d/voxel_gi.h" @@ -71,4 +71,4 @@ public: ~VoxelGIEditorPlugin(); }; -#endif // VOXEL_GIEDITORPLUGIN_H +#endif // VOXEL_GI_EDITOR_PLUGIN_H diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index ed13afc235..1c9afa8be8 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -50,7 +50,7 @@ void BackgroundProgress::_add_task(const String &p_task, const String &p_label, Control *ec = memnew(Control); ec->set_h_size_flags(SIZE_EXPAND_FILL); ec->set_v_size_flags(SIZE_EXPAND_FILL); - t.progress->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + t.progress->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); ec->add_child(t.progress); ec->set_custom_minimum_size(Size2(80, 5) * EDSCALE); t.hb->add_child(ec); @@ -235,7 +235,7 @@ void ProgressDialog::_bind_methods() { ProgressDialog::ProgressDialog() { main = memnew(VBoxContainer); add_child(main); - main->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + main->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); set_exclusive(true); last_progress_tick = 0; singleton = this; diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 654ebf4573..421e56f9a1 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -42,7 +42,8 @@ const int ERROR_CODE = 77; #include "core/templates/hash_map.h" #include "core/templates/list.h" -const int CONVERSION_MAX_FILE_SIZE = 1024 * 1024 * 4; // 4 MB +const uint64_t CONVERSION_MAX_FILE_SIZE_MB = 4; +const uint64_t CONVERSION_MAX_FILE_SIZE = 1024 * 1024 * CONVERSION_MAX_FILE_SIZE_MB; static const char *enum_renames[][2] = { //// constants @@ -120,7 +121,7 @@ static const char *enum_renames[][2] = { { "JOINT_PIN", "JOINT_TYPE_PIN" }, // PhysicsServer2D { "JOINT_SLIDER", "JOINT_TYPE_SLIDER" }, // PhysicsServer3D { "KEY_CONTROL", "KEY_CTRL" }, // Globals - { "LOOP_PING_PONG", "LOOP_PINGPONG" }, //AudioStreamSample + { "LOOP_PING_PONG", "LOOP_PINGPONG" }, // AudioStreamWAV { "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc { "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc { "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc @@ -255,6 +256,7 @@ static const char *gdscript_function_renames[][2] = { { "damped_spring_joint_create", "joint_make_damped_spring" }, // PhysicsServer2D { "damped_string_joint_get_param", "damped_spring_joint_get_param" }, // PhysicsServer2D { "damped_string_joint_set_param", "damped_spring_joint_set_param" }, // PhysicsServer2D + { "dectime", "move_toward" }, // GDScript, Math functions { "delete_char_at_cursor", "delete_char_at_caret" }, // LineEdit { "deselect_items", "deselect_all" }, // FileDialog { "disable_plugin", "_disable_plugin" }, // EditorPlugin @@ -427,6 +429,7 @@ static const char *gdscript_function_renames[][2] = { { "joint_create_slider", "joint_make_slider" }, // PhysicsServer3D { "line_intersects_line_2d", "line_intersects_line" }, // Geometry2D { "load_from_globals", "load_from_project_settings" }, // InputMap + { "load_interactive", "load_threaded_request" }, // ResourceLoader - load_threaded_request is alternative, but is used differently { "make_convex_from_brothers", "make_convex_from_siblings" }, // CollisionShape3D { "make_visible", "_make_visible" }, // EditorPlugin { "merge_polygons_2d", "merge_polygons" }, // Geometry2D @@ -484,6 +487,7 @@ static const char *gdscript_function_renames[][2] = { { "set_enabled_focus_mode", "set_focus_mode" }, // BaseButton { "set_endian_swap", "set_big_endian" }, // File { "set_expand_to_text_length", "set_expand_to_text_length_enabled" }, // LineEdit + { "set_filename", "set_scene_file_path" }, // Node, WARNING, this may be used in a lot of other places { "set_focus_neighbour", "set_focus_neighbor" }, // Control { "set_frame_color", "set_color" }, // ColorRect { "set_global_rate_scale", "set_playback_speed_scale" }, // AudioServer @@ -975,6 +979,7 @@ static const char *gdscript_properties_renames[][2] = { // { "wrap_enabled", "wrap_mode" }, // TextEdit // { "zfar", "far" }, // Camera3D // { "znear", "near" }, // Camera3D + // { "filename", "scene_file_path" }, // Node { "as_normalmap", "as_normal_map" }, // NoiseTexture { "bbcode_text", "text" }, // RichTextLabel { "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit @@ -1250,7 +1255,9 @@ static const char *class_renames[][2] = { { "AnimatedSprite", "AnimatedSprite2D" }, { "AnimationTreePlayer", "AnimationTree" }, { "Area", "Area3D" }, // Be careful, this will be used everywhere + { "AudioStreamOGGVorbis", "AudioStreamOggVorbis" }, { "AudioStreamRandomPitch", "AudioStreamRandomizer" }, + { "AudioStreamSample", "AudioStreamWAV" }, { "BakedLightmap", "LightmapGI" }, { "BakedLightmapData", "LightmapGIData" }, { "BitmapFont", "FontFile" }, @@ -1593,12 +1600,33 @@ static const char *colors_renames[][2] = { { nullptr, nullptr }, }; +class ProjectConverter3To4::RegExContainer { +public: + RegEx reg_is_empty = RegEx("\\bempty\\("); + RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])"); + RegEx reg_json_to = RegEx("\\bto_json\\b"); + RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)"); + RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)"); + RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)"); + RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)"); + RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)"); + RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$"); + RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$"); + RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)"); + RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)"); + RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)"); + RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)"); + RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)"); +}; + // Function responsible for converting project int ProjectConverter3To4::convert() { print_line("Starting conversion."); + RegExContainer reg_container = RegExContainer(); + ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays."); - ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); + ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); // Checking if folder contains valid Godot 3 project. // Project cannot be converted 2 times @@ -1638,7 +1666,7 @@ int ProjectConverter3To4::convert() { uint64_t start_time = Time::get_singleton()->get_ticks_msec(); if (file_name.ends_with(".shader")) { - DirAccess::remove_file_or_error(file_name); + DirAccess::remove_file_or_error(file_name.trim_prefix("res://")); file_name = file_name.replace(".shader", ".gdshader"); } @@ -1651,7 +1679,7 @@ int ProjectConverter3To4::convert() { rename_enums(file_content); // Require to additional rename rename_common(gdscript_function_renames, file_content); - rename_gdscript_functions(file_content); // Require to additional rename + rename_gdscript_functions(file_content, reg_container, false); // Require to additional rename rename_common(project_settings_renames, file_content); rename_gdscript_keywords(file_content); @@ -1669,7 +1697,7 @@ int ProjectConverter3To4::convert() { rename_enums(file_content); // Require to additional rename rename_common(gdscript_function_renames, file_content); - rename_gdscript_functions(file_content); // Require to additional rename + rename_gdscript_functions(file_content, reg_container, true); // Require to additional rename rename_common(project_settings_renames, file_content); rename_gdscript_keywords(file_content); @@ -1686,6 +1714,7 @@ int ProjectConverter3To4::convert() { rename_common(csharp_properties_renames, file_content); rename_common(csharp_signals_renames, file_content); rename_csharp_functions(file_content); + rename_csharp_attributes(file_content); custom_rename(file_content, "public class ", "public partial class "); } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) { rename_common(shaders_renames, file_content); @@ -1706,7 +1735,7 @@ int ProjectConverter3To4::convert() { continue; } } else { - reason.append(" ERROR: File has exceeded the maximum size allowed - 500 KB"); + reason.append(" ERROR: File has exceeded the maximum size allowed - " + itos(CONVERSION_MAX_FILE_SIZE_MB) + " MB"); is_ignored = true; } @@ -1716,7 +1745,7 @@ int ProjectConverter3To4::convert() { uint64_t hash_after = file_content.hash64(); // Don't need to save file without any changes // Save if this is a shader, because it was renamed - if (hash_before != hash_after || file_name.find(".gdshader") != -1) { + if (hash_before != hash_after || file_name.ends_with(".gdshader")) { converted_files++; Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::WRITE); @@ -1740,8 +1769,10 @@ int ProjectConverter3To4::convert() { int ProjectConverter3To4::validate_conversion() { print_line("Starting checking if project conversion can be done."); + RegExContainer reg_container = RegExContainer(); + ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays."); - ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); + ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); // Checking if folder contains valid Godot 3 project. // Project cannot be converted 2 times @@ -1782,7 +1813,7 @@ int ProjectConverter3To4::validate_conversion() { bool is_ignored = false; uint64_t start_time = Time::get_singleton()->get_ticks_msec(); - if (file_name.ends_with(".sader")) { + if (file_name.ends_with(".shader")) { reason.append("\tFile extension will be renamed from `shader` to `gdshader`."); } @@ -1794,7 +1825,7 @@ int ProjectConverter3To4::validate_conversion() { changed_elements.append_array(check_for_rename_enums(file_content)); changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content)); - changed_elements.append_array(check_for_rename_gdscript_functions(file_content)); + changed_elements.append_array(check_for_rename_gdscript_functions(file_content, reg_container, false)); changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content)); changed_elements.append_array(check_for_rename_gdscript_keywords(file_content)); @@ -1812,7 +1843,7 @@ int ProjectConverter3To4::validate_conversion() { changed_elements.append_array(check_for_rename_enums(file_content)); changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content)); - changed_elements.append_array(check_for_rename_gdscript_functions(file_content)); + changed_elements.append_array(check_for_rename_gdscript_functions(file_content, reg_container, true)); changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content)); changed_elements.append_array(check_for_rename_gdscript_keywords(file_content)); @@ -1829,6 +1860,7 @@ int ProjectConverter3To4::validate_conversion() { changed_elements.append_array(check_for_rename_common(csharp_properties_renames, file_content)); changed_elements.append_array(check_for_rename_common(csharp_signals_renames, file_content)); changed_elements.append_array(check_for_rename_csharp_functions(file_content)); + changed_elements.append_array(check_for_rename_csharp_attributes(file_content)); changed_elements.append_array(check_for_custom_rename(file_content, "public class ", "public partial class ")); } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) { changed_elements.append_array(check_for_rename_common(shaders_renames, file_content)); @@ -1849,7 +1881,7 @@ int ProjectConverter3To4::validate_conversion() { continue; } } else { - reason.append("\tERROR: File has exceeded the maximum size allowed - 500 KB"); + reason.append("\tERROR: File has exceeded the maximum size allowed - " + itos(CONVERSION_MAX_FILE_SIZE_MB) + " MB"); is_ignored = true; } @@ -1896,14 +1928,14 @@ Vector<String> ProjectConverter3To4::check_for_files() { continue; } if (dir.current_is_dir()) { - directories_to_check.append(current_dir + file_name + "/"); + directories_to_check.append(current_dir.plus_file(file_name) + "/"); } else { bool proper_extension = false; if (file_name.ends_with(".gd") || file_name.ends_with(".shader") || file_name.ends_with(".tscn") || file_name.ends_with(".tres") || file_name.ends_with(".godot") || file_name.ends_with(".cs") || file_name.ends_with(".csproj")) proper_extension = true; if (proper_extension) { - collected_files.append(current_dir + file_name); + collected_files.append(current_dir.plus_file(file_name)); } } file_name = dir.get_next(); @@ -1926,6 +1958,17 @@ bool ProjectConverter3To4::test_conversion_single_additional(String name, String return true; } +bool ProjectConverter3To4::test_conversion_single_additional_builtin(String name, String expected, void (ProjectConverter3To4::*func)(String &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin_script) { + String got = name; + (this->*func)(got, reg_container, builtin_script); + if (expected != got) { + ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got + "`"); + return false; + } + + return true; +} + bool ProjectConverter3To4::test_conversion_single_normal(String name, String expected, const char *array[][2], String what) { String got = name; rename_common(array, got); @@ -1937,7 +1980,7 @@ bool ProjectConverter3To4::test_conversion_single_normal(String name, String exp } // Validate if conversions are proper -bool ProjectConverter3To4::test_conversion() { +bool ProjectConverter3To4::test_conversion(const RegExContainer ®_container) { bool valid = true; valid = valid & test_conversion_single_normal("Spatial", "Node3D", class_renames, "class"); @@ -1968,26 +2011,37 @@ bool ProjectConverter3To4::test_conversion() { valid = valid & test_conversion_single_additional("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp"); valid = valid & test_conversion_single_additional("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename"); - valid = valid & test_conversion_single_additional("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional("[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[Sync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[Slave]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[Puppet]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[PuppetSync]", "[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[Master]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); + valid = valid & test_conversion_single_additional("[MasterSync]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp"); - valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); + valid = valid & test_conversion_single_additional_builtin("OS.get_window_safe_area()", "DisplayServer.get_display_safe_area()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_single_additional("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_single_additional("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_single_additional("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_single_additional("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_single_additional("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid & test_conversion_single_additional("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); valid = valid & test_conversion_single_additional("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); @@ -2000,82 +2054,88 @@ bool ProjectConverter3To4::test_conversion() { valid = valid & test_conversion_single_additional("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); valid = valid & test_conversion_single_additional("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); valid = valid & test_conversion_single_additional("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\nmaster func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\npuppet func", "\n\n@rpc(auth) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\nremote func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\nremotesync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\nsync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\npuppetsync func", "\n\n@rpc(auth,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - valid = valid & test_conversion_single_additional("\n\nmastersync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); - - valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); // TODO, this is only a workaround - valid = valid & test_conversion_single_additional("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("(start(A,B,C,D,E,F,G) != OK):", "(start(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("(connect(A,B,C,D,E,F,G) != OK):", "(connect(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("map_to_world(a, b,c)", "map_to_world(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional(" aa", " aa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\taa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("\t aa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional(" \taa", " \taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - - valid = valid & test_conversion_single_additional("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); - valid = valid & test_conversion_single_additional("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); + valid = valid & test_conversion_single_additional("\n\nremote func", "\n\n@rpc(any_peer) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\nremotesync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\nsync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\npuppetsync func", "\n\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + valid = valid & test_conversion_single_additional("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword"); + + valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("yield(this, \"timeout\")", "await this.\"timeout\"", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); + + valid = valid & test_conversion_single_additional_builtin(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround + valid = valid & test_conversion_single_additional_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,D) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("(start(A,B) != OK):", "(start(Callable(A,B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A,B).bind(C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("map_to_world(a, b,c)", "map_to_world(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin(" aa", " aa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\taa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("\t aa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin(" \taa", " \taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid & test_conversion_single_additional_builtin("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid & test_conversion_single_additional_builtin("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid & test_conversion_single_additional("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_enums, "custom rename"); @@ -2209,7 +2269,7 @@ bool ProjectConverter3To4::test_array_names() { // Callable is special class, to which normal classes may be renamed if (!ClassDB::class_exists(StringName(new_class)) && new_class != "Callable") { - ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in convertion."); + ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in conversion."); valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI } current_index++; @@ -2295,7 +2355,7 @@ bool ProjectConverter3To4::test_array_names() { } // Validate in one array if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode` -// Also checks if in name contains spaces at the end or beggining +// Also checks if in name contains spaces at the end or beginning bool ProjectConverter3To4::test_single_array(const char *array[][2], bool ignore_second_check) { bool valid = true; int current_index = 0; @@ -2517,7 +2577,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_enums(Vector<String> &file int current_line = 1; for (String &line : file_content) { - Array reg_match = reg.search_all(line); + TypedArray<RegExMatch> reg_match = reg.search_all(line); if (reg_match.size() > 0) { found_things.append(line_formatter(current_line, colors_renames[current_index][0], colors_renames[current_index][1], line)); } @@ -2533,7 +2593,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_enums(Vector<String> &file void ProjectConverter3To4::rename_classes(String &file_content) { int current_index = 0; - // TODO Maybe it is better way to not rename gd, tscn and other files which are named are classes + // TODO Maybe it is better way to not rename gd, tscn and other files which are named as classes while (class_renames[current_index][0]) { // Begin renaming workaround `Resource.gd` -> `RefCounter.gd` RegEx reg_before = RegEx(String("\\b") + class_renames[current_index][0] + ".tscn\\b"); @@ -2594,7 +2654,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &fi line = reg_before.sub(line, "TEMP_RENAMED_CLASS.tscn", true); line = reg_before2.sub(line, "TEMP_RENAMED_CLASS.gd", true); - Array reg_match = reg.search_all(line); + TypedArray<RegExMatch> reg_match = reg.search_all(line); if (reg_match.size() > 0) { found_things.append(line_formatter(current_line, class_renames[current_index][0], class_renames[current_index][1], line)); } @@ -2623,432 +2683,11 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &fi return found_things; } -void ProjectConverter3To4::rename_gdscript_functions(String &file_content) { - // Custom renaming, each rule needs to be set manually - // Don't forget to put validate each rule in validate_conversion function +void ProjectConverter3To4::rename_gdscript_functions(String &file_content, const RegExContainer ®_container, bool builtin) { Vector<String> lines = file_content.split("\n"); - RegEx reg_is_empty = RegEx("\\bempty\\("); - RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])"); - RegEx reg_json_to = RegEx("\\bto_json\\b"); - RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)"); - RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)"); - RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)"); - RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)"); - RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)"); - RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$"); - RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$"); - RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)"); - RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)"); - RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)"); - RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)"); - RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)"); - - CRASH_COND(!reg_is_empty.is_valid()); - CRASH_COND(!reg_super.is_valid()); - CRASH_COND(!reg_json_to.is_valid()); - CRASH_COND(!reg_json_parse.is_valid()); - CRASH_COND(!reg_json_non_new.is_valid()); - CRASH_COND(!reg_export.is_valid()); - CRASH_COND(!reg_export_advanced.is_valid()); - CRASH_COND(!reg_setget_setget.is_valid()); - CRASH_COND(!reg_setget_set.is_valid()); - CRASH_COND(!reg_setget_get.is_valid()); - CRASH_COND(!reg_join.is_valid()); - CRASH_COND(!reg_mixed_tab_space.is_valid()); - CRASH_COND(!reg_image_lock.is_valid()); - CRASH_COND(!reg_image_unlock.is_valid()); - CRASH_COND(!reg_os_fullscreen.is_valid()); - for (String &line : lines) { - if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) { - line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); - line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); - } - - // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure - line = reg_mixed_tab_space.sub(line, "$1", true); - - // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray - line = reg_join.sub(line, "$2.join($1)", true); - - // -- empty() -> is_empty() Pool*Array - line = reg_is_empty.sub(line, "is_empty(", true); - - // -- \t.func() -> \tsuper.func() Object - line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore" - - // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON - line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); - - // -- to_json(a) -> JSON.new().stringify(a) Object - line = reg_json_to.sub(line, "JSON.new().stringify", true); - - // -- parse_json(a) -> JSON.get_data() etc. Object - line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); - - // -- get_node(@ -> get_node( Node - line = line.replace("get_node(@", "get_node("); - - // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript - line = reg_export.sub(line, "export var $2: $1"); - - // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript - line = reg_export_advanced.sub(line, "export var $2$3 # ($1)"); - - // Setget Setget - line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); - - // Setget set - line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); - - // Setget get - line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true); - - // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true) - line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true); - - // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody - if (line.find("move_and_slide(") != -1) { - int start = line.find("move_and_slide("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - String base_obj = get_object_of_execution(line.substr(0, start)); - String starting_space = get_starting_space(line); - - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 1) { - String line_new; - - // motion_velocity - line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; - - // up_direction - if (parts.size() >= 2) { - line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n"; - } - - // stop_on_slope - if (parts.size() >= 3) { - line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n"; - } - - // max_slides - if (parts.size() >= 4) { - line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n"; - } - - // floor_max_angle - if (parts.size() >= 5) { - line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n"; - } - - // infiinite_interia - if (parts.size() >= 6) { - line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n"; - } - - line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); - } - } - } - - // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody - if (line.find("move_and_slide_with_snap(") != -1) { - int start = line.find("move_and_slide_with_snap("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - String base_obj = get_object_of_execution(line.substr(0, start)); - String starting_space = get_starting_space(line); - - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 1) { - String line_new; - - // motion_velocity - line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; - - // snap - if (parts.size() >= 2) { - line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n"; - } - - // up_direction - if (parts.size() >= 3) { - line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n"; - } - - // stop_on_slope - if (parts.size() >= 4) { - line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n"; - } - - // max_slides - if (parts.size() >= 5) { - line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n"; - } - - // floor_max_angle - if (parts.size() >= 6) { - line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n"; - } - - // infiinite_interia - if (parts.size() >= 7) { - line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n"; - } - - line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); - } - } - } - - // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object - if (line.find("sort_custom(") != -1) { - int start = line.find("sort_custom("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); - } - } - } - - // -- list_dir_begin( ) -> list_dir_begin() Object - if (line.find("list_dir_begin(") != -1) { - int start = line.find("list_dir_begin("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547"; - } - } - - // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem - if (line.find("draw_line(") != -1) { - int start = line.find("draw_line("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 5) { - line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start); - } - } - } - - // -- func c(var a, var b) -> func c(a, b) - if (line.find("func ") != -1 && line.find("var ") != -1) { - int start = line.find("func "); - start = line.substr(start).find("(") + start; - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - - String start_string = line.substr(0, start) + "("; - for (int i = 0; i < parts.size(); i++) { - start_string += parts[i].strip_edges().trim_prefix("var "); - if (i != parts.size() - 1) { - start_string += ", "; - } - } - line = start_string + ")" + line.substr(end + start); - } - } - - // -- yield(this, \"timeout\") -> await this.timeout GDScript - if (line.find("yield(") != -1) { - int start = line.find("yield("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start); - } - } - } - - // -- parse_json( AA ) -> TODO Object - if (line.find("parse_json(") != -1) { - int start = line.find("parse_json("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start); - } - } - - // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform - if (line.find(".xform(") != -1) { - int start = line.find(".xform("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 1) { - line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start); - } - } - } - - // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform - if (line.find(".xform_inv(") != -1) { - int start = line.find(".xform_inv("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - String object_exec = get_object_of_execution(line.substr(0, start)); - if (line.find(object_exec + ".xform") != -1) { - int start2 = line.find(object_exec + ".xform"); - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 1) { - line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start); - } - } - } - } - - // -- connect(,,,things) -> connect(,Callable(,),things) Object - if (line.find("connect(") != -1) { - int start = line.find("connect("); - // Protection from disconnect - if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - } - // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object - if (line.find("disconnect(") != -1) { - int start = line.find("disconnect("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object - if (line.find("is_connected(") != -1) { - int start = line.find("is_connected("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - // -- start(a,b,c) -> start(a,Callable(b,c)) Thread - if (line.find("start(") != -1) { - int start = line.find("start("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589 - if (line.find(" _init(") != -1) { - int start = line.find(" _init("); - int end = line.rfind(":") + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start); - } - } - // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message - if (line.find("assert(") != -1) { - int start = line.find("assert("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")"; - } - } - } - // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture - if (line.find("create_from_image(") != -1) { - int start = line.find("create_from_image("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start); - } - } - } - // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e) - if (line.find("set_cell_item(") != -1) { - int start = line.find("set_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() > 2) { - line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c)) - if (line.find("get_cell_item(") != -1) { - int start = line.find("get_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c)) - if (line.find("get_cell_item_orientation(") != -1) { - int start = line.find("get_cell_item_orientation("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - // apply_impulse(A, B) -> apply_impulse(B, A) - if (line.find("apply_impulse(") != -1) { - int start = line.find("apply_impulse("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); - } - } - } - // apply_force(A, B) -> apply_force(B, A) - if (line.find("apply_force(") != -1) { - int start = line.find("apply_force("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); - } - } - } - // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c)) - if (line.find("map_to_world(") != -1) { - int start = line.find("map_to_world("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } + process_gdscript_line(line, reg_container, builtin); } // Collect vector to string @@ -3062,478 +2701,484 @@ void ProjectConverter3To4::rename_gdscript_functions(String &file_content) { } }; -// This is almost 1:1 copy of function which rename gdscript functions -Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &file_content) { +Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &file_content, const RegExContainer ®_container, bool builtin) { int current_line = 1; Vector<String> found_things; - RegEx reg_is_empty = RegEx("\\bempty\\("); - RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])"); - RegEx reg_json_to = RegEx("\\bto_json\\b"); - RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)"); - RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)"); - RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)"); - RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)"); - RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)"); - RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$"); - RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$"); - RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)"); - RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)"); - RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)"); - RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)"); - RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)"); - - CRASH_COND(!reg_is_empty.is_valid()); - CRASH_COND(!reg_super.is_valid()); - CRASH_COND(!reg_json_to.is_valid()); - CRASH_COND(!reg_json_parse.is_valid()); - CRASH_COND(!reg_json_non_new.is_valid()); - CRASH_COND(!reg_export.is_valid()); - CRASH_COND(!reg_export_advanced.is_valid()); - CRASH_COND(!reg_setget_setget.is_valid()); - CRASH_COND(!reg_setget_set.is_valid()); - CRASH_COND(!reg_setget_get.is_valid()); - CRASH_COND(!reg_join.is_valid()); - CRASH_COND(!reg_mixed_tab_space.is_valid()); - CRASH_COND(!reg_image_lock.is_valid()); - CRASH_COND(!reg_image_unlock.is_valid()); - CRASH_COND(!reg_os_fullscreen.is_valid()); - for (String &line : file_content) { String old_line = line; - - if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) { - line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); - line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); + process_gdscript_line(line, reg_container, builtin); + if (old_line != line) { + found_things.append(simple_line_formatter(current_line, old_line, line)); } + } - // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure - line = reg_mixed_tab_space.sub(line, "$1", true); + return found_things; +} +void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContainer ®_container, bool builtin) { + if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) { + line = reg_container.reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); + line = reg_container.reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); + } - // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray - line = reg_join.sub(line, "$2.join($1)", true); + // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure + line = reg_container.reg_mixed_tab_space.sub(line, "$1", true); - // -- empty() -> is_empty() Pool*Array - line = reg_is_empty.sub(line, "is_empty(", true); + // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray + line = reg_container.reg_join.sub(line, "$2.join($1)", true); - // -- \t.func() -> \tsuper.func() Object - line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore" + // -- empty() -> is_empty() Pool*Array + line = reg_container.reg_is_empty.sub(line, "is_empty(", true); - // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON - line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); + // -- \t.func() -> \tsuper.func() Object + line = reg_container.reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore" - // -- to_json(a) -> JSON.new().stringify(a) Object - line = reg_json_to.sub(line, "JSON.new().stringify", true); + // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON + line = reg_container.reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); - // -- parse_json(a) -> JSON.get_data() etc. Object - line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); + // -- to_json(a) -> JSON.new().stringify(a) Object + line = reg_container.reg_json_to.sub(line, "JSON.new().stringify", true); - // -- get_node(@ -> get_node( Node - line = line.replace("get_node(@", "get_node("); + // -- parse_json(a) -> JSON.get_data() etc. Object + line = reg_container.reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true); - // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript - line = reg_export.sub(line, "export var $2: $1"); + // -- get_node(@ -> get_node( Node + line = line.replace("get_node(@", "get_node("); - // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript - line = reg_export_advanced.sub(line, "export var $2$3 # ($1)"); + // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript + line = reg_container.reg_export.sub(line, "export var $2: $1"); - // Setget Setget - line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); + // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript + line = reg_container.reg_export_advanced.sub(line, "export var $2$3 # ($1)"); - // Setget set - line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); + // Setget Setget + line = reg_container.reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); - // Setget get - line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true); + // Setget set + line = reg_container.reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true); - // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true) - line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true); + // Setget get + line = reg_container.reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true); - // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody - if (line.find("move_and_slide(") != -1) { - int start = line.find("move_and_slide("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - String base_obj = get_object_of_execution(line.substr(0, start)); - String starting_space = get_starting_space(line); + // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true) + if (builtin) { + line = reg_container.reg_os_fullscreen.sub(line, "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", $1)", true); + } else { + line = reg_container.reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true); + } - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 1) { - String line_new; + // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody + if (line.find("move_and_slide(") != -1) { + int start = line.find("move_and_slide("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + String base_obj = get_object_of_execution(line.substr(0, start)); + String starting_space = get_starting_space(line); - // motion_velocity - line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() >= 1) { + String line_new; - // up_direction - if (parts.size() >= 2) { - line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n"; - } + // motion_velocity + line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; - // stop_on_slope - if (parts.size() >= 3) { - line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n"; - } + // up_direction + if (parts.size() >= 2) { + line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n"; + } - // max_slides - if (parts.size() >= 4) { - line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n"; - } + // stop_on_slope + if (parts.size() >= 3) { + line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n"; + } - // floor_max_angle - if (parts.size() >= 5) { - line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n"; - } + // max_slides + if (parts.size() >= 4) { + line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n"; + } - // infiinite_interia - if (parts.size() >= 6) { - line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n"; - } + // floor_max_angle + if (parts.size() >= 5) { + line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n"; + } - line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); + // infiinite_interia + if (parts.size() >= 6) { + line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n"; } + + line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); } } + } - // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody - if (line.find("move_and_slide_with_snap(") != -1) { - int start = line.find("move_and_slide_with_snap("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - String base_obj = get_object_of_execution(line.substr(0, start)); - String starting_space = get_starting_space(line); - - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 1) { - String line_new; + // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody + if (line.find("move_and_slide_with_snap(") != -1) { + int start = line.find("move_and_slide_with_snap("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + String base_obj = get_object_of_execution(line.substr(0, start)); + String starting_space = get_starting_space(line); - // motion_velocity - line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() >= 1) { + String line_new; - // snap - if (parts.size() >= 2) { - line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n"; - } + // motion_velocity + line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n"; - // up_direction - if (parts.size() >= 3) { - line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n"; - } + // snap + if (parts.size() >= 2) { + line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n"; + } - // stop_on_slope - if (parts.size() >= 4) { - line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n"; - } + // up_direction + if (parts.size() >= 3) { + line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n"; + } - // max_slides - if (parts.size() >= 5) { - line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n"; - } + // stop_on_slope + if (parts.size() >= 4) { + line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n"; + } - // floor_max_angle - if (parts.size() >= 6) { - line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n"; - } + // max_slides + if (parts.size() >= 5) { + line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n"; + } - // infiinite_interia - if (parts.size() >= 7) { - line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n"; - } + // floor_max_angle + if (parts.size() >= 6) { + line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n"; + } - line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); + // infiinite_interia + if (parts.size() >= 7) { + line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n"; } + + line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start); } } + } - // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object - if (line.find("sort_custom(") != -1) { - int start = line.find("sort_custom("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); - } + // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object + if (line.find("sort_custom(") != -1) { + int start = line.find("sort_custom("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); } } + } - // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem - if (line.find("draw_line(") != -1) { - int start = line.find("draw_line("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 5) { - line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start); - } - } + // -- list_dir_begin( ) -> list_dir_begin() Object + if (line.find("list_dir_begin(") != -1) { + int start = line.find("list_dir_begin("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547"; } + } - // -- func c(var a, var b) -> func c(a, b) - if (line.find("func ") != -1 && line.find("var ") != -1) { - int start = line.find("func "); - start = line.substr(start).find("(") + start; - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); + // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem + if (line.find("draw_line(") != -1) { + int start = line.find("draw_line("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 5) { + line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start); + } + } + } - String start_string = line.substr(0, start) + "("; - for (int i = 0; i < parts.size(); i++) { - start_string += parts[i].strip_edges().trim_prefix("var "); - if (i != parts.size() - 1) { - start_string += ", "; - } + // -- func c(var a, var b) -> func c(a, b) + if (line.find("func ") != -1 && line.find("var ") != -1) { + int start = line.find("func "); + start = line.substr(start).find("(") + start; + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + + String start_string = line.substr(0, start) + "("; + for (int i = 0; i < parts.size(); i++) { + start_string += parts[i].strip_edges().trim_prefix("var "); + if (i != parts.size() - 1) { + start_string += ", "; } - line = start_string + ")" + line.substr(end + start); } + line = start_string + ")" + line.substr(end + start); } + } - // -- yield(this, \"timeout\") -> await this.timeout GDScript - if (line.find("yield(") != -1) { - int start = line.find("yield("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { + // -- yield(this, \"timeout\") -> await this.timeout GDScript + if (line.find("yield(") != -1) { + int start = line.find("yield("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + if (builtin) { + line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace(" ", "") + line.substr(end + start); + } else { line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start); } } } + } - // -- parse_json( AA ) -> TODO Object - if (line.find("parse_json(") != -1) { - int start = line.find("parse_json("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start); - } + // -- parse_json( AA ) -> TODO Object + if (line.find("parse_json(") != -1) { + int start = line.find("parse_json("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start); } + } - // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform - if (line.find(".xform(") != -1) { - int start = line.find(".xform("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 1) { - line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start); - } + // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform + if (line.find(".xform(") != -1) { + int start = line.find(".xform("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 1) { + line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start); } } + } - // -- .xform_inv(Vector3(a,b,c)) -> / Vector3(a,b,c) Transform - if (line.find(".xform_inv(") != -1) { - int start = line.find(".xform_inv("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { + // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform + if (line.find(".xform_inv(") != -1) { + int start = line.find(".xform_inv("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + String object_exec = get_object_of_execution(line.substr(0, start)); + if (line.find(object_exec + ".xform") != -1) { + int start2 = line.find(object_exec + ".xform"); Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 1) { - line = line.substr(0, start) + " / " + parts[0] + line.substr(end + start); + line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start); } } } + } - // -- connect(,,,things) -> connect(,Callable(,),things) Object - if (line.find("connect(") != -1) { - int start = line.find("connect("); - // Protection from disconnect - if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - } - // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object - if (line.find("disconnect(") != -1) { - int start = line.find("disconnect("); + // -- "(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) Object + if (line.find("connect(") != -1) { + int start = line.find("connect("); + // Protection from disconnect + if (start == 0 || line.get(start - 1) != 's') { int end = get_end_parenthess(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + } else if (parts.size() >= 4) { + line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ").bind(" + parts[3].lstrip("[").rstrip("]") + ")" + connect_arguments(parts, 4) + ")" + line.substr(end + start); } } } - // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object - if (line.find("is_connected(") != -1) { - int start = line.find("is_connected("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } + } + // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object + if (line.find("disconnect(") != -1) { + int start = line.find("disconnect("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } - // -- start(a,b,c) -> start(a,Callable(b,c)) Thread - if (line.find("start(") != -1) { - int start = line.find("start("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } + } + // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object + if (line.find("is_connected(") != -1) { + int start = line.find("is_connected("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } - // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589 - if (line.find(" _init(") != -1) { - int start = line.find(" _init("); - int end = line.rfind(":") + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start); + } + // -- start(a,b) -> start(Callable(a,b)) Thread + // -- start(a,b,c,d) -> start(Callable(a,b).bind(c),d) Thread + if (line.find("start(") != -1) { + int start = line.find("start("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); + } else if (parts.size() >= 3) { + line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + ").bind(" + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); } } - // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message - if (line.find("assert(") != -1) { - int start = line.find("assert("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")"; - } + } + // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589 + if (line.find(" _init(") != -1) { + int start = line.find(" _init("); + int end = line.rfind(":") + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start); + } + } + // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message + if (line.find("assert(") != -1) { + int start = line.find("assert("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")"; } } - // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture - if (line.find("create_from_image(") != -1) { - int start = line.find("create_from_image("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start); - } + } + // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture + if (line.find("create_from_image(") != -1) { + int start = line.find("create_from_image("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start); } } - // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e) - if (line.find("set_cell_item(") != -1) { - int start = line.find("set_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() > 2) { - line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } + } + // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e) + if (line.find("set_cell_item(") != -1) { + int start = line.find("set_cell_item("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() > 2) { + line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start); } } - // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c)) - if (line.find("get_cell_item(") != -1) { - int start = line.find("get_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } + } + // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c)) + if (line.find("get_cell_item(") != -1) { + int start = line.find("get_cell_item("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } - // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c)) - if (line.find("get_cell_item_orientation(") != -1) { - int start = line.find("get_cell_item_orientation("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } + } + // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c)) + if (line.find("get_cell_item_orientation(") != -1) { + int start = line.find("get_cell_item_orientation("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } - - // apply_impulse(A, B) -> apply_impulse(B, A) - if (line.find("apply_impulse(") != -1) { - int start = line.find("apply_impulse("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); - } + } + // apply_impulse(A, B) -> apply_impulse(B, A) + if (line.find("apply_impulse(") != -1) { + int start = line.find("apply_impulse("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); } } - // apply_force(A, B) -> apply_force(B, A) - if (line.find("apply_force(") != -1) { - int start = line.find("apply_force("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 2) { - line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); - } + } + // apply_force(A, B) -> apply_force(B, A) + if (line.find("apply_force(") != -1) { + int start = line.find("apply_force("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 2) { + line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start); } } - // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c)) - if (line.find("map_to_world(") != -1) { - int start = line.find("get_cell_item_orientation("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } + } + // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c)) + if (line.find("map_to_world(") != -1) { + int start = line.find("map_to_world("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } - - if (old_line != line) { - found_things.append(simple_line_formatter(current_line, old_line, line)); + } + // OS.get_window_safe_area() -> DisplayServer.get_display_safe_area() + if (line.find("OS.get_window_safe_area(") != -1) { + int start = line.find("OS.get_window_safe_area("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 0) { + line = line.substr(0, start) + "DisplayServer.get_display_safe_area()" + line.substr(end + start); + } } } - - return found_things; } -void ProjectConverter3To4::rename_csharp_functions(String &file_content) { - // Custom renaming, each rule needs to be set manually - // Don't forget to put validate each rule in validate_conversion function - Vector<String> lines = file_content.split("\n"); +void ProjectConverter3To4::process_csharp_line(String &line) { + // TODO maybe this can be changed to normal rule + line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()"); - for (String &line : lines) { - // TODO maybe this can be changed to normal rule - line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()"); - - // -- Connect(,,,things) -> Connect(,Callable(,),things) Object - if (line.find("Connect(") != -1) { - int start = line.find("Connect("); - // Protection from disconnect - if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - } - // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object - if (line.find("Disconnect(") != -1) { - int start = line.find("Disconnect("); + // -- Connect(,,,things) -> Connect(,Callable(,),things) Object + if (line.find("Connect(") != -1) { + int start = line.find("Connect("); + // Protection from disconnect + if (start == 0 || line.get(start - 1) != 's') { int end = get_end_parenthess(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + if (parts.size() >= 3) { + line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); } } } - // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object - if (line.find("IsConnected(") != -1) { - int start = line.find("IsConnected("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } + } + // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object + if (line.find("Disconnect(") != -1) { + int start = line.find("Disconnect("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); } } } + // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object + if (line.find("IsConnected(") != -1) { + int start = line.find("IsConnected("); + int end = get_end_parenthess(line.substr(start)) + 1; + if (end > -1) { + Vector<String> parts = parse_arguments(line.substr(start, end)); + if (parts.size() == 3) { + line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + } + } + } +} + +void ProjectConverter3To4::rename_csharp_functions(String &file_content) { + Vector<String> lines = file_content.split("\n"); + + for (String &line : lines) { + process_csharp_line(line); + } // Collect vector to string file_content = ""; @@ -3554,47 +3199,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<St for (String &line : file_content) { String old_line = line; - - // TODO maybe this can be changed to normal rule - line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()"); - - // -- Connect(,,,things) -> connect(,Callable(,),things) Object - if (line.find("Connect(") != -1) { - int start = line.find("Connect("); - // Protection from disconnect - if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() >= 3) { - line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); - } - } - } - } - // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object - if (line.find("Disconnect(") != -1) { - int start = line.find("Disconnect("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "Disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object - if (line.find("IsConnected(") != -1) { - int start = line.find("IsConnected("); - int end = get_end_parenthess(line.substr(start)) + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - if (parts.size() == 3) { - line = line.substr(0, start) + "IsConnected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); - } - } - } - + process_csharp_line(line); if (old_line != line) { found_things.append(simple_line_formatter(current_line, old_line, line)); } @@ -3603,88 +3208,205 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<St return found_things; } -void ProjectConverter3To4::rename_gdscript_keywords(String &file_content){ - { RegEx reg_tool = RegEx("([\n]+)tool"); -CRASH_COND(!reg_tool.is_valid()); -file_content = reg_tool.sub(file_content, "$1@tool", true); -RegEx reg_tool2 = RegEx("^tool"); -CRASH_COND(!reg_tool2.is_valid()); -file_content = reg_tool2.sub(file_content, "@tool", true); -} -{ - RegEx reg_export = RegEx("([\n\t]+)export\\b"); - CRASH_COND(!reg_export.is_valid()); - file_content = reg_export.sub(file_content, "$1@export", true); - RegEx reg_export2 = RegEx("^export"); - CRASH_COND(!reg_export2.is_valid()); - file_content = reg_export2.sub(file_content, "@export", true); -} -{ - RegEx reg_onready = RegEx("([\n]+)onready"); - CRASH_COND(!reg_onready.is_valid()); - file_content = reg_onready.sub(file_content, "$1@onready", true); - RegEx reg_onready2 = RegEx("^onready"); - CRASH_COND(!reg_onready2.is_valid()); - file_content = reg_onready2.sub(file_content, "@onready", true); -} -{ - RegEx reg_master = RegEx("([\n]+)master func"); - CRASH_COND(!reg_master.is_valid()); - file_content = reg_master.sub(file_content, "$1@rpc(any) func", true); - RegEx reg_master2 = RegEx("^master func"); - CRASH_COND(!reg_master2.is_valid()); - file_content = reg_master2.sub(file_content, "@rpc(any) func", true); -} -{ - RegEx reg_puppet = RegEx("([\n]+)puppet func"); - CRASH_COND(!reg_puppet.is_valid()); - file_content = reg_puppet.sub(file_content, "$1@rpc(auth) func", true); - RegEx reg_puppet2 = RegEx("^puppet func"); - CRASH_COND(!reg_puppet2.is_valid()); - file_content = reg_puppet2.sub(file_content, "@rpc(auth) func", true); -} -{ - RegEx reg_remote = RegEx("([\n]+)remote func"); - CRASH_COND(!reg_remote.is_valid()); - file_content = reg_remote.sub(file_content, "$1@rpc(any) func", true); - RegEx reg_remote2 = RegEx("^remote func"); - CRASH_COND(!reg_remote2.is_valid()); - file_content = reg_remote2.sub(file_content, "@rpc(any) func", true); -} -{ - RegEx reg_remotesync = RegEx("([\n]+)remotesync func"); - CRASH_COND(!reg_remotesync.is_valid()); - file_content = reg_remotesync.sub(file_content, "$1@rpc(any,sync) func", true); - RegEx reg_remotesync2 = RegEx("^remotesync func"); - CRASH_COND(!reg_remotesync2.is_valid()); - file_content = reg_remotesync2.sub(file_content, "@rpc(any,sync) func", true); -} -{ - RegEx reg_sync = RegEx("([\n]+)sync func"); - CRASH_COND(!reg_sync.is_valid()); - file_content = reg_sync.sub(file_content, "$1@rpc(any,sync) func", true); - RegEx reg_sync2 = RegEx("^sync func"); - CRASH_COND(!reg_sync2.is_valid()); - file_content = reg_sync2.sub(file_content, "@rpc(any,sync) func", true); -} -{ - RegEx reg_puppetsync = RegEx("([\n]+)puppetsync func"); - CRASH_COND(!reg_puppetsync.is_valid()); - file_content = reg_puppetsync.sub(file_content, "$1@rpc(auth,sync) func", true); - RegEx reg_puppetsync2 = RegEx("^puppetsync func"); - CRASH_COND(!reg_puppetsync2.is_valid()); - file_content = reg_puppetsync2.sub(file_content, "@rpc(auth,sync) func", true); +void ProjectConverter3To4::rename_csharp_attributes(String &file_content) { + // -- [Remote] -> [RPC(MultiplayerAPI.RPCMode.AnyPeer)] + { + RegEx reg_remote = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_remote.is_valid()); + file_content = reg_remote.sub(file_content, "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", true); + } + // -- [RemoteSync] -> [RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)] + { + RegEx reg_remotesync = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_remotesync.is_valid()); + file_content = reg_remotesync.sub(file_content, "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", true); + } + // -- [Puppet] -> [RPC] + { + RegEx reg_puppet = RegEx("\\[(Puppet|Slave)(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_puppet.is_valid()); + file_content = reg_puppet.sub(file_content, "[RPC]", true); + } + // -- [PuppetSync] -> [RPC(CallLocal = true)] + { + RegEx reg_puppetsync = RegEx("\\[PuppetSync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_puppetsync.is_valid()); + file_content = reg_puppetsync.sub(file_content, "[RPC(CallLocal = true)]", true); + } + String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n"; + // -- [Master] -> [RPC] + { + RegEx reg_remote = RegEx("\\[Master(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_remote.is_valid()); + file_content = reg_remote.sub(file_content, error_message + "[RPC]", true); + } + // -- [MasterSync] -> [RPC(CallLocal = true)] + { + RegEx reg_remote = RegEx("\\[MasterSync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!reg_remote.is_valid()); + file_content = reg_remote.sub(file_content, error_message + "[RPC(CallLocal = true)]", true); + } } -{ - RegEx reg_mastersync = RegEx("([\n]+)mastersync func"); - CRASH_COND(!reg_mastersync.is_valid()); - file_content = reg_mastersync.sub(file_content, "$1@rpc(any,sync) func", true); - RegEx reg_mastersync2 = RegEx("^mastersync func"); - CRASH_COND(!reg_mastersync2.is_valid()); - file_content = reg_mastersync2.sub(file_content, "@rpc(any,sync) func", true); + +Vector<String> ProjectConverter3To4::check_for_rename_csharp_attributes(Vector<String> &file_content) { + int current_line = 1; + + Vector<String> found_things; + + for (String &line : file_content) { + String old; + old = line; + { + RegEx regex = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", line)); + } + old = line; + { + RegEx regex = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", line)); + } + old = line; + { + RegEx regex = RegEx("\\[Puppet(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[Puppet]", "[RPC]", line)); + } + old = line; + { + RegEx regex = RegEx("\\[(Puppet|Slave)Sync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC(CallLocal = true)]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[PuppetSync]", "[RPC(CallLocal = true)]", line)); + } + old = line; + { + RegEx regex = RegEx("\\[Master(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[Master]", "[RPC]", line)); + } + old = line; + { + RegEx regex = RegEx("\\[MasterSync(Attribute)?(\\(\\))?\\]"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "[RPC(CallLocal = true)]", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "[MasterSync]", "[RPC(CallLocal = true)]", line)); + } + + current_line++; + } + + return found_things; } + +void ProjectConverter3To4::rename_gdscript_keywords(String &file_content) { + { + RegEx reg_first = RegEx("([\n]+)tool"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@tool", true); + RegEx reg_second = RegEx("^tool"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@tool", true); + } + { + RegEx reg_first = RegEx("([\n\t]+)export\\b"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@export", true); + RegEx reg_second = RegEx("^export"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@export", true); + } + { + RegEx reg_first = RegEx("([\n]+)onready"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@onready", true); + RegEx reg_second = RegEx("^onready"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@onready", true); + } + { + RegEx reg_first = RegEx("([\n]+)remote func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc(any_peer) func", true); + RegEx reg_second = RegEx("^remote func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc(any_peer) func", true); + } + { + RegEx reg_first = RegEx("([\n]+)remotesync func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc(any_peer, call_local) func", true); + RegEx reg_second = RegEx("^remotesync func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc(any_peer, call_local) func", true); + } + { + RegEx reg_first = RegEx("([\n]+)sync func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc(any_peer, call_local) func", true); + RegEx reg_second = RegEx("^sync func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc(any_peer, call_local) func", true); + } + { + RegEx reg_first = RegEx("([\n]+)slave func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc func", true); + RegEx reg_second = RegEx("^slave func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc func", true); + } + { + RegEx reg_first = RegEx("([\n]+)puppet func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc func", true); + RegEx reg_second = RegEx("^puppet func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc func", true); + } + { + RegEx reg_first = RegEx("([\n]+)puppetsync func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1@rpc(call_local) func", true); + RegEx reg_second = RegEx("^puppetsync func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, "@rpc(call_local) func", true); + } + String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n"; + { + RegEx reg_first = RegEx("([\n]+)master func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1" + error_message + "@rpc func", true); + RegEx reg_second = RegEx("^master func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, error_message + "@rpc func", true); + } + { + RegEx reg_first = RegEx("([\n]+)mastersync func"); + CRASH_COND(!reg_first.is_valid()); + file_content = reg_first.sub(file_content, "$1" + error_message + "@rpc(call_local) func", true); + RegEx reg_second = RegEx("^mastersync func"); + CRASH_COND(!reg_second.is_valid()); + file_content = reg_second.sub(file_content, error_message + "@rpc(call_local) func", true); + } } -; Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &file_content) { Vector<String> found_things; @@ -3695,96 +3417,105 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S String old; old = line; { - RegEx reg_tool2 = RegEx("^tool"); - CRASH_COND(!reg_tool2.is_valid()); - line = reg_tool2.sub(line, "@tool", true); + RegEx reg_first = RegEx("^tool"); + CRASH_COND(!reg_first.is_valid()); + line = reg_first.sub(line, "@tool", true); } if (old != line) { found_things.append(line_formatter(current_line, "tool", "@tool", line)); } old = line; { - RegEx reg_export = RegEx("([\t]+)export\\b"); - CRASH_COND(!reg_export.is_valid()); - line = reg_export.sub(line, "$1@export", true); - RegEx reg_export2 = RegEx("^export"); - CRASH_COND(!reg_export2.is_valid()); - line = reg_export2.sub(line, "@export", true); + RegEx reg_first = RegEx("([\t]+)export\\b"); + CRASH_COND(!reg_first.is_valid()); + line = reg_first.sub(line, "$1@export", true); + RegEx reg_second = RegEx("^export"); + CRASH_COND(!reg_second.is_valid()); + line = reg_second.sub(line, "@export", true); } if (old != line) { found_things.append(line_formatter(current_line, "export", "@export", line)); } old = line; { - RegEx reg_onready2 = RegEx("^onready"); - CRASH_COND(!reg_onready2.is_valid()); - line = reg_onready2.sub(line, "@onready", true); + RegEx reg_first = RegEx("^onready"); + CRASH_COND(!reg_first.is_valid()); + line = reg_first.sub(line, "@onready", true); } if (old != line) { found_things.append(line_formatter(current_line, "onready", "@onready", line)); } old = line; { - RegEx reg_master2 = RegEx("^master func"); - CRASH_COND(!reg_master2.is_valid()); - line = reg_master2.sub(line, "@rpc(any) func", true); + RegEx regex = RegEx("^remote func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc(any_peer) func", true); + } + if (old != line) { + found_things.append(line_formatter(current_line, "remote func", "@rpc(any_peer) func", line)); + } + old = line; + { + RegEx regex = RegEx("^remotesync func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc(any_peer, call_local)) func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "master func", "@rpc(any) func", line)); + found_things.append(line_formatter(current_line, "remotesync func", "@rpc(any_peer, call_local)) func", line)); } old = line; { - RegEx reg_puppet2 = RegEx("^puppet func"); - CRASH_COND(!reg_puppet2.is_valid()); - line = reg_puppet2.sub(line, "@rpc(auth) func", true); + RegEx regex = RegEx("^sync func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc(any_peer, call_local)) func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "puppet func", "@rpc(auth) func", line)); + found_things.append(line_formatter(current_line, "sync func", "@rpc(any_peer, call_local)) func", line)); } old = line; { - RegEx reg_remote2 = RegEx("^remote func"); - CRASH_COND(!reg_remote2.is_valid()); - line = reg_remote2.sub(line, "@rpc(any) func", true); + RegEx regex = RegEx("^slave func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "remote func", "@rpc(any) func", line)); + found_things.append(line_formatter(current_line, "slave func", "@rpc func", line)); } old = line; { - RegEx reg_remotesync2 = RegEx("^remotesync func"); - CRASH_COND(!reg_remotesync2.is_valid()); - line = reg_remotesync2.sub(line, "@rpc(any,sync) func", true); + RegEx regex = RegEx("^puppet func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "remotesync func", "@rpc(any,sync) func", line)); + found_things.append(line_formatter(current_line, "puppet func", "@rpc func", line)); } old = line; { - RegEx reg_sync2 = RegEx("^sync func"); - CRASH_COND(!reg_sync2.is_valid()); - line = reg_sync2.sub(line, "@rpc(any,sync) func", true); + RegEx regex = RegEx("^puppetsync func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc(call_local) func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "sync func", "@rpc(any,sync) func", line)); + found_things.append(line_formatter(current_line, "puppetsync func", "@rpc(call_local) func", line)); } old = line; { - RegEx reg_puppetsync2 = RegEx("^puppetsync func"); - CRASH_COND(!reg_puppetsync2.is_valid()); - line = reg_puppetsync2.sub(line, "@rpc(auth,sync) func", true); + RegEx regex = RegEx("^master func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "puppetsync func", "@rpc(any,sync) func", line)); + found_things.append(line_formatter(current_line, "master func", "@rpc func", line)); } old = line; { - RegEx reg_mastersync2 = RegEx("^mastersync func"); - CRASH_COND(!reg_mastersync2.is_valid()); - line = reg_mastersync2.sub(line, "@rpc(any,sync) func", true); + RegEx regex = RegEx("^mastersync func"); + CRASH_COND(!regex.is_valid()); + line = regex.sub(line, "@rpc(call_local) func", true); } if (old != line) { - found_things.append(line_formatter(current_line, "mastersync", "@rpc(any,sync) func", line)); + found_things.append(line_formatter(current_line, "mastersync func", "@rpc(call_local) func", line)); } old = line; @@ -3808,7 +3539,7 @@ Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &fil int current_line = 1; for (String &line : file_content) { - Array reg_match = reg.search_all(line); + TypedArray<RegExMatch> reg_match = reg.search_all(line); if (reg_match.size() > 0) { found_things.append(line_formatter(current_line, from.replace("\\.", "."), to, line)); // Without replacing it will print "\.shader" instead ".shader" } @@ -3839,7 +3570,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_common(const char *array[] int current_line = 1; for (String &line : file_content) { - Array reg_match = reg.search_all(line); + TypedArray<RegExMatch> reg_match = reg.search_all(line); if (reg_match.size() > 0) { found_things.append(line_formatter(current_line, array[current_index][0], array[current_index][1], line)); } diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h index 95239666e0..8526e2ceb9 100644 --- a/editor/project_converter_3_to_4.h +++ b/editor/project_converter_3_to_4.h @@ -37,17 +37,26 @@ #include "core/string/ustring.h" class ProjectConverter3To4 { +public: + class RegExContainer; + +private: void rename_enums(String &file_content); Vector<String> check_for_rename_enums(Vector<String> &file_content); void rename_classes(String &file_content); Vector<String> check_for_rename_classes(Vector<String> &file_content); - void rename_gdscript_functions(String &file_content); - Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content); + void rename_gdscript_functions(String &file_content, const RegExContainer ®_container, bool builtin); + Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content, const RegExContainer ®_container, bool builtin); + void process_gdscript_line(String &line, const RegExContainer ®_container, bool builtin); void rename_csharp_functions(String &file_content); Vector<String> check_for_rename_csharp_functions(Vector<String> &file_content); + void process_csharp_line(String &line); + + void rename_csharp_attributes(String &file_content); + Vector<String> check_for_rename_csharp_attributes(Vector<String> &file_content); void rename_gdscript_keywords(String &file_content); Vector<String> check_for_rename_gdscript_keywords(Vector<String> &file_content); @@ -71,9 +80,10 @@ class ProjectConverter3To4 { bool test_single_array(const char *array[][2], bool ignore_second_check = false); bool test_conversion_single_additional(String name, String expected, void (ProjectConverter3To4::*func)(String &), String what); + bool test_conversion_single_additional_builtin(String name, String expected, void (ProjectConverter3To4::*func)(String &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin); bool test_conversion_single_normal(String name, String expected, const char *array[][2], String what); bool test_array_names(); - bool test_conversion(); + bool test_conversion(const RegExContainer ®_container); public: int validate_conversion(); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index f7ef574205..21891e381b 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -42,6 +42,7 @@ #include "core/string/translation.h" #include "core/version.h" #include "editor/editor_file_dialog.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_themes.h" @@ -57,10 +58,6 @@ #include "servers/navigation_server_3d.h" #include "servers/physics_server_2d.h" -static inline String get_project_key_from_path(const String &dir) { - return dir.replace("/", "::"); -} - class ProjectDialog : public ConfirmationDialog { GDCLASS(ProjectDialog, ConfirmationDialog); @@ -491,7 +488,7 @@ private: if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) { set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR); } else { - ResourceSaver::save(dir.plus_file("icon.png"), create_unscaled_default_project_icon()); + ResourceSaver::save(create_unscaled_default_project_icon(), dir.plus_file("icon.png")); EditorVCSInterface::create_vcs_metadata_files(EditorVCSInterface::VCSMetadata(vcs_metadata_selection->get_selected()), dir); } } else if (mode == MODE_INSTALL) { @@ -600,9 +597,6 @@ private: if (dir.ends_with("/")) { dir = dir.substr(0, dir.length() - 1); } - String proj = get_project_key_from_path(dir); - EditorSettings::get_singleton()->set("projects/" + proj, dir); - EditorSettings::get_singleton()->save(); hide(); emit_signal(SNAME("project_created"), dir); @@ -646,14 +640,6 @@ private: protected: static void _bind_methods() { - ClassDB::bind_method("_browse_path", &ProjectDialog::_browse_path); - ClassDB::bind_method("_create_folder", &ProjectDialog::_create_folder); - ClassDB::bind_method("_text_changed", &ProjectDialog::_text_changed); - ClassDB::bind_method("_path_text_changed", &ProjectDialog::_path_text_changed); - ClassDB::bind_method("_path_selected", &ProjectDialog::_path_selected); - ClassDB::bind_method("_file_selected", &ProjectDialog::_file_selected); - ClassDB::bind_method("_install_path_selected", &ProjectDialog::_install_path_selected); - ClassDB::bind_method("_browse_install_path", &ProjectDialog::_browse_install_path); ADD_SIGNAL(MethodInfo("project_created")); ADD_SIGNAL(MethodInfo("projects_updated")); } @@ -997,7 +983,6 @@ public: // Can often be passed by copy struct Item { - String project_key; String project_name; String description; String path; @@ -1014,8 +999,7 @@ public: Item() {} - Item(const String &p_project, - const String &p_name, + Item(const String &p_name, const String &p_description, const String &p_path, const String &p_icon, @@ -1026,7 +1010,6 @@ public: bool p_grayed, bool p_missing, int p_version) { - project_key = p_project; project_name = p_name; description = p_description; path = p_path; @@ -1042,7 +1025,7 @@ public: } _FORCE_INLINE_ bool operator==(const Item &l) const { - return project_key == l.project_key; + return path == l.path; } }; @@ -1055,6 +1038,7 @@ public: void _global_menu_open_project(const Variant &p_tag); void update_dock_menu(); + void migrate_config(); void load_projects(); void set_search_term(String p_search_term); void set_order_option(int p_option); @@ -1070,6 +1054,8 @@ public: bool is_any_project_missing() const; void erase_missing_projects(); int refresh_project(const String &dir_path); + void add_project(const String &dir_path, bool favorite); + void save_config(); private: static void _bind_methods(); @@ -1090,12 +1076,15 @@ private: String _search_term; FilterOption _order_option; - HashSet<String> _selected_project_keys; + HashSet<String> _selected_project_paths; String _last_clicked; // Project key VBoxContainer *_scroll_children; int _icon_load_index; Vector<Item> _projects; + + ConfigFile _config; + String _config_path; }; struct ProjectListComparator { @@ -1111,7 +1100,7 @@ struct ProjectListComparator { } switch (order_option) { case PATH: - return a.project_key < b.project_key; + return a.path < b.path; case EDIT_DATE: return a.last_edited > b.last_edited; default: @@ -1128,6 +1117,7 @@ ProjectList::ProjectList() { _icon_load_index = 0; project_opening_initiated = false; + _config_path = EditorPaths::get_singleton()->get_data_dir().plus_file("projects.cfg"); } ProjectList::~ProjectList() { @@ -1179,9 +1169,8 @@ void ProjectList::load_project_icon(int p_index) { } // Load project data from p_property_key and return it in a ProjectList::Item. p_favorite is passed directly into the Item. -ProjectList::Item ProjectList::load_project_data(const String &p_property_key, bool p_favorite) { - String path = EditorSettings::get_singleton()->get(p_property_key); - String conf = path.plus_file("project.godot"); +ProjectList::Item ProjectList::load_project_data(const String &p_path, bool p_favorite) { + String conf = p_path.plus_file("project.godot"); bool grayed = false; bool missing = false; @@ -1217,7 +1206,7 @@ ProjectList::Item ProjectList::load_project_data(const String &p_property_key, b // when editing a project (but not when running it). last_edited = FileAccess::get_modified_time(conf); - String fscache = path.plus_file(".fscache"); + String fscache = p_path.plus_file(".fscache"); if (FileAccess::exists(fscache)) { uint64_t cache_modified = FileAccess::get_modified_time(fscache); if (cache_modified > last_edited) { @@ -1230,9 +1219,38 @@ ProjectList::Item ProjectList::load_project_data(const String &p_property_key, b print_line("Project is missing: " + conf); } - const String project_key = p_property_key.get_slice("/", 1); + return Item(project_name, description, p_path, icon, main_scene, unsupported_features, last_edited, p_favorite, grayed, missing, config_version); +} + +void ProjectList::migrate_config() { + // Proposal #1637 moved the project list from editor settings to a separate config file + // If the new config file doesn't exist, populate it from EditorSettings + if (FileAccess::exists(_config_path)) { + return; + } + print_line("Migrating legacy project list"); + + List<PropertyInfo> properties; + EditorSettings::get_singleton()->get_property_list(&properties); - return Item(project_key, project_name, description, path, icon, main_scene, unsupported_features, last_edited, p_favorite, grayed, missing, config_version); + for (const PropertyInfo &E : properties) { + // This is actually something like "projects/C:::Documents::Godot::Projects::MyGame" + String property_key = E.name; + if (!property_key.begins_with("projects/")) { + continue; + } + + String path = EditorSettings::get_singleton()->get(property_key); + String favoriteKey = "favorite_projects/" + property_key.get_slice("/", 1); + bool favorite = EditorSettings::get_singleton()->has_setting(favoriteKey); + add_project(path, favorite); + if (favorite) { + EditorSettings::get_singleton()->erase(favoriteKey); + } + EditorSettings::get_singleton()->erase(property_key); + } + + save_config(); } void ProjectList::load_projects() { @@ -1247,37 +1265,15 @@ void ProjectList::load_projects() { } _projects.clear(); _last_clicked = ""; - _selected_project_keys.clear(); - - // Load data - // TODO Would be nice to change how projects and favourites are stored... it complicates things a bit. - // Use a dictionary associating project path to metadata (like is_favorite). - - List<PropertyInfo> properties; - EditorSettings::get_singleton()->get_property_list(&properties); - - HashSet<String> favorites; - // Find favourites... - for (const PropertyInfo &E : properties) { - String property_key = E.name; - if (property_key.begins_with("favorite_projects/")) { - favorites.insert(property_key); - } - } - - for (const PropertyInfo &E : properties) { - // This is actually something like "projects/C:::Documents::Godot::Projects::MyGame" - String property_key = E.name; - if (!property_key.begins_with("projects/")) { - continue; - } - - String project_key = property_key.get_slice("/", 1); - bool favorite = favorites.has("favorite_projects/" + project_key); + _selected_project_paths.clear(); - Item item = load_project_data(property_key, favorite); + List<String> sections; + _config.load(_config_path); + _config.get_sections(§ions); - _projects.push_back(item); + for (const String &path : sections) { + bool favorite = _config.get_value(path, "favorite", false); + _projects.push_back(load_project_data(path, favorite)); } // Create controls @@ -1348,8 +1344,8 @@ void ProjectList::create_project_item_control(int p_index) { Color font_color = get_theme_color(SNAME("font_color"), SNAME("Tree")); ProjectListItemControl *hb = memnew(ProjectListItemControl); - hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw), varray(hb)); - hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input), varray(hb)); + hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw).bind(hb)); + hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input).bind(hb)); hb->add_theme_constant_override("separation", 10 * EDSCALE); hb->set_tooltip(item.description); @@ -1360,7 +1356,7 @@ void ProjectList::create_project_item_control(int p_index) { favorite->set_normal_texture(favorite_icon); // This makes the project's "hover" style display correctly when hovering the favorite icon. favorite->set_mouse_filter(MOUSE_FILTER_PASS); - favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed), varray(hb)); + favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed).bind(hb)); favorite_box->add_child(favorite); favorite_box->set_alignment(BoxContainer::ALIGNMENT_CENTER); hb->add_child(favorite_box); @@ -1433,7 +1429,7 @@ void ProjectList::create_project_item_control(int p_index) { path_hb->add_child(show); if (!item.missing) { - show->connect("pressed", callable_mp(this, &ProjectList::_show_project), varray(item.path)); + show->connect("pressed", callable_mp(this, &ProjectList::_show_project).bind(item.path)); show->set_tooltip(TTR("Show in File Manager")); } else { show->set_tooltip(TTR("Error: Project is missing on the filesystem.")); @@ -1504,19 +1500,19 @@ void ProjectList::sort_projects() { const HashSet<String> &ProjectList::get_selected_project_keys() const { // Faster if that's all you need - return _selected_project_keys; + return _selected_project_paths; } Vector<ProjectList::Item> ProjectList::get_selected_projects() const { Vector<Item> items; - if (_selected_project_keys.size() == 0) { + if (_selected_project_paths.size() == 0) { return items; } - items.resize(_selected_project_keys.size()); + items.resize(_selected_project_paths.size()); int j = 0; for (int i = 0; i < _projects.size(); ++i) { const Item &item = _projects[i]; - if (_selected_project_keys.has(item.project_key)) { + if (_selected_project_paths.has(item.path)) { items.write[j++] = item; } } @@ -1530,41 +1526,40 @@ void ProjectList::ensure_project_visible(int p_index) { } int ProjectList::get_single_selected_index() const { - if (_selected_project_keys.size() == 0) { + if (_selected_project_paths.size() == 0) { // Default selection return 0; } String key; - if (_selected_project_keys.size() == 1) { + if (_selected_project_paths.size() == 1) { // Only one selected - key = *_selected_project_keys.begin(); + key = *_selected_project_paths.begin(); } else { // Multiple selected, consider the last clicked one as "main" key = _last_clicked; } for (int i = 0; i < _projects.size(); ++i) { - if (_projects[i].project_key == key) { + if (_projects[i].path == key) { return i; } } return 0; } -void ProjectList::remove_project(int p_index, bool p_update_settings) { +void ProjectList::remove_project(int p_index, bool p_update_config) { const Item item = _projects[p_index]; // Take a copy - _selected_project_keys.erase(item.project_key); + _selected_project_paths.erase(item.path); - if (_last_clicked == item.project_key) { + if (_last_clicked == item.path) { _last_clicked = ""; } memdelete(item.control); _projects.remove_at(p_index); - if (p_update_settings) { - EditorSettings::get_singleton()->erase("projects/" + item.project_key); - EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key); + if (p_update_config) { + _config.erase_section(item.path); // Not actually saving the file, in case you are doing more changes to settings } @@ -1602,41 +1597,19 @@ void ProjectList::erase_missing_projects() { } print_line("Removed " + itos(deleted_count) + " projects from the list, remaining " + itos(remaining_count) + " projects"); - - EditorSettings::get_singleton()->save(); + save_config(); } int ProjectList::refresh_project(const String &dir_path) { - // Reads editor settings and reloads information about a specific project. + // Reloads information about a specific project. // If it wasn't loaded and should be in the list, it is added (i.e new project). // If it isn't in the list anymore, it is removed. // If it is in the list but doesn't exist anymore, it is marked as missing. - String project_key = get_project_key_from_path(dir_path); - - // Read project manager settings - bool is_favourite = false; - bool should_be_in_list = false; - String property_key = "projects/" + project_key; - { - List<PropertyInfo> properties; - EditorSettings::get_singleton()->get_property_list(&properties); - String favorite_property_key = "favorite_projects/" + project_key; - - bool found = false; - for (const PropertyInfo &E : properties) { - String prop = E.name; - if (!found && prop == property_key) { - found = true; - } else if (!is_favourite && prop == favorite_property_key) { - is_favourite = true; - } - } - - should_be_in_list = found; - } + bool should_be_in_list = _config.has_section(dir_path); + bool is_favourite = _config.get_value(dir_path, "favorite", false); - bool was_selected = _selected_project_keys.has(project_key); + bool was_selected = _selected_project_paths.has(dir_path); // Remove item in any case for (int i = 0; i < _projects.size(); ++i) { @@ -1651,7 +1624,7 @@ int ProjectList::refresh_project(const String &dir_path) { if (should_be_in_list) { // Recreate it with updated info - Item item = load_project_data(property_key, is_favourite); + Item item = load_project_data(dir_path, is_favourite); _projects.push_back(item); create_project_item_control(_projects.size() - 1); @@ -1659,7 +1632,7 @@ int ProjectList::refresh_project(const String &dir_path) { sort_projects(); for (int i = 0; i < _projects.size(); ++i) { - if (_projects[i].project_key == project_key) { + if (_projects[i].path == dir_path) { if (was_selected) { select_project(i); ensure_project_visible(i); @@ -1675,13 +1648,23 @@ int ProjectList::refresh_project(const String &dir_path) { return index; } +void ProjectList::add_project(const String &dir_path, bool favorite) { + if (!_config.has_section(dir_path)) { + _config.set_value(dir_path, "favorite", favorite); + } +} + +void ProjectList::save_config() { + _config.save(_config_path); +} + int ProjectList::get_project_count() const { return _projects.size(); } void ProjectList::select_project(int p_index) { Vector<Item> previous_selected_items = get_selected_projects(); - _selected_project_keys.clear(); + _selected_project_paths.clear(); for (int i = 0; i < previous_selected_items.size(); ++i) { previous_selected_items[i].control->update(); @@ -1703,7 +1686,7 @@ void ProjectList::select_first_visible_project() { if (!found) { // Deselect all projects if there are no visible projects in the list. - _selected_project_keys.clear(); + _selected_project_paths.clear(); } } @@ -1725,24 +1708,23 @@ void ProjectList::select_range(int p_begin, int p_end) { void ProjectList::toggle_select(int p_index) { Item &item = _projects.write[p_index]; - if (_selected_project_keys.has(item.project_key)) { - _selected_project_keys.erase(item.project_key); + if (_selected_project_paths.has(item.path)) { + _selected_project_paths.erase(item.path); } else { - _selected_project_keys.insert(item.project_key); + _selected_project_paths.insert(item.path); } item.control->update(); } void ProjectList::erase_selected_projects(bool p_delete_project_contents) { - if (_selected_project_keys.size() == 0) { + if (_selected_project_paths.size() == 0) { return; } for (int i = 0; i < _projects.size(); ++i) { Item &item = _projects.write[i]; - if (_selected_project_keys.has(item.project_key) && item.control->is_visible()) { - EditorSettings::get_singleton()->erase("projects/" + item.project_key); - EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key); + if (_selected_project_paths.has(item.path) && item.control->is_visible()) { + _config.erase_section(item.path); if (p_delete_project_contents) { OS::get_singleton()->move_to_trash(item.path); @@ -1754,9 +1736,8 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) { } } - EditorSettings::get_singleton()->save(); - - _selected_project_keys.clear(); + save_config(); + _selected_project_paths.clear(); _last_clicked = ""; update_dock_menu(); @@ -1772,9 +1753,9 @@ void ProjectList::_panel_draw(Node *p_hb) { hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree"))); } - String key = _projects[p_hb->get_index()].project_key; + String key = _projects[p_hb->get_index()].path; - if (_selected_project_keys.has(key)) { + if (_selected_project_paths.has(key)) { hb->draw_style_box(get_theme_stylebox(SNAME("selected"), SNAME("Tree")), Rect2(Point2(), hb->get_size())); } } @@ -1786,11 +1767,11 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { const Item &clicked_project = _projects[clicked_index]; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { - if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && !_last_clicked.is_empty() && clicked_project.project_key != _last_clicked) { + if (mb->is_shift_pressed() && _selected_project_paths.size() > 0 && !_last_clicked.is_empty() && clicked_project.path != _last_clicked) { int anchor_index = -1; for (int i = 0; i < _projects.size(); ++i) { const Item &p = _projects[i]; - if (p.project_key == _last_clicked) { + if (p.path == _last_clicked) { anchor_index = p.control->get_index(); break; } @@ -1802,7 +1783,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { toggle_select(clicked_index); } else { - _last_clicked = clicked_project.project_key; + _last_clicked = clicked_project.path; select_project(clicked_index); } @@ -1824,12 +1805,8 @@ void ProjectList::_favorite_pressed(Node *p_hb) { item.favorite = !item.favorite; - if (item.favorite) { - EditorSettings::get_singleton()->set("favorite_projects/" + item.project_key, item.path); - } else { - EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key); - } - EditorSettings::get_singleton()->save(); + _config.set_value(item.path, "favorite", item.favorite); + save_config(); _projects.write[index] = item; @@ -1839,7 +1816,7 @@ void ProjectList::_favorite_pressed(Node *p_hb) { if (item.favorite) { for (int i = 0; i < _projects.size(); ++i) { - if (_projects[i].project_key == item.project_key) { + if (_projects[i].path == item.path) { ensure_project_visible(i); break; } @@ -1998,7 +1975,7 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { // Pressing Command + Q quits the Project Manager // This is handled by the platform implementation on macOS, // so only define the shortcut on other platforms -#ifndef OSX_ENABLED +#ifndef MACOS_ENABLED if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::Q)) { _dim_window(); get_tree()->quit(); @@ -2097,6 +2074,8 @@ void ProjectManager::_on_projects_updated() { } void ProjectManager::_on_project_created(const String &dir) { + _project_list->add_project(dir, false); + _project_list->save_config(); search_box->clear(); int i = _project_list->refresh_project(dir); _project_list->select_project(i); @@ -2117,9 +2096,7 @@ void ProjectManager::_open_selected_projects() { const HashSet<String> &selected_list = _project_list->get_selected_project_keys(); - for (const String &E : selected_list) { - const String &selected = E; - String path = EditorSettings::get_singleton()->get("projects/" + selected); + for (const String &path : selected_list) { String conf = path.plus_file("project.godot"); if (!FileAccess::exists(conf)) { @@ -2128,7 +2105,7 @@ void ProjectManager::_open_selected_projects() { return; } - print_line("Editing project: " + path + " (" + selected + ")"); + print_line("Editing project: " + path); List<String> args; @@ -2252,8 +2229,7 @@ void ProjectManager::_run_project_confirm() { continue; } - const String &selected = selected_list[i].project_key; - String path = EditorSettings::get_singleton()->get("projects/" + selected); + const String &path = selected_list[i].path; // `.substr(6)` on `ProjectSettings::get_singleton()->get_imported_files_path()` strips away the leading "res://". if (!DirAccess::exists(path.plus_file(ProjectSettings::get_singleton()->get_imported_files_path().substr(6)))) { @@ -2262,7 +2238,7 @@ void ProjectManager::_run_project_confirm() { continue; } - print_line("Running project: " + path + " (" + selected + ")"); + print_line("Running project: " + path); List<String> args; @@ -2293,7 +2269,7 @@ void ProjectManager::_run_project() { } } -void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) { +void ProjectManager::_scan_dir(const String &path) { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error error = da->change_dir(path); ERR_FAIL_COND_MSG(error != OK, "Could not scan directory at: " + path); @@ -2301,26 +2277,18 @@ void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) { String n = da->get_next(); while (!n.is_empty()) { if (da->current_is_dir() && !n.begins_with(".")) { - _scan_dir(da->get_current_dir().plus_file(n), r_projects); + _scan_dir(da->get_current_dir().plus_file(n)); } else if (n == "project.godot") { - r_projects->push_back(da->get_current_dir()); + _project_list->add_project(da->get_current_dir(), false); } n = da->get_next(); } da->list_dir_end(); } - void ProjectManager::_scan_begin(const String &p_base) { print_line("Scanning projects at: " + p_base); - List<String> projects; - _scan_dir(p_base, &projects); - print_line("Found " + itos(projects.size()) + " projects."); - - for (const String &E : projects) { - String proj = get_project_key_from_path(E); - EditorSettings::get_singleton()->set("projects/" + proj, E); - } - EditorSettings::get_singleton()->save(); + _scan_dir(p_base); + _project_list->save_config(); _load_recent_projects(); } @@ -2346,9 +2314,7 @@ void ProjectManager::_rename_project() { } for (const String &E : selected_list) { - const String &selected = E; - String path = EditorSettings::get_singleton()->get("projects/" + selected); - npdialog->set_project_path(path); + npdialog->set_project_path(E); npdialog->set_mode(ProjectDialog::MODE_RENAME); npdialog->show_dialog(); } @@ -2451,7 +2417,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) { } if (confirm) { multi_scan_ask->get_ok_button()->disconnect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders)); - multi_scan_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders), varray(folders)); + multi_scan_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders).bind(folders)); multi_scan_ask->set_text( vformat(TTR("Are you sure to scan %s folders for existing Godot projects?\nThis could take a while."), folders.size())); multi_scan_ask->popup_centered(); @@ -2562,19 +2528,19 @@ ProjectManager::ProjectManager() { EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); - set_anchors_and_offsets_preset(Control::PRESET_WIDE); + set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); set_theme(create_custom_theme()); - set_anchors_and_offsets_preset(Control::PRESET_WIDE); + set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); Panel *panel = memnew(Panel); add_child(panel); - panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles"))); VBoxContainer *vb = memnew(VBoxContainer); panel->add_child(vb); - vb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE); + vb->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE); Control *center_box = memnew(Control); center_box->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -2582,7 +2548,7 @@ ProjectManager::ProjectManager() { tabs = memnew(TabContainer); center_box->add_child(tabs); - tabs->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + tabs->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); tabs->connect("tab_changed", callable_mp(this, &ProjectManager::_on_tab_changed)); local_projects_hb = memnew(HBoxContainer); @@ -2879,6 +2845,7 @@ ProjectManager::ProjectManager() { _build_icon_type_cache(get_theme()); } + _project_list->migrate_config(); _load_recent_projects(); Ref<DirAccess> dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM); diff --git a/editor/project_manager.h b/editor/project_manager.h index 28383e4142..10bf25c048 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -125,7 +125,7 @@ class ProjectManager : public Control { void _on_projects_updated(); void _scan_multiple_folders(PackedStringArray p_files); void _scan_begin(const String &p_base); - void _scan_dir(const String &path, List<String> *r_projects); + void _scan_dir(const String &path); void _install_project(const String &p_zip_path, const String &p_title); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 49707355a0..ca5eeaa787 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -31,14 +31,18 @@ #include "project_settings_editor.h" #include "core/config/project_settings.h" -#include "editor/editor_export.h" #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "servers/movie_writer/movie_writer.h" ProjectSettingsEditor *ProjectSettingsEditor::singleton = nullptr; +void ProjectSettingsEditor::connect_filesystem_dock_signals(FileSystemDock *p_fs_dock) { + localization_editor->connect_filesystem_dock_signals(p_fs_dock); +} + void ProjectSettingsEditor::popup_project_settings() { // Restore valid window bounds or pop up at default size. Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "project_settings", Rect2()); @@ -75,8 +79,13 @@ void ProjectSettingsEditor::_setting_edited(const String &p_name) { queue_save(); } +void ProjectSettingsEditor::_update_advanced(bool p_is_advanced) { + custom_properties->set_visible(p_is_advanced); +} + void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) { EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed); + _update_advanced(p_button_pressed); general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed); } @@ -585,35 +594,35 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->connect("toggled", callable_mp(this, &ProjectSettingsEditor::_advanced_toggled)); search_bar->add_child(advanced); - HBoxContainer *header = memnew(HBoxContainer); - general_editor->add_child(header); + custom_properties = memnew(HBoxContainer); + general_editor->add_child(custom_properties); property_box = memnew(LineEdit); property_box->set_placeholder(TTR("Select a Setting or Type its Name")); property_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); property_box->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_property_box_changed)); - header->add_child(property_box); + custom_properties->add_child(property_box); feature_box = memnew(OptionButton); feature_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE); feature_box->connect("item_selected", callable_mp(this, &ProjectSettingsEditor::_feature_selected)); - header->add_child(feature_box); + custom_properties->add_child(feature_box); type_box = memnew(OptionButton); type_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE); - header->add_child(type_box); + custom_properties->add_child(type_box); add_button = memnew(Button); add_button->set_text(TTR("Add")); add_button->set_disabled(true); add_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_add_setting)); - header->add_child(add_button); + custom_properties->add_child(add_button); del_button = memnew(Button); del_button->set_text(TTR("Delete")); del_button->set_disabled(true); del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting)); - header->add_child(del_button); + custom_properties->add_child(del_button); general_settings_inspector = memnew(SectionedInspector); general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); @@ -670,10 +679,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); tab_container->add_child(autoload_settings); - shaders_global_variables_editor = memnew(ShaderGlobalsEditor); - shaders_global_variables_editor->set_name(TTR("Shader Globals")); - shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); - tab_container->add_child(shaders_global_variables_editor); + shaders_global_shader_uniforms_editor = memnew(ShaderGlobalsEditor); + shaders_global_shader_uniforms_editor->set_name(TTR("Shader Globals")); + shaders_global_shader_uniforms_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); + tab_container->add_child(shaders_global_shader_uniforms_editor); plugin_settings = memnew(EditorPluginSettings); plugin_settings->set_name(TTR("Plugins")); @@ -694,6 +703,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->set_pressed(true); } + _update_advanced(use_advanced); general_settings_inspector->set_restrict_to_basic_settings(!use_advanced); import_defaults_editor = memnew(ImportDefaultsEditor); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 24d61db443..c2d2c2d8f4 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -43,6 +43,8 @@ #include "editor/shader_globals_editor.h" #include "scene/gui/tab_container.h" +class FileSystemDock; + class ProjectSettingsEditor : public AcceptDialog { GDCLASS(ProjectSettingsEditor, AcceptDialog); @@ -55,12 +57,13 @@ class ProjectSettingsEditor : public AcceptDialog { ActionMapEditor *action_map_editor = nullptr; LocalizationEditor *localization_editor = nullptr; EditorAutoloadSettings *autoload_settings = nullptr; - ShaderGlobalsEditor *shaders_global_variables_editor = nullptr; + ShaderGlobalsEditor *shaders_global_shader_uniforms_editor = nullptr; EditorPluginSettings *plugin_settings = nullptr; LineEdit *search_box = nullptr; CheckButton *advanced = nullptr; + HBoxContainer *custom_properties = nullptr; LineEdit *property_box = nullptr; OptionButton *feature_box = nullptr; OptionButton *type_box = nullptr; @@ -77,6 +80,7 @@ class ProjectSettingsEditor : public AcceptDialog { UndoRedo *undo_redo = nullptr; void _advanced_toggled(bool p_button_pressed); + void _update_advanced(bool p_is_advanced); void _property_box_changed(const String &p_text); void _update_property_box(); void _feature_selected(int p_index); @@ -118,6 +122,7 @@ public: TabContainer *get_tabs() { return tab_container; } void queue_save(); + void connect_filesystem_dock_signals(FileSystemDock *p_fs_dock); ProjectSettingsEditor(EditorData *p_data); }; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp deleted file mode 100644 index 277ae14e0e..0000000000 --- a/editor/property_editor.cpp +++ /dev/null @@ -1,1907 +0,0 @@ -/*************************************************************************/ -/* property_editor.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 "property_editor.h" - -#include "core/config/project_settings.h" -#include "core/input/input.h" -#include "core/io/image_loader.h" -#include "core/io/marshalls.h" -#include "core/io/resource_loader.h" -#include "core/math/expression.h" -#include "core/object/class_db.h" -#include "core/os/keyboard.h" -#include "core/string/print_string.h" -#include "core/templates/pair.h" -#include "editor/array_property_edit.h" -#include "editor/create_dialog.h" -#include "editor/dictionary_property_edit.h" -#include "editor/editor_export.h" -#include "editor/editor_file_dialog.h" -#include "editor/editor_file_system.h" -#include "editor/editor_help.h" -#include "editor/editor_node.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "editor/filesystem_dock.h" -#include "editor/multi_node_edit.h" -#include "editor/property_selector.h" -#include "editor/scene_tree_dock.h" -#include "scene/gui/label.h" -#include "scene/main/window.h" -#include "scene/resources/font.h" -#include "scene/resources/packed_scene.h" -#include "scene/scene_string_names.h" - -void EditorResourceConversionPlugin::_bind_methods() { - GDVIRTUAL_BIND(_converts_to); - GDVIRTUAL_BIND(_handles, "resource"); - GDVIRTUAL_BIND(_convert, "resource"); -} - -String EditorResourceConversionPlugin::converts_to() const { - String ret; - if (GDVIRTUAL_CALL(_converts_to, ret)) { - return ret; - } - - return ""; -} - -bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const { - bool ret; - if (GDVIRTUAL_CALL(_handles, p_resource, ret)) { - return ret; - } - - return false; -} - -Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const { - Ref<Resource> ret; - if (GDVIRTUAL_CALL(_convert, p_resource, ret)) { - return ret; - } - - return Ref<Resource>(); -} - -void CustomPropertyEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_WM_CLOSE_REQUEST: { - hide(); - } break; - } -} - -void CustomPropertyEditor::_menu_option(int p_which) { - switch (type) { - case Variant::INT: { - if (hint == PROPERTY_HINT_FLAGS) { - int idx = menu->get_item_index(p_which); - uint32_t item_value = menu->get_item_metadata(idx); - uint32_t value = v; - // If the item wasn't previously checked it means it was pressed, - // otherwise it was unpressed. - if (!menu->is_item_checked(idx)) { - v = value | item_value; - } else { - v = value & ~item_value; - } - emit_signal(SNAME("variant_changed")); - } else if (hint == PROPERTY_HINT_ENUM) { - v = menu->get_item_metadata(p_which); - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_ENUM) { - v = hint_text.get_slice(",", p_which); - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::OBJECT: { - switch (p_which) { - case OBJ_MENU_LOAD: { - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - List<String> extensions; - for (int i = 0; i < type.get_slice_count(","); i++) { - ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions); - } - - HashSet<String> valid_extensions; - for (const String &E : extensions) { - valid_extensions.insert(E); - } - - file->clear_filters(); - for (const String &E : valid_extensions) { - file->add_filter("*." + E, E.to_upper()); - } - - file->popup_file_dialog(); - } break; - - case OBJ_MENU_EDIT: { - Ref<RefCounted> r = v; - - if (!r.is_null()) { - emit_signal(SNAME("resource_edit_request")); - hide(); - } - } break; - case OBJ_MENU_CLEAR: { - v = Variant(); - emit_signal(SNAME("variant_changed")); - hide(); - } break; - - case OBJ_MENU_MAKE_UNIQUE: { - Ref<Resource> res_orig = v; - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (const PropertyInfo &pi : property_list) { - Pair<String, Variant> p; - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - String orig_type = res_orig->get_class(); - - Object *inst = ClassDB::instantiate(orig_type); - - Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst)); - - ERR_FAIL_COND(res.is_null()); - - for (const Pair<String, Variant> &p : propvalues) { - res->set(p.first, p.second); - } - - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } break; - - case OBJ_MENU_COPY: { - EditorSettings::get_singleton()->set_resource_clipboard(v); - - } break; - case OBJ_MENU_PASTE: { - v = EditorSettings::get_singleton()->get_resource_clipboard(); - emit_signal(SNAME("variant_changed")); - - } break; - case OBJ_MENU_NEW_SCRIPT: { - if (Object::cast_to<Node>(owner)) { - SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), false); - } - - } break; - case OBJ_MENU_EXTEND_SCRIPT: { - if (Object::cast_to<Node>(owner)) { - SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), true); - } - - } break; - case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { - Ref<Resource> r = v; - FileSystemDock *file_system_dock = FileSystemDock::get_singleton(); - file_system_dock->navigate_to_path(r->get_path()); - // Ensure that the FileSystem dock is visible. - TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock)); - } break; - default: { - if (p_which >= CONVERT_BASE_ID) { - int to_type = p_which - CONVERT_BASE_ID; - - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v)); - - ERR_FAIL_INDEX(to_type, conversions.size()); - - Ref<Resource> new_res = conversions[to_type]->convert(v); - - v = new_res; - emit_signal(SNAME("variant_changed")); - break; - } - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[p_which - TYPE_BASE_ID]; - - if (intype == "ViewportTexture") { - scene_tree->set_title(TTR("Pick a Viewport")); - scene_tree->popup_scenetree_dialog(); - picking_viewport = true; - return; - } - - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_BREAK(!obj); - Resource *res = Object::cast_to<Resource>(obj); - ERR_BREAK(!res); - if (owner && hint == PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Script") { - //make visual script the right type - res->call("set_instance_base_type", owner->get_class()); - } - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - - } break; - } - - } break; - default: { - } - } -} - -void CustomPropertyEditor::hide_menu() { - menu->hide(); -} - -Variant CustomPropertyEditor::get_variant() const { - return v; -} - -String CustomPropertyEditor::get_name() const { - return name; -} - -bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text) { - owner = p_owner; - updating = true; - name = p_name; - v = p_variant; - field_names.clear(); - hint = p_hint; - hint_text = p_hint_text; - type_button->hide(); - if (color_picker) { - color_picker->hide(); - } - texture_preview->hide(); - inheritors_array.clear(); - text_edit->hide(); - easing_draw->hide(); - spinbox->hide(); - slider->hide(); - menu->clear(); - menu->reset_size(); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - if (i < MAX_VALUE_EDITORS / 4) { - value_hboxes[i]->hide(); - } - value_editor[i]->hide(); - value_label[i]->hide(); - if (i < 4) { - scroll[i]->hide(); - } - } - - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - action_buttons[i]->hide(); - } - - checks20gc->hide(); - for (int i = 0; i < 20; i++) { - checks20[i]->hide(); - } - - type = (p_variant.get_type() != Variant::NIL && p_variant.get_type() != Variant::RID && p_type != Variant::OBJECT) ? p_variant.get_type() : p_type; - - switch (type) { - case Variant::BOOL: { - checks20gc->show(); - - CheckBox *c = checks20[0]; - c->set_text("True"); - checks20gc->set_position(Vector2(4, 4) * EDSCALE); - c->set_pressed(v); - c->show(); - - checks20gc->set_size(checks20gc->get_minimum_size()); - set_size(checks20gc->get_position() + checks20gc->get_size() + c->get_size() + Vector2(4, 4) * EDSCALE); - - } break; - case Variant::INT: - case Variant::FLOAT: { - if (hint == PROPERTY_HINT_RANGE) { - int c = hint_text.get_slice_count(","); - float min = 0, max = 100, step = type == Variant::FLOAT ? .01 : 1; - if (c >= 1) { - if (!hint_text.get_slice(",", 0).is_empty()) { - min = hint_text.get_slice(",", 0).to_float(); - } - } - if (c >= 2) { - if (!hint_text.get_slice(",", 1).is_empty()) { - max = hint_text.get_slice(",", 1).to_float(); - } - } - - if (c >= 3) { - if (!hint_text.get_slice(",", 2).is_empty()) { - step = hint_text.get_slice(",", 2).to_float(); - } - } - - if (c >= 4 && hint_text.get_slice(",", 3) == "slider") { - slider->set_min(min); - slider->set_max(max); - slider->set_step(step); - slider->set_value(v); - slider->show(); - set_size(Size2(110, 30) * EDSCALE); - } else { - spinbox->set_min(min); - spinbox->set_max(max); - spinbox->set_step(step); - spinbox->set_value(v); - spinbox->show(); - set_size(Size2(70, 35) * EDSCALE); - } - - } else if (hint == PROPERTY_HINT_ENUM) { - Vector<String> options = hint_text.split(","); - int current_val = 0; - for (int i = 0; i < options.size(); i++) { - Vector<String> text_split = options[i].split(":"); - if (text_split.size() != 1) { - current_val = text_split[1].to_int(); - } - menu->add_item(text_split[0]); - menu->set_item_metadata(i, current_val); - current_val += 1; - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_2D_RENDER || - hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || - hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_3D_RENDER || - hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { - String basename; - switch (hint) { - case PROPERTY_HINT_LAYERS_2D_RENDER: - basename = "layer_names/2d_render"; - break; - case PROPERTY_HINT_LAYERS_2D_PHYSICS: - basename = "layer_names/2d_physics"; - break; - case PROPERTY_HINT_LAYERS_2D_NAVIGATION: - basename = "layer_names/2d_navigation"; - break; - case PROPERTY_HINT_LAYERS_3D_RENDER: - basename = "layer_names/3d_render"; - break; - case PROPERTY_HINT_LAYERS_3D_PHYSICS: - basename = "layer_names/3d_physics"; - break; - case PROPERTY_HINT_LAYERS_3D_NAVIGATION: - basename = "layer_names/3d_navigation"; - break; - } - - checks20gc->show(); - uint32_t flgs = v; - for (int i = 0; i < 2; i++) { - Point2 ofs(4, 4); - ofs.y += 22 * i; - for (int j = 0; j < 10; j++) { - int idx = i * 10 + j; - CheckBox *c = checks20[idx]; - c->set_text(ProjectSettings::get_singleton()->get(basename + "/layer_" + itos(idx + 1))); - c->set_pressed(flgs & (1 << (i * 10 + j))); - c->show(); - } - } - - show(); - - checks20gc->set_position(Vector2(4, 4) * EDSCALE); - checks20gc->set_size(checks20gc->get_minimum_size()); - - set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size()); - - } else if (hint == PROPERTY_HINT_EXP_EASING) { - easing_draw->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -3 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_END, -25 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE); - type_button->set_text(TTR("Preset...")); - type_button->get_popup()->clear(); - type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR); - type_button->get_popup()->add_item(TTR("Ease In"), EASING_EASE_IN); - type_button->get_popup()->add_item(TTR("Ease Out"), EASING_EASE_OUT); - if (hint_text != "attenuation") { - type_button->get_popup()->add_item(TTR("Zero"), EASING_ZERO); - type_button->get_popup()->add_item(TTR("Easing In-Out"), EASING_IN_OUT); - type_button->get_popup()->add_item(TTR("Easing Out-In"), EASING_OUT_IN); - } - - type_button->show(); - easing_draw->show(); - set_size(Size2(200, 150) * EDSCALE); - } else if (hint == PROPERTY_HINT_FLAGS) { - Vector<String> flags = hint_text.split(","); - uint32_t value = v; - for (int i = 0; i < flags.size(); i++) { - uint32_t current_val; - Vector<String> text_split = flags[i].split(":"); - if (text_split.size() != 1) { - current_val = text_split[1].to_int(); - } else { - current_val = 1 << i; - } - menu->add_check_item(text_split[0], current_val); - menu->set_item_metadata(i, current_val); - if ((value & current_val) == current_val) { - menu->set_item_checked(menu->get_item_index(current_val), true); - } - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else { - List<String> names; - names.push_back("value:"); - config_value_editors(1, 1, 50, names); - value_editor[0]->set_text(TS->format_number(String::num(v))); - } - - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_LOCALE_ID) { - List<String> names; - names.push_back(TTR("Locale...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { - List<String> names; - names.push_back(TTR("File...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { - List<String> names; - names.push_back(TTR("Dir...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_ENUM) { - Vector<String> options = hint_text.split(","); - for (int i = 0; i < options.size(); i++) { - menu->add_item(options[i], i); - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_MULTILINE_TEXT) { - text_edit->show(); - text_edit->set_text(v); - text_edit->deselect(); - - int button_margin = text_edit->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs")); - int margin = text_edit->get_theme_constant(SNAME("margin"), SNAME("Dialogs")); - - action_buttons[0]->set_anchor(SIDE_LEFT, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_TOP, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_RIGHT, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END); - action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE)); - action_buttons[0]->set_end(Point2(-margin, -margin)); - action_buttons[0]->set_text(TTR("Close")); - action_buttons[0]->show(); - - } else if (hint == PROPERTY_HINT_TYPE_STRING) { - if (!create_dialog) { - create_dialog = memnew(CreateDialog); - create_dialog->connect("create", callable_mp(this, &CustomPropertyEditor::_create_dialog_callback)); - add_child(create_dialog); - } - - if (!hint_text.is_empty()) { - create_dialog->set_base_type(hint_text); - } else { - create_dialog->set_base_type("Object"); - } - - create_dialog->popup_create(false); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) { -#define MAKE_PROPSELECT \ - if (!property_select) { \ - property_select = memnew(PropertySelector); \ - property_select->connect("selected", callable_mp(this, &CustomPropertyEditor::_create_selected_property)); \ - add_child(property_select); \ - } \ - hide(); - - MAKE_PROPSELECT; - - Variant::Type type = Variant::NIL; - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (hint_text == Variant::get_type_name(Variant::Type(i))) { - type = Variant::Type(i); - } - } - if (type != Variant::NIL) { - property_select->select_method_from_basic_type(type, v); - } - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE) { - MAKE_PROPSELECT - - property_select->select_method_from_base_type(hint_text, v); - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) { - MAKE_PROPSELECT - - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (instance) { - property_select->select_method_from_instance(instance, v); - } - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) { - MAKE_PROPSELECT - - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (Object::cast_to<Script>(obj)) { - property_select->select_method_from_script(Object::cast_to<Script>(obj), v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) { - MAKE_PROPSELECT - Variant::Type type = Variant::NIL; - String tname = hint_text; - if (tname.contains(".")) { - tname = tname.get_slice(".", 0); - } - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (tname == Variant::get_type_name(Variant::Type(i))) { - type = Variant::Type(Variant::Type(i)); - } - } - - if (type != Variant::NIL) { - property_select->select_property_from_basic_type(type, v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) { - MAKE_PROPSELECT - - property_select->select_property_from_base_type(hint_text, v); - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) { - MAKE_PROPSELECT - - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (instance) { - property_select->select_property_from_instance(instance, v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) { - MAKE_PROPSELECT - - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (Object::cast_to<Script>(obj)) { - property_select->select_property_from_script(Object::cast_to<Script>(obj), v); - } - - updating = false; - return false; - - } else { - List<String> names; - names.push_back("string:"); - config_value_editors(1, 1, 50, names); - value_editor[0]->set_text(v); - } - - } break; - case Variant::VECTOR2: { - field_names.push_back("x"); - field_names.push_back("y"); - config_value_editors(2, 2, 10, field_names); - Vector2 vec = v; - value_editor[0]->set_text(String::num(vec.x)); - value_editor[1]->set_text(String::num(vec.y)); - } break; - case Variant::RECT2: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("w"); - field_names.push_back("h"); - config_value_editors(4, 4, 10, field_names); - Rect2 r = v; - value_editor[0]->set_text(String::num(r.position.x)); - value_editor[1]->set_text(String::num(r.position.y)); - value_editor[2]->set_text(String::num(r.size.x)); - value_editor[3]->set_text(String::num(r.size.y)); - } break; - case Variant::VECTOR3: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - config_value_editors(3, 3, 10, field_names); - Vector3 vec = v; - value_editor[0]->set_text(String::num(vec.x)); - value_editor[1]->set_text(String::num(vec.y)); - value_editor[2]->set_text(String::num(vec.z)); - } break; - case Variant::PLANE: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - field_names.push_back("d"); - config_value_editors(4, 4, 10, field_names); - Plane plane = v; - value_editor[0]->set_text(String::num(plane.normal.x)); - value_editor[1]->set_text(String::num(plane.normal.y)); - value_editor[2]->set_text(String::num(plane.normal.z)); - value_editor[3]->set_text(String::num(plane.d)); - - } break; - case Variant::QUATERNION: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - field_names.push_back("w"); - config_value_editors(4, 4, 10, field_names); - Quaternion q = v; - value_editor[0]->set_text(String::num(q.x)); - value_editor[1]->set_text(String::num(q.y)); - value_editor[2]->set_text(String::num(q.z)); - value_editor[3]->set_text(String::num(q.w)); - - } break; - case Variant::AABB: { - field_names.push_back("px"); - field_names.push_back("py"); - field_names.push_back("pz"); - field_names.push_back("sx"); - field_names.push_back("sy"); - field_names.push_back("sz"); - config_value_editors(6, 3, 16, field_names); - - AABB aabb = v; - value_editor[0]->set_text(String::num(aabb.position.x)); - value_editor[1]->set_text(String::num(aabb.position.y)); - value_editor[2]->set_text(String::num(aabb.position.z)); - value_editor[3]->set_text(String::num(aabb.size.x)); - value_editor[4]->set_text(String::num(aabb.size.y)); - value_editor[5]->set_text(String::num(aabb.size.z)); - - } break; - case Variant::TRANSFORM2D: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("ox"); - field_names.push_back("oy"); - config_value_editors(6, 2, 16, field_names); - - Transform2D basis = v; - for (int i = 0; i < 6; i++) { - value_editor[i]->set_text(String::num(basis.columns[i / 2][i % 2])); - } - - } break; - case Variant::BASIS: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("xz"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("yz"); - field_names.push_back("zx"); - field_names.push_back("zy"); - field_names.push_back("zz"); - config_value_editors(9, 3, 16, field_names); - - Basis basis = v; - for (int i = 0; i < 9; i++) { - value_editor[i]->set_text(String::num(basis.rows[i / 3][i % 3])); - } - - } break; - case Variant::TRANSFORM3D: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("xz"); - field_names.push_back("xo"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("yz"); - field_names.push_back("yo"); - field_names.push_back("zx"); - field_names.push_back("zy"); - field_names.push_back("zz"); - field_names.push_back("zo"); - config_value_editors(12, 4, 16, field_names); - - Transform3D tr = v; - for (int i = 0; i < 9; i++) { - value_editor[(i / 3) * 4 + i % 3]->set_text(String::num(tr.basis.rows[i / 3][i % 3])); - } - - value_editor[3]->set_text(String::num(tr.origin.x)); - value_editor[7]->set_text(String::num(tr.origin.y)); - value_editor[11]->set_text(String::num(tr.origin.z)); - - } break; - case Variant::COLOR: { - if (!color_picker) { - //late init for performance - color_picker = memnew(ColorPicker); - color_picker->set_deferred_mode(true); - value_vbox->add_child(color_picker); - color_picker->hide(); - color_picker->connect("color_changed", callable_mp(this, &CustomPropertyEditor::_color_changed)); - - // get default color picker mode from editor settings - int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode"); - color_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode); - - int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); - color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); - } - - color_picker->show(); - color_picker->set_edit_alpha(hint != PROPERTY_HINT_COLOR_NO_ALPHA); - color_picker->set_pick_color(v); - color_picker->set_focus_on_line_edit(); - - } break; - - case Variant::NODE_PATH: { - List<String> names; - names.push_back(TTR("Assign")); - names.push_back(TTR("Clear")); - - if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) { - names.push_back(TTR("Select Node")); - } - - config_action_buttons(names); - - } break; - case Variant::OBJECT: { - if (hint != PROPERTY_HINT_RESOURCE_TYPE) { - break; - } - - if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) { - menu->add_item(TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu->add_separator(); - } else if (!hint_text.is_empty()) { - int idx = 0; - - Vector<EditorData::CustomType> custom_resources; - - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - } - - for (int i = 0; i < hint_text.get_slice_count(","); i++) { - String base = hint_text.get_slice(",", i); - - HashSet<String> valid_inheritors; - valid_inheritors.insert(base); - List<StringName> inheritors; - ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - - for (int j = 0; j < custom_resources.size(); j++) { - inheritors.push_back(custom_resources[j].name); - } - - List<StringName>::Element *E = inheritors.front(); - while (E) { - valid_inheritors.insert(E->get()); - E = E->next(); - } - - for (const String &j : valid_inheritors) { - const String &t = j; - - bool is_custom_resource = false; - Ref<Texture2D> icon; - if (!custom_resources.is_empty()) { - for (int k = 0; k < custom_resources.size(); k++) { - if (custom_resources[k].name == t) { - is_custom_resource = true; - if (custom_resources[k].icon.is_valid()) { - icon = custom_resources[k].icon; - } - break; - } - } - } - - if (!is_custom_resource && (!ClassDB::can_instantiate(t) || ClassDB::is_virtual(t))) { - continue; - } - - inheritors_array.push_back(t); - - int id = TYPE_BASE_ID + idx; - - menu->add_item(vformat(TTR("New %s"), t), id); - - idx++; - } - } - - if (menu->get_item_count()) { - menu->add_separator(); - } - } - - menu->add_item(TTR("Load"), OBJ_MENU_LOAD); - - if (!Ref<Resource>(v).is_null()) { - menu->add_item(TTR("Edit"), OBJ_MENU_EDIT); - menu->add_item(TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_item(TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); - - Ref<Resource> r = v; - if (r.is_valid() && r->get_path().is_resource_file()) { - menu->add_separator(); - menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); - } - } - - Ref<Resource> cb = EditorSettings::get_singleton()->get_resource_clipboard(); - bool paste_valid = false; - if (cb.is_valid()) { - if (hint_text.is_empty()) { - paste_valid = true; - } else { - for (int i = 0; i < hint_text.get_slice_count(","); i++) { - if (ClassDB::is_parent_class(cb->get_class(), hint_text.get_slice(",", i))) { - paste_valid = true; - break; - } - } - } - } - - if (!Ref<Resource>(v).is_null() || paste_valid) { - menu->add_separator(); - - if (!Ref<Resource>(v).is_null()) { - menu->add_item(TTR("Copy"), OBJ_MENU_COPY); - } - - if (paste_valid) { - menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); - } - } - - if (!Ref<Resource>(v).is_null()) { - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v)); - if (conversions.size()) { - menu->add_separator(); - } - for (int i = 0; i < conversions.size(); i++) { - String what = conversions[i]->converts_to(); - menu->add_item(vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i); - } - } - - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - } break; - case Variant::DICTIONARY: { - } break; - case Variant::PACKED_BYTE_ARRAY: { - } break; - case Variant::PACKED_INT32_ARRAY: { - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - } break; - case Variant::PACKED_INT64_ARRAY: { - } break; - case Variant::PACKED_FLOAT64_ARRAY: { - } break; - case Variant::PACKED_STRING_ARRAY: { - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - } break; - case Variant::PACKED_COLOR_ARRAY: { - } break; - default: { - } - } - - updating = false; - return true; -} - -void CustomPropertyEditor::_file_selected(String p_file) { - switch (type) { - case Variant::STRING: { - if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_DIR) { - v = ProjectSettings::get_singleton()->localize_path(p_file); - emit_signal(SNAME("variant_changed")); - hide(); - } - - if (hint == PROPERTY_HINT_GLOBAL_FILE || hint == PROPERTY_HINT_GLOBAL_DIR) { - v = p_file; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } break; - case Variant::OBJECT: { - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - Ref<Resource> res = ResourceLoader::load(p_file, type); - if (res.is_null()) { - error->set_text(TTR("Error loading file: Not a resource!")); - error->popup_centered(); - break; - } - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } break; - default: { - } - } -} - -void CustomPropertyEditor::_locale_selected(String p_locale) { - if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) { - v = p_locale; - emit_signal(SNAME("variant_changed")); - hide(); - } -} - -void CustomPropertyEditor::_type_create_selected(int p_idx) { - if (type == Variant::INT || type == Variant::FLOAT) { - float newval = 0; - switch (p_idx) { - case EASING_LINEAR: { - newval = 1; - } break; - case EASING_EASE_IN: { - newval = 2.0; - } break; - case EASING_EASE_OUT: { - newval = 0.5; - } break; - case EASING_ZERO: { - newval = 0; - } break; - case EASING_IN_OUT: { - newval = -0.5; - } break; - case EASING_OUT_IN: { - newval = -2.0; - } break; - } - - v = newval; - emit_signal(SNAME("variant_changed")); - easing_draw->update(); - - } else if (type == Variant::OBJECT) { - ERR_FAIL_INDEX(p_idx, inheritors_array.size()); - - String intype = inheritors_array[p_idx]; - - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_FAIL_COND(!obj); - ERR_FAIL_COND(!Object::cast_to<Resource>(obj)); - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - hide(); - } -} - -void CustomPropertyEditor::_color_changed(const Color &p_color) { - v = p_color; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_node_path_selected(NodePath p_path) { - if (picking_viewport) { - Node *to_node = get_node(p_path); - if (!Object::cast_to<Viewport>(to_node)) { - EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); - return; - } - - Ref<ViewportTexture> vt; - vt.instantiate(); - vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); - vt->setup_local_to_scene(); - v = vt; - emit_signal(SNAME("variant_changed")); - return; - } - - if (hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && !hint_text.is_empty()) { - Node *node = get_node(hint_text); - if (node) { - Node *tonode = node->get_node(p_path); - if (tonode) { - p_path = node->get_path_to(tonode); - } - } - - } else if (owner) { - Node *node = nullptr; - - if (owner->is_class("Node")) { - node = Object::cast_to<Node>(owner); - } else if (owner->is_class("ArrayPropertyEdit")) { - node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node(); - } else if (owner->is_class("DictionaryPropertyEdit")) { - node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node(); - } - if (!node) { - v = p_path; - emit_signal(SNAME("variant_changed")); - call_deferred(SNAME("hide")); //to not mess with dialogs - return; - } - - Node *tonode = node->get_node(p_path); - if (tonode) { - p_path = node->get_path_to(tonode); - } - } - - v = p_path; - emit_signal(SNAME("variant_changed")); - call_deferred(SNAME("hide")); //to not mess with dialogs -} - -void CustomPropertyEditor::_action_pressed(int p_which) { - if (updating) { - return; - } - - switch (type) { - case Variant::BOOL: { - v = checks20[0]->is_pressed(); - emit_signal(SNAME("variant_changed")); - } break; - case Variant::INT: { - if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_2D_RENDER || - hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || - hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_3D_RENDER || - hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { - uint32_t f = v; - if (checks20[p_which]->is_pressed()) { - f |= (1 << p_which); - } else { - f &= ~(1 << p_which); - } - - v = f; - emit_signal(SNAME("variant_changed")); - } - - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_MULTILINE_TEXT) { - hide(); - } else if (hint == PROPERTY_HINT_LOCALE_ID) { - locale->popup_locale_dialog(); - } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { - if (p_which == 0) { - if (hint == PROPERTY_HINT_FILE) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - } else { - file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - } - - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - file->clear_filters(); - - file->clear_filters(); - - if (!hint_text.is_empty()) { - Vector<String> extensions = hint_text.split(","); - for (int i = 0; i < extensions.size(); i++) { - String filter = extensions[i]; - if (filter.begins_with(".")) { - filter = "*" + extensions[i]; - } else if (!filter.begins_with("*")) { - filter = "*." + extensions[i]; - } - - file->add_filter(filter, extensions[i].to_upper()); - } - } - file->popup_file_dialog(); - } else { - v = ""; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { - if (p_which == 0) { - if (hint == PROPERTY_HINT_DIR) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - } else { - file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - } - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); - file->clear_filters(); - file->popup_file_dialog(); - } else { - v = ""; - emit_signal(SNAME("variant_changed")); - hide(); - } - } - - } break; - case Variant::NODE_PATH: { - if (p_which == 0) { - picking_viewport = false; - scene_tree->set_title(TTR("Pick a Node")); - scene_tree->popup_scenetree_dialog(); - - } else if (p_which == 1) { - v = NodePath(); - emit_signal(SNAME("variant_changed")); - hide(); - } else if (p_which == 2) { - if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) { - Node *target_node = Object::cast_to<Node>(owner)->get_node(v); - EditorNode::get_singleton()->get_editor_selection()->clear(); - SceneTreeDock::get_singleton()->set_selected(target_node); - } - - hide(); - } - - } break; - case Variant::OBJECT: { - if (p_which == 0) { - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[0]; - - if (hint == PROPERTY_HINT_RESOURCE_TYPE) { - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_BREAK(!obj); - ERR_BREAK(!Object::cast_to<Resource>(obj)); - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - hide(); - } - } else if (p_which == 1) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - List<String> extensions; - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - ResourceLoader::get_recognized_extensions_for_type(type, &extensions); - file->clear_filters(); - for (const String &E : extensions) { - file->add_filter("*." + E, E.to_upper()); - } - - file->popup_file_dialog(); - - } else if (p_which == 2) { - Ref<Resource> r = v; - - if (!r.is_null()) { - emit_signal(SNAME("resource_edit_request")); - hide(); - } - - } else if (p_which == 3) { - v = Variant(); - emit_signal(SNAME("variant_changed")); - hide(); - } else if (p_which == 4) { - Ref<Resource> res_orig = v; - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (const PropertyInfo &pi : property_list) { - Pair<String, Variant> p; - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - Ref<Resource> res = Ref<Resource>(ClassDB::instantiate(res_orig->get_class())); - - ERR_FAIL_COND(res.is_null()); - - for (const Pair<String, Variant> &p : propvalues) { - res->set(p.first, p.second); - } - - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } break; - - default: { - }; - } -} - -void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) { - Ref<InputEventMouseMotion> mm = p_ev; - - if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { - float rel = mm->get_relative().x; - if (rel == 0) { - return; - } - - bool flip = hint_text == "attenuation"; - - if (flip) { - rel = -rel; - } - - float val = v; - if (val == 0) { - return; - } - bool sg = val < 0; - val = Math::absf(val); - - val = Math::log(val) / Math::log((float)2.0); - //logspace - val += rel * 0.05; - - val = Math::pow(2.0f, val); - if (sg) { - val = -val; - } - - v = val; - easing_draw->update(); - emit_signal(SNAME("variant_changed")); - } -} - -void CustomPropertyEditor::_draw_easing() { - RID ci = easing_draw->get_canvas_item(); - - Size2 s = easing_draw->get_size(); - Rect2 r(Point2(), s); - r = r.grow(3); - easing_draw->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->draw(ci, r); - - int points = 48; - - float prev = 1.0; - float exp = v; - bool flip = hint_text == "attenuation"; - - Ref<Font> f = easing_draw->get_theme_font(SNAME("font"), SNAME("Label")); - int font_size = easing_draw->get_theme_font_size(SNAME("font_size"), SNAME("Label")); - Color color = easing_draw->get_theme_color(SNAME("font_color"), SNAME("Label")); - - for (int i = 1; i <= points; i++) { - float ifl = i / float(points); - float iflp = (i - 1) / float(points); - - float h = 1.0 - Math::ease(ifl, exp); - - if (flip) { - ifl = 1.0 - ifl; - iflp = 1.0 - iflp; - } - - RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color); - prev = h; - } - - f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), String::num(exp, 2), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color); -} - -void CustomPropertyEditor::_text_edit_changed() { - v = text_edit->get_text(); - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_create_dialog_callback() { - v = create_dialog->get_selected_type(); - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_create_selected_property(const String &p_prop) { - v = p_prop; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_modified(String p_string) { - if (updating) { - return; - } - - Variant prev_v = v; - - updating = true; - switch (type) { - case Variant::INT: { - String text = TS->parse_number(value_editor[0]->get_text()); - Ref<Expression> expr; - expr.instantiate(); - Error err = expr->parse(text); - if (err != OK) { - v = value_editor[0]->get_text().to_int(); - return; - } else { - v = expr->execute(Array(), nullptr, false, false); - } - - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::FLOAT: { - if (hint != PROPERTY_HINT_EXP_EASING) { - String text = TS->parse_number(value_editor[0]->get_text()); - v = _parse_real_expression(text); - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } - - } break; - case Variant::STRING: { - v = value_editor[0]->get_text(); - emit_signal(SNAME("variant_changed")); - } break; - case Variant::VECTOR2: { - Vector2 vec; - vec.x = _parse_real_expression(value_editor[0]->get_text()); - vec.y = _parse_real_expression(value_editor[1]->get_text()); - v = vec; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::RECT2: { - Rect2 r2; - - r2.position.x = _parse_real_expression(value_editor[0]->get_text()); - r2.position.y = _parse_real_expression(value_editor[1]->get_text()); - r2.size.x = _parse_real_expression(value_editor[2]->get_text()); - r2.size.y = _parse_real_expression(value_editor[3]->get_text()); - v = r2; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - - case Variant::VECTOR3: { - Vector3 vec; - vec.x = _parse_real_expression(value_editor[0]->get_text()); - vec.y = _parse_real_expression(value_editor[1]->get_text()); - vec.z = _parse_real_expression(value_editor[2]->get_text()); - v = vec; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::PLANE: { - Plane pl; - pl.normal.x = _parse_real_expression(value_editor[0]->get_text()); - pl.normal.y = _parse_real_expression(value_editor[1]->get_text()); - pl.normal.z = _parse_real_expression(value_editor[2]->get_text()); - pl.d = _parse_real_expression(value_editor[3]->get_text()); - v = pl; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::QUATERNION: { - Quaternion q; - q.x = _parse_real_expression(value_editor[0]->get_text()); - q.y = _parse_real_expression(value_editor[1]->get_text()); - q.z = _parse_real_expression(value_editor[2]->get_text()); - q.w = _parse_real_expression(value_editor[3]->get_text()); - v = q; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::AABB: { - Vector3 pos; - Vector3 size; - - pos.x = _parse_real_expression(value_editor[0]->get_text()); - pos.y = _parse_real_expression(value_editor[1]->get_text()); - pos.z = _parse_real_expression(value_editor[2]->get_text()); - size.x = _parse_real_expression(value_editor[3]->get_text()); - size.y = _parse_real_expression(value_editor[4]->get_text()); - size.z = _parse_real_expression(value_editor[5]->get_text()); - v = AABB(pos, size); - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::TRANSFORM2D: { - Transform2D m; - for (int i = 0; i < 6; i++) { - m.columns[i / 2][i % 2] = _parse_real_expression(value_editor[i]->get_text()); - } - - v = m; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::BASIS: { - Basis m; - for (int i = 0; i < 9; i++) { - m.rows[i / 3][i % 3] = _parse_real_expression(value_editor[i]->get_text()); - } - - v = m; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::TRANSFORM3D: { - Basis basis; - for (int i = 0; i < 9; i++) { - basis.rows[i / 3][i % 3] = _parse_real_expression(value_editor[(i / 3) * 4 + i % 3]->get_text()); - } - - Vector3 origin; - - origin.x = _parse_real_expression(value_editor[3]->get_text()); - origin.y = _parse_real_expression(value_editor[7]->get_text()); - origin.z = _parse_real_expression(value_editor[11]->get_text()); - - v = Transform3D(basis, origin); - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::COLOR: { - } break; - - case Variant::NODE_PATH: { - v = NodePath(value_editor[0]->get_text()); - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::DICTIONARY: { - } break; - case Variant::PACKED_BYTE_ARRAY: { - } break; - case Variant::PACKED_INT32_ARRAY: { - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - } break; - case Variant::PACKED_STRING_ARRAY: { - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - } break; - case Variant::PACKED_COLOR_ARRAY: { - } break; - default: { - } - } - - updating = false; -} - -real_t CustomPropertyEditor::_parse_real_expression(String text) { - Ref<Expression> expr; - expr.instantiate(); - Error err = expr->parse(text); - real_t out; - if (err != OK) { - out = value_editor[0]->get_text().to_float(); - } else { - out = expr->execute(Array(), nullptr, false, true); - } - return out; -} - -void CustomPropertyEditor::_emit_changed_whole_or_field() { - if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) { - emit_signal(SNAME("variant_changed")); - } else { - emit_signal(SNAME("variant_field_changed"), field_names[focused_value_editor]); - } -} - -void CustomPropertyEditor::_range_modified(double p_value) { - v = p_value; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_focus_enter() { - switch (type) { - case Variant::FLOAT: - case Variant::STRING: - case Variant::VECTOR2: - case Variant::RECT2: - case Variant::VECTOR3: - case Variant::PLANE: - case Variant::QUATERNION: - case Variant::AABB: - case Variant::TRANSFORM2D: - case Variant::BASIS: - case Variant::TRANSFORM3D: { - for (int i = 0; i < MAX_VALUE_EDITORS; ++i) { - if (value_editor[i]->has_focus()) { - focused_value_editor = i; - value_editor[i]->select_all(); - break; - } - } - } break; - default: { - } - } -} - -void CustomPropertyEditor::_focus_exit() { - _modified(String()); -} - -void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) { - Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("button")); - int margin_top = sb->get_margin(SIDE_TOP); - int margin_left = sb->get_margin(SIDE_LEFT); - int margin_bottom = sb->get_margin(SIDE_BOTTOM); - int margin_right = sb->get_margin(SIDE_RIGHT); - - int max_width = 0; - int height = 0; - - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - if (i < p_strings.size()) { - action_buttons[i]->show(); - action_buttons[i]->set_text(p_strings[i]); - - Size2 btn_m_size = action_buttons[i]->get_minimum_size(); - if (btn_m_size.width > max_width) { - max_width = btn_m_size.width; - } - - } else { - action_buttons[i]->hide(); - } - } - - for (int i = 0; i < p_strings.size(); i++) { - Size2 btn_m_size = action_buttons[i]->get_size(); - action_buttons[i]->set_position(Point2(0, height) + Point2(margin_left, margin_top)); - action_buttons[i]->set_size(Size2(max_width, btn_m_size.height)); - - height += btn_m_size.height; - } - set_size(Size2(max_width, height) + Size2(margin_left + margin_right, margin_top + margin_bottom)); -} - -void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) { - int cell_width = 95; - int cell_height = 25; - int cell_margin = 5; - int rows = ((p_amount - 1) / p_columns) + 1; - - set_size(Size2(cell_margin + p_label_w + (cell_width + cell_margin + p_label_w) * p_columns, cell_margin + (cell_height + cell_margin) * rows) * EDSCALE); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - value_label[i]->get_parent()->remove_child(value_label[i]); - value_editor[i]->get_parent()->remove_child(value_editor[i]); - - int box_id = i / p_columns; - value_hboxes[box_id]->add_child(value_label[i]); - value_hboxes[box_id]->add_child(value_editor[i]); - - if (i < MAX_VALUE_EDITORS / 4) { - if (i <= p_amount / 4) { - value_hboxes[i]->show(); - } else { - value_hboxes[i]->hide(); - } - } - - if (i < p_amount) { - value_editor[i]->show(); - value_label[i]->show(); - value_label[i]->set_text(i < p_strings.size() ? p_strings[i] : String("")); - value_editor[i]->set_editable(!read_only); - } else { - value_editor[i]->hide(); - value_label[i]->hide(); - } - } -} - -void CustomPropertyEditor::_bind_methods() { - ADD_SIGNAL(MethodInfo("variant_changed")); - ADD_SIGNAL(MethodInfo("variant_field_changed", PropertyInfo(Variant::STRING, "field"))); - ADD_SIGNAL(MethodInfo("resource_edit_request")); -} - -CustomPropertyEditor::CustomPropertyEditor() { - value_vbox = memnew(VBoxContainer); - add_child(value_vbox); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - if (i < MAX_VALUE_EDITORS / 4) { - value_hboxes[i] = memnew(HBoxContainer); - value_vbox->add_child(value_hboxes[i]); - value_hboxes[i]->hide(); - } - int hbox_idx = i / 4; - value_label[i] = memnew(Label); - value_hboxes[hbox_idx]->add_child(value_label[i]); - value_label[i]->hide(); - value_editor[i] = memnew(LineEdit); - value_hboxes[hbox_idx]->add_child(value_editor[i]); - value_editor[i]->set_h_size_flags(Control::SIZE_EXPAND_FILL); - value_editor[i]->hide(); - value_editor[i]->connect("text_submitted", callable_mp(this, &CustomPropertyEditor::_modified)); - value_editor[i]->connect("focus_entered", callable_mp(this, &CustomPropertyEditor::_focus_enter)); - value_editor[i]->connect("focus_exited", callable_mp(this, &CustomPropertyEditor::_focus_exit)); - } - focused_value_editor = -1; - - for (int i = 0; i < 4; i++) { - scroll[i] = memnew(HScrollBar); - scroll[i]->hide(); - scroll[i]->set_min(0); - scroll[i]->set_max(1.0); - scroll[i]->set_step(0.01); - add_child(scroll[i]); - } - - checks20gc = memnew(GridContainer); - add_child(checks20gc); - checks20gc->set_columns(11); - - for (int i = 0; i < 20; i++) { - if (i == 5 || i == 15) { - Control *space = memnew(Control); - space->set_custom_minimum_size(Size2(20, 0) * EDSCALE); - checks20gc->add_child(space); - } - - checks20[i] = memnew(CheckBox); - checks20[i]->set_toggle_mode(true); - checks20[i]->set_focus_mode(Control::FOCUS_NONE); - checks20gc->add_child(checks20[i]); - checks20[i]->hide(); - checks20[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), make_binds(i)); - checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1 << i)); - } - - text_edit = memnew(TextEdit); - value_vbox->add_child(text_edit); - text_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); - text_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL); - text_edit->set_offset(SIDE_BOTTOM, -30); - - text_edit->hide(); - text_edit->connect("text_changed", callable_mp(this, &CustomPropertyEditor::_text_edit_changed)); - - color_picker = nullptr; - - file = memnew(EditorFileDialog); - value_vbox->add_child(file); - file->hide(); - - file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); - file->connect("dir_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); - - locale = memnew(EditorLocaleDialog); - value_vbox->add_child(locale); - locale->hide(); - - locale->connect("locale_selected", callable_mp(this, &CustomPropertyEditor::_locale_selected)); - - error = memnew(ConfirmationDialog); - error->set_title(TTR("Error!")); - value_vbox->add_child(error); - - scene_tree = memnew(SceneTreeDialog); - value_vbox->add_child(scene_tree); - scene_tree->connect("selected", callable_mp(this, &CustomPropertyEditor::_node_path_selected)); - scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - - texture_preview = memnew(TextureRect); - value_vbox->add_child(texture_preview); - texture_preview->hide(); - - easing_draw = memnew(Control); - value_vbox->add_child(easing_draw); - easing_draw->hide(); - easing_draw->connect("draw", callable_mp(this, &CustomPropertyEditor::_draw_easing)); - easing_draw->connect("gui_input", callable_mp(this, &CustomPropertyEditor::_drag_easing)); - easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE); - - type_button = memnew(MenuButton); - value_vbox->add_child(type_button); - type_button->hide(); - type_button->get_popup()->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_type_create_selected)); - - menu = memnew(PopupMenu); - // menu->set_pass_on_modal_close_click(false); - value_vbox->add_child(menu); - menu->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_menu_option)); - - evaluator = nullptr; - - spinbox = memnew(SpinBox); - value_vbox->add_child(spinbox); - spinbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); - spinbox->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); - - slider = memnew(HSlider); - value_vbox->add_child(slider); - slider->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); - slider->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); - - action_hboxes = memnew(HBoxContainer); - action_hboxes->set_alignment(BoxContainer::ALIGNMENT_CENTER); - value_vbox->add_child(action_hboxes); - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - action_buttons[i] = memnew(Button); - action_buttons[i]->hide(); - action_hboxes->add_child(action_buttons[i]); - Vector<Variant> binds; - binds.push_back(i); - action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), binds); - } - - create_dialog = nullptr; - property_select = nullptr; -} diff --git a/editor/property_editor.h b/editor/property_editor.h deleted file mode 100644 index 3230834d00..0000000000 --- a/editor/property_editor.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* property_editor.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 PROPERTY_EDITOR_H -#define PROPERTY_EDITOR_H - -#include "editor/editor_locale_dialog.h" -#include "editor/scene_tree_editor.h" -#include "scene/gui/button.h" -#include "scene/gui/check_box.h" -#include "scene/gui/check_button.h" -#include "scene/gui/color_picker.h" -#include "scene/gui/dialogs.h" -#include "scene/gui/grid_container.h" -#include "scene/gui/label.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/split_container.h" -#include "scene/gui/text_edit.h" -#include "scene/gui/texture_rect.h" -#include "scene/gui/tree.h" - -class CreateDialog; -class EditorFileDialog; -class PropertyValueEvaluator; -class PropertySelector; - -class EditorResourceConversionPlugin : public RefCounted { - GDCLASS(EditorResourceConversionPlugin, RefCounted); - -protected: - static void _bind_methods(); - - GDVIRTUAL0RC(String, _converts_to) - GDVIRTUAL1RC(bool, _handles, Ref<Resource>) - GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>) - -public: - virtual String converts_to() const; - virtual bool handles(const Ref<Resource> &p_resource) const; - virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; -}; - -class CustomPropertyEditor : public PopupPanel { - GDCLASS(CustomPropertyEditor, PopupPanel); - - enum { - MAX_VALUE_EDITORS = 12, - MAX_ACTION_BUTTONS = 5, - OBJ_MENU_LOAD = 0, - OBJ_MENU_EDIT = 1, - OBJ_MENU_CLEAR = 2, - OBJ_MENU_MAKE_UNIQUE = 3, - OBJ_MENU_COPY = 4, - OBJ_MENU_PASTE = 5, - OBJ_MENU_NEW_SCRIPT = 6, - OBJ_MENU_EXTEND_SCRIPT = 7, - OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8, - TYPE_BASE_ID = 100, - CONVERT_BASE_ID = 1000 - }; - - enum { - EASING_LINEAR, - EASING_EASE_IN, - EASING_EASE_OUT, - EASING_ZERO, - EASING_IN_OUT, - EASING_OUT_IN - }; - - PopupMenu *menu = nullptr; - SceneTreeDialog *scene_tree = nullptr; - EditorFileDialog *file = nullptr; - EditorLocaleDialog *locale = nullptr; - ConfirmationDialog *error = nullptr; - String name; - Variant::Type type; - Variant v; - List<String> field_names; - int hint = 0; - String hint_text; - HBoxContainer *value_hboxes[MAX_VALUE_EDITORS / 4]; - VBoxContainer *value_vbox = nullptr; - LineEdit *value_editor[MAX_VALUE_EDITORS]; - int focused_value_editor; - Label *value_label[MAX_VALUE_EDITORS]; - HScrollBar *scroll[4]; - HBoxContainer *action_hboxes = nullptr; - Button *action_buttons[MAX_ACTION_BUTTONS]; - MenuButton *type_button = nullptr; - Vector<String> inheritors_array; - TextureRect *texture_preview = nullptr; - ColorPicker *color_picker = nullptr; - TextEdit *text_edit = nullptr; - bool read_only = false; - bool picking_viewport = false; - GridContainer *checks20gc = nullptr; - CheckBox *checks20[20]; - SpinBox *spinbox = nullptr; - HSlider *slider = nullptr; - - Control *easing_draw = nullptr; - CreateDialog *create_dialog = nullptr; - PropertySelector *property_select = nullptr; - - Object *owner = nullptr; - - bool updating = false; - - PropertyValueEvaluator *evaluator = nullptr; - - void _text_edit_changed(); - void _file_selected(String p_file); - void _locale_selected(String p_locale); - void _modified(String p_string); - - real_t _parse_real_expression(String text); - - void _range_modified(double p_value); - void _focus_enter(); - void _focus_exit(); - void _action_pressed(int p_which); - void _type_create_selected(int p_idx); - void _create_dialog_callback(); - void _create_selected_property(const String &p_prop); - - void _color_changed(const Color &p_color); - void _draw_easing(); - void _menu_option(int p_which); - - void _drag_easing(const Ref<InputEvent> &p_ev); - - void _node_path_selected(NodePath p_path); - void show_value_editors(int p_amount); - void config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings); - void config_action_buttons(const List<String> &p_strings); - - void _emit_changed_whole_or_field(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void hide_menu(); - - Variant get_variant() const; - String get_name() const; - - void set_read_only(bool p_read_only) { read_only = p_read_only; } - - bool edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text); - - CustomPropertyEditor(); -}; - -#endif diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 841c3ff3b1..1b17a740dd 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -32,8 +32,12 @@ #include "core/os/keyboard.h" #include "editor/doc_tools.h" +#include "editor/editor_help.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" void PropertySelector::_text_changed(const String &p_newtext) { _update_search(); diff --git a/editor/property_selector.h b/editor/property_selector.h index f42f5daa3f..9f1af576dd 100644 --- a/editor/property_selector.h +++ b/editor/property_selector.h @@ -28,12 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PROPERTYSELECTOR_H -#define PROPERTYSELECTOR_H +#ifndef PROPERTY_SELECTOR_H +#define PROPERTY_SELECTOR_H -#include "editor/editor_help.h" -#include "editor/property_editor.h" -#include "scene/gui/rich_text_label.h" +#include "scene/gui/dialogs.h" + +class EditorHelpBit; +class LineEdit; +class Tree; class PropertySelector : public ConfirmationDialog { GDCLASS(PropertySelector, ConfirmationDialog); @@ -80,4 +82,4 @@ public: PropertySelector(); }; -#endif // PROPERTYSELECTOR_H +#endif // PROPERTY_SELECTOR_H diff --git a/editor/register_exporters.h b/editor/register_exporters.h index 09076af978..9aa98f509f 100644 --- a/editor/register_exporters.h +++ b/editor/register_exporters.h @@ -33,4 +33,4 @@ void register_exporters(); -#endif +#endif // REGISTER_EXPORTERS_H diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 255187e4ed..665aca6a37 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -42,6 +42,7 @@ #include "plugins/script_editor_plugin.h" #include "scene/gui/control.h" #include "scene/gui/label.h" +#include "scene/gui/separator.h" #include "scene/gui/tab_container.h" RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) { @@ -139,7 +140,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_name->set_text("NAME"); but_insert_name->set_tooltip(String("${NAME}\n") + TTR("Node name.")); but_insert_name->set_focus_mode(Control::FOCUS_NONE); - but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${NAME}")); + but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${NAME}")); but_insert_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_name); @@ -149,7 +150,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_parent->set_text("PARENT"); but_insert_parent->set_tooltip(String("${PARENT}\n") + TTR("Node's parent name, if available.")); but_insert_parent->set_focus_mode(Control::FOCUS_NONE); - but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${PARENT}")); + but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${PARENT}")); but_insert_parent->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_parent); @@ -159,7 +160,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_type->set_text("TYPE"); but_insert_type->set_tooltip(String("${TYPE}\n") + TTR("Node type.")); but_insert_type->set_focus_mode(Control::FOCUS_NONE); - but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${TYPE}")); + but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${TYPE}")); but_insert_type->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_type); @@ -169,7 +170,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_scene->set_text("SCENE"); but_insert_scene->set_tooltip(String("${SCENE}\n") + TTR("Current scene name.")); but_insert_scene->set_focus_mode(Control::FOCUS_NONE); - but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${SCENE}")); + but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${SCENE}")); but_insert_scene->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_scene); @@ -179,7 +180,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_root->set_text("ROOT"); but_insert_root->set_tooltip(String("${ROOT}\n") + TTR("Root node name.")); but_insert_root->set_focus_mode(Control::FOCUS_NONE); - but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${ROOT}")); + but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${ROOT}")); but_insert_root->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_root); @@ -189,7 +190,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_count->set_text("COUNTER"); but_insert_count->set_tooltip(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options.")); but_insert_count->set_focus_mode(Control::FOCUS_NONE); - but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${COUNTER}")); + but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${COUNTER}")); but_insert_count->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_count); @@ -321,9 +322,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und spn_count_padding->connect("value_changed", callable_mp(this, &RenameDialog::_update_preview_int)); opt_style->connect("item_selected", callable_mp(this, &RenameDialog::_update_preview_int)); opt_case->connect("item_selected", callable_mp(this, &RenameDialog::_update_preview_int)); - cbut_substitute->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray("")); - cbut_regex->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray("")); - cbut_process->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray("")); + cbut_substitute->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind("")); + cbut_regex->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind("")); + cbut_process->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind("")); but_reset->connect("pressed", callable_mp(this, &RenameDialog::reset)); diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 6a35b22210..94a5c07709 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -171,7 +171,7 @@ Node *SceneCreateDialog::create_scene_root() { break; case ROOT_USER_INTERFACE: { Control *gui = memnew(Control); - gui->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + gui->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); root = gui; } break; case ROOT_OTHER: diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index fb8be5db81..d19a40599f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -39,6 +39,7 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/multi_node_edit.h" @@ -72,7 +73,7 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT)) { - if (mb->is_pressed() && scene_tree->get_rect().has_point(mb->get_position())) { + if (mb->is_pressed() && scene_tree->get_rect().has_point(scene_tree->get_local_mouse_position())) { tree_clicked = true; } else if (!mb->is_pressed()) { tree_clicked = false; @@ -1122,7 +1123,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; case TOOL_CREATE_USER_INTERFACE: { Control *node = memnew(Control); - node->set_anchors_and_offsets_preset(PRESET_WIDE); //more useful for resizable UIs. + node->set_anchors_and_offsets_preset(PRESET_FULL_RECT); //more useful for resizable UIs. new_node = node; } break; @@ -1257,19 +1258,19 @@ void SceneTreeDock::_notification(int p_what) { beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons"))); - button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_2D_SCENE, false)); + button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_2D_SCENE, false)); button_3d = memnew(Button); beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); - button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false)); + button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_3D_SCENE, false)); button_ui = memnew(Button); beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); - button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_USER_INTERFACE, false)); + button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false)); VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer); favorite_node_shortcuts->set_name("FavoriteNodeShortcuts"); @@ -1279,19 +1280,19 @@ void SceneTreeDock::_notification(int p_what) { node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Other Node")); button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button_custom->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_NEW, false)); + button_custom->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false)); button_clipboard = memnew(Button); node_shortcuts->add_child(button_clipboard); button_clipboard->set_text(TTR("Paste From Clipboard")); button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); - button_clipboard->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_PASTE, false)); + button_clipboard->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_PASTE, false)); _update_create_root_dialog(); } break; case NOTIFICATION_ENTER_TREE: { - clear_inherit_confirm->connect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, false)); + clear_inherit_confirm->connect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, false)); scene_tree->set_auto_expand_selected(EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected"), false); } break; @@ -1337,14 +1338,14 @@ void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root UndoRedo *undo_redo = &editor_data->get_undo_redo(); switch (p_mode) { case MODE_BIDI: { - bool is_unique = p_node->is_unique_name_in_owner() && p_base->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr; - if (is_unique) { + bool disable_unique = p_node->is_unique_name_in_owner() && p_root->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr; + if (disable_unique) { // Will create a unique name conflict. Disable before setting owner. undo_redo->add_do_method(p_node, "set_unique_name_in_owner", false); } undo_redo->add_do_method(p_node, "set_owner", p_root); undo_redo->add_undo_method(p_node, "set_owner", p_base); - if (is_unique) { + if (disable_unique) { // Will create a unique name conflict. Enable after setting owner. undo_redo->add_undo_method(p_node, "set_unique_name_in_owner", true); } @@ -1952,17 +1953,36 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { return; } - editor_data->get_undo_redo().create_action(TTR("Attach Script")); - for (Node *E : selected) { - Ref<Script> existing = E->get_script(); - editor_data->get_undo_redo().add_do_method(E, "set_script", p_script); - editor_data->get_undo_redo().add_undo_method(E, "set_script", existing); + if (selected.size() == 1) { + Node *node = selected.front()->get(); + Ref<Script> existing = node->get_script(); + + editor_data->get_undo_redo().create_action(TTR("Attach Script")); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", node); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", node); + editor_data->get_undo_redo().add_do_method(node, "set_script", p_script); + editor_data->get_undo_redo().add_undo_method(node, "set_script", existing); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", node); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", node); editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); + editor_data->get_undo_redo().commit_action(); + } else { + editor_data->get_undo_redo().create_action(TTR("Attach Script")); + for (List<Node *>::Element *E = selected.front(); E; E = E->next()) { + Ref<Script> existing = E->get()->get_script(); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", E->get()); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E->get()); + editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E->get()); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E->get()); + editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); + editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); + } + editor_data->get_undo_redo().commit_action(); } - editor_data->get_undo_redo().commit_action(); - _push_item(p_script.operator->()); _update_script_button(); } @@ -2347,7 +2367,7 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop if (!(c.flags & Object::CONNECT_PERSIST)) { continue; } - newnode->connect(c.signal.get_name(), c.callable, c.binds, Object::CONNECT_PERSIST); + newnode->connect(c.signal.get_name(), c.callable, Object::CONNECT_PERSIST); } } @@ -2437,7 +2457,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { flg |= ResourceSaver::FLAG_COMPRESS; } - err = ResourceSaver::save(p_file, sdata, flg); + err = ResourceSaver::save(sdata, p_file, flg); if (err != OK) { accept->set_text(TTR("Error saving scene.")); accept->popup_centered(); @@ -2586,11 +2606,14 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) { Ref<Script> scr = ResourceLoader::load(p_file); ERR_FAIL_COND(!scr.is_valid()); - Node *n = get_node(p_to); - if (n) { + if (Node *n = get_node(p_to)) { editor_data->get_undo_redo().create_action(TTR("Attach Script")); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", n); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", n); editor_data->get_undo_redo().add_do_method(n, "set_script", scr); editor_data->get_undo_redo().add_undo_method(n, "set_script", n->get_script()); + editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", n); + editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", n); editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); editor_data->get_undo_redo().commit_action(); @@ -3177,7 +3200,7 @@ void SceneTreeDock::_update_create_root_dialog() { favorite_nodes->get_child(i)->queue_delete(); } - Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ); + Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ); if (f.is_valid()) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); @@ -3192,7 +3215,7 @@ void SceneTreeDock::_update_create_root_dialog() { name = ScriptServer::get_global_class_native_base(name); } button->set_icon(EditorNode::get_singleton()->get_class_icon(name)); - button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected), make_binds(l)); + button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected).bind(l)); } } } @@ -3374,14 +3397,14 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_add = memnew(Button); button_add->set_flat(true); - button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_NEW, false)); + button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false)); button_add->set_tooltip(TTR("Add/Create a New Node.")); button_add->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node")); filter_hbc->add_child(button_add); button_instance = memnew(Button); button_instance->set_flat(true); - button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_INSTANTIATE, false)); + button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false)); button_instance->set_tooltip(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists.")); button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene")); filter_hbc->add_child(button_instance); @@ -3396,7 +3419,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_create_script = memnew(Button); button_create_script->set_flat(true); - button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_ATTACH_SCRIPT, false)); + button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_ATTACH_SCRIPT, false)); button_create_script->set_tooltip(TTR("Attach a new or existing script to the selected node.")); button_create_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script")); filter_hbc->add_child(button_create_script); @@ -3404,7 +3427,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_detach_script = memnew(Button); button_detach_script->set_flat(true); - button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_DETACH_SCRIPT, false)); + button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_DETACH_SCRIPT, false)); button_detach_script->set_tooltip(TTR("Detach the script from the selected node.")); button_detach_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/detach_script")); filter_hbc->add_child(button_detach_script); @@ -3417,7 +3440,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec PopupMenu *tree_menu = button_tree_menu->get_popup(); tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); - tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); + tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false)); button_hb = memnew(HBoxContainer); vbc->add_child(button_hb); @@ -3454,8 +3477,8 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL); scene_tree->connect("rmb_pressed", callable_mp(this, &SceneTreeDock::_tree_rmb)); - scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), varray(), CONNECT_DEFERRED); - scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), varray(), CONNECT_DEFERRED); + scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), CONNECT_DEFERRED); + scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), CONNECT_DEFERRED); scene_tree->connect("node_prerename", callable_mp(this, &SceneTreeDock::_node_prerenamed)); scene_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request)); scene_tree->connect("open_script", callable_mp(this, &SceneTreeDock::_script_open_request)); @@ -3505,7 +3528,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec delete_dialog = memnew(ConfirmationDialog); add_child(delete_dialog); - delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm), varray(false)); + delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm).bind(false)); editable_instance_remove_dialog = memnew(ConfirmationDialog); add_child(editable_instance_remove_dialog); @@ -3522,11 +3545,11 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec menu = memnew(PopupMenu); add_child(menu); - menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); + menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false)); menu_subresources = memnew(PopupMenu); menu_subresources->set_name("Sub-Resources"); - menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); + menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false)); menu->add_child(menu_subresources); menu_properties = memnew(PopupMenu); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index dc7f3476ee..e15865036b 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -33,8 +33,8 @@ #include "editor/create_dialog.h" #include "editor/editor_data.h" +#include "editor/editor_quick_open.h" #include "editor/groups_editor.h" -#include "editor/quick_open.h" #include "editor/reparent_dialog.h" #include "editor/script_create_dialog.h" #include "scene/animation/animation_player.h" diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 86fa9222c0..282cfa80e8 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -268,7 +268,17 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { String warning = p_node->get_configuration_warnings_as_string(); if (!warning.is_empty()) { - item->add_button(0, get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning); + const int num_warnings = p_node->get_configuration_warnings().size(); + String warning_icon; + if (num_warnings == 1) { + warning_icon = SNAME("NodeWarning"); + } else if (num_warnings <= 3) { + warning_icon = vformat("NodeWarnings%d", num_warnings); + } else { + warning_icon = SNAME("NodeWarnings4Plus"); + } + + item->add_button(0, get_theme_icon(warning_icon, SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning); } if (p_node->is_unique_name_in_owner()) { @@ -358,7 +368,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { if (can_open_instance && undo_redo) { //Show buttons only when necessary(SceneTreeDock) to avoid crashes if (!p_node->is_connected("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed))) { - p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed), varray(p_node)); + p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed).bind(p_node)); } Ref<Script> script = p_node->get_script(); @@ -375,7 +385,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (p_node->has_meta("_edit_group_")) { - item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); + item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make them selectable.")); } bool v = p_node->call("is_visible"); @@ -386,7 +396,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) { - p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); + p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node)); } _update_visibility_color(p_node, item); @@ -399,7 +409,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) { - p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); + p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node)); } } else if (p_node->is_class("Node3D")) { if (p_node->has_meta("_edit_lock_")) { @@ -407,7 +417,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (p_node->has_meta("_edit_group_")) { - item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); + item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make them selectable.")); } bool v = p_node->call("is_visible"); @@ -418,7 +428,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) { - p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); + p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node)); } _update_visibility_color(p_node, item); @@ -733,7 +743,7 @@ void SceneTreeEditor::_notification(int p_what) { get_tree()->connect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed)); get_tree()->connect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed)); get_tree()->connect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed)); - get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed), varray(), CONNECT_DEFERRED); + get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed), CONNECT_DEFERRED); tree->connect("item_collapsed", callable_mp(this, &SceneTreeEditor::_cell_collapsed)); @@ -1301,7 +1311,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope blocked = 0; update_timer = memnew(Timer); - update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree), varray(false)); + update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree).bind(false)); update_timer->set_one_shot(true); update_timer->set_wait_time(0.5); add_child(update_timer); @@ -1359,6 +1369,10 @@ void SceneTreeDialog::_select() { } } +void SceneTreeDialog::_selected_changed() { + get_ok_button()->set_disabled(!tree->get_selected()); +} + void SceneTreeDialog::_filter_changed(const String &p_filter) { tree->set_filter(p_filter); } @@ -1386,6 +1400,10 @@ SceneTreeDialog::SceneTreeDialog() { tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->get_scene_tree()->connect("item_activated", callable_mp(this, &SceneTreeDialog::_select)); vbc->add_child(tree); + + // Disable the OK button when no node is selected. + get_ok_button()->set_disabled(!tree->get_selected()); + tree->connect("node_selected", callable_mp(this, &SceneTreeDialog::_selected_changed)); } SceneTreeDialog::~SceneTreeDialog() { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 5d4230059c..31772e55b5 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -176,6 +176,7 @@ class SceneTreeDialog : public ConfirmationDialog { void _select(); void _cancel(); + void _selected_changed(); void _filter_changed(const String &p_filter); void _update_theme(); @@ -191,4 +192,4 @@ public: ~SceneTreeDialog(); }; -#endif +#endif // SCENE_TREE_EDITOR_H diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index f2eabdd208..77e0321f83 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -384,7 +385,7 @@ void ScriptCreateDialog::_create_new() { } else { String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text()); scr->set_path(lpath); - Error err = ResourceSaver::save(lpath, scr, ResourceSaver::FLAG_CHANGE_PATH); + Error err = ResourceSaver::save(scr, lpath, ResourceSaver::FLAG_CHANGE_PATH); if (err != OK) { alert->set_text(TTR("Error - Could not create script in filesystem.")); alert->popup_centered(); @@ -620,9 +621,9 @@ void ScriptCreateDialog::_update_template_menu() { } else { String template_directory; if (template_location == ScriptLanguage::TEMPLATE_PROJECT) { - template_directory = EditorSettings::get_singleton()->get_project_script_templates_dir(); + template_directory = EditorPaths::get_singleton()->get_project_script_templates_dir(); } else { - template_directory = EditorSettings::get_singleton()->get_script_templates_dir(); + template_directory = EditorPaths::get_singleton()->get_script_templates_dir(); } templates_found = _get_user_templates(language, current_node, template_directory, template_location); } @@ -1008,7 +1009,7 @@ ScriptCreateDialog::ScriptCreateDialog() { parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree)); hb->add_child(parent_search_button); parent_browse_button = memnew(Button); - parent_browse_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(true, false)); + parent_browse_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path).bind(true, false)); hb->add_child(parent_browse_button); gc->add_child(memnew(Label(TTR("Inherits:")))); gc->add_child(hb); @@ -1057,7 +1058,7 @@ ScriptCreateDialog::ScriptCreateDialog() { file_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(file_path); path_button = memnew(Button); - path_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(false, true)); + path_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path).bind(false, true)); hb->add_child(path_button); Label *label = memnew(Label(TTR("Path:"))); gc->add_child(label); diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index 28e1e9bf22..bd1f2529ca 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "editor/editor_file_dialog.h" #include "editor/editor_scale.h" +#include "scene/resources/shader_include.h" #include "scene/resources/visual_shader.h" #include "servers/rendering/shader_types.h" @@ -43,15 +44,15 @@ void ShaderCreateDialog::_notification(int p_what) { String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", ""); if (!last_lang.is_empty()) { - for (int i = 0; i < language_menu->get_item_count(); i++) { - if (language_menu->get_item_text(i) == last_lang) { - language_menu->select(i); - current_language = i; + for (int i = 0; i < type_menu->get_item_count(); i++) { + if (type_menu->get_item_text(i) == last_lang) { + type_menu->select(i); + current_type = i; break; } } } else { - language_menu->select(default_language); + type_menu->select(default_type); } current_mode = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_mode", 0); @@ -67,12 +68,17 @@ void ShaderCreateDialog::_notification(int p_what) { void ShaderCreateDialog::_update_theme() { Ref<Texture2D> shader_icon = gc->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")); if (shader_icon.is_valid()) { - language_menu->set_item_icon(0, shader_icon); + type_menu->set_item_icon(0, shader_icon); } Ref<Texture2D> visual_shader_icon = gc->get_theme_icon(SNAME("VisualShader"), SNAME("EditorIcons")); if (visual_shader_icon.is_valid()) { - language_menu->set_item_icon(1, visual_shader_icon); + type_menu->set_item_icon(1, visual_shader_icon); + } + + Ref<Texture2D> include_icon = gc->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")); + if (include_icon.is_valid()) { + type_menu->set_item_icon(2, include_icon); } path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); @@ -80,7 +86,7 @@ void ShaderCreateDialog::_update_theme() { } void ShaderCreateDialog::_update_language_info() { - language_data.clear(); + type_data.clear(); for (int i = 0; i < SHADER_TYPE_MAX; i++) { ShaderTypeData data; @@ -88,12 +94,15 @@ void ShaderCreateDialog::_update_language_info() { data.use_templates = true; data.extensions.push_back("gdshader"); data.default_extension = "gdshader"; + } else if (i == int(SHADER_TYPE_INC)) { + data.extensions.push_back("gdshaderinc"); + data.default_extension = "gdshaderinc"; } else { data.default_extension = "tres"; } data.extensions.push_back("res"); data.extensions.push_back("tres"); - language_data.push_back(data); + type_data.push_back(data); } } @@ -136,69 +145,97 @@ void ShaderCreateDialog::ok_pressed() { void ShaderCreateDialog::_create_new() { Ref<Resource> shader; - - if (language_menu->get_selected() == int(SHADER_TYPE_TEXT)) { - Ref<Shader> text_shader; - text_shader.instantiate(); - shader = text_shader; - - StringBuilder code; - code += vformat("shader_type %s;\n", mode_menu->get_text().replace(" ", "").camelcase_to_underscore()); - - if (current_template == 0) { // Default template. - code += "\n"; - switch (current_mode) { - case Shader::MODE_SPATIAL: - code += "void fragment() {\n"; - code += "\t// Place fragment code here.\n"; - code += "}\n"; - break; - case Shader::MODE_CANVAS_ITEM: - code += "void fragment() {\n"; - code += "\t// Place fragment code here.\n"; - code += "}\n"; - break; - case Shader::MODE_PARTICLES: - code += "void start() {\n"; - code += "\t// Place start code here.\n"; - code += "}\n"; - code += "\n"; - code += "void process() {\n"; - code += "\t// Place process code here.\n"; - code += "}\n"; - break; - case Shader::MODE_SKY: - code += "void sky() {\n"; - code += "\t// Place sky code here.\n"; - code += "}\n"; - break; - case Shader::MODE_FOG: - code += "void fog() {\n"; - code += "\t// Place fog code here.\n"; - code += "}\n"; - break; + Ref<Resource> shader_inc; + + switch (type_menu->get_selected()) { + case SHADER_TYPE_TEXT: { + Ref<Shader> text_shader; + text_shader.instantiate(); + shader = text_shader; + + StringBuilder code; + code += vformat("shader_type %s;\n", mode_menu->get_text().replace(" ", "").camelcase_to_underscore()); + + if (current_template == 0) { // Default template. + code += "\n"; + switch (current_mode) { + case Shader::MODE_SPATIAL: + code += "void fragment() {\n"; + code += "\t// Place fragment code here.\n"; + code += "}\n"; + break; + case Shader::MODE_CANVAS_ITEM: + code += "void fragment() {\n"; + code += "\t// Place fragment code here.\n"; + code += "}\n"; + break; + case Shader::MODE_PARTICLES: + code += "void start() {\n"; + code += "\t// Place start code here.\n"; + code += "}\n"; + code += "\n"; + code += "void process() {\n"; + code += "\t// Place process code here.\n"; + code += "}\n"; + break; + case Shader::MODE_SKY: + code += "void sky() {\n"; + code += "\t// Place sky code here.\n"; + code += "}\n"; + break; + case Shader::MODE_FOG: + code += "void fog() {\n"; + code += "\t// Place fog code here.\n"; + code += "}\n"; + break; + } } - } - text_shader->set_code(code.as_string()); - } else { - Ref<VisualShader> visual_shader; - visual_shader.instantiate(); - shader = visual_shader; - visual_shader->set_mode(Shader::Mode(current_mode)); + text_shader->set_code(code.as_string()); + } break; + case SHADER_TYPE_VISUAL: { + Ref<VisualShader> visual_shader; + visual_shader.instantiate(); + shader = visual_shader; + visual_shader->set_mode(Shader::Mode(current_mode)); + } break; + case SHADER_TYPE_INC: { + Ref<ShaderInclude> include; + include.instantiate(); + shader_inc = include; + } break; + default: { + } break; } - if (!is_built_in) { + if (shader.is_null()) { String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text()); - shader->set_path(lpath); - Error err = ResourceSaver::save(lpath, shader, ResourceSaver::FLAG_CHANGE_PATH); - if (err != OK) { - alert->set_text(TTR("Error - Could not create shader in filesystem.")); + shader_inc->set_path(lpath); + + Error error = ResourceSaver::save(shader_inc, lpath, ResourceSaver::FLAG_CHANGE_PATH); + if (error != OK) { + alert->set_text(TTR("Error - Could not create shader include in filesystem.")); alert->popup_centered(); return; } + + emit_signal(SNAME("shader_include_created"), shader_inc); + } else { + if (!is_built_in) { + String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text()); + shader->set_path(lpath); + + Error error = ResourceSaver::save(shader, lpath, ResourceSaver::FLAG_CHANGE_PATH); + if (error != OK) { + alert->set_text(TTR("Error - Could not create shader in filesystem.")); + alert->popup_centered(); + return; + } + } + + emit_signal(SNAME("shader_created"), shader); } - emit_signal(SNAME("shader_created"), shader); + file_path->set_text(file_path->get_text().get_base_dir()); hide(); } @@ -215,9 +252,9 @@ void ShaderCreateDialog::_load_exist() { hide(); } -void ShaderCreateDialog::_language_changed(int p_language) { - current_language = p_language; - ShaderTypeData data = language_data[p_language]; +void ShaderCreateDialog::_type_changed(int p_language) { + current_type = p_language; + ShaderTypeData data = type_data[p_language]; String selected_ext = "." + data.default_extension; String path = file_path->get_text(); @@ -238,6 +275,8 @@ void ShaderCreateDialog::_language_changed(int p_language) { _path_changed(path); file_path->set_text(path); + type_menu->set_item_disabled(int(SHADER_TYPE_INC), load_enabled); + mode_menu->set_disabled(p_language == SHADER_TYPE_INC); template_menu->set_disabled(!data.use_templates); template_menu->clear(); @@ -253,7 +292,7 @@ void ShaderCreateDialog::_language_changed(int p_language) { template_menu->add_item(TTR("N/A")); } - EditorSettings::get_singleton()->set_project_metadata("shader_setup", "last_selected_language", language_menu->get_item_text(language_menu->get_selected())); + EditorSettings::get_singleton()->set_project_metadata("shader_setup", "last_selected_language", type_menu->get_item_text(type_menu->get_selected())); _update_dialog(); } @@ -275,7 +314,7 @@ void ShaderCreateDialog::_browse_path() { file_browse->set_disable_overwrite_warning(true); file_browse->clear_filters(); - List<String> extensions = language_data[language_menu->get_selected()].extensions; + List<String> extensions = type_data[type_menu->get_selected()].extensions; for (const String &E : extensions) { file_browse->add_filter("*." + E); @@ -330,8 +369,8 @@ void ShaderCreateDialog::_path_submitted(const String &p_path) { void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled, int p_preferred_type, int p_preferred_mode) { if (!p_base_path.is_empty()) { initial_base_path = p_base_path.get_basename(); - file_path->set_text(initial_base_path + "." + language_data[language_menu->get_selected()].default_extension); - current_language = language_menu->get_selected(); + file_path->set_text(initial_base_path + "." + type_data[type_menu->get_selected()].default_extension); + current_type = type_menu->get_selected(); } else { initial_base_path = ""; file_path->set_text(""); @@ -342,8 +381,8 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl load_enabled = p_load_enabled; if (p_preferred_type > -1) { - language_menu->select(p_preferred_type); - _language_changed(p_preferred_type); + type_menu->select(p_preferred_type); + _type_changed(p_preferred_type); } if (p_preferred_mode > -1) { @@ -351,7 +390,7 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl _mode_changed(p_preferred_mode); } - _language_changed(current_language); + _type_changed(current_type); _path_changed(file_path->get_text()); } @@ -384,14 +423,14 @@ String ShaderCreateDialog::_validate_path(const String &p_path) { HashSet<String> extensions; for (int i = 0; i < SHADER_TYPE_MAX; i++) { - for (const String &ext : language_data[i].extensions) { + for (const String &ext : type_data[i].extensions) { if (!extensions.has(ext)) { extensions.insert(ext); } } } - ShaderTypeData data = language_data[language_menu->get_selected()]; + ShaderTypeData data = type_data[type_menu->get_selected()]; bool found = false; bool match = false; @@ -399,8 +438,8 @@ String ShaderCreateDialog::_validate_path(const String &p_path) { for (const String &ext : extensions) { if (ext.nocasecmp_to(extension) == 0) { found = true; - for (const String &lang_ext : language_data[current_language].extensions) { - if (lang_ext.nocasecmp_to(extension) == 0) { + for (const String &type_ext : type_data[current_type].extensions) { + if (type_ext.nocasecmp_to(extension) == 0) { match = true; break; } @@ -504,6 +543,7 @@ void ShaderCreateDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("config", "path", "built_in_enabled", "load_enabled"), &ShaderCreateDialog::config, DEFVAL(true), DEFVAL(true)); ADD_SIGNAL(MethodInfo("shader_created", PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"))); + ADD_SIGNAL(MethodInfo("shader_include_created", PropertyInfo(Variant::OBJECT, "shader_include", PROPERTY_HINT_RESOURCE_TYPE, "ShaderInclude"))); } ShaderCreateDialog::ShaderCreateDialog() { @@ -547,24 +587,27 @@ ShaderCreateDialog::ShaderCreateDialog() { vb->add_child(status_panel); add_child(vb); - // Language. + // Type. - language_menu = memnew(OptionButton); - language_menu->set_custom_minimum_size(Size2(250, 0) * EDSCALE); - language_menu->set_h_size_flags(Control::SIZE_EXPAND_FILL); - gc->add_child(memnew(Label(TTR("Language:")))); - gc->add_child(language_menu); + type_menu = memnew(OptionButton); + type_menu->set_custom_minimum_size(Size2(250, 0) * EDSCALE); + type_menu->set_h_size_flags(Control::SIZE_EXPAND_FILL); + gc->add_child(memnew(Label(TTR("Type:")))); + gc->add_child(type_menu); for (int i = 0; i < SHADER_TYPE_MAX; i++) { - String language; + String type; bool invalid = false; switch (i) { case SHADER_TYPE_TEXT: - language = "Shader"; - default_language = i; + type = "Shader"; + default_type = i; break; case SHADER_TYPE_VISUAL: - language = "VisualShader"; + type = "VisualShader"; + break; + case SHADER_TYPE_INC: + type = "ShaderInclude"; break; case SHADER_TYPE_MAX: invalid = true; @@ -576,13 +619,13 @@ ShaderCreateDialog::ShaderCreateDialog() { if (invalid) { continue; } - language_menu->add_item(language); + type_menu->add_item(type); } - if (default_language >= 0) { - language_menu->select(default_language); + if (default_type >= 0) { + type_menu->select(default_type); } - current_language = default_language; - language_menu->connect("item_selected", callable_mp(this, &ShaderCreateDialog::_language_changed)); + current_type = default_type; + type_menu->connect("item_selected", callable_mp(this, &ShaderCreateDialog::_type_changed)); // Modes. diff --git a/editor/shader_create_dialog.h b/editor/shader_create_dialog.h index 6737ce4f10..bf031c3601 100644 --- a/editor/shader_create_dialog.h +++ b/editor/shader_create_dialog.h @@ -47,6 +47,7 @@ class ShaderCreateDialog : public ConfirmationDialog { enum ShaderType { SHADER_TYPE_TEXT, SHADER_TYPE_VISUAL, + SHADER_TYPE_INC, SHADER_TYPE_MAX, }; @@ -56,14 +57,14 @@ class ShaderCreateDialog : public ConfirmationDialog { bool use_templates = false; }; - List<ShaderTypeData> language_data; + List<ShaderTypeData> type_data; GridContainer *gc = nullptr; Label *error_label = nullptr; Label *path_error_label = nullptr; Label *builtin_warning_label = nullptr; PanelContainer *status_panel = nullptr; - OptionButton *language_menu = nullptr; + OptionButton *type_menu = nullptr; OptionButton *mode_menu = nullptr; OptionButton *template_menu = nullptr; CheckBox *internal = nullptr; @@ -79,8 +80,8 @@ class ShaderCreateDialog : public ConfirmationDialog { bool built_in_enabled = true; bool load_enabled = false; bool re_check_path = false; - int current_language = -1; - int default_language = -1; + int current_type = -1; + int default_type = -1; int current_mode = 0; int current_template = 0; @@ -89,7 +90,7 @@ class ShaderCreateDialog : public ConfirmationDialog { void _path_hbox_sorted(); void _path_changed(const String &p_path = String()); void _path_submitted(const String &p_path = String()); - void _language_changed(int p_language = 0); + void _type_changed(int p_type = 0); void _built_in_toggled(bool p_enabled); void _template_changed(int p_template = 0); void _mode_changed(int p_mode = 0); @@ -113,4 +114,4 @@ public: ShaderCreateDialog(); }; -#endif +#endif // SHADER_CREATE_DIALOG_H diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp index bfabf269bf..1cd1b4ea00 100644 --- a/editor/shader_globals_editor.cpp +++ b/editor/shader_globals_editor.cpp @@ -79,7 +79,7 @@ protected: } bool _set(const StringName &p_name, const Variant &p_value) { - Variant existing = RS::get_singleton()->global_variable_get(p_name); + Variant existing = RS::get_singleton()->global_shader_uniform_get(p_name); if (existing.get_type() == Variant::NIL) { return false; @@ -88,9 +88,9 @@ protected: UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); undo_redo->create_action(TTR("Set Shader Global Variable")); - undo_redo->add_do_method(RS::get_singleton(), "global_variable_set", p_name, p_value); - undo_redo->add_undo_method(RS::get_singleton(), "global_variable_set", p_name, existing); - RS::GlobalVariableType type = RS::get_singleton()->global_variable_get_type(p_name); + undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_set", p_name, p_value); + undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_set", p_name, existing); + RS::GlobalShaderUniformType type = RS::get_singleton()->global_shader_uniform_get_type(p_name); Dictionary gv; gv["type"] = global_var_type_names[type]; if (type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { @@ -117,17 +117,17 @@ protected: } bool _get(const StringName &p_name, Variant &r_ret) const { - r_ret = RS::get_singleton()->global_variable_get(p_name); + r_ret = RS::get_singleton()->global_shader_uniform_get(p_name); return r_ret.get_type() != Variant::NIL; } void _get_property_list(List<PropertyInfo> *p_list) const { Vector<StringName> variables; - variables = RS::get_singleton()->global_variable_get_list(); + variables = RS::get_singleton()->global_shader_uniform_get_list(); for (int i = 0; i < variables.size(); i++) { PropertyInfo pinfo; pinfo.name = variables[i]; - switch (RS::get_singleton()->global_variable_get_type(variables[i])) { + switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) { case RS::GLOBAL_VAR_TYPE_BOOL: { pinfo.type = Variant::BOOL; } break; @@ -156,7 +156,7 @@ protected: pinfo.type = Variant::VECTOR3I; } break; case RS::GLOBAL_VAR_TYPE_IVEC4: { - pinfo.type = Variant::PACKED_INT32_ARRAY; + pinfo.type = Variant::VECTOR4I; } break; case RS::GLOBAL_VAR_TYPE_RECT2I: { pinfo.type = Variant::RECT2I; @@ -171,7 +171,7 @@ protected: pinfo.type = Variant::VECTOR3I; } break; case RS::GLOBAL_VAR_TYPE_UVEC4: { - pinfo.type = Variant::PACKED_INT32_ARRAY; + pinfo.type = Variant::VECTOR4I; } break; case RS::GLOBAL_VAR_TYPE_FLOAT: { pinfo.type = Variant::FLOAT; @@ -183,7 +183,7 @@ protected: pinfo.type = Variant::VECTOR3; } break; case RS::GLOBAL_VAR_TYPE_VEC4: { - pinfo.type = Variant::QUATERNION; + pinfo.type = Variant::VECTOR4; } break; case RS::GLOBAL_VAR_TYPE_RECT2: { pinfo.type = Variant::RECT2; @@ -204,7 +204,7 @@ protected: pinfo.type = Variant::TRANSFORM3D; } break; case RS::GLOBAL_VAR_TYPE_MAT4: { - pinfo.type = Variant::PACKED_INT32_ARRAY; + pinfo.type = Variant::PROJECTION; } break; case RS::GLOBAL_VAR_TYPE_SAMPLER2D: { pinfo.type = Variant::OBJECT; @@ -241,7 +241,7 @@ public: } }; -static Variant create_var(RS::GlobalVariableType p_type) { +static Variant create_var(RS::GlobalShaderUniformType p_type) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { return false; @@ -376,12 +376,12 @@ static Variant create_var(RS::GlobalVariableType p_type) { void ShaderGlobalsEditor::_variable_added() { String var = variable_name->get_text().strip_edges(); if (var.is_empty() || !var.is_valid_identifier()) { - EditorNode::get_singleton()->show_warning(TTR("Please specify a valid variable identifier name.")); + EditorNode::get_singleton()->show_warning(TTR("Please specify a valid shader uniform identifier name.")); return; } - if (RenderingServer::get_singleton()->global_variable_get(var).get_type() != Variant::NIL) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Global variable '%s' already exists'"), var)); + if (RenderingServer::get_singleton()->global_shader_uniform_get(var).get_type() != Variant::NIL) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Global shader uniform '%s' already exists'"), var)); return; } @@ -395,11 +395,11 @@ void ShaderGlobalsEditor::_variable_added() { UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - Variant value = create_var(RS::GlobalVariableType(variable_type->get_selected())); + Variant value = create_var(RS::GlobalShaderUniformType(variable_type->get_selected())); - undo_redo->create_action(TTR("Add Shader Global Variable")); - undo_redo->add_do_method(RS::get_singleton(), "global_variable_add", var, RS::GlobalVariableType(variable_type->get_selected()), value); - undo_redo->add_undo_method(RS::get_singleton(), "global_variable_remove", var); + undo_redo->create_action(TTR("Add Shader Global Uniform")); + undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_add", var, RS::GlobalShaderUniformType(variable_type->get_selected()), value); + undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_remove", var); Dictionary gv; gv["type"] = global_var_type_names[variable_type->get_selected()]; gv["value"] = value; @@ -414,9 +414,9 @@ void ShaderGlobalsEditor::_variable_added() { void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) { UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action(TTR("Add Shader Global Variable")); - undo_redo->add_do_method(RS::get_singleton(), "global_variable_remove", p_variable); - undo_redo->add_undo_method(RS::get_singleton(), "global_variable_add", p_variable, RS::get_singleton()->global_variable_get_type(p_variable), RS::get_singleton()->global_variable_get(p_variable)); + undo_redo->create_action(TTR("Add Shader Global Uniform")); + undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_remove", p_variable); + undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_add", p_variable, RS::get_singleton()->global_shader_uniform_get_type(p_variable), RS::get_singleton()->global_shader_uniform_get(p_variable)); undo_redo->add_do_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, Variant()); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, ProjectSettings::get_singleton()->get("shader_globals/" + p_variable)); @@ -479,7 +479,7 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() { inspector->set_use_wide_editors(true); inspector->set_property_name_style(EditorPropertyNameProcessor::STYLE_RAW); inspector->set_use_deletable_properties(true); - inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), varray(), CONNECT_DEFERRED); + inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), CONNECT_DEFERRED); interface = memnew(ShaderGlobalsEditorInterface); interface->connect("var_changed", Callable(this, "_changed")); diff --git a/editor/translations/af.po b/editor/translations/af.po index db28610435..f2e389b6f5 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -473,6 +473,10 @@ msgid "Pressure" msgstr "Herset Zoem" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2187,14 +2191,15 @@ msgstr "Gunstelinge:" msgid "Recent:" msgstr "Onlangse:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Soek:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Passendes:" @@ -2256,8 +2261,8 @@ msgstr "Soek Vervanging Hulpbron:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2851,8 +2856,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Verwyder Seleksie" #: editor/editor_export.cpp #, fuzzy @@ -5566,6 +5572,10 @@ msgid "Drag And Drop Selection" msgstr "Alle Seleksie" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11864,6 +11874,11 @@ msgid "New Animation" msgstr "Optimaliseer Animasie" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Eienskappe" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20409,15 +20424,15 @@ msgstr "Kon nie vouer skep nie." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Moet 'n geldige uitbreiding gebruik." #: platform/windows/export/export.cpp #, fuzzy @@ -20441,15 +20456,15 @@ msgstr "Ongeldige naam." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Moet 'n geldige uitbreiding gebruik." #: platform/windows/export/export.cpp #, fuzzy @@ -21471,7 +21486,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstant" @@ -23434,6 +23449,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Anim Verander Transform" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 93bc2971e8..cda76c44c8 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -65,13 +65,16 @@ # Awab Najim <dev.djvan@gmail.com>, 2022. # Abderrahim <abdoudido117@gmail.com>, 2022. # Jhon Smith <jhonsmaith3@gmail.com>, 2022. +# Oo mohab oO <mohab9225@gmail.com>, 2022. +# عبد الرØÙ…Ù† أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-05 07:17+0000\n" -"Last-Translator: Jhon Smith <jhonsmaith3@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" +"Last-Translator: عبد الرØÙ…Ù† أبو سعدة ||Abd Alrahman abo saada " +"<abdalrahmanabs2005@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" "Language: ar\n" @@ -80,7 +83,7 @@ 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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -451,7 +454,7 @@ msgstr "Ù…ÙØªØ§Ø Command" #: core/os/input_event.cpp #, fuzzy msgid "Physical" -msgstr " (Ùيزيائي)" +msgstr "(Ùيزيائي)" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -485,7 +488,7 @@ msgstr "الموقع العالمي" #: core/os/input_event.cpp msgid "Factor" -msgstr "المعامل" +msgstr "العامل" #: core/os/input_event.cpp msgid "Button Index" @@ -504,6 +507,10 @@ msgid "Pressure" msgstr "الضغط" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "نسبي" @@ -548,7 +555,7 @@ msgstr "قناة" #: core/os/input_event.cpp main/main.cpp msgid "Message" -msgstr "الرسالة" +msgstr "رسالة" #: core/os/input_event.cpp msgid "Pitch" @@ -580,7 +587,7 @@ msgstr "التطبيق" #: core/project_settings.cpp main/main.cpp msgid "Config" -msgstr "تعديل" +msgstr "إعداد" #: core/project_settings.cpp msgid "Project Settings Override" @@ -597,7 +604,7 @@ msgstr "تجاوز إعدادات المشروع" #: scene/3d/skeleton.cpp scene/main/node.cpp scene/resources/mesh_library.cpp #: scene/resources/skin.cpp msgid "Name" -msgstr "الأسم" +msgstr "الاسم" #: core/project_settings.cpp editor/editor_help.cpp #: modules/visual_script/visual_script_nodes.cpp platform/uwp/export/export.cpp @@ -857,9 +864,8 @@ msgid "Compression" msgstr "ضغط" #: core/project_settings.cpp -#, fuzzy msgid "Formats" -msgstr "البنية (اللاØÙ‚Ø©)" +msgstr "التنسيقات" #: core/project_settings.cpp #, fuzzy @@ -939,7 +945,7 @@ msgstr "المسار" #: core/script_language.cpp msgid "Source Code" -msgstr "مصدر الرمز" +msgstr "الكود المصدري || Ø§Ù„Ø´ÙØ±Ø© المصدرية" #: core/translation.cpp editor/project_settings_editor.cpp msgid "Locale" @@ -951,7 +957,7 @@ msgstr "إختبار" #: core/translation.cpp scene/resources/font.cpp msgid "Fallback" -msgstr "تقهقر" +msgstr "تراجع | Ø§Ù†Ø³ØØ§Ø¨" #: core/ustring.cpp scene/resources/segment_shape_2d.cpp msgid "B" @@ -1009,7 +1015,7 @@ msgstr "ØØ¬Ù… Ùهرس المخزن المؤقت Ù„Ù„ÙˆØØ© المضلعات (K #: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp #: servers/visual_server.cpp msgid "2D" -msgstr "2D" +msgstr "ثنائي الأبعاد" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp @@ -2172,14 +2178,15 @@ msgstr "Ø§Ù„Ù…ÙØ¶Ù„Ø©:" msgid "Recent:" msgstr "Ø§Ù„ØØ§Ù„ÙŠ:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Ø¨ØØ«:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "يطابق:" @@ -2239,8 +2246,8 @@ msgstr "Ø§Ù„Ø¨ØØ« عن مورد بديل:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2813,7 +2820,7 @@ msgstr "تصدير المشروع لمنصة:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "نسخ مسار العÙقدة" #: editor/editor_export.cpp @@ -4863,7 +4870,7 @@ msgstr "نظام Ø§Ù„Ù…Ù„ÙØ§Øª" #: editor/editor_node.cpp msgid "Expand Bottom Panel" -msgstr "توسيع التبويب السÙلي" +msgstr "توسيع القائمة السÙلية" #: editor/editor_node.cpp msgid "Don't Save" @@ -5603,6 +5610,10 @@ msgid "Drag And Drop Selection" msgstr "ØªØØ¯ÙŠØ¯ الملئ خريطة-الشبكة" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "المظهر" @@ -9299,7 +9310,7 @@ msgstr "Ø§Ù„Ù…ØØ§Ø°Ø§Ø© الذكية" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Hide" -msgstr "" +msgstr "Ø§Ø®ÙØ§Ø¡" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -11842,6 +11853,11 @@ msgid "New Animation" msgstr "رسومية Ù…ØªØØ±ÙƒØ© جديدة" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ØªØ±Ø´ÙŠØ Ø§Ù„Ø¯ÙˆØ§Ù„" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "السرعة:" @@ -16278,26 +16294,24 @@ msgid "Set Room Point Position" msgstr "ØØ¯Ø¯ موقع نقطة الإنØÙ†Ø§Ø¡" #: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp -#, fuzzy msgid "Portal Margin" -msgstr "ØªØØ¯ÙŠØ¯ الهامش" +msgstr "هامش البوابة" #: editor/spatial_editor_gizmos.cpp msgid "Portal Edge" -msgstr "" +msgstr "ØØ§ÙØ© Ø§Ù„ØºØ±ÙØ©" #: editor/spatial_editor_gizmos.cpp msgid "Portal Arrow" -msgstr "" +msgstr "سهم البوابة" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Set Portal Point Position" -msgstr "ØØ¯Ø¯ موقع نقطة الإنØÙ†Ø§Ø¡" +msgstr "ØØ¯Ø¯ موقع نقطة البوابة" #: editor/spatial_editor_gizmos.cpp msgid "Portal Front" -msgstr "" +msgstr "واجهة البوابة" #: editor/spatial_editor_gizmos.cpp #, fuzzy @@ -16336,18 +16350,16 @@ msgid "Occluder Polygon Front" msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Polygon Back" -msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚" +msgstr "" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Hole" -msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚" +msgstr "" #: main/main.cpp msgid "Godot Physics" -msgstr "" +msgstr "Ùيزيائيات جودو" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp @@ -16426,9 +16438,8 @@ msgid "Driver" msgstr "" #: main/main.cpp -#, fuzzy msgid "Driver Name" -msgstr "اسم النص البرمجي:" +msgstr "اسم النص البرمجي" #: main/main.cpp msgid "Fallback To GLES2" @@ -16447,22 +16458,20 @@ msgid "Allow hiDPI" msgstr "" #: main/main.cpp -#, fuzzy msgid "V-Sync" -msgstr "مزامنة" +msgstr "مزامنة (مزامنة كرت الشاشة)" #: main/main.cpp -#, fuzzy msgid "Use V-Sync" -msgstr "استخدام Ø§Ù„Ù…ØØ§Ø°Ø§Ø©" +msgstr "استخدام مزامنة كرت الشاشة" #: main/main.cpp msgid "Per Pixel Transparency" -msgstr "" +msgstr "Ø´ÙØ§Ùية بيكسل القلم" #: main/main.cpp msgid "Allowed" -msgstr "" +msgstr "مسموØ" #: main/main.cpp msgid "Intended Usage" @@ -16474,18 +16483,16 @@ msgid "Framebuffer Allocation" msgstr "ØªØØ¯ÙŠØ¯ الإطار" #: main/main.cpp platform/uwp/os_uwp.cpp -#, fuzzy msgid "Energy Saving" -msgstr "خطأ ÙÙŠ الØÙظ" +msgstr "توÙير الطاقة" #: main/main.cpp msgid "Threads" -msgstr "" +msgstr "مسارات" #: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h -#, fuzzy msgid "Thread Model" -msgstr "أظهر المود" +msgstr "نوع المسار" #: main/main.cpp msgid "Thread Safe BVH" @@ -16503,9 +16510,8 @@ msgstr "الوثائق الإلكترونية" #: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp #: scene/main/scene_tree.cpp scene/register_scene_types.cpp -#, fuzzy msgid "Common" -msgstr "المجتمع" +msgstr "شائع" #: main/main.cpp #, fuzzy @@ -16525,7 +16531,7 @@ msgstr "" #: scene/gui/scroll_container.cpp scene/gui/text_edit.cpp scene/gui/tree.cpp #: scene/main/viewport.cpp scene/register_scene_types.cpp msgid "GUI" -msgstr "" +msgstr "واجهة المستخدم الرسومية" #: main/main.cpp msgid "Drop Mouse On GUI Input Disabled" @@ -16549,9 +16555,8 @@ msgid "Physics Interpolation" msgstr "وضعية Ø§Ù„Ø£Ø³ØªÙŠÙØ§Ø¡" #: main/main.cpp -#, fuzzy msgid "Enable Warnings" -msgstr "تمكين Ø§Ù„ØªØ±Ø´ÙŠØ Filtering" +msgstr "ØªÙØ¹ÙŠÙ„ Ø§Ù„ØªØØ°ÙŠØ±Ø§Øª" #: main/main.cpp #, fuzzy @@ -16568,25 +16573,23 @@ msgstr "" #: main/main.cpp msgid "iOS" -msgstr "" +msgstr "IOS" #: main/main.cpp msgid "Hide Home Indicator" msgstr "" #: main/main.cpp -#, fuzzy msgid "Input Devices" -msgstr "جميع الأجهزة" +msgstr "أجهزة الإدخال" #: main/main.cpp -#, fuzzy msgid "Pointing" -msgstr "نقطة" +msgstr "يشير" #: main/main.cpp msgid "Touch Delay" -msgstr "" +msgstr "تأخير اللمس" #: main/main.cpp servers/visual_server.cpp msgid "GLES3" @@ -16628,7 +16631,7 @@ msgstr "" #: main/main.cpp msgid "Fullsize" -msgstr "" +msgstr "Ø§Ù„ØØ¬Ù… الكامل" #: main/main.cpp scene/resources/dynamic_font.cpp #, fuzzy @@ -16701,21 +16704,20 @@ msgstr "انتهت المهلة." #: main/main.cpp msgid "Runtime" -msgstr "" +msgstr "اثناء التشغيل" #: main/main.cpp msgid "Unhandled Exception Policy" msgstr "" #: main/main.cpp -#, fuzzy msgid "Main Loop Type" -msgstr "إيجاد نوع العÙقدة" +msgstr "نوع الØÙ„قة الرئيسية" #: main/main.cpp scene/gui/texture_progress.cpp #: scene/gui/viewport_container.cpp msgid "Stretch" -msgstr "" +msgstr "تمدد" #: main/main.cpp #, fuzzy @@ -16770,38 +16772,33 @@ msgstr "تغيير نص٠قطر الدائرة الداخلي" #: modules/csg/csg_gizmos.cpp msgid "Change Torus Outer Radius" -msgstr "تعديل نص٠القطر الخارجي للطارة Torus Outer Radius" +msgstr "تعديل نص٠القطر الخارجي للمسنن" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Operation" -msgstr "الإعدادات" +msgstr "عملية" #: modules/csg/csg_shape.cpp msgid "Calculate Tangents" -msgstr "" +msgstr "Ø§ØØ³Ø¨ الظلال" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Use Collision" -msgstr "التصادم" +msgstr "استخدم التصادم" #: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp -#, fuzzy msgid "Collision Layer" -msgstr "وضع التصادم" +msgstr "" #: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp #: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp #: scene/resources/navigation_mesh.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Mask" -msgstr "وضع التصادم" +msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Invert Faces" -msgstr "ØØ§Ù„Ø© التØÙˆÙŠÙ„" +msgstr "اقلب الوجوه" #: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp @@ -16821,37 +16818,32 @@ msgid "Radial Segments" msgstr "معاملات المشهد الرئيس:" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Rings" -msgstr "ØªØØ°ÙŠØ±Ø§Øª" +msgstr "خواتم" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Smooth Faces" -msgstr "خطوة ناعمة" +msgstr "وجوه ناعمة" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Sides" -msgstr "أظهر الموجهات" +msgstr "جهات" #: modules/csg/csg_shape.cpp msgid "Cone" msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Inner Radius" -msgstr "تغيير نص٠قطر الدائرة الداخلي" +msgstr "القطر الداخلي" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Outer Radius" -msgstr "تعديل نص٠القطر الخارجي للطارة Torus Outer Radius" +msgstr "القطر الخارجي" #: modules/csg/csg_shape.cpp msgid "Ring Sides" -msgstr "" +msgstr "جهات الخاتم" #: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp #: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp @@ -16862,16 +16854,15 @@ msgstr "Ø§Ù„Ù…ÙØ¶Ù„عات" #: modules/csg/csg_shape.cpp msgid "Spin Degrees" -msgstr "" +msgstr "درجة الدوران" #: modules/csg/csg_shape.cpp msgid "Spin Sides" -msgstr "" +msgstr "جهة الدوران" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Node" -msgstr "لصق العÙقد" +msgstr "مسار العقدة" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16902,9 +16893,8 @@ msgid "Path Continuous U" msgstr "متواصل" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path U Distance" -msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:" +msgstr "المسار المØÙ„ÙŠ" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16912,28 +16902,26 @@ msgid "Path Joined" msgstr "دوران عشوائي:" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Compression Mode" -msgstr "وضع التصادم" +msgstr "وضع الضغط" #: modules/enet/networked_multiplayer_enet.cpp #, fuzzy msgid "Transfer Channel" -msgstr "تعديل التØÙˆÙ„ات" +msgstr "نقل القنوات" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Channel Count" -msgstr "كائن" +msgstr "عدد القنوات" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Always Ordered" -msgstr "إظهار الشبكة دوماً" +msgstr "مطلوب دائمًا" #: modules/enet/networked_multiplayer_enet.cpp +#, fuzzy msgid "Server Relay" -msgstr "" +msgstr "تناوب الخادم" #: modules/enet/networked_multiplayer_enet.cpp msgid "DTLS Verify" @@ -16957,30 +16945,25 @@ msgid "Use FBX" msgstr "" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Config File" -msgstr "تخزين الملÙ:" +msgstr "مل٠التهيئة" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Load Once" -msgstr "تØÙ…يل المورد" +msgstr "ØÙ…Ù„ مرة ÙˆØ§ØØ¯Ø©" #: modules/gdnative/gdnative.cpp #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Singleton" -msgstr "الهيكل" +msgstr "" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Symbol Prefix" -msgstr "بادئة:" +msgstr "رمز البادئة" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Reloadable" -msgstr "إعادة تØÙ…يل" +msgstr "قابل لإعادة التØÙ…يل" #: modules/gdnative/gdnative.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -16998,7 +16981,7 @@ msgstr "اختر تبعيات المكتبة لأجل هذا الإدخال" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Remove current entry" -msgstr "Ù…Ø³Ø Ø§Ù„Ù…Ø¯Ø®Ù„Ø© Ø§Ù„ØØ§Ù„ية" +msgstr "Ù…Ø³Ø Ø§Ù„Ù…Ø¯Ø®Ù„Ø§Øª Ø§Ù„ØØ§Ù„ية" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Double click to create a new entry" @@ -17047,9 +17030,8 @@ msgid "Script Class" msgstr "اسم النص البرمجي:" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Icon Path" -msgstr "مسار التركيز" +msgstr "مسار الأيقونة" #: modules/gdnative/register_types.cpp msgid "GDNative" @@ -17057,18 +17039,16 @@ msgstr "لغة البرمجة GDNative" #: modules/gdscript/editor/gdscript_highlighter.cpp #: modules/gdscript/gdscript.cpp -#, fuzzy msgid "GDScript" -msgstr "النص البرمجي" +msgstr "لغة جي دي" #: modules/gdscript/editor/gdscript_highlighter.cpp msgid "Function Definition Color" -msgstr "" +msgstr "لون تعري٠الدالة" #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Node Path Color" -msgstr "نسخ مسار العÙقدة" +msgstr "لون مسار العقدة" #: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp msgid "Max Call Stack" @@ -17096,11 +17076,11 @@ 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" -msgstr "لا يعتمد على مل٠موارد" +msgstr "غير مبني على مل٠موارد" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary format (missing @path)" @@ -17123,14 +17103,12 @@ msgid "Object can't provide a length." msgstr "لا يمكن للكائن أن ÙŠÙ…Ù†Ø Ø·ÙˆÙ„Ø§Ù‹." #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Language Server" -msgstr "اللغة:" +msgstr "لغة الخادك" #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Enable Smart Resolve" -msgstr "لا يمكن الØÙ„" +msgstr "ØªÙØ¹ÙŠÙ„ الØÙ„ الذكي" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Show Native Symbols In Editor" @@ -17138,7 +17116,7 @@ msgstr "" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Use Thread" -msgstr "" +msgstr "استخدم المسار" #: modules/gltf/editor_scene_exporter_gltf_plugin.cpp #, fuzzy @@ -17161,14 +17139,12 @@ msgid "Byte Offset" msgstr "مقدار Ø¥Ø²Ø§ØØ© الشبكة:" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Component Type" -msgstr "مكونات" +msgstr "نوع المكون" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Normalized" -msgstr "البنية (اللاØÙ‚Ø©)" +msgstr "" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17176,14 +17152,12 @@ msgid "Count" msgstr "الكمية:" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Min" -msgstr "ميبي بايت (MiB)" +msgstr "أقل" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Max" -msgstr "خلط" +msgstr "أعلى" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17233,7 +17207,7 @@ msgstr "جميع الأجهزة" #: modules/gltf/gltf_camera.cpp #, fuzzy msgid "FOV Size" -msgstr "Ø§Ù„ØØ¬Ù…:" +msgstr "ØØ¬Ù… Ù…Ø³Ø§ØØ©Ø§Ù„رؤية" #: modules/gltf/gltf_camera.cpp msgid "Zfar" @@ -17252,27 +17226,25 @@ msgstr "خطي" #: scene/resources/environment.cpp scene/resources/material.cpp #: scene/resources/particles_material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Color" msgstr "الألوان" #: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp #: scene/resources/environment.cpp msgid "Intensity" -msgstr "" +msgstr "Ø§Ù„ÙƒØ«Ø§ÙØ© | الشدة" #: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Range" -msgstr "تغير" +msgstr "نطاق" #: modules/gltf/gltf_light.cpp msgid "Inner Cone Angle" -msgstr "" +msgstr "زاوية المخروط الداخلية" #: modules/gltf/gltf_light.cpp msgid "Outer Cone Angle" -msgstr "" +msgstr "زاوية المخروط الخارجية" #: modules/gltf/gltf_mesh.cpp #, fuzzy @@ -17285,9 +17257,8 @@ msgid "Instance Materials" msgstr "تغيرات المادة:" #: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp -#, fuzzy msgid "Parent" -msgstr "إعادة اختيار الأبوة" +msgstr "أب" #: modules/gltf/gltf_node.cpp #, fuzzy @@ -17311,20 +17282,20 @@ msgstr "أبناء قابلين للتعديل" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp #, fuzzy msgid "Joints" -msgstr "نقطة" +msgstr "Ø§Ù„Ù…ÙØ§ØµÙ„" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp msgid "Roots" -msgstr "" +msgstr "الجذور" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp msgid "Unique Names" -msgstr "" +msgstr "أسماء مميزة" #: modules/gltf/gltf_skeleton.cpp #, fuzzy msgid "Godot Bone Node" -msgstr "عقدة التنقل الزمني" +msgstr "عقدة جودو العظمية" #: modules/gltf/gltf_skin.cpp #, fuzzy @@ -17341,9 +17312,8 @@ msgid "Inverse Binds" msgstr "" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Non Joints" -msgstr "ØªØØ±ÙŠÙƒ النÙقطة" +msgstr "بلا Ù…ÙØ§ØµÙ„" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Bone I" @@ -17367,12 +17337,11 @@ msgstr "" #: modules/gltf/gltf_spec_gloss.cpp msgid "Gloss Factor" -msgstr "" +msgstr "عامل اللمعان" #: modules/gltf/gltf_spec_gloss.cpp -#, fuzzy msgid "Specular Factor" -msgstr "Ù…ÙØ´ØºÙ„ الكمية القياسية Scalar." +msgstr "عامل ال" #: modules/gltf/gltf_spec_gloss.cpp msgid "Spec Gloss Img" @@ -17380,17 +17349,15 @@ msgstr "" #: modules/gltf/gltf_state.cpp msgid "Json" -msgstr "" +msgstr "جيسون" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Major Version" -msgstr "الإصدار" +msgstr "إصدار رئيسي" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Minor Version" -msgstr "الإصدار" +msgstr "إصدار ÙØ±Ø¹ÙŠ" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17411,9 +17378,8 @@ msgid "Accessors" msgstr "" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Scene Name" -msgstr "المسار للمشهد:" +msgstr "اسم المشهد" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17428,21 +17394,19 @@ msgstr "المزايا" #: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp msgid "Images" -msgstr "" +msgstr "الصور" #: modules/gltf/gltf_state.cpp msgid "Cameras" -msgstr "" +msgstr "الكاميرات" #: modules/gltf/gltf_state.cpp servers/visual_server.cpp -#, fuzzy msgid "Lights" -msgstr "ضوء" +msgstr "الأضواء" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Unique Animation Names" -msgstr "إسم رسم Ø§Ù„Ù…ØªØØ±Ùƒ جديد:" +msgstr "أسماء ØØ±ÙƒØ§Øª مميزة" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17450,37 +17414,32 @@ msgid "Skeletons" msgstr "الهيكل" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeleton To Node" -msgstr "اختر عÙقدة" +msgstr "هيكل إلى عقدة" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Animations" -msgstr "الرسومات Ø§Ù„Ù…ØªØØ±ÙƒØ©:" +msgstr "Ø§Ù„ØØ±ÙƒØ§Øª" #: modules/gltf/gltf_texture.cpp -#, fuzzy msgid "Src Image" -msgstr "إظهار العظام" +msgstr "مصدر الصورة" #: modules/gridmap/grid_map.cpp msgid "Mesh Library" msgstr "مكتبة المجسم" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Physics Material" -msgstr "نسبة الإطار الÙيزيائي %" +msgstr "مادة" #: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp -#, fuzzy msgid "Use In Baked Light" -msgstr "طبخ (إعداد) خرائط الضوء" +msgstr "استخدام ÙÙŠ الإضاءة المطبوخة" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp msgid "Cell" -msgstr "" +msgstr "خلية" #: modules/gridmap/grid_map.cpp #, fuzzy @@ -17488,19 +17447,16 @@ msgid "Octant Size" msgstr "الواجهة View الأمامية" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center X" -msgstr "المنتصÙ" +msgstr "منتص٠س" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Y" -msgstr "المنتصÙ" +msgstr "منتص٠ص" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Z" -msgstr "المنتصÙ" +msgstr "منتصÙ" #: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp #: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp @@ -17666,14 +17622,12 @@ msgid "Generate buffers" msgstr "ولد AABB" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Direct lighting" -msgstr "الاتجاهات" +msgstr "إضاءة مباشرة" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Indirect lighting" -msgstr "Ø§Ù„Ù…Ø³Ø§ÙØ© البادئة يميناً" +msgstr "إضاءة غير مباشرة" #: modules/lightmapper_cpu/lightmapper_cpu.cpp #, fuzzy @@ -17709,27 +17663,24 @@ msgstr "" #: modules/minimp3/resource_importer_mp3.cpp #: modules/stb_vorbis/audio_stream_ogg_vorbis.cpp #: modules/stb_vorbis/resource_importer_ogg_vorbis.cpp -#, fuzzy msgid "Loop Offset" -msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:" +msgstr "Ø¥Ø²Ø§ØØ© الØÙ„قة" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Eye Height" -msgstr "" +msgstr "Ø§Ø±ØªÙØ§Ø¹ الغين" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "IOD" msgstr "" #: modules/mobile_vr/mobile_vr_interface.cpp -#, fuzzy msgid "Display Width" -msgstr "عرض Ø§Ù„Ù…ÙØ®Ø·Ø· Wireframe" +msgstr "عرض الشاشة" #: modules/mobile_vr/mobile_vr_interface.cpp -#, fuzzy msgid "Display To Lens" -msgstr "عرض من غير ظلال" +msgstr "شاشة إلى عدسة" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Oversample" @@ -17748,14 +17699,12 @@ msgid "Class name can't be a reserved keyword" msgstr "لا يمكن أن يكون اسم الص٠كلمة Ù…ØØ¬ÙˆØ²Ø©" #: modules/mono/csharp_script.cpp -#, fuzzy msgid "Build Solution" -msgstr "تعبئة Ø§Ù„Ù…ÙØØ¯Ø¯" +msgstr "" #: modules/mono/editor/csharp_project.cpp -#, fuzzy msgid "Auto Update Project" -msgstr "مشروع غير مسمى" +msgstr "ØªØØ¯ÙŠØ« المشروع تلقائيًا" #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" @@ -17832,9 +17781,8 @@ msgid "Seamless" msgstr "" #: modules/opensimplex/noise_texture.cpp -#, fuzzy msgid "As Normal Map" -msgstr "ØØ¬Ù… عشوائي:" +msgstr "كخريطة عادية" #: modules/opensimplex/noise_texture.cpp msgid "Bump Strength" @@ -17842,7 +17790,7 @@ msgstr "" #: modules/opensimplex/noise_texture.cpp msgid "Noise" -msgstr "" +msgstr "ضوضاء" #: modules/opensimplex/noise_texture.cpp #, fuzzy @@ -17855,7 +17803,7 @@ msgstr "" #: modules/opensimplex/open_simplex_noise.cpp msgid "Period" -msgstr "" +msgstr "ÙØªØ±Ø©" #: modules/opensimplex/open_simplex_noise.cpp #, fuzzy @@ -17871,14 +17819,12 @@ msgid "Subject" msgstr "" #: modules/regex/regex.cpp -#, fuzzy msgid "Names" -msgstr "الأسم" +msgstr "الأسماء" #: modules/regex/regex.cpp -#, fuzzy msgid "Strings" -msgstr "الإعدادات:" +msgstr "النصوص" #: modules/upnp/upnp.cpp msgid "Discover Multicast If" @@ -17893,14 +17839,12 @@ msgid "Discover IPv6" msgstr "" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Description URL" -msgstr "الوصÙ" +msgstr "وص٠الرابط" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Service Type" -msgstr "تØÙŠØ¯ نوع المتغير" +msgstr "نوع الخدمة" #: modules/upnp/upnp_device.cpp msgid "IGD Control URL" @@ -17954,9 +17898,8 @@ msgid "Stack overflow with stack depth:" msgstr "ØØ¯ÙˆØ« تجاوز للتكدس ( Stack overflow) مع عمق التكدس:" #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Visual Script" -msgstr "Ø¨ØØ« VisualScript" +msgstr "البرمجة المرئية" #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" @@ -17987,14 +17930,12 @@ msgid "Add Output Port" msgstr "Ø£Ø¶Ù Ù…Ù†ÙØ° إخراج" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Port Type" -msgstr "تغيير النوع" +msgstr "تغيير نوع Ø§Ù„Ù…Ù†ÙØ°" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Port Name" -msgstr "غيّر اسم Ù…Ù†ÙØ° Ø§Ù„Ù…ÙØ¯Ø®Ù„ات" +msgstr "تغيير اسم Ø§Ù„Ù…Ù†ÙØ°" #: modules/visual_script/visual_script_editor.cpp msgid "Override an existing built-in function." @@ -18180,7 +18121,7 @@ msgstr "تعديل قيمة الإدخال" #: modules/visual_script/visual_script_editor.cpp msgid "Resize Comment" -msgstr "تغيير ØØ¬Ù… التعليق" +msgstr "تغيير ØØ¬Ù… Ø§Ù„Ù…Ù„Ø§ØØ¸Ø©" #: modules/visual_script/visual_script_editor.cpp msgid "Can't create function with a function node." @@ -20629,15 +20570,15 @@ msgstr "لا يمكن العثور على Ù…ÙØªØ§Ø المتجر، لا يمك٠#: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "صيغة غير ØµØ§Ù„ØØ©." #: platform/windows/export/export.cpp #, fuzzy @@ -20661,15 +20602,15 @@ msgstr "اسم غير صالØ." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "صيغة غير ØµØ§Ù„ØØ©." #: platform/windows/export/export.cpp #, fuzzy @@ -21781,7 +21722,7 @@ msgstr "Ø§Ù„Ø³ÙØ±" msgid "Rotation Degrees" msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "ثابت" @@ -22831,9 +22772,8 @@ msgstr "" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp #: scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Pixel Size" -msgstr "Ù…ØØ§Ø°Ø§Ø© البكسل" +msgstr "ØØ¬Ù… البكسل" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Billboard" @@ -23372,9 +23312,8 @@ msgid "Solver" msgstr "" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Exclude Nodes" -msgstr "ØØ°Ù العÙقد" +msgstr "استثناء العÙقد" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23440,14 +23379,12 @@ msgid "Linear Ortho" msgstr "نظر من الخل٠(متعامد/ليس له بعد ثالث)" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper Angle" -msgstr "Ø§Ù„Ø£ØØ±Ù الكبيرة (Uppercase)" +msgstr "الزاوية العلوية" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower Angle" -msgstr "Ø§Ù„Ø£ØØ±Ù الصغيرة (Lowercase)" +msgstr "الزاوية السÙلية" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23603,9 +23540,8 @@ msgid "Thickness" msgstr "" #: scene/3d/reflection_probe.cpp scene/main/viewport.cpp -#, fuzzy msgid "Update Mode" -msgstr "وضع التدوير" +msgstr "وضع Ø§Ù„ØªØØ¯ÙŠØ«" #: scene/3d/reflection_probe.cpp #, fuzzy @@ -23704,7 +23640,7 @@ msgstr "يجب ØªÙˆØ§ÙØ± مدير-غر٠(RoomManager) ÙˆØ§ØØ¯ Ùقط ÙÙŠ Ø´Ø #: scene/3d/room_manager.cpp msgid "Main" -msgstr "" +msgstr "رئيسي | الرئيسي" #: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp #: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp @@ -23913,6 +23849,11 @@ msgstr "" "قم بتغيير Ø§Ù„ØØ¬Ù… ÙÙŠ أشكال تصادم الأتباع (Children) بدلاً من ذلك." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Ø§Ù„Ø§ØØªÙاظ بالتØÙˆÙ‘Ù„ الشمولي Global" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -23962,13 +23903,12 @@ msgid "Per-Wheel Motion" msgstr "زر العجلة للأسÙÙ„" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Engine Force" -msgstr "مستندات الإنترنت" +msgstr "قوة Ø§Ù„Ù…ØØ±Ùƒ" #: scene/3d/vehicle_body.cpp msgid "Brake" -msgstr "" +msgstr "ÙØ±Ø§Ù…Ù„ | مكابØ" #: scene/3d/vehicle_body.cpp msgid "Steering" @@ -23988,9 +23928,8 @@ msgid "Use As Steering" msgstr "" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Wheel" -msgstr "العجلة Ù†ØÙˆ الأقصى." +msgstr "عجلة" #: scene/3d/vehicle_body.cpp msgid "Roll Influence" @@ -24120,14 +24059,12 @@ msgid "Fadeout Time" msgstr "وقت التلاشي X (ثواني):" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Auto Restart" -msgstr "إعادة تشغيل تلقائية:" +msgstr "إعادة تشغيل تلقائية" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Autorestart" -msgstr "إعادة تشغيل تلقائية:" +msgstr "إعادة تشغيل تلقائية" #: scene/animation/animation_blend_tree.cpp msgid "Delay" diff --git a/editor/translations/az.po b/editor/translations/az.po index 3701234f3d..af28a85240 100644 --- a/editor/translations/az.po +++ b/editor/translations/az.po @@ -5,49 +5,49 @@ # # Jafar Tarverdiyev <cefertarverdiyevv@gmail.com>, 2021. # Lucifer25x <umudyt2006@gmail.com>, 2021. +# Ümid Quliyev <lucifer25x@protonmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2021-09-16 14:36+0000\n" -"Last-Translator: Lucifer25x <umudyt2006@gmail.com>\n" +"PO-Revision-Date: 2022-08-05 01:04+0000\n" +"Last-Translator: Ümid Quliyev <lucifer25x@protonmail.com>\n" "Language-Team: Azerbaijani <https://hosted.weblate.org/projects/godot-engine/" "godot/az/>\n" "Language: az\n" "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.9-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp +#, fuzzy msgid "Tablet Driver" -msgstr "" +msgstr "PlanÅŸet sürücü" #: core/bind/core_bind.cpp -#, fuzzy msgid "Clipboard" -msgstr "Pano boÅŸdur!" +msgstr "Pano" #: core/bind/core_bind.cpp -#, fuzzy msgid "Current Screen" -msgstr "Animasiya xüsusiyyÉ™tlÉ™ri." +msgstr "Aktiv Ekran" #: core/bind/core_bind.cpp msgid "Exit Code" -msgstr "" +msgstr "Çıxış Kodu" #: core/bind/core_bind.cpp msgid "V-Sync Enabled" -msgstr "" +msgstr "V-Sync Aktivdir" #: core/bind/core_bind.cpp main/main.cpp msgid "V-Sync Via Compositor" -msgstr "" +msgstr "V-Sync Kompozitor VasitÉ™silÉ™" #: core/bind/core_bind.cpp main/main.cpp msgid "Delta Smoothing" -msgstr "" +msgstr "Delta hamarlanması" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode" @@ -59,28 +59,28 @@ msgstr "" #: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp msgid "Keep Screen On" -msgstr "" +msgstr "Ekranı Açıq Tut" #: core/bind/core_bind.cpp msgid "Min Window Size" -msgstr "" +msgstr "Minimum PÉ™ncÉ™rÉ™ Ölçüsü" #: core/bind/core_bind.cpp msgid "Max Window Size" -msgstr "" +msgstr "Maksimum PÉ™ncÉ™rÉ™ Ölçüsü" #: core/bind/core_bind.cpp msgid "Screen Orientation" -msgstr "" +msgstr "PÉ™ncÉ™rÉ™ NisbÉ™ti" #: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp #: platform/uwp/os_uwp.cpp msgid "Window" -msgstr "" +msgstr "PÉ™ncÉ™rÉ™" #: core/bind/core_bind.cpp core/project_settings.cpp msgid "Borderless" -msgstr "" +msgstr "KÉ™narsız" #: core/bind/core_bind.cpp msgid "Per Pixel Transparency Enabled" @@ -88,29 +88,28 @@ msgstr "" #: core/bind/core_bind.cpp core/project_settings.cpp msgid "Fullscreen" -msgstr "" +msgstr "Bütün Ekran" #: core/bind/core_bind.cpp msgid "Maximized" -msgstr "" +msgstr "Böyüdülmüş" #: core/bind/core_bind.cpp msgid "Minimized" -msgstr "" +msgstr "KiçildilmiÅŸ" #: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp #: scene/gui/graph_node.cpp msgid "Resizable" -msgstr "" +msgstr "Ölçüsü DÉ™yiÅŸdirilÉ™ BilÉ™r" #: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp #: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp #: scene/3d/physics_body.cpp scene/3d/remote_transform.cpp #: scene/gui/control.cpp scene/gui/line_edit.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Position" -msgstr "Animasiyanı TÉ™mizlÉ™mÉ™" +msgstr "Pozisiya" #: core/bind/core_bind.cpp core/project_settings.cpp editor/editor_settings.cpp #: main/main.cpp modules/gridmap/grid_map.cpp @@ -122,7 +121,7 @@ msgstr "Animasiyanı TÉ™mizlÉ™mÉ™" #: scene/resources/style_box.cpp scene/resources/texture.cpp #: scene/resources/visual_shader.cpp servers/visual_server.cpp msgid "Size" -msgstr "" +msgstr "Ölçü" #: core/bind/core_bind.cpp msgid "Endian Swap" @@ -131,25 +130,23 @@ msgstr "" #: core/bind/core_bind.cpp #, fuzzy msgid "Editor Hint" -msgstr "RedaktÉ™ et" +msgstr "Editor İpucu" #: core/bind/core_bind.cpp msgid "Print Error Messages" -msgstr "" +msgstr "XÉ™ta Mesajlarını Yazdır" #: core/bind/core_bind.cpp -#, fuzzy msgid "Iterations Per Second" -msgstr "İnterpolasiya rejimi" +msgstr "HÉ™r SaniyÉ™dÉ™ İterasiya Sayı" #: core/bind/core_bind.cpp msgid "Target FPS" -msgstr "" +msgstr "HÉ™dÉ™f FPS" #: core/bind/core_bind.cpp -#, fuzzy msgid "Time Scale" -msgstr "Animasya Açarlarını ÖlçülÉ™" +msgstr "Zaman Ölçəyi" #: core/bind/core_bind.cpp main/main.cpp msgid "Physics Jitter Fix" @@ -157,25 +154,23 @@ msgstr "" #: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Error" -msgstr "" +msgstr "XÉ™ta" #: core/bind/core_bind.cpp -#, fuzzy msgid "Error String" -msgstr "YüklÉ™mÉ™ xÉ™tası:" +msgstr "XÉ™ta Yazısı" #: core/bind/core_bind.cpp -#, fuzzy msgid "Error Line" -msgstr "YüklÉ™mÉ™ xÉ™tası:" +msgstr "XÉ™ta SÉ™tiri" #: core/bind/core_bind.cpp msgid "Result" -msgstr "" +msgstr "NÉ™ticÉ™" #: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp msgid "Memory" -msgstr "" +msgstr "YaddaÅŸ" #: core/command_queue_mt.cpp core/message_queue.cpp #: core/register_core_types.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp @@ -186,11 +181,11 @@ msgstr "" #: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h #: servers/visual_server.cpp msgid "Limits" -msgstr "" +msgstr "LimitlÉ™r" #: core/command_queue_mt.cpp msgid "Command Queue" -msgstr "" +msgstr "Æmr NövbÉ™si" #: core/command_queue_mt.cpp msgid "Multithreading Queue Size (KB)" @@ -200,14 +195,13 @@ msgstr "" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Function" -msgstr "Funksiyalar:" +msgstr "Funksiya" #: core/image.cpp core/packed_data_container.cpp scene/2d/polygon_2d.cpp #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp msgid "Data" -msgstr "" +msgstr "MÉ™lumat" #: core/io/file_access_network.cpp core/register_core_types.cpp #: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp @@ -215,16 +209,15 @@ msgstr "" #: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h #: scene/gui/file_dialog.cpp msgid "Network" -msgstr "" +msgstr "ŞəbÉ™kÉ™" #: core/io/file_access_network.cpp -#, fuzzy msgid "Remote FS" -msgstr "Sil" +msgstr "Uzaqdan FS" #: core/io/file_access_network.cpp msgid "Page Size" -msgstr "" +msgstr "SÉ™hifÉ™ Ölçüsü" #: core/io/file_access_network.cpp msgid "Page Read Ahead" @@ -232,12 +225,11 @@ msgstr "" #: core/io/http_client.cpp msgid "Blocking Mode Enabled" -msgstr "" +msgstr "Bloklama Modu Aktivdir" #: core/io/http_client.cpp -#, fuzzy msgid "Connection" -msgstr "QoÅŸ" +msgstr "ÆlaqÉ™" #: core/io/http_client.cpp msgid "Read Chunk Size" @@ -245,15 +237,15 @@ msgstr "" #: core/io/marshalls.cpp msgid "Object ID" -msgstr "" +msgstr "Obyekt ID" #: core/io/multiplayer_api.cpp core/io/packet_peer.cpp msgid "Allow Object Decoding" -msgstr "" +msgstr "Obyekt DeÅŸifrÉ™sinÉ™ İzn Verin" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp msgid "Refuse New Network Connections" -msgstr "" +msgstr "Yeni ŞəbÉ™kÉ™ ÆlaqÉ™lÉ™rindÉ™n İmtina Et" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp msgid "Network Peer" @@ -261,16 +253,15 @@ msgstr "" #: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp msgid "Root Node" -msgstr "" +msgstr "Kök Düyün" #: core/io/networked_multiplayer_peer.cpp -#, fuzzy msgid "Refuse New Connections" -msgstr "QoÅŸ" +msgstr "Yeni ÆlaqÉ™lÉ™rdÉ™n İmtina Et" #: core/io/networked_multiplayer_peer.cpp msgid "Transfer Mode" -msgstr "" +msgstr "Transfer Modu" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" @@ -294,16 +285,15 @@ msgstr "" #: core/io/stream_peer.cpp msgid "Data Array" -msgstr "" +msgstr "MÉ™lumat Siyahısı" #: core/io/stream_peer_ssl.cpp msgid "Blocking Handshake" -msgstr "" +msgstr "Æl Sıxmağın Qarşısının Alınması" #: core/io/udp_server.cpp -#, fuzzy msgid "Max Pending Connections" -msgstr "ÆlaqÉ™ni redaktÉ™ edin:" +msgstr "GözlÉ™nilÉ™n Maksimum ÆlaqÉ™lÉ™r" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -325,7 +315,6 @@ msgstr "" "format." #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" msgstr "İfadÉ™dÉ™ uyÄŸunsuz giriÅŸ %d (ötürülmÉ™di)" @@ -464,6 +453,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2159,14 +2152,15 @@ msgstr "FavoritlÉ™r:" msgid "Recent:" msgstr "Son:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Axtar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "UyÄŸunlaÅŸmalar:" @@ -2226,8 +2220,8 @@ msgstr "ÆvÉ™zetmÉ™ mÉ™nbÉ™yini axtarın:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2805,8 +2799,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Animasiyanı TÉ™mizlÉ™mÉ™" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5406,6 +5401,10 @@ msgid "Drag And Drop Selection" msgstr "ÖlçmÉ™ seçimi" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11441,6 +11440,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Animasiyanı TÉ™mizlÉ™mÉ™" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19627,14 +19631,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19656,14 +19659,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20644,7 +20646,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22555,6 +22557,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Animasiyanı TÉ™mizlÉ™mÉ™" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 105aad00db..d2d7a56dc3 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -492,6 +492,10 @@ msgid "Pressure" msgstr "ÐатиÑк" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2173,14 +2177,15 @@ msgstr "Любими:" msgid "Recent:" msgstr "ПоÑледни:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "ТърÑене:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "СъвпадениÑ:" @@ -2240,8 +2245,8 @@ msgstr "ТърÑене на замеÑтващ реÑурÑ:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2809,8 +2814,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Копиране на избраното" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5490,6 +5496,10 @@ msgid "Drag And Drop Selection" msgstr "ÐаÑтройки" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11655,6 +11665,11 @@ msgid "New Animation" msgstr "Ðова анимациÑ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Филтриране на методите" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "СкороÑÑ‚:" @@ -20096,15 +20111,15 @@ msgstr "Ðе е намерено хранилище за ключове. ИзнР#: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Ðеправилно разширение." #: platform/windows/export/export.cpp #, fuzzy @@ -20128,15 +20143,15 @@ msgstr "Ðеправилно име." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Ðеправилно разширение." #: platform/windows/export/export.cpp #, fuzzy @@ -21205,7 +21220,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "ГрадуÑи на завъртане" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Глобална конÑтанта" @@ -23243,6 +23258,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ИзчиÑтване на транÑформациÑта" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index 0e99518ac1..6f1e8f945d 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -484,6 +484,10 @@ msgid "Pressure" msgstr "পà§à¦°à¦¿à¦¸à§‡à¦Ÿ..." #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "আপেকà§à¦·à¦¿à¦• সà§à¦¨à§à¦¯à¦¾à¦ª" @@ -2229,14 +2233,15 @@ msgstr "ফেবরিট/পà§à¦°à¦¿à¦¯à¦¼-সমূহ:" msgid "Recent:" msgstr "সামà§à¦ªà§à¦°à¦¤à¦¿à¦•:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "মিলসমূহ:" @@ -2298,8 +2303,8 @@ msgstr "পà§à¦°à¦¤à¦¿à¦¸à§à¦¥à¦¾à¦ªà¦• রিসোরà§à¦¸-à¦à¦° অনৠ#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2899,7 +2904,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "পথ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨" #: editor/editor_export.cpp @@ -5817,6 +5822,10 @@ msgid "Drag And Drop Selection" msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12478,6 +12487,11 @@ msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy +msgid "Filter animations" +msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy msgid "Speed:" msgstr "গতি (FPS):" @@ -21525,15 +21539,15 @@ msgstr "ফোলà§à¦¡à¦¾à¦° তৈরী করা সমà§à¦à¦¬ হয়নঠ#: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨" #: platform/windows/export/export.cpp #, fuzzy @@ -21557,15 +21571,15 @@ msgstr "অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ নাম।" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨" #: platform/windows/export/export.cpp #, fuzzy @@ -22658,7 +22672,7 @@ msgstr "à¦à§à¦°à¦®à¦£" msgid "Rotation Degrees" msgstr "%s ডিগà§à¦°à¦¿ ঘূরà§à¦£à¦¿à¦¤ হচà§à¦›à§‡à¥¤" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "ধà§à¦°à§à¦¬à¦•/কনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦Ÿ" @@ -24731,6 +24745,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "সারà§à¦¬à¦œà¦¨à§€à¦¨ রূপানà§à¦¤à¦° রাখà§à¦¨" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/br.po b/editor/translations/br.po index 101a0f7581..823490a280 100644 --- a/editor/translations/br.po +++ b/editor/translations/br.po @@ -454,6 +454,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2104,14 +2108,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2167,8 +2172,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2727,8 +2732,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Tro Fiñvskeudenn" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5314,6 +5320,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11305,6 +11315,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Tro Fiñvskeudenn" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19419,14 +19434,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19448,14 +19462,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20424,7 +20437,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22317,6 +22330,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Tro Fiñvskeudenn" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index c9726505d3..04c9b7761c 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -22,7 +22,7 @@ msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-06-26 16:15+0000\n" +"PO-Revision-Date: 2022-07-09 21:11+0000\n" "Last-Translator: Roger VC <rogervilarasau@gmail.com>\n" "Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/" "godot/ca/>\n" @@ -67,7 +67,7 @@ msgstr "Mode de Baix Us del Processador" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode Sleep (µsec)" -msgstr "" +msgstr "Mode d'ús del processador baix en repòs (µseg)" #: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp msgid "Keep Screen On" @@ -136,8 +136,9 @@ msgid "Size" msgstr "Mida" #: core/bind/core_bind.cpp +#, fuzzy msgid "Endian Swap" -msgstr "" +msgstr "Intercanvi d'endian" #: core/bind/core_bind.cpp msgid "Editor Hint" @@ -161,9 +162,8 @@ msgid "Time Scale" msgstr "Escala de Temps" #: core/bind/core_bind.cpp main/main.cpp -#, fuzzy msgid "Physics Jitter Fix" -msgstr "Fotograma de FÃsica %" +msgstr "Correcció de fluctuacions de fÃsica" #: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Error" @@ -246,25 +246,23 @@ msgstr "Connexió" #: core/io/http_client.cpp msgid "Read Chunk Size" -msgstr "" +msgstr "Llegeix la mida del fragment" #: core/io/marshalls.cpp msgid "Object ID" msgstr "ID de l'Objecte" #: core/io/multiplayer_api.cpp core/io/packet_peer.cpp -#, fuzzy msgid "Allow Object Decoding" -msgstr "Activa l'Efecte Paper Ceba" +msgstr "Permet la descodificació d'objectes" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp msgid "Refuse New Network Connections" msgstr "Rebutja les noves connexions de xarxa" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Network Peer" -msgstr "Perfilador de Xarxa" +msgstr "Parell de xarxa" #: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp msgid "Root Node" @@ -275,13 +273,12 @@ msgid "Refuse New Connections" msgstr "Rebutjar Noves Connexions" #: core/io/networked_multiplayer_peer.cpp -#, fuzzy msgid "Transfer Mode" -msgstr "Tipus de Transformació" +msgstr "Mode de transferència" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" -msgstr "" +msgstr "Mida mà xima de la memòria intermèdia de codificació" #: core/io/packet_peer.cpp msgid "Input Buffer Max Size" @@ -297,7 +294,7 @@ msgstr "" #: core/io/stream_peer.cpp msgid "Big Endian" -msgstr "" +msgstr "Endian gran" #: core/io/stream_peer.cpp msgid "Data Array" @@ -373,14 +370,12 @@ msgid "Max Size (KB)" msgstr "Mida mà xima (KB)" #: core/os/input.cpp -#, fuzzy msgid "Mouse Mode" -msgstr "Mode de moviment" +msgstr "Mode ratolÃ" #: core/os/input.cpp -#, fuzzy msgid "Use Accumulated Input" -msgstr "Elimina l'Entrada" +msgstr "Utilitza l'entrada acumulada" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -388,9 +383,8 @@ msgid "Device" msgstr "Dispositiu" #: core/os/input_event.cpp -#, fuzzy msgid "Alt" -msgstr "Tot" +msgstr "Alt" #: core/os/input_event.cpp msgid "Shift" @@ -410,9 +404,8 @@ msgid "Command" msgstr "Comunitat" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr "Fotograma de FÃsica %" +msgstr "FÃsic" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -421,9 +414,8 @@ msgid "Pressed" msgstr "Premut" #: core/os/input_event.cpp -#, fuzzy msgid "Scancode" -msgstr "Explora" +msgstr "Codi d'escaneig" #: core/os/input_event.cpp msgid "Physical Scancode" @@ -468,6 +460,10 @@ msgid "Pressure" msgstr "Configuracions prestablertes" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relatiu" @@ -799,7 +795,7 @@ msgstr "Renderitzat" #: scene/resources/multimesh.cpp servers/visual/visual_server_scene.cpp #: servers/visual_server.cpp msgid "Quality" -msgstr "" +msgstr "Qualitat" #: core/project_settings.cpp scene/gui/file_dialog.cpp #: scene/main/scene_tree.cpp scene/resources/navigation_mesh.cpp @@ -808,8 +804,9 @@ msgid "Filters" msgstr "Filtres" #: core/project_settings.cpp scene/main/viewport.cpp +#, fuzzy msgid "Sharpen Intensity" -msgstr "" +msgstr "Intensitat d'agudització" #: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp @@ -834,9 +831,8 @@ msgid "Profiler" msgstr "Perfilador" #: core/project_settings.cpp -#, fuzzy msgid "Max Functions" -msgstr "Reanomena Funció" +msgstr "Funcions mà ximes" #: core/project_settings.cpp scene/3d/vehicle_body.cpp msgid "Compression" @@ -848,39 +844,39 @@ msgstr "Formats" #: core/project_settings.cpp msgid "Zstd" -msgstr "" +msgstr "Zstd" #: core/project_settings.cpp msgid "Long Distance Matching" -msgstr "" +msgstr "Coincidència de llarga distà ncia" #: core/project_settings.cpp msgid "Compression Level" -msgstr "" +msgstr "Nivell de compressió" #: core/project_settings.cpp msgid "Window Log Size" -msgstr "" +msgstr "Mida del registre de la finestra" #: core/project_settings.cpp msgid "Zlib" -msgstr "" +msgstr "Zlib" #: core/project_settings.cpp msgid "Gzip" -msgstr "" +msgstr "Gzip" #: core/project_settings.cpp platform/android/export/export.cpp msgid "Android" -msgstr "" +msgstr "Android" #: core/project_settings.cpp msgid "Modules" -msgstr "" +msgstr "Mòduls" #: core/register_core_types.cpp msgid "TCP" -msgstr "" +msgstr "TCP" #: core/register_core_types.cpp msgid "Connect Timeout Seconds" @@ -892,11 +888,11 @@ msgstr "" #: core/register_core_types.cpp msgid "Max Buffer (Power of 2)" -msgstr "" +msgstr "Memòria intermèdia mà xima (potència de 2)" #: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp msgid "SSL" -msgstr "" +msgstr "SSL" #: core/register_core_types.cpp main/main.cpp msgid "Certificates" @@ -909,9 +905,8 @@ msgid "Resource" msgstr "Recurs" #: core/resource.cpp -#, fuzzy msgid "Local To Scene" -msgstr "Tanca l'Escena" +msgstr "Local a l'escena" #: core/resource.cpp editor/dependency_editor.cpp #: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp @@ -980,7 +975,7 @@ msgstr "" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Canvas Polygon Index Buffer Size (KB)" -msgstr "" +msgstr "Mida de la memòria intermèdia de l'Ãndex del polÃgon de llenç (KB)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp @@ -992,7 +987,7 @@ msgstr "" #: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp #: servers/visual_server.cpp msgid "2D" -msgstr "" +msgstr "2D" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp @@ -1002,14 +997,13 @@ msgstr "Ajustament Intel·ligent" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Use GPU Pixel Snap" -msgstr "Utilitzar ajustament amb els PÃxels" +msgstr "Utilitza l'ajust de pÃxels de la GPU" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Immediate Buffer Size (KB)" -msgstr "" +msgstr "Mida de la memòria intermèdia immediata (KB)" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp @@ -1020,28 +1014,27 @@ msgstr "Precalcular Lightmaps" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp msgid "Use Bicubic Sampling" -msgstr "" +msgstr "Utilitza el mostreig bicúbic" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Elements" -msgstr "" +msgstr "Elements renderitzables mà xims" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Lights" -msgstr "" +msgstr "Llums mà ximes renderitzables" #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Max Renderable Reflections" -msgstr "Centra la Selecció" +msgstr "Reflexions mà ximes renderitzables" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Lights Per Object" -msgstr "" +msgstr "Llums mà ximes per objecte" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Subsurface Scattering" -msgstr "" +msgstr "Dispersió subsuperficial" #: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp @@ -1057,9 +1050,8 @@ msgid "Scale" msgstr "Escala" #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Follow Surface" -msgstr "Omple la SuperfÃcie" +msgstr "Segueix la superfÃcie" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Weight Samples" @@ -1067,11 +1059,11 @@ msgstr "" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Voxel Cone Tracing" -msgstr "" +msgstr "Traçat del con Voxel" #: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp msgid "High Quality" -msgstr "" +msgstr "Alta qualitat" #: drivers/gles3/rasterizer_storage_gles3.cpp msgid "Blend Shape Max Buffer Size (KB)" @@ -1149,9 +1141,8 @@ msgstr "Canviar crida d'animació" #: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Frame" -msgstr "% del Fotograma" +msgstr "Fotograma" #: editor/animation_track_editor.cpp editor/editor_profiler.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp @@ -1162,9 +1153,8 @@ msgstr "Temps" #: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp #: platform/osx/export/export.cpp -#, fuzzy msgid "Location" -msgstr "Localització" +msgstr "Ubicació" #: editor/animation_track_editor.cpp modules/gltf/gltf_node.cpp #: scene/2d/polygon_2d.cpp scene/2d/remote_transform_2d.cpp @@ -1184,7 +1174,7 @@ msgstr "Quantitat d'arguments" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp msgid "Args" -msgstr "" +msgstr "Args" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp @@ -1348,9 +1338,8 @@ msgid "Position:" msgstr "Posició:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Rotation:" -msgstr "Pas de la Rotació:" +msgstr "Rotació:" #: editor/animation_track_editor.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp @@ -1373,7 +1362,7 @@ msgstr "(No và lid, tipus esperat: %s)" #: editor/animation_track_editor.cpp #, fuzzy msgid "Easing:" -msgstr "Esmorteeix Entrada-Sortida" +msgstr "Alleugeriment:" #: editor/animation_track_editor.cpp #, fuzzy @@ -1391,19 +1380,16 @@ msgid "Stream:" msgstr "Element de rà dio" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "Reinici (s):" +msgstr "Inici (s):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End (s):" -msgstr "Fosa d'entrada (s):" +msgstr "Final (s):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Clip:" -msgstr "Animacions:" +msgstr "Clip d'animació:" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -1492,9 +1478,8 @@ msgid "Editors" msgstr "Editors" #: editor/animation_track_editor.cpp editor/editor_settings.cpp -#, fuzzy msgid "Confirm Insert Track" -msgstr "Insereix una Pista i una Clau" +msgstr "Confirmeu la inserció de pista" #. TRANSLATORS: %s will be replaced by a phrase describing the target of track. #: editor/animation_track_editor.cpp @@ -1773,9 +1758,8 @@ msgid "Go to Previous Step" msgstr "Anar al Pas Anterior" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Apply Reset" -msgstr "Resetejar" +msgstr "Aplica reinicialització" #: editor/animation_track_editor.cpp msgid "Optimize Animation" @@ -2159,14 +2143,15 @@ msgstr "Favorits:" msgid "Recent:" msgstr "Recents:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Cerca:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Coincidències:" @@ -2226,8 +2211,8 @@ msgstr "Cerca Recurs Reemplaçant:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2236,7 +2221,7 @@ msgstr "Obre" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Propietaris de: %s (Total: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2430,10 +2415,10 @@ msgid "Licenses" msgstr "Llicències" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Error opening asset file for \"%s\" (not in ZIP format)." msgstr "" -"S'ha produit un error en obrir el fitxer comprimit, no té el format ZIP." +"S'ha produït un error en obrir el fitxer de recursos per a \"%s\" (no en " +"format ZIP)." #: editor/editor_asset_installer.cpp msgid "%s (already exists)" @@ -2456,9 +2441,8 @@ msgid "Uncompressing Assets" msgstr "Descomprimint Recursos" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "The following files failed extraction from asset \"%s\":" -msgstr "Ha fracassat l'extracció del paquet dels següents fitxers:" +msgstr "Els fitxers següents no s'han pogut extraure del recurs \"%s\":" #: editor/editor_asset_installer.cpp msgid "(and %s more files)" @@ -2478,9 +2462,8 @@ msgid "Install" msgstr "Instal·la" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Asset Installer" -msgstr "Instal·lador de paquets" +msgstr "Instal·lador de recursos" #: editor/editor_audio_buses.cpp msgid "Speakers" @@ -2650,9 +2633,8 @@ msgid "Create a new Bus Layout." msgstr "Crea un nou Disseny de Bus." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Audio Bus Layout" -msgstr "Obre un Disseny de Bus d'Àudio" +msgstr "Disseny del bus d'à udio" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -2808,7 +2790,8 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "Completat amb errors." #: editor/editor_export.cpp @@ -5626,6 +5609,10 @@ msgid "Drag And Drop Selection" msgstr "Elimina la Selecció del GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11981,6 +11968,11 @@ msgstr "Nova Animació" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy +msgid "Filter animations" +msgstr "Filtrar mètodes" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy msgid "Speed:" msgstr "Velocitat (FPS):" @@ -20982,15 +20974,15 @@ msgstr "No es pot obrir la plantilla per exportar." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "L'extensió no és và lida." #: platform/windows/export/export.cpp #, fuzzy @@ -21014,15 +21006,15 @@ msgstr "Nom no và lid." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "L'extensió no és và lida." #: platform/windows/export/export.cpp #, fuzzy @@ -22126,7 +22118,7 @@ msgstr "Viatge" msgid "Rotation Degrees" msgstr "Rotació de %s graus." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constant" @@ -24240,6 +24232,11 @@ msgstr "" "Modifica la mida de les Formes de Col. lisió Filles." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Manté la Transformació Global" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index 0c0b8b63ca..1e92a92ae7 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -516,6 +516,10 @@ msgid "Pressure" msgstr "Profil" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "PÅ™ichytávat relativnÄ›" @@ -2234,14 +2238,15 @@ msgstr "OblÃbené:" msgid "Recent:" msgstr "Nedávné:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Hledat:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Shody:" @@ -2301,8 +2306,8 @@ msgstr "Hledat náhradnà zdroj:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2877,7 +2882,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "KopÃrovat cestu k uzlu" #: editor/editor_export.cpp @@ -5677,6 +5682,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap Vyplnit výbÄ›r" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11949,6 +11958,11 @@ msgid "New Animation" msgstr "Nová animace" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrovat metody" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Rychlost:" @@ -20720,15 +20734,15 @@ msgstr "NepodaÅ™ilo se najÃt úložiÅ¡tÄ› klÃÄů, nelze exportovat." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Neplatná pÅ™Ãpona." #: platform/windows/export/export.cpp #, fuzzy @@ -20752,15 +20766,15 @@ msgstr "Neplatný název." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Neplatná pÅ™Ãpona." #: platform/windows/export/export.cpp #, fuzzy @@ -21860,7 +21874,7 @@ msgstr "Cestovat" msgid "Rotation Degrees" msgstr "Rotuji %s stupňů." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "KonstantnÃ" @@ -23970,6 +23984,11 @@ msgstr "" "Změňte velikost koliznÃch tvarů v uzlech potomků." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Zachovat globálnà transformaci" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/da.po b/editor/translations/da.po index 3b19f24ec8..1bb05be6f9 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -486,6 +486,10 @@ msgid "Pressure" msgstr "Forudindstillet..." #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2223,14 +2227,15 @@ msgstr "Favoritter:" msgid "Recent:" msgstr "Seneste:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Søgning:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Matches:" @@ -2292,8 +2297,8 @@ msgstr "Søg Erstatnings Ressource:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2890,8 +2895,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Fjern Markering" #: editor/editor_export.cpp #, fuzzy @@ -5730,6 +5736,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap Slet Markerede" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12141,6 +12151,11 @@ msgid "New Animation" msgstr "Ny Animation Navn:" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filter mode:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20897,15 +20912,15 @@ msgstr "Kan ikke Ã¥bne skabelon til eksport:\n" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Du skal bruge en gyldig udvidelse." #: platform/windows/export/export.cpp #, fuzzy @@ -20929,15 +20944,15 @@ msgstr "Ugyldigt navn." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Du skal bruge en gyldig udvidelse." #: platform/windows/export/export.cpp #, fuzzy @@ -21994,7 +22009,7 @@ msgstr "Rejse" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstant" @@ -24018,6 +24033,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Anim Skift Transformering" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/de.po b/editor/translations/de.po index f0c79cda0f..aa92914ada 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -82,13 +82,14 @@ # Christian Packenius <christian@packenius.com>, 2022. # Sajeg <jfx@posteo.de>, 2022. # Tobias Jacobs <tobi@jacobs.rocks>, 2022. +# JeremyStarTM <jeremystartm@tuta.io>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-06-30 16:42+0000\n" -"Last-Translator: So Wieso <sowieso@dukun.de>\n" +"PO-Revision-Date: 2022-07-31 18:34+0000\n" +"Last-Translator: JeremyStarTM <jeremystartm@tuta.io>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" "Language: de\n" @@ -96,7 +97,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -466,9 +467,8 @@ msgid "Command" msgstr "Befehl" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (physisch)" +msgstr "Physisch" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -521,6 +521,10 @@ msgid "Pressure" msgstr "Druck" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Stift invertiert" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativ" @@ -1629,7 +1633,7 @@ msgstr "Methodenaufrufsspurschlüssel hinzufügen" #: editor/animation_track_editor.cpp msgid "Method not found in object:" -msgstr "Methode nicht in Objekt gefunden:" +msgstr "Methode im Objekt nicht gefunden:" #: editor/animation_track_editor.cpp msgid "Anim Move Keys" @@ -2165,14 +2169,15 @@ msgstr "Favoriten:" msgid "Recent:" msgstr "Kürzlich:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Suche:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Treffer:" @@ -2232,8 +2237,8 @@ msgstr "Ersatzressource suchen:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2810,7 +2815,8 @@ msgid "Project export for platform:" msgstr "Projektexport für Plattform:" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "Fertiggestellt mit Fehlern." #: editor/editor_export.cpp @@ -5560,9 +5566,12 @@ msgid "Mouse Extra Buttons Navigate History" msgstr "Extramaustasten blättern durch Verlauf" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "GridMap-Auswahl" +msgstr "Auswahl ziehen und fallen lassen" + +#: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "Im Skript Editor bei ausgewähltem Node bleiben" #: editor/editor_settings.cpp msgid "Appearance" @@ -11690,6 +11699,10 @@ msgid "New Animation" msgstr "Neue Animation" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "Animationen filtern" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Geschwindigkeit:" @@ -18139,7 +18152,7 @@ msgstr "Ungültiges Argument vom Typ:" #: modules/visual_script/visual_script_nodes.cpp msgid "Invalid arguments:" -msgstr "Ungültige Argumente:" +msgstr "Ungültige Parameter:" #: modules/visual_script/visual_script_nodes.cpp msgid "a if cond, else b" @@ -18449,9 +18462,8 @@ msgid "The package must have at least one '.' separator." msgstr "Das Paket muss mindestens einen Punkt-Unterteiler ‚.‘ haben." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Build" -msgstr "Einen Build verwenden" +msgstr "Eigener Build" #: platform/android/export/export_plugin.cpp msgid "Use Custom Build" @@ -18743,66 +18755,69 @@ msgstr "" "„Use Custom Build“ muss aktiviert werden um die Plugins nutzen zu können." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" " "or \"OpenXR\"." msgstr "" -"„Hand Tracking“ ist nur gültig wenn „Xr Mode“ als „Occulus Mobile VrApi“ " -"oder „OpenXR“ gesetzt wurde." +"„Hand Tracking“ ist nur gültig wenn „XR Mode“ als „Oculus Mobile VrApi“ oder " +"„OpenXR“ gesetzt wurde." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"." msgstr "" -"„Passthrough“ ist nur gültig wenn „Xr Mode“ als „OpenXR“ gesetzt wurde." +"„Passthrough“ ist nur gültig wenn „XR Mode“ als „OpenXR“ gesetzt wurde." #: platform/android/export/export_plugin.cpp msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled." msgstr "„Export AAB“ ist nur gültig wenn „Use Custom Build“ aktiviert ist." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled." msgstr "" -"Das „Min Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert " -"ist." +"Das „Min SDK“ zu überschreiben ist nur möglich wenn „Use Custom Build“ " +"aktiviert ist." #: platform/android/export/export_plugin.cpp msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid." msgstr "" +"„Min SDK“ sollte eine gültige Ganzzahl sein, war aber „%s“, was ungültig ist." #: platform/android/export/export_plugin.cpp msgid "" "\"Min SDK\" cannot be lower than %d, which is the version needed by the " "Godot library." msgstr "" +"„Min SDK“ kann nicht niedriger als %d sein, der Version, die die Godot-" +"Bibliothek benötigt." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled." msgstr "" -"Das „Target Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert " +"„Target SDK“ kann nur überschrieben werden wenn „Use Custom Build“ aktiviert " "ist." #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid." msgstr "" +"„Taret SDK“ sollte eine gültige Ganzzahl sein, war aber „%s“, was ungültig " +"ist." #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" %d is higher than the default version %d. This may work, but " "wasn't tested and may be unstable." msgstr "" +"„Target SDK“ %d ist höher als die Standardversion %d. Diese Kombination " +"könnte funktionieren, wurde aber nicht getestet und könnte gegebenenfalls " +"instabil sein." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version." msgstr "" -"Die Version des „Target Sdk“ muss größer gleich der des „Min Sdk“ sein." +"Die „Target SDK“-Version muss größer gleich der „Min SDK“-Version sein." #: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp @@ -19638,8 +19653,8 @@ msgid "" "Could not start codesign executable, make sure Xcode command line tools are " "installed." msgstr "" -"Codesign-Anwendung konnte nicht gestartet werden. Wurden die Xcode-" -"Kommandozeilen-Hilfsprogramme installiert?" +"Codesign-Anwendung konnte nicht gestartet werden, stelle sicher dass die " +"Xcode-Kommandozeilen-Tools installiert sind." #: platform/osx/export/export.cpp platform/windows/export/export.cpp msgid "No identity found." @@ -20131,17 +20146,18 @@ msgid "Could not find wine executable at \"%s\"." msgstr "Anwendung wine konnte nicht gefunden werden in „%s“." #: platform/windows/export/export.cpp +#, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "Anwendung rcedit konnte nicht gestartet werden. Bitte rcedit-Pfad in " "Editoreinstellungen festlegen (Export > Windows > Rcedit)." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +#, fuzzy +msgid "rcedit failed to modify executable: %s." msgstr "" "Modifikation der Anwendung durch rcedit fehlgeschlagen:\n" "%s" @@ -20163,17 +20179,18 @@ msgid "Invalid timestamp server." msgstr "Ungültiger Zeitstempelserver." #: platform/windows/export/export.cpp +#, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "Anwendung signtool konnte nicht gestartet werden. Bitte signtool-Pfad in " "Editoreinstellungen festlegen (Export > Windows > Signtool)." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +#, fuzzy +msgid "Signtool failed to sign executable: %s." msgstr "" "Signieren der Anwendung durch Signtool ist fehlgeschlagen:\n" "%s" @@ -21093,9 +21110,8 @@ msgstr "" "map_get_path()‘ zu verwenden." #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Pathfinding" -msgstr "Zuordnung" +msgstr "Pfadfinden" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Path Desired Distance" @@ -21110,9 +21126,8 @@ msgid "Path Max Distance" msgstr "Max Pfad-Distanz" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance" -msgstr "Erweitert" +msgstr "Vermeiden" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Avoidance Enabled" @@ -21177,7 +21192,7 @@ msgstr "Reisekosten" msgid "Rotation Degrees" msgstr "Rotationswinkel" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "Globale Rotation" @@ -23106,6 +23121,10 @@ msgstr "" "geändert werden." #: scene/3d/spatial.cpp +msgid "Global Translation" +msgstr "Globale Verschiebung" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "Matrix" @@ -24213,9 +24232,8 @@ msgid "Fold Gutter" msgstr "Einklappenspalte" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Drag And Drop Selection Enabled" -msgstr "Textauswahl möglich" +msgstr "Ziehen-und-Fallenlassen-Auswahl aktiviert" #: scene/gui/text_edit.cpp msgid "Hiding Enabled" @@ -24592,6 +24610,11 @@ msgid "" "Effects.\n" "HDR will be disabled for this Viewport." msgstr "" +"In diesem Ansichtsfenster ist HDR aktiv, jedoch wurde dessen Nutzung auf 2D " +"oder 2D-No-Sampling eingestellt.\n" +"HDR wird nur in Ansichtsfenstern deren Nutzung auf 3D oder 3D-No-Effects " +"eingestellt sind unterstützt.\n" +"HDR wird für dieses Ansichtsfenster deaktiviert." #: scene/main/viewport.cpp msgid "ARVR" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 5d2d5f1cbc..23c58c5ffb 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -435,6 +435,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2056,14 +2060,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2119,8 +2124,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2679,7 +2684,7 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "" #: editor/editor_export.cpp @@ -5252,6 +5257,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11202,6 +11211,10 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19245,14 +19258,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19273,14 +19285,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20231,7 +20242,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22046,6 +22057,10 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +msgid "Global Translation" +msgstr "" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index a061cc5a59..4b71ed8528 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -469,6 +469,10 @@ msgid "Pressure" msgstr "Πίεση" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Σχετικό" @@ -2180,14 +2184,15 @@ msgstr "ΑγαπημÎνα:" msgid "Recent:" msgstr "Î Ïόσφατα:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Αναζήτηση:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Αντιστοιχίες:" @@ -2247,8 +2252,8 @@ msgstr "Αναζήτηση αντικαταστάτη πόÏου:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2836,7 +2841,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "ΑντιγÏαφή διαδÏομής κόμβου" #: editor/editor_export.cpp @@ -5659,6 +5664,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap ΓÎμισμα Επιλογής" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12040,6 +12049,11 @@ msgid "New Animation" msgstr "ÎÎα Κίνηση" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ΦιλτÏάÏισμα μεθόδων" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "ΤαχÏτητα:" @@ -20893,15 +20907,15 @@ msgstr "Σφάλμα κατά το άνοιγμα Ï€ÏοτÏπου για εξα #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "ΆκυÏη επÎκταση." #: platform/windows/export/export.cpp #, fuzzy @@ -20925,15 +20939,15 @@ msgstr "Μη ÎγκυÏο όνομα." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "ΆκυÏη επÎκταση." #: platform/windows/export/export.cpp #, fuzzy @@ -22038,7 +22052,7 @@ msgstr "Ταξίδι" msgid "Rotation Degrees" msgstr "ΠεÏιστÏοφή %s μοίÏες." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "ΣταθεÏή" @@ -24163,6 +24177,11 @@ msgstr "" "Αλλάξτε μÎγεθος στα σχήματα σÏγκÏουσης των παιδιών." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ΔιατήÏηση παγκόσμιου μετασχηματισμοÏ" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/en_Shaw.po b/editor/translations/en_Shaw.po index 1f648844a2..361c10ce1a 100644 --- a/editor/translations/en_Shaw.po +++ b/editor/translations/en_Shaw.po @@ -447,6 +447,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2079,14 +2083,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2142,8 +2147,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2702,8 +2707,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "ð‘“ð‘³ð‘™ð‘’ð‘–ð‘©ð‘¯ð‘Ÿ:" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5280,6 +5286,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11253,6 +11263,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ð‘¦ð‘¯ð‘‘ð‘»ð‘ð‘©ð‘¤ð‘±ð‘–ð‘©ð‘¯ ð‘¥ð‘´ð‘›" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19339,14 +19354,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19368,14 +19382,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20337,7 +20350,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22218,6 +22231,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ð‘“ð‘³ð‘™ð‘’ð‘–ð‘©ð‘¯ð‘Ÿ:" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/eo.po b/editor/translations/eo.po index 2eef4fc0d0..0139382972 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -493,6 +493,10 @@ msgid "Pressure" msgstr "AntaÅagordo" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Kapti relative" @@ -2202,14 +2206,15 @@ msgstr "Favoritaj:" msgid "Recent:" msgstr "Lastatempe:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Serĉo:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Matĉoj:" @@ -2269,8 +2274,8 @@ msgstr "Serĉi anstataÅiga risurco:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2847,8 +2852,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Kopii elektaron" #: editor/editor_export.cpp #, fuzzy @@ -5652,6 +5658,10 @@ msgid "Drag And Drop Selection" msgstr "Enkadrigi elekton" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11935,6 +11945,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Forigi animacion?" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20541,15 +20556,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Nevalida kromprogramo." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20571,15 +20586,15 @@ msgstr "Malvalida nomo." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Nevalida kromprogramo." #: platform/windows/export/export.cpp #, fuzzy @@ -21632,7 +21647,7 @@ msgstr "VojaÄa" msgid "Rotation Degrees" msgstr "Rotacia paÅo:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstanto" @@ -23654,6 +23669,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transformo" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/es.po b/editor/translations/es.po index febff41060..173b195cc4 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -81,13 +81,17 @@ # David MartÃnez <goddrinksjava@gmail.com>, 2022. # Nagamine-j <jimmy.kochi@unmsm.edu.pe>, 2022. # Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>, 2022. +# Luis Ortiz <luisortiz66@hotmail.com>, 2022. +# Angel Andrade <aandradeb99@gmail.com>, 2022. +# Juan Felipe Gómez López <juanfgomez0912@gmail.com>, 2022. +# Pineappletooth <yochank003@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-06-29 10:04+0000\n" -"Last-Translator: Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>\n" +"PO-Revision-Date: 2022-08-05 01:04+0000\n" +"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -95,7 +99,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -225,7 +229,7 @@ msgstr "Escala de Tiempo" #: core/bind/core_bind.cpp main/main.cpp msgid "Physics Jitter Fix" -msgstr "Arreglo de las Fluctuaciones FÃsicas" +msgstr "Corrección de Fluctuaciones de FÃsica" #: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Error" @@ -467,9 +471,8 @@ msgid "Command" msgstr "Command" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (FÃsica)" +msgstr "FÃsica" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -522,6 +525,10 @@ msgid "Pressure" msgstr "Presionado" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Pluma Invertida" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativo" @@ -721,14 +728,12 @@ msgid "Script Templates Search Path" msgstr "Ruta de Búsqueda de Plantillas de Scripts" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "Cargar automáticamente al inicio" +msgstr "Carga Automática de Control de Versiones al Inicio" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Plugin Name" -msgstr "Control de Versiones" +msgstr "Nombre del Plugin de Control de Versiones" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -1218,21 +1223,19 @@ msgid "Type" msgstr "Tipo" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "Establecer Manipulador" +msgstr "En el Manipulador" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out Handle" -msgstr "Establecer Manipulador" +msgstr "Fuera del Manipulador" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp msgid "Stream" -msgstr "" +msgstr "Stream" #: editor/animation_track_editor.cpp msgid "Start Offset" @@ -1253,9 +1256,8 @@ msgid "Animation" msgstr "Animación" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing" -msgstr "Entrada-Salida Suave" +msgstr "Suavizar" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" @@ -1410,19 +1412,16 @@ msgid "Stream:" msgstr "Stream:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "Reiniciar (s):" +msgstr "Inicio (s):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End (s):" -msgstr "Fundido de entrada (s):" +msgstr "Fin (s):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Clip:" -msgstr "Animaciones:" +msgstr "Clip de Animación:" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -2176,14 +2175,15 @@ msgstr "Favoritos:" msgid "Recent:" msgstr "Recientes:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Buscar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Coincidencias:" @@ -2243,8 +2243,8 @@ msgstr "Buscar Recurso de Reemplazo:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2253,7 +2253,7 @@ msgstr "Abrir" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Propietarios de: %s (Total: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2817,7 +2817,8 @@ msgid "Project export for platform:" msgstr "Exportar proyecto para la plataforma:" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "Completado con errores." #: editor/editor_export.cpp @@ -2980,9 +2981,8 @@ msgid "Custom release template not found." msgstr "Plantilla release personalizada no encontrada." #: editor/editor_export.cpp -#, fuzzy msgid "Prepare Template" -msgstr "Administrar Plantillas" +msgstr "Preparar Plantilla" #: editor/editor_export.cpp platform/osx/export/export.cpp msgid "The given export path doesn't exist." @@ -2998,9 +2998,8 @@ msgstr "Fallo al copiar la plantilla de exportación." #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp -#, fuzzy msgid "PCK Embedding" -msgstr "Relleno" +msgstr "Integrar PCK" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." @@ -3399,7 +3398,7 @@ msgstr "Mostrar/Ocultar archivos ocultos." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails." -msgstr "Ver elementos como una cuadrÃcula de miniaturas." +msgstr "Sesgo del nivel de división de la cuadrÃcula." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a list." @@ -4579,7 +4578,7 @@ msgstr "Exportar…" #: editor/editor_node.cpp msgid "Install Android Build Template..." -msgstr "Instalar plantilla de compilación de Android..." +msgstr "Instalar Plantilla de Compilación de Android..." #: editor/editor_node.cpp msgid "Open User Data Folder" @@ -4898,8 +4897,8 @@ msgstr "" "personalizado al exportarlo (agregando módulos, cambiando el AndroidManifest." "xml, etc.).\n" "Ten en cuenta que para realizar compilaciones personalizadas en lugar de " -"usar APKs predefinidos, la opción \"Use Custom Build\" deberÃa estar " -"habilitada en la configuración de exportación de Android." +"usar APKs predefinidos, la opción \"Usar Compilación Personalizada\" deberÃa " +"estar habilitada en la configuración de exportación de Android." #: editor/editor_node.cpp msgid "" @@ -5281,9 +5280,8 @@ msgstr "" "preset existente como ejecutable." #: editor/editor_run_native.cpp -#, fuzzy msgid "Project Run" -msgstr "Proyecto" +msgstr "Ejecutar Proyecto" #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." @@ -5355,11 +5353,11 @@ msgstr "Atenuar Editor en Diálogo de Popup" #: editor/editor_settings.cpp main/main.cpp msgid "Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Modo de Reposo en Consumo Bajo del Procesador (µsec)" #: editor/editor_settings.cpp msgid "Unfocused Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Modo de Bajo Uso del Procesador Desconectado (µseg)" #: editor/editor_settings.cpp msgid "Separate Distraction Mode" @@ -5371,7 +5369,7 @@ msgstr "Abrir Capturas De Pantalla Automáticamente" #: editor/editor_settings.cpp msgid "Max Array Dictionary Items Per Page" -msgstr "" +msgstr "Cantidad Máxima de Elementos del Diccionario por Página" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp @@ -5449,7 +5447,7 @@ msgstr "Comprimir Recursos Binarios" #: editor/editor_settings.cpp msgid "Safe Save On Backup Then Rename" -msgstr "" +msgstr "Guardar de Forma Segura en el Backup y luego Renombrar" #: editor/editor_settings.cpp msgid "File Dialog" @@ -5461,7 +5459,7 @@ msgstr "Tamaño de las Miniaturas" #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "Paneles" #: editor/editor_settings.cpp msgid "Scene Tree" @@ -5484,9 +5482,8 @@ msgid "Auto Refresh Interval" msgstr "Intervalo de Auto Refrescar" #: editor/editor_settings.cpp -#, fuzzy msgid "Subresource Hue Tint" -msgstr "Sub-Recursos" +msgstr "Subrecurso Tinte del Tono" #: editor/editor_settings.cpp msgid "Color Theme" @@ -5566,9 +5563,12 @@ msgid "Mouse Extra Buttons Navigate History" msgstr "Botones Extra del Ratón Navegar por el Historial" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "Seleccionar GridMap" +msgstr "Arrastrar y Soltar la Selección" + +#: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "Permanecer En Editor de Scripts En Nodo Seleccionado" #: editor/editor_settings.cpp msgid "Appearance" @@ -5612,7 +5612,7 @@ msgstr "Directriz de longitud de LÃnea de Columna Flexible" #: editor/editor_settings.cpp msgid "Line Length Guideline Hard Column" -msgstr "" +msgstr "Longitud de LÃnea de la GuÃa de la Columna RÃgida" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Script List" @@ -5698,11 +5698,11 @@ msgstr "Espera de Completado de Código" #: editor/editor_settings.cpp msgid "Put Callhint Tooltip Below Current Line" -msgstr "Colocar la Información Sobre la Llamada Debajo de la LÃnea Actual" +msgstr "Colocar Tooltip de Llamada Debajo de la LÃnea Actual" #: editor/editor_settings.cpp msgid "Callhint Tooltip Offset" -msgstr "Desplazamiento de la Información Sobre la Llamada" +msgstr "Desplazamiento del Tooltip de Llamada" #: editor/editor_settings.cpp msgid "Complete File Paths" @@ -5802,7 +5802,7 @@ msgstr "Nivel MÃnimo de División de CuadrÃcula" #: editor/editor_settings.cpp msgid "Grid Division Level Bias" -msgstr "" +msgstr "Sesgo del Nivel de División de la CuadrÃcula" #: editor/editor_settings.cpp msgid "Grid XZ Plane" @@ -5861,23 +5861,20 @@ msgid "Orbit Modifier" msgstr "Modificador de Órbita" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Modifier" -msgstr "Modo desplazamiento lateral" +msgstr "Modificador Panorámico" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Modifier" -msgstr "Modificado/s" +msgstr "Modificador de Zoom" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Warped Mouse Panning" -msgstr "" +msgstr "Paneo del Mouse Deformado" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Feel" -msgstr "Modo de Navegación" +msgstr "Sensación de Navegación" #: editor/editor_settings.cpp msgid "Orbit Sensitivity" @@ -5920,9 +5917,8 @@ msgid "Freelook Activation Modifier" msgstr "Modificador de Activación de Vista Libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Speed Zoom Link" -msgstr "Modificador de Velocidad de Vista Libre" +msgstr "Velocidad de Zoom de Vista Libre" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Grid Color" @@ -5970,7 +5966,7 @@ msgstr "Color del Borde del Viewport" #: editor/editor_settings.cpp msgid "Constrain Editor View" -msgstr "" +msgstr "Vista del Editor de Restricciones" #: editor/editor_settings.cpp msgid "Simple Panning" @@ -6031,14 +6027,12 @@ msgstr "Ubicación de la Ventana" #: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp #: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp #: scene/gui/control.cpp -#, fuzzy msgid "Rect" -msgstr "Completo" +msgstr "Rect" #: editor/editor_settings.cpp -#, fuzzy msgid "Rect Custom Position" -msgstr "Establecer Posición de Salida de Curva" +msgstr "Posición Personalizada de Rect" #: editor/editor_settings.cpp platform/android/export/export_plugin.cpp msgid "Screen" @@ -6104,24 +6098,23 @@ msgstr "Color de Palabra Clave" #: editor/editor_settings.cpp msgid "Control Flow Keyword Color" -msgstr "" +msgstr "Control de Flujo Color de Palabra Clave" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Type Color" -msgstr "Tipo Base" +msgstr "Tipo de Color Base" #: editor/editor_settings.cpp msgid "Engine Type Color" -msgstr "" +msgstr "Tipo de Color del Engine" #: editor/editor_settings.cpp msgid "User Type Color" -msgstr "" +msgstr "Tipo de Color del Usuario" #: editor/editor_settings.cpp msgid "Comment Color" -msgstr "" +msgstr "Color de los Comentarios" #: editor/editor_settings.cpp msgid "String Color" @@ -6138,25 +6131,24 @@ msgid "Completion Background Color" msgstr "Completar Color de Fondo" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Selected Color" -msgstr "Importar Seleccionado" +msgstr "Completar Color Seleccionado" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Existing Color" -msgstr "" +msgstr "Completar Color Existente" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Scroll Color" -msgstr "" +msgstr "Completar Color de Scroll" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Font Color" -msgstr "" +msgstr "Completar Color de la Fuente" #: editor/editor_settings.cpp msgid "Text Color" -msgstr "Color de Texto" +msgstr "Color del Texto" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Line Number Color" @@ -6168,7 +6160,7 @@ msgstr "Color de Número de LÃnea Seguro" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Color" -msgstr "" +msgstr "Color del Caret" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Background Color" @@ -6195,33 +6187,28 @@ msgid "Line Length Guideline Color" msgstr "" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Word Highlighted Color" -msgstr "Resaltador de Sintaxis" +msgstr "Color de la Palabra Resaltada" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Number Color" -msgstr "" +msgstr "Número del Color" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Function Color" -msgstr "Función" +msgstr "Función Color" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Member Variable Color" -msgstr "Cambiar nombre de variable" +msgstr "Color de la Variable Miembro" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Mark Color" -msgstr "Seleccionar Color" +msgstr "Marcar Color" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Bookmark Color" -msgstr "Marcadores" +msgstr "Color del Marcador" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Breakpoint Color" @@ -6229,21 +6216,19 @@ msgstr "Puntos de Interrupción" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Executing Line Color" -msgstr "" +msgstr "Color de la lÃnea de ejecución" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Code Folding Color" msgstr "" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Color" -msgstr "Resultados de la Búsqueda" +msgstr "Color del Resultado de Búsqueda" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Border Color" -msgstr "Resultados de la Búsqueda" +msgstr "Color de los Bordes del Resultado de Búsqueda" #: editor/editor_spin_slider.cpp msgid "Hold %s to round to integers. Hold Shift for more precise changes." @@ -6252,14 +6237,12 @@ msgstr "" "la tecla Mayús para cambios más precisos." #: editor/editor_spin_slider.cpp scene/gui/button.cpp -#, fuzzy msgid "Flat" -msgstr "Plano 0" +msgstr "Plano" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hide Slider" -msgstr "Modo de Colisión" +msgstr "Ocultar Deslizador" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -6937,9 +6920,8 @@ msgid "Use Ambient" msgstr "" #: editor/import/resource_importer_bitmask.cpp -#, fuzzy msgid "Create From" -msgstr "Crear Carpeta" +msgstr "Crear Desde" #: editor/import/resource_importer_bitmask.cpp #: servers/audio/effects/audio_effect_compressor.cpp @@ -6959,9 +6941,8 @@ msgid "Delimiter" msgstr "Delimitador" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "ColorCorrect" -msgstr "Corrección del Color" +msgstr "Corrección de Color" #: editor/import/resource_importer_layered_texture.cpp msgid "No BPTC If RGB" @@ -6989,9 +6970,8 @@ msgstr "Filtro" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Mipmaps" -msgstr "Señales" +msgstr "Mipmaps" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp @@ -7022,14 +7002,12 @@ msgid "Vertical" msgstr "Vertical" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Generate Tangents" -msgstr "Generar puntos" +msgstr "Generar Tangentes" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Scale Mesh" -msgstr "Modo de Escalado" +msgstr "Escalar Mesh" #: editor/import/resource_importer_obj.cpp msgid "Offset Mesh" @@ -7037,14 +7015,12 @@ msgstr "Offset de Malla" #: editor/import/resource_importer_obj.cpp #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Octahedral Compression" -msgstr "Compresión" +msgstr "Compresión Octaédrica" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Optimize Mesh Flags" -msgstr "Tamaño de los Indicadores" +msgstr "Optimizar Marcadores de Malla" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" @@ -7088,29 +7064,24 @@ msgstr "Importar como Escenas y Materiales Múltiples" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Nodes" msgstr "Nodos" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Type" -msgstr "Regresar" +msgstr "Tipo de RaÃz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Name" -msgstr "Nombre Remoto" +msgstr "Nombre de RaÃz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Scale" -msgstr "Escala" +msgstr "Escala de RaÃz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Custom Script" -msgstr "CustomNode" +msgstr "Script Personalizado" #: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp msgid "Storage" @@ -7125,62 +7096,52 @@ msgid "Materials" msgstr "Materiales" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep On Reimport" -msgstr "Reimportar" +msgstr "Seguir Reimportando" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp -#, fuzzy msgid "Meshes" -msgstr "Malla" +msgstr "Meshes" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Ensure Tangents" -msgstr "Modificar Tangente de Curva" +msgstr "Asegurar Tangentes" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Light Baking" -msgstr "Lightmapping" +msgstr "Bake de Luces" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Lightmap Texel Size" -msgstr "Calcular Lightmaps" +msgstr "Tamaño Lightmap Texel" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Skins" msgstr "" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Use Named Skins" -msgstr "Usar Ajuste de Escalado" +msgstr "Usar Skins con Nombre" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "External Files" -msgstr "Abrir un Archivo" +msgstr "Archivos Externos" #: editor/import/resource_importer_scene.cpp msgid "Store In Subdir" msgstr "" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Filter Script" -msgstr "Filtrar scripts" +msgstr "Filtrar Script" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep Custom Tracks" -msgstr "Transformar" +msgstr "Mantener Pistas Personalizadas" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Optimizer" -msgstr "Optimizar" +msgstr "Optimizador" #: editor/import/resource_importer_scene.cpp #: editor/plugins/item_list_editor_plugin.cpp main/main.cpp @@ -7194,9 +7155,8 @@ msgstr "Optimizar" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp #: scene/gui/rich_text_label.cpp scene/resources/curve.cpp #: scene/resources/environment.cpp scene/resources/material.cpp -#, fuzzy msgid "Enabled" -msgstr "Activar" +msgstr "Activado" #: editor/import/resource_importer_scene.cpp msgid "Max Linear Error" @@ -7207,19 +7167,16 @@ msgid "Max Angular Error" msgstr "Error Angular Máximo" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Angle" -msgstr "Valor" +msgstr "Ãngulo Máximo" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Remove Unused Tracks" -msgstr "Eliminar Pista de Animación" +msgstr "Eliminar Pistas Sin Usar" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Clips" -msgstr "Clips de Animación" +msgstr "Clips" #: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp @@ -7286,18 +7243,16 @@ msgid "2D, Detect 3D" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "2D Pixel" -msgstr "Pixeles Sólidos" +msgstr "Pixel 2D" #: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp msgid "Lossy Quality" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "HDR Mode" -msgstr "Modo de Selección" +msgstr "Modo HDR" #: editor/import/resource_importer_texture.cpp msgid "BPTC LDR" @@ -7311,45 +7266,40 @@ msgid "Normal Map" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Process" -msgstr "Post procesado" +msgstr "Proceso" #: editor/import/resource_importer_texture.cpp msgid "Fix Alpha Border" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Premult Alpha" -msgstr "Editar PolÃgono" +msgstr "Premult Alpha" #: editor/import/resource_importer_texture.cpp msgid "Hdr As Srgb" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Invert Color" -msgstr "Vértice" +msgstr "Invertir Color" #: editor/import/resource_importer_texture.cpp msgid "Normal Map Invert Y" msgstr "Invertir Y en Mapa Normal" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Size Limit" -msgstr "LÃmites" +msgstr "Tamaño LÃmite" #: editor/import/resource_importer_texture.cpp msgid "Detect 3D" msgstr "" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "SVG" -msgstr "HSV" +msgstr "SVG" #: editor/import/resource_importer_texture.cpp msgid "" @@ -7366,18 +7316,16 @@ msgid "Import Mode" msgstr "Modo de Importación" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Crop To Region" -msgstr "Establecer Región de Tile" +msgstr "Recortar la Región" #: editor/import/resource_importer_texture_atlas.cpp msgid "Trim Alpha Border From Region" msgstr "" #: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Force" -msgstr "Forzar Push" +msgstr "Fuerza" #: editor/import/resource_importer_wav.cpp msgid "8 Bit" @@ -7389,41 +7337,35 @@ msgid "Mono" msgstr "" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate" -msgstr "Nodo Mix" +msgstr "Tasa Máxima" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate Hz" -msgstr "Nodo Mix" +msgstr "Tasa Máxima Hz" #: editor/import/resource_importer_wav.cpp msgid "Trim" msgstr "" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Normalize" -msgstr "Formato" +msgstr "Normalizar" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Mode" -msgstr "Modo de Movimiento" +msgstr "Modo Bucle" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Begin" -msgstr "Modo de Movimiento" +msgstr "Inicio del Bucle" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop End" -msgstr "Modo de Movimiento" +msgstr "Fin del Bucle" #: editor/import_defaults_editor.cpp msgid "Select Importer" @@ -7510,14 +7452,12 @@ msgid "Raw" msgstr "Raw" #: editor/inspector_dock.cpp -#, fuzzy msgid "Capitalized" -msgstr "Capitalizar" +msgstr "Capitalización" #: editor/inspector_dock.cpp -#, fuzzy msgid "Localized" -msgstr "Idioma" +msgstr "Localizado" #: editor/inspector_dock.cpp msgid "Localization not available for current language." @@ -8071,9 +8011,8 @@ msgid "New" msgstr "Nuevo" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Paste As Reference" -msgstr "%s Referencia de Clase" +msgstr "Pegar Como Referencia" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -8565,25 +8504,21 @@ msgid "Loading..." msgstr "Cargar..." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "First" msgstr "Primero" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Previous" msgstr "Anterior" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Next" msgstr "Siguiente" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Last" msgstr "Último" @@ -9202,9 +9137,8 @@ msgid "View" msgstr "Ver" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show" -msgstr "Ver CuadrÃcula" +msgstr "Mostrar" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show When Snapping" @@ -9212,12 +9146,11 @@ msgstr "Mostrar Al Ajustar" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Hide" -msgstr "" +msgstr "Ocultar" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid" -msgstr "Cambiar Modo" +msgstr "Cambiar CuadrÃcula" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -9839,7 +9772,6 @@ msgstr "" "%s" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "MeshLibrary" msgstr "LibrerÃa de Mallas" @@ -9864,14 +9796,12 @@ msgid "Update from Scene" msgstr "Actualizar desde escena" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply without Transforms" -msgstr "Aplicar Transformaciones al MeshInstance" +msgstr "Aplicar sin Transformaciones" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply with Transforms" -msgstr "Aplicar Transformaciones al MeshInstance" +msgstr "Aplicar con Transformaciones" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." @@ -10219,7 +10149,7 @@ msgid "" "viewport." msgstr "" "El polÃgono 2D tiene vértices internos, por lo que ya no se puede editar en " -"la ventanilla." +"el viewport." #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" @@ -10740,19 +10670,16 @@ msgid "External" msgstr "" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Use External Editor" -msgstr "Depurar con Editor Externo" +msgstr "Usar un Editor Externo" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Exec Path" -msgstr "Ruta de Exportación" +msgstr "Ruta de Ejecución" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script Temperature Enabled" -msgstr "Seleccionar el archivo de la plantilla" +msgstr "Temperatura del Script Activada" #: editor/plugins/script_editor_plugin.cpp msgid "Highlight Current Script" @@ -10767,14 +10694,12 @@ msgid "Current Script Background Color" msgstr "Color de Fondo del Script Actual" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Group Help Pages" -msgstr "Agrupar Seleccionados" +msgstr "Páginas de Ayuda para Grupos" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Sort Scripts By" -msgstr "Crear Script" +msgstr "Ordenar Scripts por" #: editor/plugins/script_editor_plugin.cpp msgid "List Script Names As" @@ -10991,8 +10916,8 @@ msgid "" "This shader has been modified on on disk.\n" "What action should be taken?" msgstr "" -"Este shader ha sido modificado en disco.\n" -"¿Qué acciones deben tomarse?" +"Este shader ha sido modificado en el disco.\n" +"¿Qué acción debe tomarse?" #: editor/plugins/shader_editor_plugin.cpp scene/resources/material.cpp msgid "Shader" @@ -11490,27 +11415,27 @@ msgstr "Dialogo de Transformación..." #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" -msgstr "1 Ventana" +msgstr "1 Viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports" -msgstr "2 Ventanas" +msgstr "2 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "2 Ventanas (Alt)" +msgstr "2 Viewports (Alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" -msgstr "3 Ventanas" +msgstr "3 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "3 Ventanas (Alt)" +msgstr "3 Viewports (Alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" -msgstr "4 Ventanas" +msgstr "4 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "Gizmos" @@ -11555,7 +11480,7 @@ msgstr "Ajuste de Escala (%):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" -msgstr "Configuración de ventanilla" +msgstr "Configuración del Viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "Perspective FOV (deg.):" @@ -11606,9 +11531,8 @@ msgid "Manipulator Gizmo Opacity" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Show Viewport Rotation Gizmo" -msgstr "Bloquear Rotación de Vista" +msgstr "Mostrar Gizmo de Rotación del Viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "Unnamed Gizmo" @@ -11660,9 +11584,8 @@ msgid "Invalid geometry, can't replace by mesh." msgstr "GeometrÃa inválida, no puede ser reemplazada por una malla." #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Convert to MeshInstance2D" -msgstr "Convertir a Mesh2D" +msgstr "Convertir a MeshInstance2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't create polygon." @@ -11765,6 +11688,10 @@ msgid "New Animation" msgstr "Nueva Animación" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "Filtrar animaciones" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocidad:" @@ -12062,9 +11989,8 @@ msgstr "" "¿Cerrar de todos modos?" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Type" -msgstr "Eliminar Tile" +msgstr "Eliminar Tipo" #: editor/plugins/theme_editor_plugin.cpp msgid "" @@ -12108,14 +12034,12 @@ msgstr "" "Añade más propiedades manualmente o impórtalas desde otro Theme." #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Add Theme Type" -msgstr "Añadir Tipo de Elemento" +msgstr "Añadir Tipo de Theme" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Theme Type" -msgstr "Eliminar Remoto" +msgstr "Eliminar Tipo de Theme" #: editor/plugins/theme_editor_plugin.cpp msgid "Add Color Item" @@ -12562,55 +12486,46 @@ msgid "Clear Transform" msgstr "Reestablecer Transformación" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Tile Map" -msgstr "Dibujar TileMap" +msgstr "Mapa de Tiles" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Palette Min Width" -msgstr "" +msgstr "Ancho MÃnimo de la Paleta" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Palette Item H Separation" -msgstr "Separador con nombre" +msgstr "Separación del Elemento H de la Paleta" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Names" -msgstr "Mostrar Todos los Idiomas" +msgstr "Mostrar Nombres de Tiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Ids" -msgstr "Mostrar Reglas" +msgstr "Mostrar ID de los Tiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Sort Tiles By Name" -msgstr "Ordenar archivos" +msgstr "Ordenar Tiles por Nombre" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Bucket Fill Preview" -msgstr "Bote de Relleno" +msgstr "Vista previa del Bote de Relleno" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Editor Side" -msgstr "Editor" +msgstr "Lado del Editor" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Display Grid" -msgstr "Mostrar Overdraw" +msgstr "Mostrar CuadrÃcula" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Axis Color" -msgstr "Seleccionar Color" +msgstr "Color de los Ejes" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Add Texture(s) to TileSet." @@ -12949,7 +12864,6 @@ msgid "This property can't be changed." msgstr "Esta propiedad no se puede cambiar." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Snap Options" msgstr "Opciones de Ajuste" @@ -12978,9 +12892,8 @@ msgid "Separation" msgstr "Separación" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Tile" -msgstr "Seleccionar" +msgstr "Tiles Seleccionados" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp @@ -12989,14 +12902,12 @@ msgstr "Seleccionar" #: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp #: scene/resources/material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Texture" -msgstr "Texto" +msgstr "Textura" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tex Offset" -msgstr "Desplazamiento de Byte" +msgstr "Desplazamiento de Textura" #: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp #: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp @@ -13006,79 +12917,64 @@ msgstr "Material" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Modulate" -msgstr "Rellenar" +msgstr "Modular" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Mode" -msgstr "Cambiar Modo" +msgstr "Modo Tile" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Autotile Bitmask Mode" -msgstr "Modo de Bitmask" +msgstr "Modo Bitmask Automático" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Size" -msgstr "Tamaño del Contorno" +msgstr "Tamaño de Subtile" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Spacing" -msgstr "Espaciado de LÃnea" +msgstr "Espaciado de Subtile" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Occluder Offset" -msgstr "Crear PolÃgono Oclusor" +msgstr "Desplazamiento del Oclusor" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation Offset" -msgstr "Modo de Navegación" +msgstr "Desplazamiento de Navegación" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Offset" -msgstr "Desplazamiento Base" +msgstr "Desplazamiento del Shape" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Transform" -msgstr "Transformar" +msgstr "Transformar Shape" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision" -msgstr "Colisión" +msgstr "Colisión Seleccionada" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way" -msgstr "Sólo selección" +msgstr "Colisión Seleccionada en Una Dirección" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way Margin" -msgstr "Modo de Colisión" +msgstr "Margen Seleccionado de Colisión en Una Dirección" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Navigation" -msgstr "Navegación Visible" +msgstr "Navegación Seleccionada" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Occlusion" -msgstr "Seleccionar" +msgstr "Oclusión Seleccionada" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tileset Script" -msgstr "Filtrar scripts" +msgstr "Script de Tileset" #: editor/plugins/tile_set_editor_plugin.cpp msgid "TileSet" @@ -14289,9 +14185,8 @@ msgid "" msgstr "" #: editor/project_export.cpp -#, fuzzy msgid "More Info..." -msgstr "Mover a..." +msgstr "Más información..." #: editor/project_export.cpp msgid "Export PCK/Zip..." @@ -14318,18 +14213,16 @@ msgid "ZIP File" msgstr "Archivo ZIP" #: editor/project_export.cpp -#, fuzzy msgid "Godot Project Pack" -msgstr "Godot Game Pack" +msgstr "Paquete de Proyectos de Godot" #: editor/project_export.cpp msgid "Export templates for this platform are missing:" msgstr "Faltan plantillas de exportación para esta plataforma:" #: editor/project_export.cpp -#, fuzzy msgid "Project Export" -msgstr "Fundadores del Proyecto" +msgstr "Exportación del Proyecto" #: editor/project_export.cpp msgid "Manage Export Templates" @@ -14644,7 +14537,6 @@ msgstr "" #. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp -#, fuzzy msgctxt "Application" msgid "Project Manager" msgstr "Administrador de Proyectos" @@ -15452,14 +15344,12 @@ msgid "Another node already uses this unique name in the scene." msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Enable Scene Unique Name" -msgstr "Nombre Único" +msgstr "Activar Nombre Único de Escena" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -#, fuzzy msgid "Disable Scene Unique Name" -msgstr "Nombre Único" +msgstr "Desactivar Nombre Único de Escena" #: editor/scene_tree_dock.cpp msgid "New Scene Root" @@ -15634,18 +15524,16 @@ msgid "Clear Inheritance? (No Undo!)" msgstr "¿Quieres limpiar la herencia? (No se puede deshacer)" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Show Scene Tree Root Selection" -msgstr "Centrar Selección" +msgstr "Mostrar Selección de la RaÃz del Ãrbol de Escenas" #: editor/scene_tree_dock.cpp msgid "Derive Script Globals By Name" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Use Favorites Root Selection" -msgstr "Seleccionar Fotogramas" +msgstr "Usar Selección de RaÃces Favoritas" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" @@ -16104,23 +15992,20 @@ msgid "Change Particles AABB" msgstr "Cambiar partÃculas AABB" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Reflection Probe" -msgstr "Seleccionar Propiedad" +msgstr "Sonda de Reflexión" #: editor/spatial_editor_gizmos.cpp msgid "Change Probe Extents" msgstr "Cambiar Alcance de la Sonda" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "GI Probe" -msgstr "Calcular GI Probe" +msgstr "Sonda GI" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Baked Indirect Light" -msgstr "Iluminación indirecta" +msgstr "Iluminación Indirecta Bakeada" #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp msgid "Change Sphere Shape Radius" @@ -16151,24 +16036,20 @@ msgid "Change Ray Shape Length" msgstr "Cambiar Longitud de la Forma del Rayo" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge" -msgstr "Modo de Navegación" +msgstr "Borde de Navegación" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge Disabled" -msgstr "Modo de Navegación" +msgstr "Borde de Navegación Desactivado" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid" -msgstr "Modo de Navegación" +msgstr "Navegación Sólida" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid Disabled" -msgstr "Modo de Navegación" +msgstr "Navegación Sólida Desactivada" #: editor/spatial_editor_gizmos.cpp msgid "Joint Body A" @@ -16191,9 +16072,8 @@ msgid "Set Room Point Position" msgstr "Establecer Posición del Room Point" #: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp -#, fuzzy msgid "Portal Margin" -msgstr "Asignar Margen" +msgstr "Margen del Portal" #: editor/spatial_editor_gizmos.cpp msgid "Portal Edge" @@ -16212,15 +16092,13 @@ msgid "Portal Front" msgstr "" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Portal Back" -msgstr "Retroceder" +msgstr "Portal de Regreso" #: editor/spatial_editor_gizmos.cpp scene/2d/light_occluder_2d.cpp #: scene/2d/tile_map.cpp -#, fuzzy msgid "Occluder" -msgstr "Modo de Oclusión" +msgstr "Oclusor" #: editor/spatial_editor_gizmos.cpp msgid "Set Occluder Sphere Radius" @@ -16239,19 +16117,16 @@ msgid "Set Occluder Hole Point Position" msgstr "Establecer posición del orificio del oclusor" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Polygon Front" -msgstr "Crear PolÃgono Oclusor" +msgstr "Frente del PolÃgono Oclusor" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Polygon Back" -msgstr "Crear PolÃgono Oclusor" +msgstr "Posterior del PolÃgono Oclusor" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Hole" -msgstr "Crear PolÃgono Oclusor" +msgstr "Orificio Oclusor" #: main/main.cpp msgid "Godot Physics" @@ -16260,32 +16135,28 @@ msgstr "" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp msgid "Use BVH" -msgstr "" +msgstr "Usar BVH" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp -#, fuzzy msgid "BVH Collision Margin" -msgstr "Modo de Colisión" +msgstr "Margen de Colisión BVH" #: main/main.cpp -#, fuzzy msgid "Crash Handler" -msgstr "Establecer Manipulador" +msgstr "Manipulador de Colisiones" #: main/main.cpp -#, fuzzy msgid "Multithreaded Server" -msgstr "Establecer multinodo" +msgstr "Servidor Multihilo" #: main/main.cpp msgid "RID Pool Prealloc" msgstr "" #: main/main.cpp -#, fuzzy msgid "Debugger stdout" -msgstr "Depurador" +msgstr "Depurador stdout" #: main/main.cpp msgid "Max Chars Per Second" @@ -16316,14 +16187,12 @@ msgid "File Logging" msgstr "" #: main/main.cpp -#, fuzzy msgid "Enable File Logging" -msgstr "Habilitar Filtrado" +msgstr "Activar Registro de Archivos" #: main/main.cpp -#, fuzzy msgid "Log Path" -msgstr "Copiar Ruta" +msgstr "Ruta del Registro" #: main/main.cpp msgid "Max Log Files" @@ -16354,14 +16223,12 @@ msgid "Allow hiDPI" msgstr "" #: main/main.cpp -#, fuzzy msgid "V-Sync" -msgstr "Sincronizar" +msgstr "Sincronización Vertical" #: main/main.cpp -#, fuzzy msgid "Use V-Sync" -msgstr "Usar Snap" +msgstr "Usar Sincronización Vertical" #: main/main.cpp msgid "Per Pixel Transparency" @@ -16376,23 +16243,20 @@ msgid "Intended Usage" msgstr "" #: main/main.cpp -#, fuzzy msgid "Framebuffer Allocation" -msgstr "Seleccionar Fotogramas" +msgstr "Asignación del Buffer de Imágenes" #: main/main.cpp platform/uwp/os_uwp.cpp -#, fuzzy msgid "Energy Saving" -msgstr "Error al Guardar" +msgstr "Ahorro de EnergÃa" #: main/main.cpp msgid "Threads" msgstr "" #: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h -#, fuzzy msgid "Thread Model" -msgstr "Cambiar Modo" +msgstr "Modelo de Hilo" #: main/main.cpp msgid "Thread Safe BVH" @@ -16404,25 +16268,21 @@ msgstr "" #: main/main.cpp platform/javascript/export/export.cpp #: platform/uwp/export/export.cpp -#, fuzzy msgid "Orientation" -msgstr "Documentación en lÃnea" +msgstr "Orientación" #: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp #: scene/main/scene_tree.cpp scene/register_scene_types.cpp -#, fuzzy msgid "Common" -msgstr "Comunidad" +msgstr "Común" #: main/main.cpp -#, fuzzy msgid "Physics FPS" -msgstr "Fotogramas de FÃsica %" +msgstr "FÃsica FPS" #: main/main.cpp -#, fuzzy msgid "Force FPS" -msgstr "Forzar Push" +msgstr "Forzar FPS" #: main/main.cpp msgid "Enable Pause Aware Picking" @@ -16451,19 +16311,16 @@ msgid "Verbose stdout" msgstr "" #: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp -#, fuzzy msgid "Physics Interpolation" -msgstr "Modo de Interpolación" +msgstr "Interpolación de FÃsica" #: main/main.cpp -#, fuzzy msgid "Enable Warnings" -msgstr "Habilitar Filtrado" +msgstr "Activar Advertencias" #: main/main.cpp -#, fuzzy msgid "Frame Delay Msec" -msgstr "Seleccionar Fotogramas" +msgstr "Retraso de los Fotogramas Msec" #: main/main.cpp msgid "Low Processor Mode" @@ -16482,14 +16339,12 @@ msgid "Hide Home Indicator" msgstr "" #: main/main.cpp -#, fuzzy msgid "Input Devices" -msgstr "Todos los Dispositivos" +msgstr "Dispositivos de Entrada" #: main/main.cpp -#, fuzzy msgid "Pointing" -msgstr "Punto" +msgstr "Apuntador" #: main/main.cpp msgid "Touch Delay" @@ -16500,21 +16355,18 @@ msgid "GLES3" msgstr "" #: main/main.cpp servers/visual_server.cpp -#, fuzzy msgid "Shaders" -msgstr "Shader" +msgstr "Shaders" #: main/main.cpp -#, fuzzy msgid "Debug Shader Fallbacks" -msgstr "Forzar Shader Fallbacks" +msgstr "Depurar Fallbacks de Shader" #: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp #: scene/3d/world_environment.cpp scene/main/scene_tree.cpp #: scene/resources/world.cpp -#, fuzzy msgid "Environment" -msgstr "Ver Entorno" +msgstr "Entorno" #: main/main.cpp msgid "Default Clear Color" @@ -16525,9 +16377,8 @@ msgid "Boot Splash" msgstr "" #: main/main.cpp -#, fuzzy msgid "Show Image" -msgstr "Mostrar Huesos" +msgstr "Mostrar Imagen" #: main/main.cpp msgid "Image" @@ -16542,14 +16393,12 @@ msgid "Use Filter" msgstr "Usar Filtro" #: main/main.cpp scene/resources/style_box.cpp -#, fuzzy msgid "BG Color" -msgstr "Colores" +msgstr "Color de Fondo" #: main/main.cpp -#, fuzzy msgid "macOS Native Icon" -msgstr "Establecer Icono de Tile" +msgstr "Icono Nativo de macOS" #: main/main.cpp msgid "Windows Native Icon" @@ -16572,14 +16421,12 @@ msgid "Emulate Mouse From Touch" msgstr "" #: main/main.cpp -#, fuzzy msgid "Mouse Cursor" -msgstr "Botón del Mouse" +msgstr "Cursor del Mouse" #: main/main.cpp -#, fuzzy msgid "Custom Image" -msgstr "CustomNode" +msgstr "Imagen Personalizada" #: main/main.cpp msgid "Custom Image Hotspot" @@ -16587,17 +16434,15 @@ msgstr "" #: main/main.cpp msgid "Tooltip Position Offset" -msgstr "Offset de la Posición del Tooltip" +msgstr "Desplazamiento de Posición del Tooltip" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Debugger Agent" -msgstr "Depurador" +msgstr "Agente de Depuración" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Wait For Debugger" -msgstr "Depurador" +msgstr "Esperar al Depurador" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Wait Timeout" @@ -16612,20 +16457,17 @@ msgid "Unhandled Exception Policy" msgstr "" #: main/main.cpp -#, fuzzy msgid "Main Loop Type" -msgstr "Buscar Tipo de Nodo" +msgstr "Tipo de Bucle Principal" #: main/main.cpp scene/gui/texture_progress.cpp #: scene/gui/viewport_container.cpp -#, fuzzy msgid "Stretch" -msgstr "Buscar" +msgstr "Estirar" #: main/main.cpp -#, fuzzy msgid "Aspect" -msgstr "Inspector" +msgstr "Aspecto" #: main/main.cpp msgid "Shrink" @@ -16636,14 +16478,12 @@ msgid "Auto Accept Quit" msgstr "" #: main/main.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Quit On Go Back" -msgstr "Retroceder" +msgstr "Salir y Regresar" #: main/main.cpp scene/main/viewport.cpp -#, fuzzy msgid "Snap Controls To Pixels" -msgstr "Ajustar a los Lados del Nodo" +msgstr "Ajustar Controles a PÃxeles" #: main/main.cpp msgid "Dynamic Fonts" @@ -16678,35 +16518,30 @@ msgid "Change Torus Outer Radius" msgstr "Cambiar Radio Externo de Torus" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Operation" -msgstr "Opciones" +msgstr "Operación" #: modules/csg/csg_shape.cpp msgid "Calculate Tangents" msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Use Collision" -msgstr "Colisión" +msgstr "Usar Colisión" #: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp -#, fuzzy msgid "Collision Layer" -msgstr "Modo de Colisión" +msgstr "Capa de Colisión" #: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp #: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp #: scene/resources/navigation_mesh.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Mask" -msgstr "Modo de Colisión" +msgstr "Máscara de Colisión" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Invert Faces" -msgstr "Convertir Mayúsculas/Minúsculas" +msgstr "Invertir Caras" #: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp @@ -16724,33 +16559,28 @@ msgid "Radial Segments" msgstr "Segmentos Radiales" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Rings" -msgstr "Advertencias" +msgstr "Anillos" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Smooth Faces" -msgstr "Suavizado" +msgstr "Caras Suaves" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Sides" -msgstr "Mostrar GuÃas" +msgstr "Lados" #: modules/csg/csg_shape.cpp msgid "Cone" msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Inner Radius" -msgstr "Cambiar Radio Interno de Torus" +msgstr "Radio Interior" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Outer Radius" -msgstr "Cambiar Radio Externo de Torus" +msgstr "Radio Exterior" #: modules/csg/csg_shape.cpp msgid "Ring Sides" @@ -16759,9 +16589,8 @@ msgstr "" #: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp #: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp #: scene/3d/collision_polygon.cpp -#, fuzzy msgid "Polygon" -msgstr "PolÃgonos" +msgstr "PolÃgono" #: modules/csg/csg_shape.cpp msgid "Spin Degrees" @@ -16772,14 +16601,12 @@ msgid "Spin Sides" msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Node" -msgstr "Pegar Nodos" +msgstr "Ruta del Nodo" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Interval Type" -msgstr "Crear Vértice Interno" +msgstr "Tipo de Intervalo de Ruta" #: modules/csg/csg_shape.cpp msgid "Path Interval" @@ -16794,14 +16621,12 @@ msgid "Path Rotation" msgstr "Rotación de Trayectoria" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Local" -msgstr "Crear Local" +msgstr "Ruta Local" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Continuous U" -msgstr "Continuo" +msgstr "Ruta Continua U" #: modules/csg/csg_shape.cpp msgid "Path U Distance" @@ -16812,24 +16637,20 @@ msgid "Path Joined" msgstr "Ruta Unida" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Compression Mode" -msgstr "Modo de Colisión" +msgstr "Modo de Compresión" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Transfer Channel" -msgstr "Cambio de Transformación" +msgstr "Canal de Transferencia" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Channel Count" -msgstr "Instanciar" +msgstr "Conteo de Canales" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Always Ordered" -msgstr "Mostrar Siempre la CuadrÃcula" +msgstr "Siempre Ordenado" #: modules/enet/networked_multiplayer_enet.cpp msgid "Server Relay" @@ -16844,9 +16665,8 @@ msgid "DTLS Hostname" msgstr "" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Use DTLS" -msgstr "Usar Snap" +msgstr "Usar DTLS" #: modules/fbx/editor_scene_importer_fbx.cpp msgid "FBX" @@ -16861,24 +16681,21 @@ msgid "Config File" msgstr "Archivo de Configuración" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Load Once" -msgstr "Cargar Recurso" +msgstr "Cargar Una Vez" #: modules/gdnative/gdnative.cpp #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Singleton" -msgstr "Esqueleto" +msgstr "Singleton" #: modules/gdnative/gdnative.cpp msgid "Symbol Prefix" msgstr "Prefijo de SÃmbolo" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Reloadable" -msgstr "Recargar" +msgstr "Recargable" #: modules/gdnative/gdnative.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -16943,9 +16760,8 @@ msgid "Script Class" msgstr "Clase del Script" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Icon Path" -msgstr "Foco en Ruta" +msgstr "Ruta del Icono" #: modules/gdnative/register_types.cpp msgid "GDNative" @@ -16953,18 +16769,16 @@ msgstr "GDNative" #: modules/gdscript/editor/gdscript_highlighter.cpp #: modules/gdscript/gdscript.cpp -#, fuzzy msgid "GDScript" -msgstr "Script" +msgstr "GDScript" #: modules/gdscript/editor/gdscript_highlighter.cpp msgid "Function Definition Color" msgstr "" #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Node Path Color" -msgstr "Copiar Ruta del Nodo" +msgstr "Color de la Ruta del Nodo" #: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp msgid "Max Call Stack" @@ -17027,9 +16841,8 @@ msgid "Language Server" msgstr "Servidor de Lenguaje" #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Enable Smart Resolve" -msgstr "No se puede resolver" +msgstr "Activar Smart Resolve" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Show Native Symbols In Editor" @@ -17048,42 +16861,36 @@ msgid "Export GLTF..." msgstr "Exportar GLTF..." #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Buffer View" -msgstr "Vista Trasera" +msgstr "Vista del Buffer" #: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp msgid "Byte Offset" msgstr "Desplazamiento de Byte" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Component Type" -msgstr "Componentes" +msgstr "Tipo de Componente" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Normalized" -msgstr "Formato" +msgstr "Normalizado" #: modules/gltf/gltf_accessor.cpp msgid "Count" msgstr "Cuenta" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Min" -msgstr "MiB" +msgstr "Min" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Max" -msgstr "Mix" +msgstr "Max" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Sparse Count" -msgstr "Instanciar" +msgstr "Recuento Parcial" #: modules/gltf/gltf_accessor.cpp msgid "Sparse Indices Buffer View" @@ -17106,23 +16913,20 @@ msgid "Sparse Values Byte Offset" msgstr "" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Buffer" -msgstr "Vista Trasera" +msgstr "Buffer" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Byte Length" -msgstr "Theme Predeterminado" +msgstr "Longitud de Bytes" #: modules/gltf/gltf_buffer_view.cpp msgid "Byte Stride" msgstr "" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Indices" -msgstr "Todos los Dispositivos" +msgstr "Ãndices" #: modules/gltf/gltf_camera.cpp msgid "FOV Size" @@ -17133,9 +16937,8 @@ msgid "Zfar" msgstr "" #: modules/gltf/gltf_camera.cpp -#, fuzzy msgid "Znear" -msgstr "Lineal" +msgstr "Znear" #: modules/gltf/gltf_light.cpp scene/2d/canvas_modulate.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/light_2d.cpp scene/2d/polygon_2d.cpp @@ -17145,9 +16948,8 @@ msgstr "Lineal" #: scene/resources/environment.cpp scene/resources/material.cpp #: scene/resources/particles_material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Color" -msgstr "Colores" +msgstr "Color" #: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp #: scene/resources/environment.cpp @@ -17155,9 +16957,8 @@ msgid "Intensity" msgstr "" #: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Range" -msgstr "Cambiar" +msgstr "Rango" #: modules/gltf/gltf_light.cpp msgid "Inner Cone Angle" @@ -17168,42 +16969,36 @@ msgid "Outer Cone Angle" msgstr "" #: modules/gltf/gltf_mesh.cpp -#, fuzzy msgid "Blend Weights" -msgstr "Calcular Lightmaps" +msgstr "Mezcla de Pesos" #: modules/gltf/gltf_mesh.cpp msgid "Instance Materials" msgstr "Materiales de Instancia" #: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp -#, fuzzy msgid "Parent" -msgstr "Reemparentar" +msgstr "Padre" #: modules/gltf/gltf_node.cpp -#, fuzzy msgid "Xform" -msgstr "Plataforma" +msgstr "Xform" #: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp msgid "Skin" msgstr "" #: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Translation" -msgstr "Traducciones" +msgstr "Traducción" #: modules/gltf/gltf_node.cpp -#, fuzzy msgid "Children" -msgstr "Hijos Editables" +msgstr "Hijos" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints" -msgstr "Punto" +msgstr "Articulaciones" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp msgid "Roots" @@ -17214,28 +17009,24 @@ msgid "Unique Names" msgstr "" #: modules/gltf/gltf_skeleton.cpp -#, fuzzy msgid "Godot Bone Node" -msgstr "Obtener Nodo de Escena" +msgstr "Nodo de Huesos de Godot" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Skin Root" -msgstr "Nueva RaÃz de Escena" +msgstr "RaÃz de la Skin" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints Original" -msgstr "Foco en Origen" +msgstr "Articulaciones Originales" #: modules/gltf/gltf_skin.cpp msgid "Inverse Binds" msgstr "" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Non Joints" -msgstr "Mover Unión" +msgstr "Sin Articulaciones" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Bone I" @@ -17274,28 +17065,24 @@ msgid "Json" msgstr "" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Major Version" -msgstr "Versión" +msgstr "Versión Mayor" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Minor Version" -msgstr "Versión" +msgstr "Versión Menor" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "GLB Data" -msgstr "Con Datos" +msgstr "Datos GLB" #: modules/gltf/gltf_state.cpp msgid "Use Named Skin Binds" msgstr "" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Buffer Views" -msgstr "Vista Trasera" +msgstr "Vistas del Buffer" #: modules/gltf/gltf_state.cpp msgid "Accessors" @@ -17306,15 +17093,13 @@ msgid "Scene Name" msgstr "Nombre de la Escena" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Root Nodes" -msgstr "Nombre del nodo raÃz" +msgstr "Nodos RaÃz" #: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp -#, fuzzy msgid "Textures" -msgstr "CaracterÃsticas" +msgstr "Texturas" #: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp msgid "Images" @@ -17325,70 +17110,60 @@ msgid "Cameras" msgstr "" #: modules/gltf/gltf_state.cpp servers/visual_server.cpp -#, fuzzy msgid "Lights" -msgstr "Luz" +msgstr "Luces" #: modules/gltf/gltf_state.cpp msgid "Unique Animation Names" msgstr "Nombres Únicos de Animación" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeletons" -msgstr "Esqueleto" +msgstr "Esqueletos" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeleton To Node" -msgstr "Selecciona un Nodo" +msgstr "Esqueleto a Nodo" #: modules/gltf/gltf_state.cpp msgid "Animations" msgstr "Animaciones" #: modules/gltf/gltf_texture.cpp -#, fuzzy msgid "Src Image" -msgstr "Mostrar Huesos" +msgstr "Imagen de Origen" #: modules/gridmap/grid_map.cpp msgid "Mesh Library" msgstr "LibrerÃa de Mallas" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Physics Material" -msgstr "Fotogramas de FÃsica %" +msgstr "Material de FÃsica" #: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp -#, fuzzy msgid "Use In Baked Light" -msgstr "Calcular Lightmaps" +msgstr "Uso en Luz Bakeada" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp msgid "Cell" msgstr "" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Octant Size" -msgstr "Vista Frontal" +msgstr "Tamaño del Octante" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center X" -msgstr "Centro" +msgstr "Centro X" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Y" -msgstr "Centro" +msgstr "Centro Y" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Z" -msgstr "Centro" +msgstr "Centro Z" #: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp #: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp @@ -17397,17 +17172,15 @@ msgid "Mask" msgstr "" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp -#, fuzzy msgid "Bake Navigation" -msgstr "Navegación" +msgstr "Bakear Navegación" #: modules/gridmap/grid_map.cpp scene/2d/navigation_2d.cpp #: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp #: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp #: scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Navigation Layers" -msgstr "Modo de Navegación" +msgstr "Capas de Navegación" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Next Plane" @@ -17567,9 +17340,8 @@ msgid "Plotting lightmaps" msgstr "Trazar lightmaps" #: modules/lightmapper_cpu/register_types.cpp -#, fuzzy msgid "CPU Lightmapper" -msgstr "Calcular Lightmaps" +msgstr "CPU Lightmapper" #: modules/lightmapper_cpu/register_types.cpp msgid "Low Quality Ray Count" @@ -17603,14 +17375,12 @@ msgid "IOD" msgstr "" #: modules/mobile_vr/mobile_vr_interface.cpp -#, fuzzy msgid "Display Width" -msgstr "Mostrar Wireframe" +msgstr "Ancho de Pantalla" #: modules/mobile_vr/mobile_vr_interface.cpp -#, fuzzy msgid "Display To Lens" -msgstr "Mostrar Sin Sombreado" +msgstr "Pantalla a Lente" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Oversample" @@ -17633,9 +17403,8 @@ msgid "Build Solution" msgstr "Crear Solución" #: modules/mono/editor/csharp_project.cpp -#, fuzzy msgid "Auto Update Project" -msgstr "Proyecto Sin Nombre" +msgstr "Actualización Automática del Proyecto" #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" @@ -17737,9 +17506,8 @@ msgid "Period" msgstr "" #: modules/opensimplex/open_simplex_noise.cpp -#, fuzzy msgid "Persistence" -msgstr "Perspectiva" +msgstr "Persistencia" #: modules/opensimplex/open_simplex_noise.cpp msgid "Lacunarity" @@ -17750,9 +17518,8 @@ msgid "Subject" msgstr "" #: modules/regex/regex.cpp -#, fuzzy msgid "Names" -msgstr "Nombre" +msgstr "Nombres" #: modules/regex/regex.cpp msgid "Strings" @@ -17771,32 +17538,28 @@ msgid "Discover IPv6" msgstr "" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Description URL" -msgstr "Descripción" +msgstr "Descripción URL" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Service Type" -msgstr "Establecer Tipo de la Variable" +msgstr "Tipo de Servicio" #: modules/upnp/upnp_device.cpp msgid "IGD Control URL" msgstr "" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "IGD Service Type" -msgstr "Establecer Tipo de la Variable" +msgstr "Tipo de Servicio IGD" #: modules/upnp/upnp_device.cpp msgid "IGD Our Addr" msgstr "" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "IGD Status" -msgstr "Estado" +msgstr "Estado del IGD" #: modules/visual_script/visual_script.cpp msgid "" @@ -17837,9 +17600,8 @@ msgid "Stack overflow with stack depth:" msgstr "Desbordamiento de pila con profundidad de pila:" #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Visual Script" -msgstr "Buscar en VisualScript" +msgstr "Visual Script" #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" @@ -18169,14 +17931,12 @@ msgid "Return" msgstr "Regresar" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Return Enabled" -msgstr "Ejecutable" +msgstr "Retorno Activado" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Return Type" -msgstr "Regresar" +msgstr "Tipo de Retorno" #: modules/visual_script/visual_script_flow_control.cpp #: scene/resources/visual_shader_nodes.cpp @@ -18224,9 +17984,8 @@ msgid "in order:" msgstr "en orden:" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Steps" -msgstr "Paso" +msgstr "Pasos" #: modules/visual_script/visual_script_flow_control.cpp msgid "Switch" @@ -18246,9 +18005,8 @@ msgstr "¿Es %s?" #: modules/visual_script/visual_script_flow_control.cpp #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Base Script" -msgstr "Nuevo Script" +msgstr "Script Base" #: modules/visual_script/visual_script_func_nodes.cpp msgid "On %s" @@ -18260,36 +18018,31 @@ msgstr "Sobre Sà Mismo" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Call Mode" -msgstr "Modo de Escalado" +msgstr "Modo de Llamada" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Basic Type" -msgstr "Tipo Base" +msgstr "Tipo Básico" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Node Path" -msgstr "Copiar Ruta del Nodo" +msgstr "Ruta del Nodo" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Use Default Args" -msgstr "Restablecer Valores por Defecto" +msgstr "Usar Argumentos por Defecto" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Validate" msgstr "Validar" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "RPC Call Mode" -msgstr "Modo de Escalado" +msgstr "Modo de Llamada RPC" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Subtract %s" @@ -18328,14 +18081,12 @@ msgid "BitXor %s" msgstr "BitXor %s" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Set Mode" -msgstr "Modo de Selección" +msgstr "Modo de Ajuste" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Assign Op" -msgstr "Asignar" +msgstr "Asignar Op" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp @@ -18352,9 +18103,8 @@ msgid "Base object is not a Node!" msgstr "¡El objeto base no es un nodo!" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Path does not lead to Node!" -msgstr "¡La ruta no apunta a un Nodo!" +msgstr "¡La ruta no lleva al nodo!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." @@ -18370,9 +18120,8 @@ msgstr "Ordenar Array" #: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Operator" -msgstr "Iterador" +msgstr "Operador" #: modules/visual_script/visual_script_nodes.cpp msgid "Invalid argument of type:" @@ -18387,9 +18136,8 @@ msgid "a if cond, else b" msgstr "a si cond, sino b" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Var Name" -msgstr "Nombre" +msgstr "Nombre de la Variable" #: modules/visual_script/visual_script_nodes.cpp msgid "VariableGet not found in script:" @@ -18514,9 +18262,8 @@ msgid "%s sec(s)" msgstr "%s seg(s)" #: modules/visual_script/visual_script_yield_nodes.cpp scene/main/timer.cpp -#, fuzzy msgid "Wait Time" -msgstr "Dibujar Tile" +msgstr "Tiempo de Espera" #: modules/visual_script/visual_script_yield_nodes.cpp msgid "WaitSignal" @@ -18531,18 +18278,16 @@ msgid "WaitInstanceSignal" msgstr "WaitInstanceSignal" #: modules/webrtc/webrtc_data_channel.cpp -#, fuzzy msgid "Write Mode" -msgstr "Modo de Prioridad" +msgstr "Modo de Escritura" #: modules/webrtc/webrtc_data_channel.h msgid "WebRTC" msgstr "" #: modules/webrtc/webrtc_data_channel.h -#, fuzzy msgid "Max Channel In Buffer (KB)" -msgstr "Tamaño del buffer del Ãndice del polÃgono del lienzo (KB)" +msgstr "Buffer de Canal Máximo (KB)" #: modules/websocket/websocket_client.cpp msgid "Verify SSL" @@ -18553,59 +18298,52 @@ msgid "Trusted SSL Certificate" msgstr "" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Client" -msgstr "Red de Pares" +msgstr "Cliente WebSocket" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max In Buffer (KB)" -msgstr "Tamaño Máximo (KB)" +msgstr "Buffer de Entrada Máximo (KB)" #: modules/websocket/websocket_macros.h msgid "Max In Packets" msgstr "" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max Out Buffer (KB)" -msgstr "Tamaño Máximo (KB)" +msgstr "Buffer de Salida Máximo (KB)" #: modules/websocket/websocket_macros.h msgid "Max Out Packets" msgstr "" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Server" -msgstr "Red de Pares" +msgstr "Servidor WebSocket" #: modules/websocket/websocket_server.cpp msgid "Bind IP" msgstr "" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "Private Key" -msgstr "Ruta de la Clave Privada SSH" +msgstr "Clave Privada" #: modules/websocket/websocket_server.cpp platform/javascript/export/export.cpp msgid "SSL Certificate" msgstr "" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "CA Chain" -msgstr "Reestrablecer cadena IK" +msgstr "Cadena CA" #: modules/websocket/websocket_server.cpp msgid "Handshake Timeout" msgstr "Tiempo de Espera del Handshake" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Session Mode" -msgstr "Modo de Región" +msgstr "Modo de Sesión" #: modules/webxr/webxr_interface.cpp msgid "Required Features" @@ -18624,28 +18362,24 @@ msgid "Reference Space Type" msgstr "" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Visibility State" -msgstr "Cambiar Visibilidad" +msgstr "Estado de Visibilidad" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Bounds Geometry" -msgstr "Reintentar" +msgstr "LÃmites Geométricos" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "XR Standard Mapping" -msgstr "Ajuste Inteligente" +msgstr "Mapeo Estándar XR" #: platform/android/export/export.cpp msgid "Android SDK Path" msgstr "" #: platform/android/export/export.cpp -#, fuzzy msgid "Debug Keystore" -msgstr "Depurador" +msgstr "Debug Keystore" #: platform/android/export/export.cpp msgid "Debug Keystore User" @@ -18707,84 +18441,72 @@ msgid "The package must have at least one '.' separator." msgstr "El paquete debe tener al menos un '.' como separador." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Build" -msgstr "CustomNode" +msgstr "Build Personalizada" #: platform/android/export/export_plugin.cpp msgid "Use Custom Build" -msgstr "" +msgstr "Usar Compilación Personalizada" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Export Format" -msgstr "Ruta de Exportación" +msgstr "Formato de Exportación" #: platform/android/export/export_plugin.cpp msgid "Min SDK" msgstr "SDK MÃnimo" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Target SDK" -msgstr "Objetivo de FPS" +msgstr "SDK de Destino" #: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp -#, fuzzy msgid "Architectures" -msgstr "Añadir una entrada de arquitectura" +msgstr "Arquitecturas" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Keystore" -msgstr "Depurador" +msgstr "Keystore" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Debug User" -msgstr "Depurador" +msgstr "Usuario de Depuración" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Debug Password" -msgstr "Contraseña" +msgstr "Contraseña de Depuración" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Release User" -msgstr "Release" +msgstr "Usuario de Release" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Release Password" -msgstr "Contraseña" +msgstr "Contraseña de Release" #: platform/android/export/export_plugin.cpp msgid "One Click Deploy" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Clear Previous Install" -msgstr "Inspeccionar Instancia Anterior" +msgstr "Limpiar Instalación Previa" #: platform/android/export/export_plugin.cpp msgid "Code" msgstr "" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Package" -msgstr "Empaquetando" +msgstr "Paquete" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp msgid "Unique Name" msgstr "Nombre Único" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Signed" -msgstr "Señal" +msgstr "Firmado" #: platform/android/export/export_plugin.cpp msgid "Classify As Game" @@ -18795,33 +18517,28 @@ msgid "Retain Data On Uninstall" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Exclude From Recents" -msgstr "Eliminar Nodos" +msgstr "Excluir de los Recientes" #: platform/android/export/export_plugin.cpp msgid "Graphics" msgstr "Gráficos" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "OpenGL Debug" -msgstr "Abrir" +msgstr "Depuración de OpenGL" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "XR Features" -msgstr "CaracterÃsticas" +msgstr "CaracterÃsticas del XR" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "XR Mode" -msgstr "Modo desplazamiento lateral" +msgstr "Modo XR" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Hand Tracking" -msgstr "Empaquetando" +msgstr "Seguimiento de Manos" #: platform/android/export/export_plugin.cpp msgid "Hand Tracking Frequency" @@ -18832,71 +18549,60 @@ msgid "Passthrough" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Immersive Mode" -msgstr "Modo de Prioridad" +msgstr "Modo Inmersivo" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Support Small" -msgstr "Soporte" +msgstr "Soporte Pequeño" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Support Normal" -msgstr "Soporte" +msgstr "Soporte Normal" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Support Large" -msgstr "Soporte" +msgstr "Soporte Grande" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Support Xlarge" -msgstr "Soporte" +msgstr "Soporte Xlarge" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "User Data Backup" -msgstr "Interfaz de usuario" +msgstr "Backup de Datos del Usuario" #: platform/android/export/export_plugin.cpp msgid "Allow" msgstr "" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Command Line" -msgstr "Command" +msgstr "LÃnea de Comandos" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp msgid "Extra Args" msgstr "Argumentos extras" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "APK Expansion" -msgstr "Expresión" +msgstr "Expansión del APK" #: platform/android/export/export_plugin.cpp msgid "Salt" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Public Key" -msgstr "Ruta de la clave pública SSH" +msgstr "Clave Pública" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Permissions" -msgstr "Máscara de Emisión" +msgstr "Permisos" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Permissions" -msgstr "Reproducir Escena Personalizada" +msgstr "Permisos Personalizados" #: platform/android/export/export_plugin.cpp msgid "Select device from the list" @@ -19025,34 +18731,33 @@ msgstr "" #: platform/android/export/export_plugin.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "\"Use Custom Build\" debe estar activado para usar los plugins." +msgstr "" +"\"Usar Compilación Personalizada\" debe estar activado para usar los plugins." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" " "or \"OpenXR\"." msgstr "" -"\"Hand Tracking\" solo es válido cuando \"Xr Mode\" es \"Oculus Mobile " -"VrApi\" u \"OpenXR\"." +"\"Seguimiento de Manos\" solo es válido cuando el \"Modo XR\" es \"Oculus " +"Mobile VrApi\" u \"OpenXR\"." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"." -msgstr "\"Passthrough\" solo es válido cuando \"Xr Mode\" es \"OpenXR\"." +msgstr "\"Passthrough\" solo es válido cuando el \"Modo XR\" es \"OpenXR\"." #: platform/android/export/export_plugin.cpp msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled." msgstr "" -"\"Export AAB\" sólo es válido cuando \"Use Custom Build\" está activado." +"\"Exportar AAB\" solo es válido cuando \"Usar Compilación Personalizada\" " +"está activado." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled." msgstr "" -"Cambiar el \"Min Sdk\" solo es válido cuando \"Use Custom Build\" está " -"activado." +"\"Min SDK\" solo puede sobrescribirse cuando está activada la opción \"Usar " +"Compilación Personalizada\"." #: platform/android/export/export_plugin.cpp msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid." @@ -19065,36 +18770,36 @@ msgid "" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled." msgstr "" -"Cambiar el \"Target Sdk\" solo es válido cuando \"Use Custom Build\" está " -"activado." +"\"SDK de Destino\" solo se puede sobrescribir cuando \"Usar Compilación " +"Personalizada\" está activado." #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid." msgstr "" +"\"SDK de Destino\" deberÃa ser un entero válido, pero obtuvo \"%s\" inválido." #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" %d is higher than the default version %d. This may work, but " "wasn't tested and may be unstable." msgstr "" +"\"SDK de Destino\" %d es superior a la versión por defecto %d. PodrÃa " +"funcionar, pero no se ha probado y puede ser inestable." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version." msgstr "" -"La versión de \"Target Sdk\" debe ser mayor o igual que la versión de \"Min " -"Sdk\"." +"La versión \"SDK de Destino\" debe ser mayor o igual a la versión \"Min " +"SDK\"." #: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Code Signing" -msgstr "Firma de código DMG" +msgstr "Firma del Código" #: platform/android/export/export_plugin.cpp msgid "" @@ -19324,9 +19029,8 @@ msgid "Code Sign Identity Debug" msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Export Method Debug" -msgstr "Exportar Con Depuración" +msgstr "Exportar Método de Depuración" #: platform/iphone/export/export.cpp msgid "Provisioning Profile UUID Release" @@ -19353,39 +19057,33 @@ msgid "Identifier" msgstr "Identificador" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Signature" -msgstr "Señal" +msgstr "Firma" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Short Version" -msgstr "Versión" +msgstr "Versión Corta" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Copyright" -msgstr "Superior Derecha" +msgstr "Copyright" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Capabilities" -msgstr "Capitalizar Propiedades" +msgstr "Capacidades" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Access Wi-Fi" -msgstr "Acceso" +msgstr "Acceso Wi-Fi" #: platform/iphone/export/export.cpp msgid "Push Notifications" msgstr "Notificaciones Push" #: platform/iphone/export/export.cpp -#, fuzzy msgid "User Data" -msgstr "Interfaz de usuario" +msgstr "Datos de Usuario" #: platform/iphone/export/export.cpp msgid "Accessible From Files App" @@ -19396,24 +19094,20 @@ msgid "Accessible From iTunes Sharing" msgstr "" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Privacy" -msgstr "Ruta de la Clave Privada SSH" +msgstr "Privacidad" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Camera Usage Description" -msgstr "Descripción" +msgstr "Descripción del Uso de la Cámara" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Microphone Usage Description" -msgstr "Descripciones de Propiedades" +msgstr "Descripción del Uso del Micrófono" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Photolibrary Usage Description" -msgstr "Descripciones de Propiedades" +msgstr "Descripción del Uso de la FotolibrerÃa" #: platform/iphone/export/export.cpp msgid "iPhone 120 X 120" @@ -19456,40 +19150,33 @@ msgid "Use Launch Screen Storyboard" msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Image Scale Mode" -msgstr "Modo de Escalado" +msgstr "Modo de Escalado de Imagen" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom Image @2x" -msgstr "CustomNode" +msgstr "Imagen Personalizada @2x" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom Image @3x" -msgstr "CustomNode" +msgstr "Imagen Personalizada @3x" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Use Custom BG Color" -msgstr "CustomNode" +msgstr "Usar Color de Fondo Personalizado" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom BG Color" -msgstr "CustomNode" +msgstr "Color de Fondo Personalizado" #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp -#, fuzzy msgid "Prepare Templates" -msgstr "Administrar Plantillas" +msgstr "Preparar Plantillas" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Export template not found." -msgstr "Plantilla release personalizada no encontrada." +msgstr "No se ha encontrado la plantilla de exportación." #: platform/iphone/export/export.cpp msgid "App Store Team ID not specified - cannot configure the project." @@ -19525,9 +19212,8 @@ msgid "Could not write file: \"%s\"." msgstr "No se pudo escribir el archivo: \"%s\"." #: platform/javascript/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Icon Creation" -msgstr "Asignar Margen" +msgstr "Creación de Iconos" #: platform/javascript/export/export.cpp msgid "Could not read file: \"%s\"." @@ -19542,14 +19228,12 @@ msgid "Variant" msgstr "Variante" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Export Type" -msgstr "Exportar" +msgstr "Tipo de Exportación" #: platform/javascript/export/export.cpp -#, fuzzy msgid "VRAM Texture Compression" -msgstr "Expresión" +msgstr "Compresión de Texturas en la VRAM" #: platform/javascript/export/export.cpp msgid "For Desktop" @@ -19564,14 +19248,12 @@ msgid "HTML" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Export Icon" -msgstr "Expandir Todo" +msgstr "Icono de Exportación" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Custom HTML Shell" -msgstr "CustomNode" +msgstr "HTML Shell Personalizado" #: platform/javascript/export/export.cpp msgid "Head Include" @@ -19586,9 +19268,8 @@ msgid "Focus Canvas On Start" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Experimental Virtual Keyboard" -msgstr "Filtrar señales" +msgstr "Teclado Virtual Experimental" #: platform/javascript/export/export.cpp msgid "Progressive Web App" @@ -19635,9 +19316,8 @@ msgid "HTTP Port" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Use SSL" -msgstr "Usar Snap" +msgstr "Usar SSL" #: platform/javascript/export/export.cpp msgid "SSL Key" @@ -19724,33 +19404,28 @@ msgid "High Res" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Location Usage Description" -msgstr "Descripción" +msgstr "Ubicación de la Descripción de Uso" #: platform/osx/export/export.cpp msgid "Address Book Usage Description" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Calendar Usage Description" -msgstr "Descripción" +msgstr "Descripción del Uso del Calendario" #: platform/osx/export/export.cpp -#, fuzzy msgid "Photos Library Usage Description" -msgstr "Descripciones de Propiedades" +msgstr "Descripción de Uso de la LibrerÃa de Fotos" #: platform/osx/export/export.cpp -#, fuzzy msgid "Desktop Folder Usage Description" -msgstr "Descripciones de Métodos" +msgstr "Descripción de Uso de la Carpeta de Escritorio" #: platform/osx/export/export.cpp -#, fuzzy msgid "Documents Folder Usage Description" -msgstr "Descripciones de Métodos" +msgstr "Descripción de Uso de la Carpeta de Documentos" #: platform/osx/export/export.cpp msgid "Downloads Folder Usage Description" @@ -19765,39 +19440,33 @@ msgid "Removable Volumes Usage Description" msgstr "" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Codesign" -msgstr "Firma de código DMG" +msgstr "Codesign" #: platform/osx/export/export.cpp platform/uwp/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Identity" -msgstr "Indentar a la Izquierda" +msgstr "Identidad" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Timestamp" -msgstr "Tiempo" +msgstr "Marca de Tiempo" #: platform/osx/export/export.cpp msgid "Hardened Runtime" -msgstr "" +msgstr "Hardened Runtime" #: platform/osx/export/export.cpp -#, fuzzy msgid "Replace Existing Signature" -msgstr "Reemplazar en Archivos" +msgstr "Reemplazar Firma Existente" #: platform/osx/export/export.cpp -#, fuzzy msgid "Entitlements" -msgstr "Gizmos" +msgstr "Derechos" #: platform/osx/export/export.cpp -#, fuzzy msgid "Custom File" -msgstr "CustomNode" +msgstr "Archivo Personalizado" #: platform/osx/export/export.cpp msgid "Allow JIT Code Execution" @@ -19812,14 +19481,12 @@ msgid "Allow Dyld Environment Variables" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Disable Library Validation" -msgstr "Botón Desactivado" +msgstr "Desactivar Validación de Bibliotecas" #: platform/osx/export/export.cpp -#, fuzzy msgid "Audio Input" -msgstr "Añadir Entrada" +msgstr "Entrada de Audio" #: platform/osx/export/export.cpp msgid "Address Book" @@ -19830,81 +19497,68 @@ msgid "Calendars" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Photos Library" -msgstr "Exportar LibrerÃa" +msgstr "LibrerÃa de Fotos" #: platform/osx/export/export.cpp -#, fuzzy msgid "Apple Events" -msgstr "Añadir Evento" +msgstr "Eventos de Apple" #: platform/osx/export/export.cpp -#, fuzzy msgid "Debugging" -msgstr "Depurar" +msgstr "Depuración" #: platform/osx/export/export.cpp msgid "App Sandbox" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Network Server" -msgstr "Red de Pares" +msgstr "Servidor de Red" #: platform/osx/export/export.cpp -#, fuzzy msgid "Network Client" -msgstr "Red de Pares" +msgstr "Cliente de Red" #: platform/osx/export/export.cpp -#, fuzzy msgid "Device USB" -msgstr "Dispositivo" +msgstr "Dispositivo USB" #: platform/osx/export/export.cpp msgid "Device Bluetooth" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Files Downloads" -msgstr "Descargar" +msgstr "Descargas de Archivos" #: platform/osx/export/export.cpp -#, fuzzy msgid "Files Pictures" -msgstr "CaracterÃsticas" +msgstr "Archivos de Imágenes" #: platform/osx/export/export.cpp -#, fuzzy msgid "Files Music" -msgstr "Archivo" +msgstr "Archivos de Música" #: platform/osx/export/export.cpp -#, fuzzy msgid "Files Movies" -msgstr "Filtrar tiles" +msgstr "Archivos de VÃdeo" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Custom Options" -msgstr "Opciones de Bus" +msgstr "Opciones Personalizadas" #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization" -msgstr "Traducciones" +msgstr "Notarización" #: platform/osx/export/export.cpp msgid "Apple ID Name" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Apple ID Password" -msgstr "Contraseña" +msgstr "Contraseña del ID de Apple" #: platform/osx/export/export.cpp msgid "Apple Team ID" @@ -19927,13 +19581,12 @@ msgid "Notarization request UUID: \"%s\"" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "" "The notarization process generally takes less than an hour. When the process " "is completed, you'll receive an email." msgstr "" -"Nota: El proceso de notarización generalmente toma menos de una hora. Cuando " -"se complete el proceso, recibirá un correo electrónico." +"El proceso de notarización suele durar menos de una hora. Cuando el proceso " +"haya finalizado, recibirás un correo electrónico." #: platform/osx/export/export.cpp msgid "" @@ -19952,17 +19605,15 @@ msgstr "" "notarial a la aplicación exportada (opcional):" #: platform/osx/export/export.cpp -#, fuzzy msgid "Timestamping is not compatible with ad-hoc signature, and was disabled!" msgstr "" -"El sellado de tiempo no es compatible con la firma ad-hoc, y se desactivará!" +"¡La marca de tiempo no es compatible con la firma ad-hoc, y fue desactivada!" #: platform/osx/export/export.cpp -#, fuzzy msgid "" "Hardened Runtime is not compatible with ad-hoc signature, and was disabled!" msgstr "" -"Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!" +"¡Hardened Runtime no es compatible con la firma ad-hoc, y fue desactivado!" #: platform/osx/export/export.cpp msgid "Built-in CodeSign failed with error \"%s\"." @@ -19987,16 +19638,14 @@ msgid "Cannot sign file %s." msgstr "No se puede firmar el archivo %s." #: platform/osx/export/export.cpp -#, fuzzy msgid "Relative symlinks are not supported, exported \"%s\" might be broken!" msgstr "" -"Los enlaces simbólicos relativos no son compatibles con este sistema " -"operativo, ¡el proyecto exportado podrÃa estar dañado!" +"Los enlaces simbólicos relativos no son compatibles, ¡los \"%s\" exportados " +"podrÃan estar rotos!" #: platform/osx/export/export.cpp -#, fuzzy msgid "DMG Creation" -msgstr "Direcciones" +msgstr "Creación de DMG" #: platform/osx/export/export.cpp msgid "Could not start hdiutil executable." @@ -20032,13 +19681,12 @@ msgstr "" "operativo, ¡el proyecto exportado podrÃa estar dañado!" #: platform/osx/export/export.cpp -#, fuzzy msgid "" "Requested template binary \"%s\" not found. It might be missing from your " "template archive." msgstr "" -"Plantilla binaria solicitada '%s' no encontrada. Es posible que falte en el " -"archivo de plantillas." +"No se ha encontrado la plantilla binaria \"%s\" solicitada. Es posible que " +"no se encuentre en el archivo de plantillas." #: platform/osx/export/export.cpp msgid "Making PKG" @@ -20081,9 +19729,8 @@ msgid "Sending archive for notarization" msgstr "Enviando archivo para notarización" #: platform/osx/export/export.cpp -#, fuzzy msgid "ZIP Creation" -msgstr "Proyecto" +msgstr "Creación de ZIP" #: platform/osx/export/export.cpp msgid "Could not open file to read from path \"%s\"." @@ -20122,9 +19769,7 @@ msgstr "Notarización: Se requiere la firma del código para la notarización." #: platform/osx/export/export.cpp msgid "Notarization: Hardened runtime is required for notarization." -msgstr "" -"Notarización: se requiere tiempo de ejecución endurecido para la " -"certificación notarial." +msgstr "Notarización: Se requiere Hardened runtime para la notarización." #: platform/osx/export/export.cpp msgid "Notarization: Timestamp runtime is required for notarization." @@ -20161,7 +19806,7 @@ msgid "" "Hardened Runtime is not compatible with ad-hoc signature, and will be " "disabled!" msgstr "" -"Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!" +"¡Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!" #: platform/osx/export/export.cpp msgid "" @@ -20233,14 +19878,12 @@ msgid "Force Builtin Codesign" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Architecture" -msgstr "Añadir una entrada de arquitectura" +msgstr "Arquitectura" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Display Name" -msgstr "Escala de Visualización" +msgstr "Nombre a Mostrar" #: platform/uwp/export/export.cpp msgid "Short Name" @@ -20259,24 +19902,20 @@ msgid "Product GUID" msgstr "GUID del producto" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Publisher GUID" -msgstr "Limpiar GuÃas" +msgstr "GUID del Editor" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Signing" -msgstr "Señal" +msgstr "Firmando" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Certificate" -msgstr "Certificados" +msgstr "Certificado" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Algorithm" -msgstr "Depurador" +msgstr "Algoritmo" #: platform/uwp/export/export.cpp msgid "Major" @@ -20287,23 +19926,20 @@ msgid "Minor" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Build" -msgstr "Modo de Regla" +msgstr "Compilación" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Revision" -msgstr "Expresión" +msgstr "Revisión" #: platform/uwp/export/export.cpp msgid "Landscape" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Portrait" -msgstr "Voltear Portales" +msgstr "Retrato" #: platform/uwp/export/export.cpp msgid "Landscape Flipped" @@ -20314,9 +19950,8 @@ msgid "Portrait Flipped" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Store Logo" -msgstr "Modo de Escalado" +msgstr "Logo de Tienda" #: platform/uwp/export/export.cpp msgid "Square 44 X 44 Logo" @@ -20343,9 +19978,8 @@ msgid "Splash Screen" msgstr "Pantalla de Bienvenida" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Tiles" -msgstr "Archivo" +msgstr "Tiles" #: platform/uwp/export/export.cpp msgid "Show Name On Square 150 X 150" @@ -20429,18 +20063,16 @@ msgid "UWP" msgstr "" #: platform/uwp/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Signtool" -msgstr "Señal" +msgstr "Signtool" #: platform/uwp/export/export.cpp msgid "Debug Certificate" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Debug Algorithm" -msgstr "Depurador" +msgstr "Algoritmo de Depuración" #: platform/windows/export/export.cpp msgid "Failed to rename temporary file \"%s\"." @@ -20455,19 +20087,16 @@ msgid "Timestamp Server URL" msgstr "" #: platform/windows/export/export.cpp -#, fuzzy msgid "Digest Algorithm" -msgstr "Depurador" +msgstr "Algoritmo de Compilación" #: platform/windows/export/export.cpp -#, fuzzy msgid "Modify Resources" -msgstr "Copiar Recurso" +msgstr "Modificar Recursos" #: platform/windows/export/export.cpp -#, fuzzy msgid "File Version" -msgstr "Versión" +msgstr "Versión del Archivo" #: platform/windows/export/export.cpp msgid "Product Version" @@ -20482,79 +20111,70 @@ msgid "Product Name" msgstr "Nombre del Producto" #: platform/windows/export/export.cpp -#, fuzzy msgid "File Description" -msgstr "Descripción" +msgstr "Descripción del Archivo" #: platform/windows/export/export.cpp msgid "Trademarks" msgstr "" #: platform/windows/export/export.cpp -#, fuzzy msgid "Resources Modification" -msgstr "Notificaciones Push" +msgstr "Modificación de los Recursos" #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find rcedit executable at \"%s\"." -msgstr "No se pudo encontrar la keystore, no se puedo exportar." +msgstr "No se pudo encontrar el ejecutable rcedit en \"%s\"." #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find wine executable at \"%s\"." -msgstr "No se pudo encontrar la keystore, no se puedo exportar." +msgstr "No se pudo encontrar el ejecutable de wine en \"%s\"." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" -"La herramienta rcedit debe configurarse en la configuración del editor " -"(Exportar > Windows > Rcedit) para cambiar los datos de información del " -"Ãcono o la aplicación." +"No se ha podido iniciar el ejecutable rcedit, configura la ruta de rcedit en " +"la configuración del editor (Exportar > Windows > Rcedit)." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Fallo al abrir el archivo ejecutable \"%s\"." #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find signtool executable at \"%s\"." -msgstr "No se pudo encontrar la keystore, no se puedo exportar." +msgstr "No se pudo encontrar el ejecutable de signtool en \"%s\"." #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find osslsigncode executable at \"%s\"." -msgstr "No se pudo encontrar la keystore, no se puedo exportar." +msgstr "No se pudo encontrar el ejecutable osslsigncode en \"%s\"." #: platform/windows/export/export.cpp msgid "Invalid identity type." msgstr "Tipo de identificador inválido." #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid timestamp server." -msgstr "Nombre inválido." +msgstr "Servidor de marcas de tiempo inválido." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" -"La herramienta rcedit debe configurarse en la configuración del editor " -"(Exportar > Windows > Rcedit) para cambiar los datos de información del " -"Ãcono o la aplicación." +"No se ha podido iniciar el ejecutable de signtool, configura la ruta de " +"signtool en la configuración del editor (Exportar > Windows > Signtool)." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Fallo al abrir el archivo ejecutable \"%s\"." #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -20586,9 +20206,8 @@ msgid "Windows executables cannot be >= 4 GiB." msgstr "" #: platform/windows/export/export.cpp platform/x11/export/export.cpp -#, fuzzy msgid "Failed to open executable file \"%s\"." -msgstr "Archivo ejecutable no válido." +msgstr "Fallo al abrir el archivo ejecutable \"%s\"." #: platform/windows/export/export.cpp platform/x11/export/export.cpp msgid "Executable file header corrupted." @@ -20599,9 +20218,8 @@ msgid "Executable \"pck\" section not found." msgstr "" #: platform/windows/export/export.cpp -#, fuzzy msgid "Windows" -msgstr "Nueva Ventana" +msgstr "Windows" #: platform/windows/export/export.cpp msgid "Rcedit" @@ -20621,9 +20239,8 @@ msgstr "" #: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Frames" -msgstr "Fotograma %" +msgstr "Fotogramas" #: scene/2d/animated_sprite.cpp msgid "" @@ -20635,21 +20252,18 @@ msgstr "" #: scene/2d/animated_sprite.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Speed Scale" -msgstr "Escala" +msgstr "Escala de Velocidad" #: scene/2d/animated_sprite.cpp scene/2d/audio_stream_player_2d.cpp #: scene/3d/audio_stream_player_3d.cpp scene/3d/sprite_3d.cpp #: scene/audio/audio_stream_player.cpp -#, fuzzy msgid "Playing" msgstr "Reproducir" #: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Centered" -msgstr "Centro" +msgstr "Centrado" #: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp @@ -20662,39 +20276,32 @@ msgid "Flip V" msgstr "" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Monitoring" -msgstr "Monitor" +msgstr "Monitorización" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Monitorable" -msgstr "Monitor" +msgstr "Monitorizable" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Physics Overrides" -msgstr "Anulaciones" +msgstr "Anulaciones de FÃsicas" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Space Override" -msgstr "Anulaciones" +msgstr "Anulación de Espacio" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Point" -msgstr "Generar puntos" +msgstr "Punto de Gravedad" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Distance Scale" -msgstr "WaitInstanceSignal" +msgstr "Escala de Distancia de la Gravedad" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Vec" -msgstr "Vista Previa Por Defecto" +msgstr "Velocidad de la Gravedad" #: scene/2d/area_2d.cpp scene/2d/cpu_particles_2d.cpp scene/3d/area.cpp #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp @@ -20702,42 +20309,36 @@ msgid "Gravity" msgstr "" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Linear Damp" -msgstr "Lineal" +msgstr "Amortiguación Lineal" #: scene/2d/area_2d.cpp scene/3d/area.cpp msgid "Angular Damp" msgstr "" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Audio Bus" -msgstr "Añadir Bus de Audio" +msgstr "Bus de Audio" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Override" -msgstr "Anulaciones" +msgstr "Anular" #: scene/2d/audio_stream_player_2d.cpp scene/audio/audio_stream_player.cpp #: scene/gui/video_player.cpp servers/audio/effects/audio_effect_amplify.cpp -#, fuzzy msgid "Volume dB" -msgstr "Volumen" +msgstr "Volumen dB" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp #: servers/audio/effects/audio_effect_pitch_shift.cpp -#, fuzzy msgid "Pitch Scale" -msgstr "Escala" +msgstr "Escala de Tono" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp -#, fuzzy msgid "Autoplay" -msgstr "Act./Desact. Reproducción Automática" +msgstr "Reproducción Automática" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp @@ -20752,29 +20353,25 @@ msgid "Max Distance" msgstr "Distancia Maxima" #: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Attenuation" -msgstr "Animación" +msgstr "Atenuación" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp -#, fuzzy msgid "Bus" -msgstr "Añadir Bus" +msgstr "Bus" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp msgid "Area Mask" msgstr "" #: scene/2d/back_buffer_copy.cpp -#, fuzzy msgid "Copy Mode" -msgstr "Copiar Nodos" +msgstr "Modo de Copia" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Anchor Mode" -msgstr "Modo de Icono" +msgstr "Modo de Anclaje" #: scene/2d/camera_2d.cpp msgid "Rotating" @@ -20786,83 +20383,70 @@ msgid "Current" msgstr "Actual" #: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom" -msgstr "Acercar Zoom" +msgstr "Zoom" #: scene/2d/camera_2d.cpp scene/main/canvas_layer.cpp -#, fuzzy msgid "Custom Viewport" -msgstr "1 Viewport" +msgstr "Viewport Personalizado" #: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp #: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp #: scene/animation/animation_tree_player.cpp scene/main/timer.cpp -#, fuzzy msgid "Process Mode" -msgstr "Modo de Movimiento" +msgstr "Modo de Proceso" #: scene/2d/camera_2d.cpp msgid "Limit" -msgstr "" +msgstr "Limite" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp -#, fuzzy msgid "Left" -msgstr "UI Izquierda" +msgstr "Izquierda" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp -#, fuzzy msgid "Right" -msgstr "Luz" +msgstr "Derecha" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/dynamic_font.cpp scene/resources/style_box.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Bottom" -msgstr "Inferior Izquierda" +msgstr "Inferior" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Smoothed" msgstr "Suavizado" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Margin" -msgstr "Asignar Margen" +msgstr "Margen de Arrastre" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Drag Margin H Enabled" -msgstr "Asignar Margen" +msgstr "Margen de Arrastre H Activado" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Drag Margin V Enabled" -msgstr "Asignar Margen" +msgstr "Margen de Arrastre V Activado" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Smoothing" -msgstr "Suavizado" +msgstr "Suavizar" #: scene/2d/camera_2d.cpp msgid "H" msgstr "" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "V" -msgstr "UV" +msgstr "V" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Drag Margin" -msgstr "Asignar Margen" +msgstr "Margen de Arrastre" #: scene/2d/camera_2d.cpp msgid "Draw Screen" @@ -20873,25 +20457,21 @@ msgid "Draw Limits" msgstr "LÃmites de Dibujo" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Drag Margin" -msgstr "Asignar Margen" +msgstr "Margen de Arrastre del Trazado" #: scene/2d/canvas_item.cpp scene/resources/environment.cpp #: scene/resources/material.cpp -#, fuzzy msgid "Blend Mode" -msgstr "Nodo Blend2" +msgstr "Modo de Fusión" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Light Mode" -msgstr "Ancho Derecha" +msgstr "Modo de Iluminación" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Particles Animation" -msgstr "PartÃculas" +msgstr "Animación de PartÃculas" #: scene/2d/canvas_item.cpp msgid "Particles Anim H Frames" @@ -20902,40 +20482,34 @@ msgid "Particles Anim V Frames" msgstr "" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Particles Anim Loop" -msgstr "PartÃculas" +msgstr "Bucle de Animación de PartÃculas" #: scene/2d/canvas_item.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Visibility" -msgstr "Cambiar Visibilidad" +msgstr "Visibilidad" #: scene/2d/canvas_item.cpp scene/3d/spatial.cpp scene/gui/progress_bar.cpp #: scene/gui/rich_text_effect.cpp scene/main/canvas_layer.cpp -#, fuzzy msgid "Visible" -msgstr "Cambiar Visibilidad" +msgstr "Visible" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Self Modulate" -msgstr "Rellenar" +msgstr "Modulación Automática" #: scene/2d/canvas_item.cpp msgid "Show Behind Parent" msgstr "" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Show On Top" -msgstr "Mostrar Origen" +msgstr "Mostrar Arriba" #: scene/2d/canvas_item.cpp scene/2d/light_occluder_2d.cpp #: scene/2d/tile_map.cpp -#, fuzzy msgid "Light Mask" -msgstr "Luz" +msgstr "Máscara de Luz" #: scene/2d/canvas_item.cpp msgid "Use Parent Material" @@ -20962,9 +20536,8 @@ msgstr "" "CollisionPolygon2D para definir su forma." #: scene/2d/collision_object_2d.cpp -#, fuzzy msgid "Pickable" -msgstr "Elegir Tile" +msgstr "Seleccionable" #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -20997,29 +20570,27 @@ msgstr "" msgid "" "The One Way Collision property will be ignored when the parent is an Area2D." msgstr "" +"La propiedad Colisión en Una Dirección será ignorada cuando el padre sea un " +"Area2D." #: scene/2d/collision_polygon_2d.cpp -#, fuzzy msgid "Build Mode" -msgstr "Modo de Regla" +msgstr "Modo de Compilación" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp #: scene/3d/collision_polygon.cpp scene/3d/collision_shape.cpp #: scene/animation/animation_node_state_machine.cpp scene/gui/base_button.cpp #: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Disabled" -msgstr "Desactivar Elemento" +msgstr "Desactivado" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp -#, fuzzy msgid "One Way Collision" -msgstr "Crear PolÃgono de Colisión" +msgstr "Colisión en Una Dirección" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp -#, fuzzy msgid "One Way Collision Margin" -msgstr "Crear PolÃgono de Colisión" +msgstr "Margen de Colisión en Una Dirección" #: scene/2d/collision_shape_2d.cpp msgid "" @@ -21068,15 +20639,13 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp -#, fuzzy msgid "One Shot" -msgstr "Nodo OneShot" +msgstr "Un Disparo" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Preprocess" -msgstr "Post procesado" +msgstr "Preproceso" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21095,9 +20664,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Fixed FPS" -msgstr "Ver FPS" +msgstr "FPS Fijos" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21111,9 +20679,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Local Coords" -msgstr "Proyectos Locales" +msgstr "Coordenadas Locales" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21122,9 +20689,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Emission Shape" -msgstr "Máscara de Emisión" +msgstr "Forma de la Emisión" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21132,26 +20698,22 @@ msgid "Sphere Radius" msgstr "Radio de la Esfera" #: scene/2d/cpu_particles_2d.cpp -#, fuzzy msgid "Rect Extents" -msgstr "Gizmos" +msgstr "Extender Completo" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp -#, fuzzy msgid "Normals" -msgstr "Formato" +msgstr "Normales" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Align Y" -msgstr "Asignar" +msgstr "Alineación Y" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Direction" -msgstr "Direcciones" +msgstr "Dirección" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21161,15 +20723,13 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Initial Velocity" -msgstr "Inicializar" +msgstr "Velocidad Inicial" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Velocity Random" -msgstr "Velocidad" +msgstr "Velocidad Aleatoria" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp @@ -21179,27 +20739,23 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Velocity Curve" -msgstr "Velocidad" +msgstr "Curva de Velocidad" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Orbit Velocity" -msgstr "Vista de Órbita Derecha" +msgstr "Velocidad de la Órbita" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Linear Accel" -msgstr "Lineal" +msgstr "Aceleración Lineal" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Accel" -msgstr "Acceso" +msgstr "Aceleración" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21208,9 +20764,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Accel Curve" -msgstr "Partir Curva" +msgstr "Curva de Aceleración" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21237,9 +20792,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Damping Curve" -msgstr "Partir Curva" +msgstr "Curva de Amortiguación" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp #: scene/resources/particles_material.cpp @@ -21253,9 +20807,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Angle Curve" -msgstr "Cerrar Curva" +msgstr "Curva de Ãngulo" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp msgid "Scale Amount" @@ -21266,15 +20819,13 @@ msgid "Scale Amount Random" msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp -#, fuzzy msgid "Scale Amount Curve" -msgstr "Escalar Desde Cursor" +msgstr "Curva de Cantidad de Escala" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Color Ramp" -msgstr "Colores" +msgstr "Rampa de Color" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21303,15 +20854,13 @@ msgstr "Curva de Variación" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Speed Random" -msgstr "Escala" +msgstr "Velocidad Aleatoria" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Speed Curve" -msgstr "Partir Curva" +msgstr "Curva de Velocidad" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21320,9 +20869,8 @@ msgstr "Desplazamiento Aleatorio" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Offset Curve" -msgstr "Cerrar Curva" +msgstr "Curva de Desplazamiento" #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be PhysicsBody2Ds" @@ -21345,14 +20893,12 @@ msgid "Node A and Node B must be different PhysicsBody2Ds" msgstr "El Nodo A y el Nodo B deben ser diferentes PhysicsBody2D" #: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Node A" -msgstr "Nodos" +msgstr "Nodo A" #: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Node B" -msgstr "Nodos" +msgstr "Nodo B" #: scene/2d/joints_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp @@ -21361,9 +20907,8 @@ msgid "Bias" msgstr "" #: scene/2d/joints_2d.cpp -#, fuzzy msgid "Disable Collision" -msgstr "Botón Desactivado" +msgstr "Desactivar Colisión" #: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Softness" @@ -21375,9 +20920,8 @@ msgid "Length" msgstr "" #: scene/2d/joints_2d.cpp -#, fuzzy msgid "Initial Offset" -msgstr "Inicializar" +msgstr "Desplazamiento Inicial" #: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp msgid "Rest Length" @@ -21396,14 +20940,12 @@ msgstr "" "Texture\"." #: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp -#, fuzzy msgid "Editor Only" -msgstr "Editor" +msgstr "Sólo para el Editor" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Texture Scale" -msgstr "Región de Textura" +msgstr "Escala de Textura" #: scene/2d/light_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/light.cpp scene/resources/environment.cpp @@ -21420,48 +20962,40 @@ msgid "Z Max" msgstr "" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Layer Min" -msgstr "Cambiar Tamaño de Cámara" +msgstr "Capa MÃnima" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Layer Max" -msgstr "Capa" +msgstr "Capa Máxima" #: scene/2d/light_2d.cpp msgid "Item Cull Mask" msgstr "" #: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Shadow" -msgstr "Shader" +msgstr "Sombra" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Buffer Size" -msgstr "Vista Trasera" +msgstr "Tamaño del Buffer" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Gradient Length" -msgstr "Degradado Editado" +msgstr "Longitud del Gradiente" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Filter Smooth" -msgstr "Filtrar métodos" +msgstr "Filtro Suavizado" #: scene/2d/light_occluder_2d.cpp -#, fuzzy msgid "Closed" -msgstr "Cerrar" +msgstr "Cerrado" #: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp -#, fuzzy msgid "Cull Mode" -msgstr "Modo de Regla" +msgstr "Modo de Sacrificio" #: scene/2d/light_occluder_2d.cpp msgid "" @@ -21477,47 +21011,40 @@ msgstr "" "polÃgono." #: scene/2d/line_2d.cpp -#, fuzzy msgid "Width Curve" -msgstr "Partir Curva" +msgstr "Curva de Ancho" #: scene/2d/line_2d.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Default Color" -msgstr "Por defecto" +msgstr "Color por Defecto" #: scene/2d/line_2d.cpp scene/resources/texture.cpp msgid "Fill" -msgstr "" +msgstr "Rellenar" #: scene/2d/line_2d.cpp scene/resources/texture.cpp -#, fuzzy msgid "Gradient" -msgstr "Degradado Editado" +msgstr "Gradiente" #: scene/2d/line_2d.cpp -#, fuzzy msgid "Texture Mode" -msgstr "Región de Textura" +msgstr "Modo de Textura" #: scene/2d/line_2d.cpp msgid "Capping" -msgstr "" +msgstr "Tapado" #: scene/2d/line_2d.cpp -#, fuzzy msgid "Joint Mode" -msgstr "Modo de Icono" +msgstr "Modo de Unión" #: scene/2d/line_2d.cpp -#, fuzzy msgid "Begin Cap Mode" -msgstr "Modo de Región" +msgstr "Iniciar Modo Cap" #: scene/2d/line_2d.cpp -#, fuzzy msgid "End Cap Mode" -msgstr "Modo de Ajuste:" +msgstr "Modo Tapón" #: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp msgid "Border" @@ -21533,14 +21060,12 @@ msgstr "" #: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp #: scene/resources/dynamic_font.cpp -#, fuzzy msgid "Antialiased" -msgstr "Inicializar" +msgstr "Suavizado Espacial" #: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp -#, fuzzy msgid "Multimesh" -msgstr "Multiplicar %s" +msgstr "Multimesh" #: scene/2d/navigation_2d.cpp scene/3d/baked_lightmap.cpp #: scene/3d/navigation.cpp scene/animation/root_motion_view.cpp @@ -21560,60 +21085,54 @@ msgid "" msgstr "" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Pathfinding" -msgstr "Vinculación" +msgstr "Pathfinding" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Path Desired Distance" -msgstr "Distancia de la Ruta U" +msgstr "Ruta Distancia Deseada" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Target Desired Distance" -msgstr "" +msgstr "Distancia Deseada del Objetivo" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Path Max Distance" -msgstr "Distancia Máxima de Ruta" +msgstr "Distancia Máxima de la Ruta" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance" -msgstr "Avanzado" +msgstr "Evasión" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance Enabled" -msgstr "Activar" +msgstr "Evasión Activada" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Neighbor Dist" -msgstr "" +msgstr "Dist. de Vecinos" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Max Neighbors" -msgstr "" +msgstr "Máximo de Vecinos" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Time Horizon" -msgstr "Voltear Horizontalmente" +msgstr "Horizonte del Tiempo" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Max Speed" msgstr "Velocidad Máxima" #: scene/2d/navigation_agent_2d.cpp -#, fuzzy msgid "" "The NavigationAgent2D can be used only under a Node2D inheriting parent node." -msgstr "El NavigationAgent2D sólo puede utilizarse bajo un nodo Node2D." +msgstr "" +"El NavigationAgent2D sólo puede utilizarse bajo un nodo padre hijo de Node2D." #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp -#, fuzzy msgid "Estimate Radius" -msgstr "Cambiar Radio Externo de Torus" +msgstr "Estimación del Radio" #: scene/2d/navigation_obstacle_2d.cpp msgid "" @@ -21628,32 +21147,29 @@ msgid "" "A NavigationPolygon resource must be set or created for this node to work. " "Please set a property or draw a polygon." msgstr "" -"Se debe crear o asignar un recurso NavigationPolygon a este nodo para que " -"funcione. Por favor, establece la propiedad o dibuja un polÃgono." +"Un recurso NavigationPolygon debe ser establecido o creado para que este " +"nodo funcione. Por favor, establece una propiedad o dibuja un polÃgono." #: scene/2d/navigation_polygon.cpp msgid "Navpoly" -msgstr "" +msgstr "Navpoly" #: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Enter Cost" -msgstr "Centro Inferior" +msgstr "Introduce Costo" #: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Travel Cost" -msgstr "Viaje" +msgstr "Costo del Viaje" #: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp #: scene/main/canvas_layer.cpp msgid "Rotation Degrees" msgstr "Grados de Rotación" -#: scene/2d/node_2d.cpp -#, fuzzy +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" -msgstr "Constante Global" +msgstr "Rotación Global" #: scene/2d/node_2d.cpp msgid "Global Rotation Degrees" @@ -21664,41 +21180,37 @@ msgid "Global Scale" msgstr "Escala Global" #: scene/2d/node_2d.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Global Transform" -msgstr "Mantener transformación global" +msgstr "Transformación Global" #: scene/2d/node_2d.cpp -#, fuzzy msgid "Z As Relative" -msgstr "Ajuste Relativo" +msgstr "Z Como Relativo" #: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Scroll" -msgstr "" +msgstr "Scroll" #: scene/2d/parallax_background.cpp msgid "Base Offset" msgstr "Desplazamiento Base" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Base Scale" -msgstr "Usar Ajuste de Escalado" +msgstr "Escala Base" #: scene/2d/parallax_background.cpp msgid "Limit Begin" -msgstr "" +msgstr "Inicio del LÃmite" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Limit End" -msgstr "Al Final" +msgstr "Fin del LÃmite" #: scene/2d/parallax_background.cpp msgid "Ignore Camera Zoom" -msgstr "" +msgstr "Ignorar Zoom de la Cámara" #: scene/2d/parallax_layer.cpp msgid "" @@ -21710,12 +21222,10 @@ msgstr "" #: scene/2d/parallax_layer.cpp scene/2d/physics_body_2d.cpp #: scene/3d/physics_body.cpp scene/3d/vehicle_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Motion" -msgstr "Acción" +msgstr "Movimiento" #: scene/2d/parallax_layer.cpp -#, fuzzy msgid "Mirroring" msgstr "Reflejar" @@ -21762,9 +21272,8 @@ msgstr "" "\"Particles Animation\" activado." #: scene/2d/particles_2d.cpp -#, fuzzy msgid "Visibility Rect" -msgstr "Modo de Prioridad" +msgstr "Visibilidad Rect" #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "Process Material" @@ -21772,9 +21281,8 @@ msgstr "" #: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Curve" -msgstr "Partir Curva" +msgstr "Curva" #: scene/2d/path_2d.cpp msgid "PathFollow2D only works when set as a child of a Path2D node." @@ -21802,25 +21310,21 @@ msgid "Lookahead" msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp -#, fuzzy msgid "Layers" -msgstr "Capa" +msgstr "Capas" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Constant Linear Velocity" -msgstr "Inicializar" +msgstr "Velocidad Lineal Constante" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Constant Angular Velocity" -msgstr "Inicializar" +msgstr "Velocidad Angular Constante" #: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp #: scene/resources/physics_material.cpp -#, fuzzy msgid "Friction" -msgstr "Función" +msgstr "Fricción" #: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp #: scene/resources/physics_material.cpp @@ -21833,9 +21337,8 @@ msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: scene/resources/world.cpp scene/resources/world_2d.cpp -#, fuzzy msgid "Default Gravity" -msgstr "Vista Previa Por Defecto" +msgstr "Gravedad por Defecto" #: scene/2d/physics_body_2d.cpp msgid "" @@ -21856,38 +21359,33 @@ msgid "Inertia" msgstr "Inercia" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Weight" -msgstr "Luz" +msgstr "Peso" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Gravity Scale" msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Custom Integrator" -msgstr "CustomNode" +msgstr "Integrador Personalizado" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Continuous CD" -msgstr "Continuo" +msgstr "CD Continuo" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Contacts Reported" msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Contact Monitor" -msgstr "Seleccionar Color" +msgstr "Monitor de Contacto" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Sleeping" -msgstr "Ajuste Inteligente" +msgstr "Resposo" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Can Sleep" @@ -21910,18 +21408,16 @@ msgid "Torque" msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Safe Margin" -msgstr "Asignar Margen" +msgstr "Margen de Seguridad" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Sync To Physics" msgstr "Sincronización Con La FÃsica" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Moving Platform" -msgstr "Moviendo salida" +msgstr "Plataforma Móvil" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Apply Velocity On Leave" @@ -21931,24 +21427,21 @@ msgstr "" #: scene/3d/physics_body.cpp scene/gui/texture_button.cpp #: scene/resources/default_theme/default_theme.cpp #: scene/resources/line_shape_2d.cpp scene/resources/material.cpp -#, fuzzy msgid "Normal" -msgstr "Formato" +msgstr "Normal" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Remainder" msgstr "Recordatorio" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Local Shape" -msgstr "Idioma" +msgstr "Forma Local" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider" -msgstr "Modo de Colisión" +msgstr "Colisionador" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp @@ -21957,26 +21450,22 @@ msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider RID" -msgstr "RID inválido" +msgstr "Colisionador RID" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider Shape" -msgstr "Modo de Colisión" +msgstr "Forma de Colisión" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Collider Shape Index" -msgstr "Modo de Colisión" +msgstr "Ãndice de Formas de Colisión" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider Velocity" -msgstr "Vista de Órbita Derecha" +msgstr "Velocidad del Colisionador" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Collider Metadata" @@ -21987,28 +21476,24 @@ msgid "Invert" msgstr "" #: scene/2d/polygon_2d.cpp -#, fuzzy msgid "Vertex Colors" -msgstr "Vértice" +msgstr "Color de los Vértices" #: scene/2d/polygon_2d.cpp -#, fuzzy msgid "Internal Vertex Count" -msgstr "Crear Vértice Interno" +msgstr "Conteo de Vértices Internos" #: scene/2d/position_2d.cpp -#, fuzzy msgid "Gizmo Extents" -msgstr "Gizmos" +msgstr "Extensión de Gizmos" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp msgid "Exclude Parent" msgstr "" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp -#, fuzzy msgid "Cast To" -msgstr "Crear Nodo Shader" +msgstr "Lanzar A" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp msgid "Collide With" @@ -22027,24 +21512,20 @@ msgid "Path property must point to a valid Node2D node to work." msgstr "La propiedad Path debe apuntar a un nodo Node2D válido para funcionar." #: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp -#, fuzzy msgid "Remote Path" -msgstr "Eliminar Punto" +msgstr "Ruta Remota" #: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp -#, fuzzy msgid "Use Global Coordinates" -msgstr "Siguiente Coordenada" +msgstr "Utilizar Coordenadas Globales" #: scene/2d/skeleton_2d.cpp scene/3d/skeleton.cpp -#, fuzzy msgid "Rest" -msgstr "Reiniciar" +msgstr "Reposo" #: scene/2d/skeleton_2d.cpp -#, fuzzy msgid "Default Length" -msgstr "Theme Predeterminado" +msgstr "Longitud por Defecto" #: scene/2d/skeleton_2d.cpp msgid "This Bone2D chain should end at a Skeleton2D node." @@ -22071,14 +21552,12 @@ msgid "Vframes" msgstr "" #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Frame Coords" -msgstr "Fotograma %" +msgstr "Coordenadas del Marco" #: scene/2d/sprite.cpp scene/resources/texture.cpp -#, fuzzy msgid "Filter Clip" -msgstr "Filtrar scripts" +msgstr "Filtrar Clips" #: scene/2d/tile_map.cpp msgid "" @@ -22091,44 +21570,36 @@ msgstr "" "RigidBody2D, KinematicBody2D, etc. para que puedan tener forma." #: scene/2d/tile_map.cpp -#, fuzzy msgid "Tile Set" -msgstr "TileSet" +msgstr "Tile Set" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Quadrant Size" -msgstr "Cambiar Tamaño de Cámara" +msgstr "Tamaño del Cuadrante" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Custom Transform" -msgstr "Transformar" +msgstr "Transformación Personalizada" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Half Offset" -msgstr "Inicializar" +msgstr "Medio Desplazamiento" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Tile Origin" -msgstr "Ver Origen" +msgstr "Origen de los Tiles" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Y Sort" -msgstr "Ordenar" +msgstr "Ordenar Y" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Show Collision" -msgstr "Colisión" +msgstr "Mostrar Colisión" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Compatibility Mode" -msgstr "Modo de Prioridad" +msgstr "Modo de Compatibilidad" #: scene/2d/tile_map.cpp msgid "Centered Textures" @@ -22139,32 +21610,28 @@ msgid "Cell Clip UV" msgstr "" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Use Parent" -msgstr "Modo de Colisión" +msgstr "Usar Padres" #: scene/2d/tile_map.cpp msgid "Use Kinematic" msgstr "" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Shape Centered" -msgstr "Ajustar al Centro del Nodo" +msgstr "Forma Centrada" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Shape Visible" -msgstr "Act./Desact. Visible" +msgstr "Forma Visible" #: scene/2d/touch_screen_button.cpp msgid "Passby Press" msgstr "" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Visibility Mode" -msgstr "Modo de Prioridad" +msgstr "Modo de Visibilidad" #: scene/2d/visibility_notifier_2d.cpp msgid "" @@ -22175,28 +21642,24 @@ msgstr "" "editada directamente como padre." #: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp -#, fuzzy msgid "Pause Animations" -msgstr "Pegar Animación" +msgstr "Pausar Animaciones" #: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp msgid "Freeze Bodies" msgstr "" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Pause Particles" -msgstr "PartÃculas" +msgstr "Pausar PartÃculas" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Pause Animated Sprites" -msgstr "Pegar Animación" +msgstr "Pausar Sprites Animados" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Process Parent" -msgstr "Activar Prioridad" +msgstr "Procesamiento de los Padres" #: scene/2d/visibility_notifier_2d.cpp msgid "Physics Process Parent" @@ -22207,9 +21670,8 @@ msgid "Reverb Bus" msgstr "" #: scene/3d/area.cpp -#, fuzzy msgid "Uniformity" -msgstr "Establecer Nombre de Uniform" +msgstr "Uniformidad" #: scene/3d/arvr_nodes.cpp msgid "ARVRCamera must have an ARVROrigin node as its parent." @@ -22236,9 +21698,8 @@ msgstr "" "un controlador real." #: scene/3d/arvr_nodes.cpp -#, fuzzy msgid "Anchor ID" -msgstr "Sólo anclado" +msgstr "ID de Ancla" #: scene/3d/arvr_nodes.cpp msgid "ARVRAnchor must have an ARVROrigin node as its parent." @@ -22261,9 +21722,8 @@ msgid "World Scale" msgstr "Escala del Mundo" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Attenuation Model" -msgstr "Nodo de Animación" +msgstr "Modelo de Atenuación" #: scene/3d/audio_stream_player_3d.cpp msgid "Unit dB" @@ -22282,18 +21742,16 @@ msgid "Out Of Range Mode" msgstr "" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Emission Angle" -msgstr "Colores de Emisión" +msgstr "Ãngulo de Emisión" #: scene/3d/audio_stream_player_3d.cpp msgid "Degrees" msgstr "Grados" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Filter Attenuation dB" -msgstr "Animación" +msgstr "Filtro de Atenuación dB" #: scene/3d/audio_stream_player_3d.cpp msgid "Attenuation Filter" @@ -22307,19 +21765,16 @@ msgstr "" #: scene/3d/audio_stream_player_3d.cpp #: servers/audio/effects/audio_effect_filter.cpp -#, fuzzy msgid "dB" -msgstr "B" +msgstr "dB" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Doppler" -msgstr "Activar Doppler" +msgstr "Doppler" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Tracking" -msgstr "Empaquetando" +msgstr "Seguimiento" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/reflection_probe.cpp @@ -22353,9 +21808,8 @@ msgstr "Hecho" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/reflection_probe.cpp scene/resources/box_shape.cpp #: scene/resources/rectangle_shape_2d.cpp -#, fuzzy msgid "Extents" -msgstr "Gizmos" +msgstr "Extensiones" #: scene/3d/baked_lightmap.cpp msgid "Tweaks" @@ -22378,66 +21832,56 @@ msgid "Use HDR" msgstr "" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Use Color" -msgstr "Colores" +msgstr "Usar Color" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Default Texels Per Unit" -msgstr "Theme Predeterminado" +msgstr "Texeles Por Unidad Predeterminados" #: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp -#, fuzzy msgid "Atlas" -msgstr "Nuevo Atlas" +msgstr "Atlas" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Generate" -msgstr "General" +msgstr "Generar" #: scene/3d/baked_lightmap.cpp msgid "Max Size" msgstr "Tamaño Máximo" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Sky" -msgstr "CustomNode" +msgstr "Cielo Personalizado" #: scene/3d/baked_lightmap.cpp msgid "Custom Sky Rotation Degrees" msgstr "Grados de Rotación del Cielo Personalizados" #: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp -#, fuzzy msgid "Custom Color" -msgstr "CustomNode" +msgstr "Color Personalizado" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Energy" -msgstr "Mover Efecto de Bus" +msgstr "EnergÃa Personalizada" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Min Light" -msgstr "Indentar a la Derecha" +msgstr "Luz MÃnima" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp -#, fuzzy msgid "Propagation" -msgstr "Navegación" +msgstr "Propagación" #: scene/3d/baked_lightmap.cpp msgid "Image Path" msgstr "" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Light Data" -msgstr "Con Datos" +msgstr "Datos de Iluminación" #: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp msgid "Bone Name" @@ -22452,14 +21896,12 @@ msgid "Cull Mask" msgstr "" #: scene/3d/camera.cpp -#, fuzzy msgid "Doppler Tracking" -msgstr "Pista de Propiedades" +msgstr "Seguimiento de Doppler" #: scene/3d/camera.cpp -#, fuzzy msgid "Projection" -msgstr "Proyecto" +msgstr "Proyección" #: scene/3d/camera.cpp msgid "FOV" @@ -22470,9 +21912,8 @@ msgid "Frustum Offset" msgstr "Offset de Frustum" #: scene/3d/camera.cpp -#, fuzzy msgid "Near" -msgstr "Más Cercano" +msgstr "Cercano" #: scene/3d/camera.cpp msgid "Far" @@ -22483,23 +21924,20 @@ msgstr "" #: scene/resources/shape.cpp scene/resources/style_box.cpp #: scene/resources/texture.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp -#, fuzzy msgid "Margin" -msgstr "Asignar Margen" +msgstr "Margen" #: scene/3d/camera.cpp -#, fuzzy msgid "Clip To" -msgstr "Clip Arriba" +msgstr "Recortar A" #: scene/3d/collision_object.cpp scene/3d/soft_body.cpp msgid "Ray Pickable" msgstr "" #: scene/3d/collision_object.cpp -#, fuzzy msgid "Capture On Drag" -msgstr "Captura" +msgstr "Captura Al Arrastrar" #: scene/3d/collision_object.cpp msgid "" @@ -22571,53 +22009,44 @@ msgstr "" "Billboard esté ajustado a \"Particle Billboard\"." #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Box Extents" -msgstr "Gizmos" +msgstr "Extensión de Cajas" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Radius" -msgstr "Máscara de Emisión" +msgstr "Radio del Anillo" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Inner Radius" -msgstr "Cambiar Radio Interno de Torus" +msgstr "Radio Interior del Anillo" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Height" -msgstr "Rotar a la Derecha" +msgstr "Altura del Anillo" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Axis" -msgstr "Advertencias" +msgstr "Eje del Anillo" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Rotate Y" -msgstr "Rotar" +msgstr "Rotar Y" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Disable Z" -msgstr "Desactivar Elemento" +msgstr "Desactivar Z" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp msgid "Flatness" msgstr "" #: scene/3d/cull_instance.cpp servers/visual_server.cpp -#, fuzzy msgid "Portals" -msgstr "Voltear Portales" +msgstr "Portales" #: scene/3d/cull_instance.cpp -#, fuzzy msgid "Portal Mode" -msgstr "Modo de Prioridad" +msgstr "Modo Portal" #: scene/3d/cull_instance.cpp msgid "Include In Bound" @@ -22628,9 +22057,8 @@ msgid "Allow Merging" msgstr "" #: scene/3d/cull_instance.cpp -#, fuzzy msgid "Autoplace Priority" -msgstr "Activar Prioridad" +msgstr "Prioridad de Autoemplazamiento" #: scene/3d/gi_probe.cpp msgid "Plotting Meshes" @@ -22663,9 +22091,8 @@ msgid "Subdiv" msgstr "" #: scene/3d/gi_probe.cpp -#, fuzzy msgid "Dynamic Range" -msgstr "LibrerÃa Dinámica" +msgstr "Rango Dinámico" #: scene/3d/gi_probe.cpp scene/3d/light.cpp msgid "Normal Bias" @@ -22673,18 +22100,16 @@ msgstr "" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp #: scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Pixel Size" -msgstr "Ajuste de PÃxeles" +msgstr "Tamaño de PÃxeles" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Billboard" msgstr "" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Shaded" -msgstr "Shader" +msgstr "Sombreado" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Double Sided" @@ -22695,9 +22120,8 @@ msgid "No Depth Test" msgstr "" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp -#, fuzzy msgid "Fixed Size" -msgstr "Vista Frontal" +msgstr "Tamaño Fijo" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Alpha Cut" @@ -22708,119 +22132,98 @@ msgid "Alpha Scissor Threshold" msgstr "" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp -#, fuzzy msgid "Render Priority" -msgstr "Activar Prioridad" +msgstr "Prioridad de Renderización" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Outline Render Priority" -msgstr "Activar Prioridad" +msgstr "Prioridad de Renderización del Contorno" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Outline Modulate" -msgstr "Forzar Modulación en Blanco" +msgstr "Modular Contorno" #: scene/3d/label_3d.cpp scene/resources/default_theme/default_theme.cpp #: scene/resources/dynamic_font.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Font" -msgstr "Fuentes" +msgstr "Fuente" #: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Horizontal Alignment" -msgstr "Horizontal Activado" +msgstr "Alineación Horizontal" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Vertical Alignment" -msgstr "Filtrar señales" +msgstr "Alineación Vertical" #: scene/3d/label_3d.cpp scene/gui/dialogs.cpp scene/gui/label.cpp -#, fuzzy msgid "Autowrap" -msgstr "AutoLoad" +msgstr "Envoltura Automática" #: scene/3d/light.cpp -#, fuzzy msgid "Indirect Energy" -msgstr "Colores de Emisión" +msgstr "EnergÃa Indirecta" #: scene/3d/light.cpp -#, fuzzy msgid "Negative" -msgstr "GDNative" +msgstr "Negativo" #: scene/3d/light.cpp scene/resources/material.cpp #: scene/resources/visual_shader.cpp -#, fuzzy msgid "Specular" -msgstr "Modo de Regla" +msgstr "Especular" #: scene/3d/light.cpp -#, fuzzy msgid "Bake Mode" -msgstr "Modo de Bitmask" +msgstr "Modo de Bakeo" #: scene/3d/light.cpp -#, fuzzy msgid "Contact" -msgstr "Seleccionar Color" +msgstr "Contacto" #: scene/3d/light.cpp -#, fuzzy msgid "Reverse Cull Face" -msgstr "Restablecer Volumen de Bus" +msgstr "Eliminar Caras Invertidas" #: scene/3d/light.cpp servers/visual_server.cpp -#, fuzzy msgid "Directional Shadow" -msgstr "Direcciones" +msgstr "Sombra Direccional" #: scene/3d/light.cpp -#, fuzzy msgid "Split 1" -msgstr "Dividir" +msgstr "Dividir 1" #: scene/3d/light.cpp -#, fuzzy msgid "Split 2" -msgstr "Dividir" +msgstr "Dividir 2" #: scene/3d/light.cpp -#, fuzzy msgid "Split 3" -msgstr "Dividir" +msgstr "Dividir 3" #: scene/3d/light.cpp msgid "Blend Splits" msgstr "Mezclar Divisiones" #: scene/3d/light.cpp -#, fuzzy msgid "Bias Split Scale" -msgstr "Usar Ajuste de Escalado" +msgstr "Escala de División del Sesgo" #: scene/3d/light.cpp -#, fuzzy msgid "Depth Range" -msgstr "Profundidad" +msgstr "Rango de Profundidad" #: scene/3d/light.cpp msgid "Omni" msgstr "" #: scene/3d/light.cpp -#, fuzzy msgid "Shadow Mode" -msgstr "Shader" +msgstr "Modo de Sombreado" #: scene/3d/light.cpp -#, fuzzy msgid "Shadow Detail" -msgstr "Mostrar Por Defecto" +msgstr "Detalle de la Sombra" #: scene/3d/light.cpp msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows." @@ -22832,9 +22235,8 @@ msgid "Spot" msgstr "" #: scene/3d/light.cpp -#, fuzzy msgid "Angle Attenuation" -msgstr "Animación" +msgstr "Atenuación del Ãngulo" #: scene/3d/mesh_instance.cpp msgid "Software Skinning" @@ -22852,43 +22254,38 @@ msgid "" msgstr "" #: scene/3d/navigation.cpp scene/resources/curve.cpp -#, fuzzy msgid "Up Vector" -msgstr "Vector" +msgstr "Vector Superior" #: scene/3d/navigation.cpp -#, fuzzy msgid "Cell Height" -msgstr "Prueba" +msgstr "Altura de la Celda" #: scene/3d/navigation_agent.cpp msgid "Agent Height Offset" msgstr "" #: scene/3d/navigation_agent.cpp -#, fuzzy msgid "Ignore Y" -msgstr "[Ignorar]" +msgstr "Ignorar Y" #: scene/3d/navigation_agent.cpp -#, fuzzy msgid "" "The NavigationAgent can be used only under a Spatial inheriting parent node." -msgstr "El NavigationAgent sólo puede utilizarse bajo un nodo spatial." +msgstr "" +"El NavigationAgent solo puede utilizarse en un nodo padre de tipo Spatial." #: scene/3d/navigation_mesh_instance.cpp scene/resources/mesh_library.cpp -#, fuzzy msgid "NavMesh" -msgstr "Calcular NavMesh" +msgstr "NavMesh" #: scene/3d/navigation_obstacle.cpp -#, fuzzy msgid "" "The NavigationObstacle only serves to provide collision avoidance to a " "Spatial inheriting parent object." msgstr "" -"El NavigationObstacle sólo sirve para evitar la colisión de un objeto " -"spatial." +"El NavigationObstacle solo sirve para evitar colisiones en un objeto padre " +"de tipo Spatial." #: scene/3d/occluder.cpp msgid "No shape is set." @@ -22939,9 +22336,8 @@ msgstr "" "Billboard esté ajustado a \"Particle Billboard\"." #: scene/3d/particles.cpp -#, fuzzy msgid "Visibility AABB" -msgstr "Cambiar Visibilidad" +msgstr "Visibilidad AABB" #: scene/3d/particles.cpp msgid "Draw Passes" @@ -22965,7 +22361,6 @@ msgstr "" "el recurso Curve de su Path padre." #: scene/3d/path.cpp -#, fuzzy msgid "Rotation Mode" msgstr "Modo de Rotación" @@ -22980,65 +22375,56 @@ msgstr "" "En su lugar, cambia el tamaño en las formas de colisión de los hijos." #: scene/3d/physics_body.cpp -#, fuzzy msgid "Axis Lock" -msgstr "Eje" +msgstr "Bloquear Ejes" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear X" -msgstr "Lineal" +msgstr "Lineal X" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Y" -msgstr "Lineal" +msgstr "Lineal Y" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Z" -msgstr "Lineal" +msgstr "Lineal Z" #: scene/3d/physics_body.cpp msgid "Angular X" -msgstr "" +msgstr "Angular X" #: scene/3d/physics_body.cpp msgid "Angular Y" -msgstr "" +msgstr "Angular Y" #: scene/3d/physics_body.cpp msgid "Angular Z" -msgstr "" +msgstr "Angular Z" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion X" -msgstr "Acción" +msgstr "Movimiento X" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion Y" -msgstr "Acción" +msgstr "Movimiento Y" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion Z" -msgstr "Acción" +msgstr "Movimiento Z" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Joint Constraints" -msgstr "Constantes" +msgstr "Restringir Articulaciones" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Impulse Clamp" msgstr "" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Swing Span" -msgstr "Guardar Escena" +msgstr "Expansión de Swing" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Twist Span" @@ -23050,147 +22436,124 @@ msgid "Relaxation" msgstr "Relajación" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Enabled" -msgstr "Filtrar señales" +msgstr "LÃmite Angular Activado" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Upper" -msgstr "Lineal" +msgstr "LÃmite Angular Superior" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Lower" -msgstr "Ortogonal Angular" +msgstr "LÃmite Angular Inferior" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Bias" -msgstr "Lineal" +msgstr "Sesgo de LÃmite Angular" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Softness" -msgstr "Animación" +msgstr "LÃmite Angular de Suavizado" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Relaxation" -msgstr "Animación" +msgstr "Relajación del LÃmite Angular" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Upper" -msgstr "Lineal" +msgstr "LÃmite Lineal Superior" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Lower" -msgstr "Lineal" +msgstr "LÃmite Lineal Inferior" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Softness" -msgstr "Lineal" +msgstr "LÃmite Lineal de Suavizado" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Restitution" -msgstr "Lineal" +msgstr "Restitución del LÃmite Lineal" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Damping" -msgstr "Lineal" +msgstr "Amortiguación de LÃmite Lineal" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Restitution" -msgstr "Animación" +msgstr "Restitución del LÃmite Angular" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Damping" -msgstr "Animación" +msgstr "Amortiguación de LÃmite Angular" #: scene/3d/physics_body.cpp msgid "X" -msgstr "" +msgstr "X" #: scene/3d/physics_body.cpp msgid "Y" -msgstr "" +msgstr "Y" #: scene/3d/physics_body.cpp msgid "Z" -msgstr "" +msgstr "Z" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Enabled" -msgstr "Lineal" +msgstr "LÃmite Lineal Activado" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Enabled" -msgstr "Lineal" +msgstr "Amortiguador Lineal Activado" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Stiffness" -msgstr "Lineal" +msgstr "Rigidez Lineal del Amortiguador" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Damping" -msgstr "Lineal" +msgstr "Atenuación Lineal del Amortiguador" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Equilibrium Point" -msgstr "Lineal" +msgstr "Punto de Equilibrio Lineal" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Restitution" -msgstr "Descripción" +msgstr "Restitución Lineal" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Damping" -msgstr "Lineal" +msgstr "Amortiguación Lineal" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Restitution" -msgstr "Descripción" +msgstr "Restitución Angular" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Damping" -msgstr "Animación" +msgstr "Amortiguación Angular" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "ERP" -msgstr "" +msgstr "ERP" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Spring Enabled" -msgstr "Filtrar señales" +msgstr "Amortiguación Angular Activada" #: scene/3d/physics_body.cpp msgid "Angular Spring Stiffness" -msgstr "" +msgstr "Rigidez del Amortiguador Angular" #: scene/3d/physics_body.cpp msgid "Angular Spring Damping" -msgstr "" +msgstr "Amortiguación Angular del Muelle" #: scene/3d/physics_body.cpp msgid "Angular Equilibrium Point" -msgstr "" +msgstr "Punto de Equilibrio Angular" #: scene/3d/physics_body.cpp msgid "Body Offset" @@ -23221,9 +22584,8 @@ msgid "Solver" msgstr "" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Exclude Nodes" -msgstr "Eliminar Nodos" +msgstr "Excluir Nodos" #: scene/3d/physics_joint.cpp msgid "Params" @@ -23234,32 +22596,28 @@ msgid "Angular Limit" msgstr "" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper" -msgstr "Mayúsculas" +msgstr "Superior" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower" -msgstr "Minúsculas" +msgstr "Inferior" #: scene/3d/physics_joint.cpp msgid "Motor" -msgstr "" +msgstr "Motor" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Target Velocity" -msgstr "Vista de Órbita Derecha" +msgstr "Velocidad del Objetivo" #: scene/3d/physics_joint.cpp msgid "Max Impulse" msgstr "Impulso Máximo" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit" -msgstr "Lineal" +msgstr "LÃmite Lineal" #: scene/3d/physics_joint.cpp msgid "Upper Distance" @@ -23270,57 +22628,48 @@ msgid "Lower Distance" msgstr "Distancia Inferior" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Restitution" -msgstr "Descripción" +msgstr "Restitución" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motion" -msgstr "Inicializar" +msgstr "Movimiento Lineal" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Ortho" -msgstr "Ortogonal Trasera" +msgstr "Ortogonal Lineal" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper Angle" -msgstr "Mayúsculas" +msgstr "Ãngulo Superior" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower Angle" -msgstr "Minúsculas" +msgstr "Ãngulo Inferior" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Angular Motion" -msgstr "Animación" +msgstr "Movimiento Angular" #: scene/3d/physics_joint.cpp msgid "Angular Ortho" msgstr "Ortogonal Angular" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit X" -msgstr "Lineal" +msgstr "LÃmite Lineal X" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor X" -msgstr "Inicializar" +msgstr "Motor Lineal X" #: scene/3d/physics_joint.cpp msgid "Force Limit" msgstr "Forzar LÃmite" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring X" -msgstr "Lineal" +msgstr "Amortiguación Lineal X" #: scene/3d/physics_joint.cpp msgid "Equilibrium Point" @@ -23336,22 +22685,19 @@ msgstr "" #: scene/3d/physics_joint.cpp msgid "Angular Spring X" -msgstr "" +msgstr "Amortiguación Angular X" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit Y" -msgstr "Lineal" +msgstr "LÃmite Lineal Y" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor Y" -msgstr "Inicializar" +msgstr "Motor Lineal Y" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring Y" -msgstr "Lineal" +msgstr "Amortiguación Lineal Y" #: scene/3d/physics_joint.cpp msgid "Angular Limit Y" @@ -23363,22 +22709,19 @@ msgstr "" #: scene/3d/physics_joint.cpp msgid "Angular Spring Y" -msgstr "" +msgstr "Amortiguación Angular Y" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit Z" -msgstr "Lineal" +msgstr "LÃmite Lineal Z" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor Z" -msgstr "Inicializar" +msgstr "Motor Lineal Z" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring Z" -msgstr "Lineal" +msgstr "Amortiguación Lineal Z" #: scene/3d/physics_joint.cpp msgid "Angular Limit Z" @@ -23390,7 +22733,7 @@ msgstr "" #: scene/3d/physics_joint.cpp msgid "Angular Spring Z" -msgstr "" +msgstr "Amortiguación Angular Z" #: scene/3d/portal.cpp msgid "The RoomManager should not be a child or grandchild of a Portal." @@ -23417,14 +22760,12 @@ msgid "Linked Room" msgstr "Sala Vinculada" #: scene/3d/portal.cpp -#, fuzzy msgid "Use Default Margin" -msgstr "Por defecto" +msgstr "Usar Margen por Defecto" #: scene/3d/proximity_group.cpp -#, fuzzy msgid "Group Name" -msgstr "Agrupado" +msgstr "Nombre del Grupo" #: scene/3d/proximity_group.cpp msgid "Dispatch Mode" @@ -23435,47 +22776,40 @@ msgid "Grid Radius" msgstr "Radio de CuadrÃcula" #: scene/3d/ray_cast.cpp -#, fuzzy msgid "Debug Shape" -msgstr "Depurador" +msgstr "Depurar Shape" #: scene/3d/ray_cast.cpp scene/resources/style_box.cpp msgid "Thickness" msgstr "" #: scene/3d/reflection_probe.cpp scene/main/viewport.cpp -#, fuzzy msgid "Update Mode" -msgstr "Modo de Rotación" +msgstr "Modo de Actualización" #: scene/3d/reflection_probe.cpp msgid "Origin Offset" msgstr "Desplazamiento de Origen" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Box Projection" -msgstr "Proyecto" +msgstr "Proyección de Cajas" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Enable Shadows" -msgstr "Activar Ajuste" +msgstr "Activar Sombras" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Ambient Color" -msgstr "Seleccionar Color" +msgstr "Color de Ambiente" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Ambient Energy" -msgstr "Colores de Emisión" +msgstr "EnergÃa Ambiental" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Ambient Contrib" -msgstr "Indentar a la Derecha" +msgstr "Contribución Ambiental" #: scene/3d/remote_transform.cpp msgid "" @@ -23519,9 +22853,8 @@ msgid "Bound" msgstr "" #: scene/3d/room_group.cpp -#, fuzzy msgid "Roomgroup Priority" -msgstr "Prioridad" +msgstr "Prioridad del Roomgroup" #: scene/3d/room_group.cpp msgid "The RoomManager should not be placed inside a RoomGroup." @@ -23555,80 +22888,68 @@ msgstr "" #: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp #: scene/animation/animation_tree_player.cpp #: servers/audio/effects/audio_effect_delay.cpp -#, fuzzy msgid "Active" -msgstr "Acción" +msgstr "Activo" #: scene/3d/room_manager.cpp msgid "Roomlist" msgstr "" #: scene/3d/room_manager.cpp servers/visual_server.cpp -#, fuzzy msgid "PVS" -msgstr "FPS" +msgstr "PVS" #: scene/3d/room_manager.cpp -#, fuzzy msgid "PVS Mode" -msgstr "Modo desplazamiento lateral" +msgstr "Modo PVS" #: scene/3d/room_manager.cpp -#, fuzzy msgid "PVS Filename" -msgstr "Archivo ZIP" +msgstr "Nombre del Archivo PVS" #: scene/3d/room_manager.cpp servers/visual_server.cpp msgid "Gameplay" msgstr "" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Gameplay Monitor" -msgstr "Monitor" +msgstr "Monitor de Juego" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Use Secondary PVS" -msgstr "Usar Ajuste de Escalado" +msgstr "Usar PVS Secundario" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Merge Meshes" -msgstr "Malla" +msgstr "Fusionar Mallas" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Show Margins" -msgstr "Mostrar Origen" +msgstr "Mostrar Márgenes" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Debug Sprawl" -msgstr "Depurar" +msgstr "Depurar Extensión" #: scene/3d/room_manager.cpp msgid "Overlap Warning Threshold" msgstr "" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Preview Camera" -msgstr "Vista Previa" +msgstr "Vista previa de la Cámara" #: scene/3d/room_manager.cpp msgid "Portal Depth Limit" msgstr "" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Default Portal Margin" -msgstr "Asignar Margen" +msgstr "Margen del Portal por Defecto" #: scene/3d/room_manager.cpp -#, fuzzy msgid "Roaming Expansion Margin" -msgstr "Expandir Todo" +msgstr "Margen de Expansión del Roaming" #: scene/3d/room_manager.cpp msgid "" @@ -23681,43 +23002,36 @@ msgstr "" "Asegúrate de que todas las rooms contienen geometrÃa o lÃmites manuales." #: scene/3d/skeleton.cpp scene/resources/skin.cpp -#, fuzzy msgid "Pose" -msgstr "Copiar Pose" +msgstr "Pose" #: scene/3d/skeleton.cpp -#, fuzzy msgid "Bound Children" -msgstr "Hijos Editables" +msgstr "Hijos Vinculados" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Pinned Points" -msgstr "Fijado %s" +msgstr "Puntos de Anclaje" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Attachments" -msgstr "Gizmos" +msgstr "Adjuntos" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Point Index" -msgstr "Obtener Ãndice" +msgstr "Ãndice de Puntos" #: scene/3d/soft_body.cpp msgid "Spatial Attachment Path" msgstr "" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Physics Enabled" -msgstr "Fotogramas de FÃsica %" +msgstr "FÃsica Activada" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Parent Collision Ignore" -msgstr "Crear PolÃgono de Colisión" +msgstr "Ignorar Colisión de los Padres" #: scene/3d/soft_body.cpp msgid "Simulation Precision" @@ -23770,31 +23084,32 @@ msgstr "" "En su lugar, cambia el tamaño en las formas de colisión de los hijos." #: scene/3d/spatial.cpp +msgid "Global Translation" +msgstr "Transformación Global" + +#: scene/3d/spatial.cpp msgid "Matrix" -msgstr "" +msgstr "Matriz" #: scene/3d/spatial.cpp -#, fuzzy msgid "Gizmo" -msgstr "Gizmos" +msgstr "Gizmo" #: scene/3d/spatial_velocity_tracker.cpp -#, fuzzy msgid "Track Physics Step" -msgstr "Fotogramas de FÃsica %" +msgstr "Paso de FÃsica de Pistas" #: scene/3d/spring_arm.cpp msgid "Spring Length" -msgstr "" +msgstr "Cantidad de Amortiguación" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp msgid "Opacity" msgstr "" #: scene/3d/sprite_3d.cpp scene/resources/material.cpp -#, fuzzy msgid "Transparent" -msgstr "Transponer" +msgstr "Transparente" #: scene/3d/sprite_3d.cpp msgid "" @@ -23813,14 +23128,12 @@ msgstr "" "Por favor, úselo como hijo de un VehicleBody." #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Per-Wheel Motion" -msgstr "Botón Bajar la Rueda" +msgstr "Movimiento por Rueda" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Engine Force" -msgstr "Documentación Online" +msgstr "Fuerza del Motor" #: scene/3d/vehicle_body.cpp msgid "Brake" @@ -23851,19 +23164,16 @@ msgid "Roll Influence" msgstr "" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Friction Slip" -msgstr "Función" +msgstr "Deslizamiento por Fricción" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Suspension" -msgstr "Expresión" +msgstr "Suspensión" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Max Force" -msgstr "Error" +msgstr "Fuerza Máxima" #: scene/3d/visibility_notifier.cpp msgid "AABB" @@ -23890,14 +23200,12 @@ msgid "Extra Cull Margin" msgstr "Margen de Sacrificio Extra" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Baked Light" -msgstr "Calcular Lightmaps" +msgstr "Bakear Luces" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Generate Lightmap" -msgstr "Generando Lightmaps" +msgstr "Generar Lightmap" #: scene/3d/visual_instance.cpp msgid "Lightmap Scale" @@ -23953,9 +23261,8 @@ msgid "Animation not found: '%s'" msgstr "No se encontró la animación: '%s'" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Mix Mode" -msgstr "Nodo Mix" +msgstr "Modo Mix" #: scene/animation/animation_blend_tree.cpp msgid "Fadein Time" @@ -23982,24 +23289,20 @@ msgid "Random Delay" msgstr "Retraso Aleatorio" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Add Amount" -msgstr "Cantidad" +msgstr "Añadir Cantidad" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Blend Amount" -msgstr "Cantidad de Escala" +msgstr "Cantidad de Mezcla" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Seek Position" -msgstr "Establecer Posición de Entrada de Curva" +msgstr "Buscar Posición" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Input Count" -msgstr "Añadir Puerto de Entrada" +msgstr "Conteo de Entradas" #: scene/animation/animation_blend_tree.cpp #: scene/animation/animation_node_state_machine.cpp @@ -24007,56 +23310,48 @@ msgid "Xfade Time" msgstr "Tiempo de Fundido Cruzado" #: scene/animation/animation_node_state_machine.cpp -#, fuzzy msgid "Switch Mode" -msgstr "Cambiar" +msgstr "Modo de Conmutación" #: scene/animation/animation_node_state_machine.cpp -#, fuzzy msgid "Auto Advance" -msgstr "Establecer avance automático" +msgstr "Auto Avance" #: scene/animation/animation_node_state_machine.cpp -#, fuzzy msgid "Advance Condition" -msgstr "Opciones Avanzadas" +msgstr "Condición de Avance" #: scene/animation/animation_player.cpp msgid "Anim Apply Reset" msgstr "Aplicar Reset de la Animación" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Current Animation" -msgstr "Establecer Animación" +msgstr "Animación Actual" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Assigned Animation" -msgstr "Añadir Animación" +msgstr "Animación Asignada" #: scene/animation/animation_player.cpp msgid "Reset On Save" msgstr "" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Current Animation Length" -msgstr "Cambiar Duración de la Animación" +msgstr "Duración Actual de la Animación" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Current Animation Position" -msgstr "Añadir Punto de Animación" +msgstr "Posición Actual de la Animación" #: scene/animation/animation_player.cpp msgid "Playback Options" msgstr "Opciones de Reproducción" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Default Blend Time" -msgstr "Theme Predeterminado" +msgstr "Tiempo de Mezcla por Defecto" #: scene/animation/animation_player.cpp msgid "Method Call Mode" @@ -24097,67 +23392,56 @@ msgid "Tree Root" msgstr "RaÃz del Ãrbol" #: scene/animation/animation_tree.cpp -#, fuzzy msgid "Anim Player" -msgstr "Fijar AnimationPlayer" +msgstr "Reproductor de Animación" #: scene/animation/animation_tree.cpp msgid "Root Motion" msgstr "" #: scene/animation/animation_tree.cpp -#, fuzzy msgid "Track" -msgstr "Agregar Pista" +msgstr "Pista" #: scene/animation/animation_tree_player.cpp msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Este nodo ha quedado obsoleto. Usa AnimationTree en su lugar." #: scene/animation/animation_tree_player.cpp -#, fuzzy msgid "Playback" msgstr "Reproducir" #: scene/animation/animation_tree_player.cpp -#, fuzzy msgid "Master Player" -msgstr "Pegar Parámetros" +msgstr "Reproductor Principal" #: scene/animation/animation_tree_player.cpp -#, fuzzy msgid "Base Path" -msgstr "Ruta de Exportación" +msgstr "Ruta Base" #: scene/animation/root_motion_view.cpp -#, fuzzy msgid "Animation Path" -msgstr "Animación" +msgstr "Ruta de la Animación" #: scene/animation/root_motion_view.cpp -#, fuzzy msgid "Zero Y" -msgstr "Cero" +msgstr "Cero Y" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Root Bone" -msgstr "Nombre del nodo raÃz" +msgstr "Hueso RaÃz" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Tip Bone" -msgstr "Huesos" +msgstr "Punta del Hueso" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Interpolation" -msgstr "Modo de Interpolación" +msgstr "Interpolación" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Override Tip Basis" -msgstr "Anulaciones" +msgstr "Anular Base de la Punta" #: scene/animation/skeleton_ik.cpp msgid "Use Magnet" @@ -24168,54 +23452,46 @@ msgid "Magnet" msgstr "" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Target Node" -msgstr "Reemparentar nodo" +msgstr "Nodo Objetivo" #: scene/animation/skeleton_ik.cpp -#, fuzzy msgid "Max Iterations" -msgstr "Crear Función" +msgstr "Iteraciones Máximas" #: scene/animation/tween.cpp msgid "Playback Process Mode" msgstr "" #: scene/animation/tween.cpp -#, fuzzy msgid "Playback Speed" -msgstr "Reproducir Escena" +msgstr "Velocidad de Reproducción" #: scene/audio/audio_stream_player.cpp -#, fuzzy msgid "Mix Target" -msgstr "Objetivo" +msgstr "Objetivo de la Mezcla" #: scene/gui/aspect_ratio_container.cpp scene/gui/range.cpp #: servers/audio/effects/audio_effect_compressor.cpp -#, fuzzy msgid "Ratio" -msgstr "Mantener Proporciones" +msgstr "Proporción" #: scene/gui/aspect_ratio_container.cpp scene/gui/texture_button.cpp #: scene/gui/texture_rect.cpp -#, fuzzy msgid "Stretch Mode" -msgstr "Modo de Selección" +msgstr "Modo de Estiramiento" #: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp msgid "Alignment" msgstr "" #: scene/gui/base_button.cpp -#, fuzzy msgid "Shortcut In Tooltip" -msgstr "Mostrar Origen" +msgstr "Atajo en el Tooltip" #: scene/gui/base_button.cpp -#, fuzzy msgid "Action Mode" -msgstr "Modo de Icono" +msgstr "Modo de Acción" #: scene/gui/base_button.cpp msgid "Enabled Focus Mode" @@ -24226,38 +23502,33 @@ msgid "Keep Pressed Outside" msgstr "" #: scene/gui/base_button.cpp scene/gui/shortcut.cpp -#, fuzzy msgid "Shortcut" -msgstr "Atajos" +msgstr "Atajo" #: scene/gui/base_button.cpp -#, fuzzy msgid "Group" -msgstr "Grupos" +msgstr "Grupo" #: scene/gui/button.cpp scene/gui/label.cpp -#, fuzzy msgid "Clip Text" -msgstr "Copiar Texto" +msgstr "Texto del Clip" #: scene/gui/button.cpp scene/gui/label.cpp scene/gui/line_edit.cpp #: scene/gui/spin_box.cpp msgid "Align" -msgstr "" +msgstr "Alinear" #: scene/gui/button.cpp msgid "Icon Align" -msgstr "" +msgstr "Alinear Icono" #: scene/gui/button.cpp -#, fuzzy msgid "Expand Icon" -msgstr "Expandir Todo" +msgstr "Expandir Icono" #: scene/gui/center_container.cpp -#, fuzzy msgid "Use Top Left" -msgstr "Superior Izquierda" +msgstr "Usar Superior Izquierda" #: scene/gui/color_picker.cpp msgid "" @@ -24270,34 +23541,28 @@ msgstr "" "Clic der: Borrar configuración predeterminada" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Edit Alpha" -msgstr "Editar PolÃgono" +msgstr "Editar Alfa" #: scene/gui/color_picker.cpp -#, fuzzy msgid "HSV Mode" -msgstr "Modo de Selección" +msgstr "Modo HSV" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Raw Mode" -msgstr "Modo desplazamiento lateral" +msgstr "Modo Raw" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Deferred Mode" -msgstr "Diferido" +msgstr "Modo Diferido" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Presets Enabled" -msgstr "Ajustes preestablecidos" +msgstr "Preajustes Activados" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Presets Visible" -msgstr "Act./Desact. Visible" +msgstr "Preajustes Visibles" #: scene/gui/color_picker.cpp msgid "Pick a color from the editor window." @@ -24327,9 +23592,8 @@ msgstr "" "sencillo." #: scene/gui/control.cpp -#, fuzzy msgid "Theme Overrides" -msgstr "Anulaciones" +msgstr "Anulación de Temas" #: scene/gui/control.cpp msgid "" @@ -24341,14 +23605,12 @@ msgstr "" "Filtro del Ratón en \"Stop\" o \"Pass\"." #: scene/gui/control.cpp -#, fuzzy msgid "Anchor" -msgstr "Sólo anclado" +msgstr "Anclaje" #: scene/gui/control.cpp -#, fuzzy msgid "Grow Direction" -msgstr "Direcciones" +msgstr "Dirección de Crecimiento" #: scene/gui/control.cpp scene/resources/navigation_mesh.cpp msgid "Min Size" @@ -24359,40 +23621,36 @@ msgid "Pivot Offset" msgstr "Pivote de Desplazamiento" #: scene/gui/control.cpp -#, fuzzy msgid "Clip Content" -msgstr "Constante de Clase" +msgstr "Contenido del Clip" #: scene/gui/control.cpp scene/resources/visual_shader_nodes.cpp msgid "Hint" msgstr "" #: scene/gui/control.cpp -#, fuzzy msgid "Tooltip" -msgstr "Herramientas" +msgstr "Tooltip" #: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Focus" -msgstr "Foco en Ruta" +msgstr "Foco" #: scene/gui/control.cpp msgid "Neighbour Left" -msgstr "" +msgstr "Vecino Izquierda" #: scene/gui/control.cpp msgid "Neighbour Top" -msgstr "" +msgstr "Vecino Superior" #: scene/gui/control.cpp msgid "Neighbour Right" -msgstr "" +msgstr "Vecino Derecha" #: scene/gui/control.cpp -#, fuzzy msgid "Neighbour Bottom" -msgstr "Centro Inferior" +msgstr "Vecino Inferior" #: scene/gui/control.cpp msgid "Next" @@ -24419,23 +23677,20 @@ msgid "Size Flags" msgstr "Tamaño de los Indicadores" #: scene/gui/control.cpp -#, fuzzy msgid "Stretch Ratio" -msgstr "Modo de Selección" +msgstr "Relación de Estiramiento" #: scene/gui/control.cpp -#, fuzzy msgid "Theme Type Variation" -msgstr "Propiedades del Theme" +msgstr "Propiedades del Tema" #: scene/gui/dialogs.cpp msgid "Window Title" msgstr "" #: scene/gui/dialogs.cpp -#, fuzzy msgid "Dialog" -msgstr "Diálogo XForm" +msgstr "Diálogo" #: scene/gui/dialogs.cpp msgid "Hide On OK" @@ -24450,18 +23705,16 @@ msgid "Please Confirm..." msgstr "Por favor, Confirma..." #: scene/gui/file_dialog.cpp -#, fuzzy msgid "Mode Overrides Title" -msgstr "Elemento de Anulación" +msgstr "Sobreescritura" #: scene/gui/file_dialog.cpp msgid "Must use a valid extension." msgstr "Debe tener una extensión válida." #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Right Disconnects" -msgstr "Desconectar" +msgstr "Desconexión Correcta" #: scene/gui/graph_edit.cpp msgid "Scroll Offset" @@ -24472,24 +23725,20 @@ msgid "Snap Distance" msgstr "Ajustar Distancia" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom Min" -msgstr "Acercar Zoom" +msgstr "Zoom MÃnimo" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom Max" -msgstr "Acercar Zoom" +msgstr "Zoom Máximo" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom Step" -msgstr "Alejar Zoom" +msgstr "Paso Zoom" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Show Zoom Label" -msgstr "Mostrar Huesos" +msgstr "Mostrar Etiqueta Zoom" #: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp #: scene/resources/default_theme/default_theme.cpp @@ -24501,58 +23750,50 @@ msgid "Enable grid minimap." msgstr "Activar minimapa de cuadrÃcula." #: scene/gui/graph_node.cpp -#, fuzzy msgid "Show Close" -msgstr "Mostrar Huesos" +msgstr "Mostrar Cerrar" #: scene/gui/graph_node.cpp scene/gui/option_button.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Selected" -msgstr "Seleccionar" +msgstr "Seleccionado" #: scene/gui/graph_node.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Comment" -msgstr "Confirmar" +msgstr "Comentario" #: scene/gui/graph_node.cpp msgid "Overlay" msgstr "" #: scene/gui/grid_container.cpp scene/gui/item_list.cpp scene/gui/tree.cpp -#, fuzzy msgid "Columns" -msgstr "Volumen" +msgstr "Columnas" #: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/text_edit.cpp #: scene/gui/tree.cpp scene/main/viewport.cpp -#, fuzzy msgid "Timers" -msgstr "Tiempo" +msgstr "Temporizadores" #: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/tree.cpp msgid "Incremental Search Max Interval Msec" msgstr "" #: scene/gui/item_list.cpp scene/gui/tree.cpp -#, fuzzy msgid "Allow Reselect" -msgstr "Aplicar Restablecer" +msgstr "Permitir Volver A Seleccionar" #: scene/gui/item_list.cpp scene/gui/tree.cpp -#, fuzzy msgid "Allow RMB Select" -msgstr "Rellenar Selección" +msgstr "Permitir Selección Con Botón Derecho Del Ratón" #: scene/gui/item_list.cpp msgid "Max Text Lines" msgstr "" #: scene/gui/item_list.cpp -#, fuzzy msgid "Auto Height" -msgstr "Prueba" +msgstr "Altura Automática" #: scene/gui/item_list.cpp msgid "Max Columns" @@ -24571,23 +23812,20 @@ msgid "Icon Scale" msgstr "Escala de Icono" #: scene/gui/item_list.cpp -#, fuzzy msgid "Fixed Icon Size" -msgstr "Vista Frontal" +msgstr "Tamaño Fijo de Icono" #: scene/gui/label.cpp -#, fuzzy msgid "V Align" -msgstr "Asignar" +msgstr "Alineamiento V" #: scene/gui/label.cpp scene/gui/rich_text_label.cpp msgid "Visible Characters" msgstr "Caracteres Visibles" #: scene/gui/label.cpp scene/gui/rich_text_label.cpp -#, fuzzy msgid "Percent Visible" -msgstr "Act./Desact. Visible" +msgstr "Porcentaje Visible" #: scene/gui/label.cpp msgid "Lines Skipped" @@ -24614,34 +23852,28 @@ msgid "Expand To Text Length" msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Context Menu Enabled" -msgstr "Ayuda Contextual" +msgstr "Menú Contextual Activado" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Virtual Keyboard Enabled" -msgstr "Filtrar señales" +msgstr "Teclado Virtual Activado" #: scene/gui/line_edit.cpp -#, fuzzy msgid "Clear Button Enabled" -msgstr "Filtrar señales" +msgstr "Botón de Borrado Activado" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Shortcut Keys Enabled" -msgstr "Atajos" +msgstr "Atajos Activados" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Middle Mouse Paste Enabled" -msgstr "Filtrar señales" +msgstr "Pegar Con Botón Intermedio Ratón Activado" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Selecting Enabled" -msgstr "Sólo selección" +msgstr "Selección Activada" #: scene/gui/line_edit.cpp scene/gui/rich_text_label.cpp #: scene/gui/text_edit.cpp @@ -24649,14 +23881,12 @@ msgid "Deselect On Focus Loss Enabled" msgstr "" #: scene/gui/line_edit.cpp -#, fuzzy msgid "Right Icon" -msgstr "Botón Derecho" +msgstr "Icono Derecho" #: scene/gui/line_edit.cpp -#, fuzzy msgid "Placeholder" -msgstr "Cargar Como Placeholder" +msgstr "Marcador" #: scene/gui/line_edit.cpp msgid "Alpha" @@ -24679,24 +23909,20 @@ msgid "Underline" msgstr "" #: scene/gui/menu_button.cpp -#, fuzzy msgid "Switch On Hover" -msgstr "Cambiar" +msgstr "Cambiar Al Pasar Por Encima" #: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Draw Center" -msgstr "Centro" +msgstr "Dibujar al Centro" #: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Region Rect" -msgstr "Establecer Region Rect" +msgstr "Región Rectángulo" #: scene/gui/nine_patch_rect.cpp -#, fuzzy msgid "Patch Margin" -msgstr "Asignar Margen" +msgstr "Parche de Margen" #: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp msgid "Axis Stretch" @@ -24715,14 +23941,12 @@ msgstr "" "como Stretch en su lugar." #: scene/gui/popup.cpp -#, fuzzy msgid "Popup" -msgstr "Rellenar" +msgstr "Popup" #: scene/gui/popup.cpp -#, fuzzy msgid "Exclusive" -msgstr "Inclusivo" +msgstr "Exclusivo" #: scene/gui/popup.cpp msgid "" @@ -24735,28 +23959,24 @@ msgstr "" "edición, pero se esconderán al iniciar." #: scene/gui/popup_menu.cpp -#, fuzzy msgid "Hide On Item Selection" -msgstr "Centrar Selección" +msgstr "Ocultar Al Seleccionar Elemento" #: scene/gui/popup_menu.cpp -#, fuzzy msgid "Hide On Checkable Item Selection" -msgstr "Eliminar Selección de GridMap" +msgstr "Ocultar Al Seleccionar Elemento Activable" #: scene/gui/popup_menu.cpp -#, fuzzy msgid "Hide On State Item Selection" -msgstr "Eliminar Selección" +msgstr "Ocultar Al Seleccionar Elemento de Estado" #: scene/gui/popup_menu.cpp msgid "Submenu Popup Delay" msgstr "" #: scene/gui/popup_menu.cpp -#, fuzzy msgid "Allow Search" -msgstr "Buscar" +msgstr "Permitir Búsqueda" #: scene/gui/progress_bar.cpp msgid "Percent" @@ -24767,28 +23987,24 @@ msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0." msgstr "Si \"Exp Edit\" está activado, \"Min Value\" debe ser mayor que 0." #: scene/gui/range.cpp scene/resources/curve.cpp -#, fuzzy msgid "Min Value" -msgstr "Fijar Valor" +msgstr "Valor MÃnimo" #: scene/gui/range.cpp scene/resources/curve.cpp -#, fuzzy msgid "Max Value" -msgstr "Valor" +msgstr "Valor Máximo" #: scene/gui/range.cpp msgid "Page" msgstr "Página" #: scene/gui/range.cpp -#, fuzzy msgid "Exp Edit" -msgstr "Editar" +msgstr "Editar Exp" #: scene/gui/range.cpp -#, fuzzy msgid "Rounded" -msgstr "Agrupado" +msgstr "Redondeado" #: scene/gui/range.cpp msgid "Allow Greater" @@ -24799,24 +24015,20 @@ msgid "Allow Lesser" msgstr "" #: scene/gui/reference_rect.cpp -#, fuzzy msgid "Border Color" -msgstr "Cambiar Nombre del Elemento Color" +msgstr "Color Del Borde" #: scene/gui/reference_rect.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Border Width" -msgstr "PÃxeles del Borde" +msgstr "Anchura Del Borde" #: scene/gui/rich_text_effect.cpp -#, fuzzy msgid "Relative Index" -msgstr "Obtener Ãndice" +msgstr "Ãndice Relativo" #: scene/gui/rich_text_effect.cpp -#, fuzzy msgid "Absolute Index" -msgstr "Auto SangrÃa" +msgstr "Ãndice Absoluto" #: scene/gui/rich_text_effect.cpp msgid "Elapsed Time" @@ -24825,7 +24037,7 @@ msgstr "Tiempo Transcurrido" #: scene/gui/rich_text_effect.cpp #, fuzzy msgid "Env" -msgstr "Fin" +msgstr "Env" #: scene/gui/rich_text_effect.cpp msgid "Character" @@ -24844,9 +24056,8 @@ msgid "Tab Size" msgstr "Tamaño de Tabulación" #: scene/gui/rich_text_label.cpp -#, fuzzy msgid "Fit Content Height" -msgstr "Pintar Peso de Huesos" +msgstr "Ajustar Altura Del Contenido" #: scene/gui/rich_text_label.cpp msgid "Scroll Active" @@ -24857,23 +24068,20 @@ msgid "Scroll Following" msgstr "" #: scene/gui/rich_text_label.cpp -#, fuzzy msgid "Selection Enabled" -msgstr "Sólo selección" +msgstr "Selección Activada" #: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp msgid "Override Selected Font Color" msgstr "Sobrescribir Color de Fuente Seleccionada" #: scene/gui/rich_text_label.cpp -#, fuzzy msgid "Custom Effects" -msgstr "Mover Efecto de Bus" +msgstr "Efectos Personalizados" #: scene/gui/scroll_bar.cpp -#, fuzzy msgid "Custom Step" -msgstr "CustomNode" +msgstr "Paso Personalizado" #: scene/gui/scroll_container.cpp msgid "" @@ -24886,18 +24094,16 @@ msgstr "" "manualmente el tamaño mÃnimo personalizado." #: scene/gui/scroll_container.cpp -#, fuzzy msgid "Follow Focus" -msgstr "Llenar superficie" +msgstr "Seguir Focus" #: scene/gui/scroll_container.cpp msgid "Horizontal Enabled" msgstr "Horizontal Activado" #: scene/gui/scroll_container.cpp -#, fuzzy msgid "Vertical Enabled" -msgstr "Filtrar señales" +msgstr "Vertical Activada" #: scene/gui/scroll_container.cpp msgid "Default Scroll Deadzone" @@ -24908,9 +24114,8 @@ msgid "Scrollable" msgstr "" #: scene/gui/slider.cpp -#, fuzzy msgid "Tick Count" -msgstr "Seleccionar Color" +msgstr "Cantidad De Marcas" #: scene/gui/slider.cpp msgid "Ticks On Borders" @@ -24929,14 +24134,12 @@ msgid "Split Offset" msgstr "Desplazamiento de División" #: scene/gui/split_container.cpp scene/gui/tree.cpp -#, fuzzy msgid "Collapsed" -msgstr "Colapsar Todo" +msgstr "Colapsado" #: scene/gui/split_container.cpp -#, fuzzy msgid "Dragger Visibility" -msgstr "Cambiar Visibilidad" +msgstr "Visibilidad de los Arrastradores" #: scene/gui/tab_container.cpp scene/gui/tabs.cpp msgid "Tab Align" @@ -24947,9 +24150,8 @@ msgid "Current Tab" msgstr "Pestaña Actual" #: scene/gui/tab_container.cpp -#, fuzzy msgid "Tabs Visible" -msgstr "Act./Desact. Visible" +msgstr "Pestañas Visibles" #: scene/gui/tab_container.cpp msgid "All Tabs In Front" @@ -24976,33 +24178,28 @@ msgid "Readonly" msgstr "" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Bookmark Gutter" -msgstr "Marcadores" +msgstr "Canalón de Marcadores" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Breakpoint Gutter" -msgstr "Saltar Breakpoints" +msgstr "Canalón de Puntos de Ruptura" #: scene/gui/text_edit.cpp msgid "Fold Gutter" -msgstr "Plegar Gutter" +msgstr "Canalón Plegable" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Drag And Drop Selection Enabled" -msgstr "Sólo selección" +msgstr "Selección de Arrastrar y Soltar Activada" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Hiding Enabled" -msgstr "Activar" +msgstr "Ocultación Activada" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Wrap Enabled" -msgstr "Activar" +msgstr "Ajuste Activado" #: scene/gui/text_edit.cpp msgid "Scroll Vertical" @@ -25017,9 +24214,8 @@ msgid "Draw" msgstr "Dibujar" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Block Mode" -msgstr "Desbloquear Nodo" +msgstr "Modo Bloque" #: scene/gui/text_edit.cpp msgid "Moving By Right Click" @@ -25038,34 +24234,29 @@ msgid "Hover" msgstr "" #: scene/gui/texture_button.cpp -#, fuzzy msgid "Focused" -msgstr "Foco en Ruta" +msgstr "Enfocado" #: scene/gui/texture_button.cpp -#, fuzzy msgid "Click Mask" -msgstr "Modo de Colisión" +msgstr "Máscara de Clic" #: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp #: scene/gui/video_player.cpp -#, fuzzy msgid "Expand" -msgstr "Expandir Todo" +msgstr "Expandir" #: scene/gui/texture_progress.cpp msgid "Under" msgstr "" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Over" -msgstr "Sobreescribir" +msgstr "Sobre" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Progress" -msgstr "Propiedades del Theme" +msgstr "Progreso" #: scene/gui/texture_progress.cpp msgid "Progress Offset" @@ -25084,43 +24275,36 @@ msgid "Radial Fill" msgstr "" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Initial Angle" -msgstr "Inicializar" +msgstr "Ãngulo Inicial" #: scene/gui/texture_progress.cpp msgid "Fill Degrees" msgstr "Completar Grados" #: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Center Offset" -msgstr "Centro Izquierda" +msgstr "Desplazamiento Central" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Nine Patch Stretch" -msgstr "Modo de Interpolación" +msgstr "Estiramiento de Nine Patch" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Stretch Margin Left" -msgstr "Asignar Margen" +msgstr "Estiramiento de Margen Izquierdo" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Stretch Margin Top" -msgstr "Asignar Margen" +msgstr "Estiramiento de Margen Superior" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Stretch Margin Right" -msgstr "Asignar Margen" +msgstr "Estiramiento de Margen Derecho" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Stretch Margin Bottom" -msgstr "Modo de Selección" +msgstr "Estiramiento de Margen Inferior" #: scene/gui/tree.cpp msgid "Custom Minimum Height" @@ -25131,14 +24315,12 @@ msgid "(Other)" msgstr "(Otros)" #: scene/gui/tree.cpp -#, fuzzy msgid "Column Titles Visible" -msgstr "Act./Desact. Visible" +msgstr "TÃtulos de Columnas Visibles" #: scene/gui/tree.cpp -#, fuzzy msgid "Hide Folding" -msgstr "Botón Desactivado" +msgstr "Plegado de Pieles" #: scene/gui/tree.cpp msgid "Hide Root" @@ -25149,43 +24331,36 @@ msgid "Drop Mode Flags" msgstr "" #: scene/gui/video_player.cpp -#, fuzzy msgid "Audio Track" -msgstr "Agregar Pista" +msgstr "Pista de Audio" #: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp msgid "Paused" -msgstr "" +msgstr "Pausado" #: scene/gui/video_player.cpp -#, fuzzy msgid "Buffering Msec" -msgstr "Vista Trasera" +msgstr "Buffering Msec" #: scene/gui/video_player.cpp -#, fuzzy msgid "Stream Position" -msgstr "Establecer Posición de Entrada de Curva" +msgstr "Posición del Stream" #: scene/gui/viewport_container.cpp -#, fuzzy msgid "Stretch Shrink" -msgstr "Buscar" +msgstr "Encogimiento por Estiramiento" #: scene/main/canvas_layer.cpp -#, fuzzy msgid "Follow Viewport" -msgstr "Mostrar Viewport" +msgstr "Seguir el Viewport" #: scene/main/http_request.cpp -#, fuzzy msgid "Download File" -msgstr "Descargar" +msgstr "Descargar Archivo" #: scene/main/http_request.cpp -#, fuzzy msgid "Download Chunk Size" -msgstr "Descargando" +msgstr "Descargar Tamaño del Fragmento" #: scene/main/http_request.cpp msgid "Body Size Limit" @@ -25206,89 +24381,76 @@ msgid "" msgstr "" #: scene/main/node.cpp -#, fuzzy msgid "Name Num Separator" -msgstr "Separador con nombre" +msgstr "Separador Numérico del Nombre" #: scene/main/node.cpp msgid "Name Casing" msgstr "" #: scene/main/node.cpp -#, fuzzy msgid "Editor Description" -msgstr "Descripción" +msgstr "Descripción del Editor" #: scene/main/node.cpp -#, fuzzy msgid "Pause Mode" -msgstr "Modo desplazamiento lateral" +msgstr "Modo Pausa" #: scene/main/node.cpp -#, fuzzy msgid "Physics Interpolation Mode" -msgstr "Modo de Interpolación" +msgstr "Modo de Interpolación FÃsica" #: scene/main/node.cpp -#, fuzzy msgid "Display Folded" -msgstr "Mostrar Sin Sombreado" +msgstr "Vista Plegada" #: scene/main/node.cpp -#, fuzzy msgid "Filename" -msgstr "Renombrar" +msgstr "Nombre del Archivo" #: scene/main/node.cpp msgid "Owner" msgstr "Propietario" #: scene/main/node.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Multiplayer" -msgstr "Multiplicar %s" +msgstr "Multijugador" #: scene/main/node.cpp msgid "Custom Multiplayer" msgstr "Multijugador Personalizado" #: scene/main/node.cpp -#, fuzzy msgid "Process Priority" -msgstr "Activar Prioridad" +msgstr "Prioridad del Proceso" #: scene/main/scene_tree.cpp scene/main/timer.cpp -#, fuzzy msgid "Time Left" -msgstr "Superior Izquierda" +msgstr "Tiempo Restante" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Debug Collisions Hint" -msgstr "Modo de Colisión" +msgstr "Sugerencia de Depuración de Colisiones" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Debug Navigation Hint" -msgstr "Modo de Navegación" +msgstr "Sugerencia de Depuración de Navegación" #: scene/main/scene_tree.cpp msgid "Use Font Oversampling" msgstr "" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Edited Scene Root" -msgstr "Nueva RaÃz de Escena" +msgstr "Escena RaÃz Editada" #: scene/main/scene_tree.cpp msgid "Root" msgstr "" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Multiplayer Poll" -msgstr "Multiplicar %s" +msgstr "Encuesta Multijugador" #: scene/main/scene_tree.cpp scene/resources/mesh_library.cpp #: scene/resources/shape_2d.cpp @@ -25300,32 +24462,28 @@ msgid "Shape Color" msgstr "" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Contact Color" -msgstr "Seleccionar Color" +msgstr "Color de Contacto" #: scene/main/scene_tree.cpp msgid "Geometry Color" msgstr "" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Disabled Geometry Color" -msgstr "Desactivar Elemento" +msgstr "Color de la GeometrÃa Desactivada" #: scene/main/scene_tree.cpp msgid "Max Contacts Displayed" msgstr "" #: scene/main/scene_tree.cpp scene/resources/shape_2d.cpp -#, fuzzy msgid "Draw 2D Outlines" -msgstr "Crear Outline" +msgstr "Dibujar Contornos 2D" #: scene/main/scene_tree.cpp servers/visual_server.cpp -#, fuzzy msgid "Reflections" -msgstr "Direcciones" +msgstr "Reflexiones" #: scene/main/scene_tree.cpp msgid "Atlas Size" @@ -25356,9 +24514,8 @@ msgid "Use 32 BPC Depth" msgstr "" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Default Environment" -msgstr "Ver Entorno" +msgstr "Entorno por Defecto" #: scene/main/scene_tree.cpp msgid "" @@ -25369,9 +24526,8 @@ msgstr "" "(Rendering -> Environment -> Default Environment) no se ha podido cargar." #: scene/main/scene_tree.cpp -#, fuzzy msgid "Enable Object Picking" -msgstr "Activar Papel Cebolla" +msgstr "Activar Selección de Objetos" #: scene/main/timer.cpp msgid "" @@ -25391,9 +24547,8 @@ msgid "Autostart" msgstr "Inicio Automático" #: scene/main/viewport.cpp -#, fuzzy msgid "Viewport Path" -msgstr "Ruta de Exportación" +msgstr "Ruta del Viewport" #: scene/main/viewport.cpp msgid "" @@ -25411,65 +24566,64 @@ msgid "" "Effects.\n" "HDR will be disabled for this Viewport." msgstr "" +"Este Viewport tiene HDR habilitado, pero su uso está establecido en 2D o 2D " +"sin muestreo.\n" +"El HDR solo está soportado en los Viewports que tienen su uso establecido en " +"3D o 3D Sin Efectos.\n" +"El HDR estará desactivado para esta ventana." #: scene/main/viewport.cpp msgid "ARVR" -msgstr "" +msgstr "ARVR" #: scene/main/viewport.cpp -#, fuzzy msgid "Size Override Stretch" -msgstr "Elemento de Anulación" +msgstr "Anulación del Tamaño de Estiramiento" #: scene/main/viewport.cpp msgid "Own World" -msgstr "" +msgstr "Mundo Propio" #: scene/main/viewport.cpp scene/resources/world_2d.cpp msgid "World" -msgstr "" +msgstr "Mundo" #: scene/main/viewport.cpp msgid "World 2D" -msgstr "" +msgstr "Mundo 2D" #: scene/main/viewport.cpp -#, fuzzy msgid "Transparent BG" -msgstr "Transponer" +msgstr "Fondo Transparente" #: scene/main/viewport.cpp -#, fuzzy msgid "Handle Input Locally" -msgstr "Cambiar Valor de Entrada" +msgstr "Manejar Entradas Localmente" #: scene/main/viewport.cpp msgid "FXAA" -msgstr "" +msgstr "FXAA" #: scene/main/viewport.cpp #, fuzzy msgid "Debanding" -msgstr "Vinculación" +msgstr "Debanding" #: scene/main/viewport.cpp -#, fuzzy msgid "Disable 3D" -msgstr "Desactivar Elemento" +msgstr "Desactivar 3D" #: scene/main/viewport.cpp -#, fuzzy msgid "Keep 3D Linear" -msgstr "Izquierda Lineal" +msgstr "Mantener 3D Lineal" #: scene/main/viewport.cpp msgid "Render Direct To Screen" -msgstr "" +msgstr "Renderización Directa en Pantalla" #: scene/main/viewport.cpp -#, fuzzy msgid "Debug Draw" -msgstr "Depurar" +msgstr "Depurar Dibujo" #: scene/main/viewport.cpp msgid "Render Target" @@ -25480,34 +24634,28 @@ msgid "V Flip" msgstr "" #: scene/main/viewport.cpp -#, fuzzy msgid "Clear Mode" -msgstr "Modo de Regla" +msgstr "Modo de Limpieza" #: scene/main/viewport.cpp -#, fuzzy msgid "Enable 2D" -msgstr "Activar" +msgstr "Activar 2D" #: scene/main/viewport.cpp -#, fuzzy msgid "Enable 3D" -msgstr "Activar" +msgstr "Activar 3D" #: scene/main/viewport.cpp -#, fuzzy msgid "Object Picking" -msgstr "Activar Papel Cebolla" +msgstr "Selección de Objetos" #: scene/main/viewport.cpp -#, fuzzy msgid "Disable Input" -msgstr "Desactivar Elemento" +msgstr "Desactivar Entrada" #: scene/main/viewport.cpp servers/visual_server.cpp -#, fuzzy msgid "Shadow Atlas" -msgstr "Nuevo Atlas" +msgstr "Sombra del Atlas" #: scene/main/viewport.cpp msgid "Quad 0" @@ -25526,78 +24674,66 @@ msgid "Quad 3" msgstr "" #: scene/main/viewport.cpp -#, fuzzy msgid "Canvas Transform" -msgstr "Reestablecer Transformación" +msgstr "Transformación del Canvas" #: scene/main/viewport.cpp -#, fuzzy msgid "Global Canvas Transform" -msgstr "Mantener transformación global" +msgstr "Transformación Global del Canvas" #: scene/main/viewport.cpp msgid "Tooltip Delay (sec)" -msgstr "" +msgstr "Retraso del Tooltip (sec)" #: scene/register_scene_types.cpp #, fuzzy msgid "Swap OK Cancel" -msgstr "Cancelar UI" +msgstr "Intercambio OK Cancelar" #: scene/register_scene_types.cpp -#, fuzzy msgid "Layer Names" -msgstr "Nombre" +msgstr "Nombres de las Capas" #: scene/register_scene_types.cpp -#, fuzzy msgid "2D Render" -msgstr "Renderización" +msgstr "Renderización 2D" #: scene/register_scene_types.cpp -#, fuzzy msgid "3D Render" -msgstr "Renderización" +msgstr "Renderización 3D" #: scene/register_scene_types.cpp -#, fuzzy msgid "2D Physics" -msgstr "FÃsica" +msgstr "FÃsica 2D" #: scene/register_scene_types.cpp -#, fuzzy msgid "3D Physics" -msgstr "FÃsica" +msgstr "FÃsica 3D" #: scene/register_scene_types.cpp -#, fuzzy msgid "2D Navigation" -msgstr "Navegación" +msgstr "Navegación 2D" #: scene/register_scene_types.cpp -#, fuzzy msgid "3D Navigation" -msgstr "Navegación" +msgstr "Navegación 3D" #: scene/register_scene_types.cpp msgid "Use hiDPI" msgstr "" #: scene/register_scene_types.cpp -#, fuzzy msgid "Custom" -msgstr "CustomNode" +msgstr "Personalizado" #: scene/register_scene_types.cpp -#, fuzzy msgid "Custom Font" -msgstr "CustomNode" +msgstr "Fuente Personalizada" #: scene/resources/audio_stream_sample.cpp #: servers/audio/effects/audio_stream_generator.cpp servers/audio_server.cpp -#, fuzzy msgid "Mix Rate" -msgstr "Nodo Mix" +msgstr "Tasa de Mezcla" #: scene/resources/audio_stream_sample.cpp msgid "Stereo" @@ -25608,9 +24744,8 @@ msgid "Segments" msgstr "Segmentos" #: scene/resources/curve.cpp -#, fuzzy msgid "Bake Resolution" -msgstr "Media Resolución" +msgstr "Bakear Resolución" #: scene/resources/curve.cpp msgid "Bake Interval" @@ -25621,77 +24756,64 @@ msgid "Panel" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color" -msgstr "Seleccionar Color" +msgstr "Color de la Fuente" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Pressed" -msgstr "Color Hueso 1" +msgstr "Color de la Fuente Presionada" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Hover" -msgstr "Color Hueso 1" +msgstr "Color de la Fuente por Encima" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Focus" -msgstr "Llenar superficie" +msgstr "Color de la Fuente Enfocada" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Disabled" -msgstr "Clip Deshabilitado" +msgstr "Color de la Fuente Desactivada" #: scene/resources/default_theme/default_theme.cpp msgid "H Separation" msgstr "Separación en H" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Underline Spacing" -msgstr "Espaciado de LÃnea" +msgstr "Espaciado del Subrayado" #: scene/resources/default_theme/default_theme.cpp msgid "Arrow" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Arrow Margin" -msgstr "Asignar Margen" +msgstr "Margen de la Flecha" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Hover Pressed" -msgstr "Preset" +msgstr "Presionado por Encima" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Checked Disabled" -msgstr "Chequeable" +msgstr "Marcado Desactivado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Unchecked" -msgstr "Chequeado" +msgstr "Sin marcar" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Unchecked Disabled" -msgstr "Desactivar Elemento" +msgstr "Sin marcar Desactivado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Radio Checked" -msgstr "Chequeado" +msgstr "Radio Marcado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Radio Checked Disabled" -msgstr "(Editor Desactivado)" +msgstr "Radio Marcado Desactivado" #: scene/resources/default_theme/default_theme.cpp msgid "Radio Unchecked" @@ -25712,27 +24834,23 @@ msgstr "" #: scene/resources/default_theme/default_theme.cpp #, fuzzy msgid "On Disabled" -msgstr "Desactivar Elemento" +msgstr "Desactivado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Off" -msgstr "Desplazamiento" +msgstr "Apagado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Off Disabled" -msgstr "Desactivar Elemento" +msgstr "Apagado Desactivado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Shadow" -msgstr "Color Hueso 1" +msgstr "Color de la Sombra de la Fuente" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Outline Modulate" -msgstr "Forzar Modulación en Blanco" +msgstr "Modulación del Contorno de la Fuente" #: scene/resources/default_theme/default_theme.cpp msgid "Shadow Offset X" @@ -25743,59 +24861,50 @@ msgid "Shadow Offset Y" msgstr "Desplazamiento de la Sombra en Y" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Shadow As Outline" -msgstr "Mostrar Contorno Anterior" +msgstr "Sombra como Contorno" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Selected" -msgstr "Desbloquear Seleccionado" +msgstr "Color de Fuente Seleccionada" #: scene/resources/default_theme/default_theme.cpp msgid "Font Color Uneditable" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Cursor Color" -msgstr "CustomNode" +msgstr "Color del Cursor" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Clear Button Color" -msgstr "Filtrar señales" +msgstr "Limpiar Color del Botón" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Clear Button Color Pressed" -msgstr "Filtrar señales" +msgstr "Limpiar Color del Botón Presionado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Minimum Spaces" -msgstr "Escena Principal" +msgstr "Espacios MÃnimos" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "BG" -msgstr "B" +msgstr "BG" #: scene/resources/default_theme/default_theme.cpp msgid "FG" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Tab" -msgstr "Tab 1" +msgstr "Tab" #: scene/resources/default_theme/default_theme.cpp #: scene/resources/dynamic_font.cpp scene/resources/world.cpp #: scene/resources/world_2d.cpp -#, fuzzy msgid "Space" -msgstr "Escena Principal" +msgstr "Espacio" #: scene/resources/default_theme/default_theme.cpp msgid "Folded" @@ -25810,9 +24919,8 @@ msgid "Font Color Readonly" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Lines" -msgstr "Completar" +msgstr "Finalización de LÃneas" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25871,9 +24979,8 @@ msgid "Decrement Pressed" msgstr "" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Slider" -msgstr "Modo de Colisión" +msgstr "Deslizador" #: scene/resources/default_theme/default_theme.cpp msgid "Grabber Area" @@ -26312,13 +25419,12 @@ msgid "Mono Font" msgstr "Fuente Principal" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Table H Separation" -msgstr "Separación de Tabla H" +msgstr "Separación H de Tabla" #: scene/resources/default_theme/default_theme.cpp msgid "Table V Separation" -msgstr "Separación de Tabla V" +msgstr "Separación V de Tabla" #: scene/resources/default_theme/default_theme.cpp msgid "Margin Left" @@ -27591,7 +26697,7 @@ msgstr "Margen de Conexión de Bordes" #: scene/resources/world_2d.cpp msgid "Canvas" -msgstr "" +msgstr "Lienzo" #: servers/arvr/arvr_interface.cpp msgid "Is Primary" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index eeea3a9922..10a562d0b8 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -20,13 +20,14 @@ # M3CG <cgmario1999@gmail.com>, 2021, 2022. # Manuel González <mgoopazo@gmail.com>, 2021. # emnrx <emanuelermancia@gmail.com>, 2022. +# Mau_Restor <restor@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-06-21 15:56+0000\n" -"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" +"Last-Translator: Mau_Restor <restor@gmail.com>\n" "Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/" "godot-engine/godot/es_AR/>\n" "Language: es_AR\n" @@ -34,7 +35,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -268,9 +269,8 @@ msgid "Network Peer" msgstr "Profiler de Red" #: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp -#, fuzzy msgid "Root Node" -msgstr "Nombre del nodo raÃz" +msgstr "Nodo raÃz" #: core/io/networked_multiplayer_peer.cpp msgid "Refuse New Connections" @@ -302,7 +302,7 @@ msgstr "" #: core/io/stream_peer.cpp msgid "Data Array" -msgstr "" +msgstr "Array de datos" #: core/io/stream_peer_ssl.cpp msgid "Blocking Handshake" @@ -331,9 +331,8 @@ msgstr "" "No hay suficientes bytes para decodificar bytes, o el formato es inválido." #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" -msgstr "Entrada inválida %i (no se transmitió) en la expresión" +msgstr "Entrada inválida %d (no se transmitió) en la expresión" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -362,7 +361,7 @@ msgstr "En la llamada a '%s':" #: core/math/random_number_generator.cpp #: modules/opensimplex/open_simplex_noise.cpp msgid "Seed" -msgstr "" +msgstr "Semilla" #: core/math/random_number_generator.cpp #, fuzzy @@ -371,16 +370,15 @@ msgstr "Estado" #: core/message_queue.cpp msgid "Message Queue" -msgstr "" +msgstr "Cola de mesajes" #: core/message_queue.cpp msgid "Max Size (KB)" -msgstr "" +msgstr "Tamaño máximo (KB)" #: core/os/input.cpp -#, fuzzy msgid "Mouse Mode" -msgstr "Modo Mover" +msgstr "Modo Mouse" #: core/os/input.cpp #, fuzzy @@ -409,9 +407,8 @@ msgid "Meta" msgstr "Meta" #: core/os/input_event.cpp -#, fuzzy msgid "Command" -msgstr "Comunidad" +msgstr "Comando" #: core/os/input_event.cpp #, fuzzy @@ -440,7 +437,7 @@ msgstr "Unicode" #: core/os/input_event.cpp msgid "Echo" -msgstr "" +msgstr "Echo" #: core/os/input_event.cpp scene/gui/base_button.cpp msgid "Button Mask" @@ -464,7 +461,7 @@ msgstr "Dobleclick" #: core/os/input_event.cpp msgid "Tilt" -msgstr "" +msgstr "Inclinación" #: core/os/input_event.cpp #, fuzzy @@ -473,8 +470,12 @@ msgstr "Preset" #: core/os/input_event.cpp #, fuzzy +msgid "Pen Inverted" +msgstr "Invertir" + +#: core/os/input_event.cpp msgid "Relative" -msgstr "Ajuste Relativo" +msgstr "Relativo" #: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp @@ -532,7 +533,7 @@ msgstr "Velocidad" #: core/os/input_event.cpp msgid "Instrument" -msgstr "" +msgstr "Instrumento" #: core/os/input_event.cpp msgid "Controller Number" @@ -540,7 +541,7 @@ msgstr "Número de Controlador" #: core/os/input_event.cpp msgid "Controller Value" -msgstr "" +msgstr "Valor del controlador" #: core/project_settings.cpp editor/editor_node.cpp main/main.cpp #: platform/iphone/export/export.cpp platform/osx/export/export.cpp @@ -612,9 +613,8 @@ msgstr "Nombre de Directorio de Usuario Personalizado" #: core/project_settings.cpp main/main.cpp #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #: platform/uwp/os_uwp.cpp -#, fuzzy msgid "Display" -msgstr "Mostrar Todo" +msgstr "Mostrar" #: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp #: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp @@ -633,17 +633,15 @@ msgstr "Altura" #: core/project_settings.cpp msgid "Always On Top" -msgstr "" +msgstr "Siempre encima" #: core/project_settings.cpp -#, fuzzy msgid "Test Width" -msgstr "Izquierda Ancha" +msgstr "probar ancho" #: core/project_settings.cpp -#, fuzzy msgid "Test Height" -msgstr "Prueba" +msgstr "probar altura" #: core/project_settings.cpp editor/animation_track_editor.cpp #: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp @@ -681,14 +679,12 @@ msgid "Script Templates Search Path" msgstr "Ruta de Búsqueda de Plantillas de Scripts" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "Sistema de Control de Versiones" +msgstr "Al iniciar el Sistema de Control de Versiones" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Plugin Name" -msgstr "Control de Versiones" +msgstr "Nombre del sistema de control de versiones" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -697,17 +693,15 @@ msgstr "Entrada" #: core/project_settings.cpp msgid "UI Accept" -msgstr "" +msgstr "Aceptar Interfaz del usuario" #: core/project_settings.cpp -#, fuzzy msgid "UI Select" -msgstr "Seleccionar" +msgstr "Seleccionar Interfaz de Usuario" #: core/project_settings.cpp -#, fuzzy msgid "UI Cancel" -msgstr "Cancelar" +msgstr "Cancelar la interfaz de usuario" #: core/project_settings.cpp #, fuzzy @@ -749,12 +743,11 @@ msgstr "" #: core/project_settings.cpp msgid "UI Home" -msgstr "" +msgstr "Inicio de la interfaz de usuario" #: core/project_settings.cpp -#, fuzzy msgid "UI End" -msgstr "Al Final" +msgstr "Al Final de la interfaz de usuario" #: core/project_settings.cpp main/main.cpp modules/bullet/register_types.cpp #: modules/bullet/space_bullet.cpp scene/2d/physics_body_2d.cpp @@ -812,7 +805,7 @@ msgstr "Filtros" #: core/project_settings.cpp scene/main/viewport.cpp msgid "Sharpen Intensity" -msgstr "" +msgstr "Intensidad de la nitidez" #: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp @@ -862,7 +855,7 @@ msgstr "Nivel de Compresión" #: core/project_settings.cpp msgid "Window Log Size" -msgstr "" +msgstr "medida del registro de la ventana" #: core/project_settings.cpp msgid "Zlib" @@ -885,9 +878,8 @@ msgid "TCP" msgstr "TCP" #: core/register_core_types.cpp -#, fuzzy msgid "Connect Timeout Seconds" -msgstr "Conexiones al método:" +msgstr "Tiempo de espera en segundos de la conexion" #: core/register_core_types.cpp msgid "Packet Peer Stream" @@ -912,9 +904,8 @@ msgid "Resource" msgstr "Recursos" #: core/resource.cpp -#, fuzzy msgid "Local To Scene" -msgstr "Cerrar Escena" +msgstr "Local a la escena" #: core/resource.cpp editor/dependency_editor.cpp #: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp @@ -1195,9 +1186,8 @@ msgid "Type" msgstr "Tipo" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "Setear Handle" +msgstr "En manejo" #: editor/animation_track_editor.cpp #, fuzzy @@ -1348,9 +1338,8 @@ msgid "Time (s):" msgstr "Tiempo (s): " #: editor/animation_track_editor.cpp -#, fuzzy msgid "Position:" -msgstr "Posición del Panel" +msgstr "Posición:" #: editor/animation_track_editor.cpp #, fuzzy @@ -2163,14 +2152,15 @@ msgstr "Favoritos:" msgid "Recent:" msgstr "Recientes:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Buscar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Coincidencias:" @@ -2230,8 +2220,8 @@ msgstr "Buscar Reemplazo de Recurso:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2810,7 +2800,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Copiar Ruta del Nodo" #: editor/editor_export.cpp @@ -5640,6 +5630,10 @@ msgid "Drag And Drop Selection" msgstr "Selección de GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11927,6 +11921,11 @@ msgid "New Animation" msgstr "Nueva Animación" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrar métodos" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocidad:" @@ -20743,15 +20742,15 @@ msgstr "No se pudo encontrar la keystore, no se puedo exportar." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Archivo ejecutable no válido." #: platform/windows/export/export.cpp #, fuzzy @@ -20775,15 +20774,15 @@ msgstr "Nombre inválido." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Archivo ejecutable no válido." #: platform/windows/export/export.cpp #, fuzzy @@ -21890,7 +21889,7 @@ msgstr "Viaje" msgid "Rotation Degrees" msgstr "Rotando %s grados." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constante Global" @@ -23995,6 +23994,11 @@ msgstr "" "En su lugar, cambiá el tamaño de los collision shapes hijos." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Mantener Transformación Global" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "Matriz" diff --git a/editor/translations/et.po b/editor/translations/et.po index b7ed666bb0..3976c9f0bd 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -477,6 +477,10 @@ msgid "Pressure" msgstr "Eelseadistus" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2150,14 +2154,15 @@ msgstr "Lemmikud:" msgid "Recent:" msgstr "Hiljutised:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Otsi:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Vasted:" @@ -2213,8 +2218,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2784,7 +2789,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Kopeeri sõlme tee" #: editor/editor_export.cpp @@ -5483,6 +5488,10 @@ msgid "Drag And Drop Selection" msgstr "Kopeeri valik" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11585,6 +11594,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Kustuta animatsioon?" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19999,15 +20013,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Vigane nimi." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20029,15 +20043,15 @@ msgstr "Vigane nimi." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Vigane nimi." #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -21068,7 +21082,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstant" @@ -23041,6 +23055,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Tõlked" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/eu.po b/editor/translations/eu.po index ff9601ad57..3e69f3c4b9 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -451,6 +451,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Atxikitze erlatiboa" @@ -2112,14 +2116,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2175,8 +2180,8 @@ msgstr "Bilatu ordezko baliabidea:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2751,8 +2756,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Kargatu animazioa" #: editor/editor_export.cpp #, fuzzy @@ -5389,6 +5395,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11463,6 +11473,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Ezabatu animazioa?" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19801,15 +19816,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Animazio izen baliogabea!" #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -19831,15 +19846,15 @@ msgstr "Animazio izen baliogabea!" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Animazio izen baliogabea!" #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -20844,7 +20859,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstantea" @@ -22790,6 +22805,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Translazio atzikitzea:" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/fa.po b/editor/translations/fa.po index ae8a37388a..86b847e530 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -503,6 +503,10 @@ msgid "Pressure" msgstr "بازنشانی بزرگنمایی" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "GDNative" @@ -2194,14 +2198,15 @@ msgstr "برگزیده‌ها:" msgid "Recent:" msgstr "اخیر:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "جستجو:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "تطبیق‌ها:" @@ -2261,8 +2266,8 @@ msgstr "منبع جایگزینی را جستجو Ú©Ù†:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2835,7 +2840,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Ú©Ù¾ÛŒ کردن مسیر node" #: editor/editor_export.cpp @@ -5545,6 +5550,10 @@ msgid "Drag And Drop Selection" msgstr "انتخاب شده را ØØ°Ù Ú©Ù†" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11958,6 +11967,11 @@ msgid "New Animation" msgstr "تغییر نام انیمیشن" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ØØ§Ù„ت صاÙÛŒ:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20738,15 +20752,15 @@ msgstr "نمی‌تواند یک پوشه ایجاد شود." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "باید از یک پسوند معتبر Ø§Ø³ØªÙØ§Ø¯Ù‡ شود." #: platform/windows/export/export.cpp #, fuzzy @@ -20770,15 +20784,15 @@ msgstr "نام نامعتبر." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "باید از یک پسوند معتبر Ø§Ø³ØªÙØ§Ø¯Ù‡ شود." #: platform/windows/export/export.cpp #, fuzzy @@ -21832,7 +21846,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "ثابت" @@ -23857,6 +23871,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "انتقال را در انیمیشن تغییر بده" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 7613bdfcce..db841ef48a 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -501,6 +501,10 @@ msgid "Pressure" msgstr "Esiasetukset" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Suhteellinen tarttuminen" @@ -2212,14 +2216,15 @@ msgstr "Suosikit:" msgid "Recent:" msgstr "Viimeaikaiset:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Hae:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Osumat:" @@ -2279,8 +2284,8 @@ msgstr "Etsi korvaava resurssi:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2859,7 +2864,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Kopioi solmun polku" #: editor/editor_export.cpp @@ -5672,6 +5677,10 @@ msgid "Drag And Drop Selection" msgstr "Ruudukon valinta" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11946,6 +11955,11 @@ msgid "New Animation" msgstr "Uusi animaatio" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Suodata metodeja" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Nopeus:" @@ -20742,17 +20756,17 @@ msgstr "Keystorea ei löytynyt, ei voida viedä." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "rcedit-työkalu täytyy olla konfiguroituna editorin asetuksissa (Export > " "Windows > Rcedit) ikonin tai sovelluksen tietojen muuttamiseksi." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Virheellinen käynnistystiedosto." #: platform/windows/export/export.cpp #, fuzzy @@ -20777,17 +20791,17 @@ msgstr "Virheellinen nimi." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "rcedit-työkalu täytyy olla konfiguroituna editorin asetuksissa (Export > " "Windows > Rcedit) ikonin tai sovelluksen tietojen muuttamiseksi." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Virheellinen käynnistystiedosto." #: platform/windows/export/export.cpp #, fuzzy @@ -21899,7 +21913,7 @@ msgstr "Matkaa" msgid "Rotation Degrees" msgstr "Kierto %s astetta." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Globaali vakio" @@ -24049,6 +24063,11 @@ msgstr "" "Muuta kokoa sen sijaan alisolmujen törmäysmuodoissa." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Pidä globaali muunnos" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 24a5742ef6..0a154fd6ae 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -448,6 +448,10 @@ msgid "Pressure" msgstr "Presyur" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relatibo" @@ -2084,14 +2088,15 @@ msgstr "Mga Paborito:" msgid "Recent:" msgstr "Kamakailan:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Paghahanap:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2147,8 +2152,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2707,8 +2712,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Pagulit ng Animation" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5306,6 +5312,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11317,6 +11327,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Pagulit ng Animation" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19487,14 +19502,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19516,14 +19530,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20496,7 +20509,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22368,6 +22381,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "3D Transform Track" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 8822d35687..88c4966b54 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -99,13 +99,16 @@ # HOUA <ninjacowzx@gmail.com>, 2022. # DinosaurHorseSword <ewenlandry@mailfence.com>, 2022. # Arnaud Lier <arnaud@ric-rac.org>, 2022. +# Jérémie Guegain <mirejai@orange.fr>, 2022. +# cwulveryck <cwulveryck@online.fr>, 2022. +# Helix Sir <vincentbarkmann@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-03 00:44+0000\n" -"Last-Translator: Sofiane <Sofiane-77@caramail.fr>\n" +"PO-Revision-Date: 2022-08-05 01:04+0000\n" +"Last-Translator: Helix Sir <vincentbarkmann@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -113,7 +116,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -145,11 +148,11 @@ msgstr "Lissage de Delta" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode" -msgstr "Mode d'Utilisation Faible du Processeur" +msgstr "Mode d'utilisation faible du processeur" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode Sleep (µsec)" -msgstr "Mode d'Utilisation Faible du Processeur (µs)" +msgstr "Mode d'utilisation faible du processeur Veille (µsec)" #: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp msgid "Keep Screen On" @@ -242,9 +245,8 @@ msgid "Time Scale" msgstr "Echelle de temps" #: core/bind/core_bind.cpp main/main.cpp -#, fuzzy msgid "Physics Jitter Fix" -msgstr "Correction de la physique gigue" +msgstr "Correction des sursauts de physique" #: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Error" @@ -315,7 +317,7 @@ msgstr "Taille de page" #: core/io/file_access_network.cpp msgid "Page Read Ahead" -msgstr "" +msgstr "Pré-lecture de page" #: core/io/http_client.cpp msgid "Blocking Mode Enabled" @@ -327,7 +329,7 @@ msgstr "Connexion" #: core/io/http_client.cpp msgid "Read Chunk Size" -msgstr "" +msgstr "Taile des tronçons de lecture" #: core/io/marshalls.cpp msgid "Object ID" @@ -359,19 +361,19 @@ msgstr "Mode de Transfert" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" -msgstr "" +msgstr "Taille maximale du tampon d'encodage" #: core/io/packet_peer.cpp msgid "Input Buffer Max Size" -msgstr "" +msgstr "Taille maximale du tampon d'entrée" #: core/io/packet_peer.cpp msgid "Output Buffer Max Size" -msgstr "" +msgstr "Taille maximale du tampon de sortie" #: core/io/packet_peer.cpp msgid "Stream Peer" -msgstr "" +msgstr "Pair de flux" #: core/io/stream_peer.cpp msgid "Big Endian" @@ -484,9 +486,8 @@ msgid "Command" msgstr "Commande" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (physique)" +msgstr "Physique" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -496,7 +497,7 @@ msgstr "Pressé" #: core/os/input_event.cpp msgid "Scancode" -msgstr "Scancode" +msgstr "Code de scan" #: core/os/input_event.cpp msgid "Physical Scancode" @@ -539,6 +540,10 @@ msgid "Pressure" msgstr "Pression" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Stylo Inversé" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relatif" @@ -615,7 +620,7 @@ msgstr "Application" #: core/project_settings.cpp main/main.cpp msgid "Config" -msgstr "Config" +msgstr "Configuration" #: core/project_settings.cpp msgid "Project Settings Override" @@ -722,9 +727,8 @@ msgid "Editor" msgstr "Éditeur" #: core/project_settings.cpp -#, fuzzy msgid "Main Run Args" -msgstr "Arguments de la scène principale :" +msgstr "Paramètres d'exécution du programme principal" #: core/project_settings.cpp msgid "Scene Naming" @@ -732,11 +736,11 @@ msgstr "Noms de scènes" #: core/project_settings.cpp msgid "Search In File Extensions" -msgstr "" +msgstr "Rechercher dans les extensions de fichiers" #: core/project_settings.cpp msgid "Script Templates Search Path" -msgstr "" +msgstr "Chemin où chercher les modèles de scripts" #: core/project_settings.cpp msgid "Version Control Autoload On Startup" @@ -753,15 +757,13 @@ msgstr "Entrée" #: core/project_settings.cpp msgid "UI Accept" -msgstr "" +msgstr "Accepter" #: core/project_settings.cpp -#, fuzzy msgid "UI Select" msgstr "Sélectionner" #: core/project_settings.cpp -#, fuzzy msgid "UI Cancel" msgstr "Annuler" @@ -783,24 +785,23 @@ msgstr "Droite" #: core/project_settings.cpp msgid "UI Up" -msgstr "" +msgstr "Haut" #: core/project_settings.cpp msgid "UI Down" msgstr "Bas" #: core/project_settings.cpp -#, fuzzy msgid "UI Page Up" -msgstr "Page Haut" +msgstr "Page Haut (Interface)" #: core/project_settings.cpp msgid "UI Page Down" -msgstr "" +msgstr "Page Bas" #: core/project_settings.cpp msgid "UI Home" -msgstr "" +msgstr "Accueil Interface Utilisateur" #: core/project_settings.cpp msgid "UI End" @@ -828,9 +829,8 @@ msgid "3D" msgstr "3D" #: core/project_settings.cpp -#, fuzzy msgid "Smooth Trimesh Collision" -msgstr "Collision Lisse Trimesh" +msgstr "Lissage de Collision Trimesh" #: core/project_settings.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles2/rasterizer_scene_gles2.cpp @@ -862,7 +862,7 @@ msgstr "Filtres" #: core/project_settings.cpp scene/main/viewport.cpp msgid "Sharpen Intensity" -msgstr "" +msgstr "Augmenter l'intensité" #: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp @@ -900,11 +900,11 @@ msgstr "Formats" #: core/project_settings.cpp msgid "Zstd" -msgstr "" +msgstr "Zstd" #: core/project_settings.cpp msgid "Long Distance Matching" -msgstr "" +msgstr "Appairement longue distance" #: core/project_settings.cpp msgid "Compression Level" @@ -912,7 +912,7 @@ msgstr "Niveau de Compression" #: core/project_settings.cpp msgid "Window Log Size" -msgstr "" +msgstr "Taille du journal de la fenêtre" #: core/project_settings.cpp msgid "Zlib" @@ -928,7 +928,7 @@ msgstr "Android" #: core/project_settings.cpp msgid "Modules" -msgstr "" +msgstr "Modules" #: core/register_core_types.cpp msgid "TCP" @@ -940,11 +940,11 @@ msgstr "Délai d'expiration de la connexion en secondes" #: core/register_core_types.cpp msgid "Packet Peer Stream" -msgstr "" +msgstr "Flux de pair de paquet" #: core/register_core_types.cpp msgid "Max Buffer (Power of 2)" -msgstr "" +msgstr "Tampon Max (puissance de 2)" #: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp msgid "SSL" @@ -985,7 +985,7 @@ msgstr "Test" #: core/translation.cpp scene/resources/font.cpp msgid "Fallback" -msgstr "" +msgstr "Repli" #: core/ustring.cpp scene/resources/segment_shape_2d.cpp msgid "B" @@ -1021,17 +1021,17 @@ msgstr "Eio" #: drivers/gles3/rasterizer_scene_gles3.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp modules/gltf/gltf_state.cpp msgid "Buffers" -msgstr "" +msgstr "Tampons" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Canvas Polygon Buffer Size (KB)" -msgstr "" +msgstr "Taille du tampon des polygones du canevas (Ko)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Canvas Polygon Index Buffer Size (KB)" -msgstr "" +msgstr "Taille de l'index des polygones du canevas (Ko)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp @@ -1043,56 +1043,52 @@ msgstr "" #: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp #: servers/visual_server.cpp msgid "2D" -msgstr "" +msgstr "2D" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Snapping" -msgstr "Magnétisme intelligent" +msgstr "Magnétisme" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Use GPU Pixel Snap" -msgstr "Aligner au pixel près" +msgstr "Arrondissement GPU au pixel le plus proche" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Immediate Buffer Size (KB)" -msgstr "" +msgstr "Taille du tampon immédiat (Ko)" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp -#, fuzzy msgid "Lightmapping" -msgstr "Précalculer les lightmaps" +msgstr "Cartographie des lumières" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp msgid "Use Bicubic Sampling" -msgstr "" +msgstr "Utiliser l’échantillonnage bicubique" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Elements" -msgstr "" +msgstr "Maximum d'éléments pouvant être rendus" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Lights" -msgstr "" +msgstr "Maximum de lumières pouvant être rendues" #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Max Renderable Reflections" -msgstr "Centrer sur la sélection" +msgstr "Nombre maximum de reflets pouvant être rendus" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Lights Per Object" -msgstr "" +msgstr "Maximum de lumières par objet" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Subsurface Scattering" -msgstr "" +msgstr "Transluminescence" #: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp @@ -1113,11 +1109,11 @@ msgstr "Suivre la surface" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Weight Samples" -msgstr "" +msgstr "Échantillons de poids" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Voxel Cone Tracing" -msgstr "" +msgstr "Traçage de cone voxel" #: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp msgid "High Quality" @@ -1125,7 +1121,7 @@ msgstr "Haute Qualité" #: drivers/gles3/rasterizer_storage_gles3.cpp msgid "Blend Shape Max Buffer Size (KB)" -msgstr "" +msgstr "Taille max du tampon de mélange de formes" #. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror). #: editor/animation_bezier_editor.cpp @@ -1182,7 +1178,7 @@ msgstr "Modifier le temps de l’image-clé" #: editor/animation_track_editor.cpp msgid "Anim Change Transition" -msgstr "Changer la transition de l’animation" +msgstr "Transition de changement de l’animation" #: editor/animation_track_editor.cpp msgid "Anim Change Transform" @@ -1199,9 +1195,8 @@ msgstr "Changer l’appel de l’animation" #: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Frame" -msgstr "Image %" +msgstr "Trame" #: editor/animation_track_editor.cpp editor/editor_profiler.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp @@ -1227,14 +1222,13 @@ msgid "Value" msgstr "Valeur" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Arg Count" -msgstr "Compte" +msgstr "Nombre d'arguments" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp msgid "Args" -msgstr "" +msgstr "Args" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp @@ -1244,31 +1238,27 @@ msgid "Type" msgstr "Type" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "Définir la poignée" +msgstr "Poignée d'entrée" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out Handle" -msgstr "Définir la poignée" +msgstr "Poignée de sortie" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp msgid "Stream" -msgstr "" +msgstr "Flux" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start Offset" -msgstr "Décalage du Pivot" +msgstr "Décalage du Départ" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End Offset" -msgstr "Décalage :" +msgstr "Décalage à la fin" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/import/resource_importer_scene.cpp @@ -1281,9 +1271,8 @@ msgid "Animation" msgstr "Animation" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing" -msgstr "Ease in-out" +msgstr "Transition entrée-sortie" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" @@ -1418,44 +1407,36 @@ msgid "Type:" msgstr "Type :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "(Invalid, expected type: %s)" -msgstr "Modèle d'exportation non valide :" +msgstr "(Invalide, type attendu : %s)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing:" -msgstr "Ease in-out" +msgstr "Transition entrée-sortie :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In-Handle:" -msgstr "Définir la poignée" +msgstr "Poignée d'entrée :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out-Handle:" -msgstr "Définir la poignée" +msgstr "Poignée de sortie :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Stream:" -msgstr "Item radio" +msgstr "Flux :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "Redémarrer (s) :" +msgstr "Début (s) :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End (s):" -msgstr "Fondu entrant (s) :" +msgstr "Fin (s) :" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Clip:" -msgstr "Animations :" +msgstr "Clip d'animation :" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -1543,9 +1524,8 @@ msgid "Editors" msgstr "Éditeurs" #: editor/animation_track_editor.cpp editor/editor_settings.cpp -#, fuzzy msgid "Confirm Insert Track" -msgstr "Insérer une piste et clé d’animation" +msgstr "Confirmer l'ajout de piste" #. TRANSLATORS: %s will be replaced by a phrase describing the target of track. #: editor/animation_track_editor.cpp @@ -1695,7 +1675,7 @@ msgstr "Méthodes" #: editor/animation_track_editor.cpp msgid "Bezier" -msgstr "" +msgstr "Bezier" #: editor/animation_track_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -2212,14 +2192,15 @@ msgstr "Favoris :" msgid "Recent:" msgstr "Récents :" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Rechercher :" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Correspondances :" @@ -2279,8 +2260,8 @@ msgstr "Recherche ressource de remplacement :" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2289,7 +2270,7 @@ msgstr "Ouvrir" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Possesseur de : %s (Total : %d)" #: editor/dependency_editor.cpp msgid "" @@ -2857,22 +2838,19 @@ msgstr "Choisir" #: editor/editor_export.cpp msgid "Project export for platform:" -msgstr "" +msgstr "Exportation du projet pour la plateforme :" #: editor/editor_export.cpp -#, fuzzy -msgid "Completed with errors." -msgstr "Copier le chemin du nÅ“ud" +msgid "Completed with warnings." +msgstr "Terminé avec des avertissements." #: editor/editor_export.cpp -#, fuzzy msgid "Completed successfully." -msgstr "Paquetage installé avec succès !" +msgstr "Terminé avec succès." #: editor/editor_export.cpp -#, fuzzy msgid "Failed." -msgstr "Échec :" +msgstr "Échec." #: editor/editor_export.cpp msgid "Storing File:" @@ -2887,29 +2865,24 @@ msgid "Packing" msgstr "Empaquetage" #: editor/editor_export.cpp -#, fuzzy msgid "Save PCK" -msgstr "Enregistrer sous" +msgstr "Enregistrer PCK" #: editor/editor_export.cpp -#, fuzzy msgid "Cannot create file \"%s\"." -msgstr "Impossible de créer le dossier." +msgstr "Impossible de créer le fichier \"%s\"." #: editor/editor_export.cpp -#, fuzzy msgid "Failed to export project files." -msgstr "Impossible d'exporter les fichiers du projet" +msgstr "Impossible d'exporter les fichiers du projet." #: editor/editor_export.cpp -#, fuzzy msgid "Can't open file to read from path \"%s\"." -msgstr "Impossible d'ouvrir le fichier pour écriture :" +msgstr "Impossible d'ouvrir le fichier en lecture depuis le chemin \"%s\"." #: editor/editor_export.cpp -#, fuzzy msgid "Save ZIP" -msgstr "Enregistrer sous" +msgstr "Enregistrer le ZIP" #: editor/editor_export.cpp msgid "" @@ -2990,28 +2963,27 @@ msgstr "64 Bits" #: editor/editor_export.cpp msgid "Embed PCK" -msgstr "" +msgstr "Intégrer PCK" #: editor/editor_export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Texture Format" -msgstr "RegionDeTexture" +msgstr "Format de la texture" #: editor/editor_export.cpp msgid "BPTC" -msgstr "" +msgstr "BPTC" #: editor/editor_export.cpp platform/osx/export/export.cpp msgid "S3TC" -msgstr "" +msgstr "S3TC" #: editor/editor_export.cpp platform/osx/export/export.cpp msgid "ETC" -msgstr "" +msgstr "ETC" #: editor/editor_export.cpp platform/osx/export/export.cpp msgid "ETC2" -msgstr "" +msgstr "ETC2" #: editor/editor_export.cpp msgid "No BPTC Fallbacks" @@ -3030,30 +3002,25 @@ msgid "Custom release template not found." msgstr "Modèle de version personnalisée introuvable." #: editor/editor_export.cpp -#, fuzzy msgid "Prepare Template" -msgstr "Gérer les modèles" +msgstr "Préparer le modèle type" #: editor/editor_export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "The given export path doesn't exist." -msgstr "Le chemin de l'exportation donné n'existe pas :" +msgstr "Le chemin de l'exportation donné n'existe pas." #: editor/editor_export.cpp platform/javascript/export/export.cpp -#, fuzzy msgid "Template file not found: \"%s\"." -msgstr "Fichier modèle introuvable :" +msgstr "Fichier modèle introuvable : \"%s\"." #: editor/editor_export.cpp -#, fuzzy msgid "Failed to copy export template." -msgstr "Modèle d'exportation non valide :" +msgstr "La copie du modèle d'exportation a échoué." #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp -#, fuzzy msgid "PCK Embedding" -msgstr "Remplissage(Padding)" +msgstr "Intégration PCK" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." @@ -3061,7 +3028,7 @@ msgstr "Le PCK inclus dans un export 32-bits ne peut dépasser 4 Go." #: editor/editor_export.cpp msgid "Convert Text Resources To Binary On Export" -msgstr "" +msgstr "Convertir les ressources textuelles en binaire lors de l'exportation" #: editor/editor_feature_profile.cpp msgid "3D Editor" @@ -3274,9 +3241,8 @@ msgid "Manage Editor Feature Profiles" msgstr "Gérer les profils de fonctionnalités de l'éditeur" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Default Feature Profile" -msgstr "Profil des fonctionnalités de Godot" +msgstr "Profil de fonctionalités par défaut" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -3388,7 +3354,7 @@ msgstr "Afficher les fichiers cachés" #: editor/editor_file_dialog.cpp msgid "Disable Overwrite Warning" -msgstr "" +msgstr "Désactiver l'avertissement de réécriture" #: editor/editor_file_dialog.cpp msgid "Go Back" @@ -3491,7 +3457,7 @@ msgstr "Ré-importation des assets" #: editor/editor_file_system.cpp msgid "Reimport Missing Imported Files" -msgstr "" +msgstr "Réimporter les fichiers importés manquants" #: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp #: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp @@ -3602,7 +3568,7 @@ msgstr "Aide" #: editor/editor_help.cpp msgid "Sort Functions Alphabetically" -msgstr "" +msgstr "Trier les fonctions par ordre alphabétique" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp @@ -3691,25 +3657,21 @@ msgid "Read Only" msgstr "Lecture Seule" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp -#, fuzzy msgid "Checkable" -msgstr "Item à cocher" +msgstr "Cochable" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Checked" -msgstr "Item coché" +msgstr "Coché" #: editor/editor_inspector.cpp -#, fuzzy msgid "Draw Red" -msgstr "Appels de dessin :" +msgstr "Dessiner en rouge" #: editor/editor_inspector.cpp -#, fuzzy msgid "Keying" -msgstr "Jouer" +msgstr "En train de taper" #: editor/editor_inspector.cpp msgid "Pin value" @@ -4083,9 +4045,8 @@ msgid "Save & Reload" msgstr "Sauvegarder & Recharger" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to '%s' before reloading?" -msgstr "Sauvegarder les modifications effectuées à « %s » avant de quitter ?" +msgstr "Sauvegarder les modifications dans '%s' avant de recharger ?" #: editor/editor_node.cpp msgid "Save & Close" @@ -4204,11 +4165,9 @@ msgid "Open Project Manager?" msgstr "Ouvrir le gestionnaire de projets ?" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to the following scene(s) before reloading?" msgstr "" -"Sauvegarder les modifications sur la (les) scène(s) suivante(s) avant de " -"quitter ?" +"Sauvegarder les modifications de scène(s) suivante(s) avant de recharger ?" #: editor/editor_node.cpp msgid "Save & Quit" @@ -4404,6 +4363,8 @@ msgstr "%d fichiers supplémentaires" msgid "" "Unable to write to file '%s', file in use, locked or lacking permissions." msgstr "" +"Impossible d'écrire dans le fichier '%s', le fichier est peut être utilisé, " +"verrouillé ou vous n'avez pas les permissions pour écrire dessus." #: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp #: servers/arvr/arvr_interface.cpp @@ -4411,58 +4372,52 @@ msgid "Interface" msgstr "Interface" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Scene Tabs" -msgstr "Basculer entre onglets de scène" +msgstr "Onglets de scène" #: editor/editor_node.cpp -#, fuzzy msgid "Always Show Close Button" -msgstr "Toujours afficher la grille" +msgstr "Toujours afficher le bouton fermer" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Resize If Many Tabs" -msgstr "" +msgstr "Redimensionner si plusieurs onglets" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Minimum Width" -msgstr "" +msgstr "Largeur Minimum" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Output" msgstr "Sortie" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Always Clear Output On Play" -msgstr "Effacer la sortie" +msgstr "Toujours nettoyer la sortie lors du lancement" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Open Output On Play" -msgstr "" +msgstr "Toujours afficher la sortie lors du lancement" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Close Output On Stop" -msgstr "" +msgstr "Toujours fermer la sortie à l'arrêt" #: editor/editor_node.cpp msgid "Save On Focus Loss" -msgstr "" +msgstr "Enregistrer lorsque le focus est perdu" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Save Each Scene On Quit" -msgstr "Sauvegarder la branche comme scène" +msgstr "Enregistrer toutes les scènes à la fermeture" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Quit Confirmation" -msgstr "Voir information" +msgstr "Confirmer avant de quitter" #: editor/editor_node.cpp -#, fuzzy msgid "Show Update Spinner" -msgstr "Cacher l'indicateur d'activité" +msgstr "Afficher l'indicateur d'activité" #: editor/editor_node.cpp msgid "Update Continuously" @@ -4474,62 +4429,56 @@ msgid "Update Vital Only" msgstr "Changements de matériau" #: editor/editor_node.cpp -#, fuzzy msgid "Localize Settings" -msgstr "Localisation" +msgstr "Traduction des réglages" #: editor/editor_node.cpp -#, fuzzy msgid "Restore Scenes On Load" -msgstr "Le nÅ“ud de la scène" +msgstr "Restaurer les scènes au chargement" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Show Thumbnail On Hover" -msgstr "" +msgstr "Afficher l’aperçu au survol" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Inspector" msgstr "Inspecteur" #: editor/editor_node.cpp -#, fuzzy msgid "Default Property Name Style" -msgstr "Chemin du projet :" +msgstr "Style par défaut des noms de propriétés" #: editor/editor_node.cpp msgid "Default Float Step" -msgstr "" +msgstr "Pas par défaut des flottant" #: editor/editor_node.cpp scene/gui/tree.cpp -#, fuzzy msgid "Disable Folding" -msgstr "Bouton désactivé" +msgstr "Désactiver le repliage" #: editor/editor_node.cpp msgid "Auto Unfold Foreign Scenes" -msgstr "" +msgstr "Déplier automatiquement les scènes étrangères" #: editor/editor_node.cpp msgid "Horizontal Vector2 Editing" -msgstr "" +msgstr "Édition horizontale de Vector2" #: editor/editor_node.cpp msgid "Horizontal Vector Types Editing" -msgstr "" +msgstr "Édition de Types de Vecteur Horizontal" #: editor/editor_node.cpp -#, fuzzy msgid "Open Resources In Current Inspector" -msgstr "Ouvrir dans l'Inspecteur" +msgstr "Ouvrir les ressources dans l'inspecteur actuel" #: editor/editor_node.cpp -#, fuzzy msgid "Resources To Open In New Inspector" -msgstr "Ouvrir dans l'Inspecteur" +msgstr "Ressources à ouvrir dans un nouvel inspecteur" #: editor/editor_node.cpp msgid "Default Color Picker Mode" -msgstr "" +msgstr "Mode par défaut du sélectionneur de couleur" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Version Control" @@ -5190,12 +5139,11 @@ msgstr "Débogueur" #: editor/editor_profiler.cpp msgid "Profiler Frame History Size" -msgstr "" +msgstr "Taille de l'historique de la trame du profileur" #: editor/editor_profiler.cpp -#, fuzzy msgid "Profiler Frame Max Functions" -msgstr "Renommer la fonction" +msgstr "Nombre maximum de fonctions par trame de profileur" #: editor/editor_properties.cpp msgid "Edit Text:" @@ -5328,20 +5276,17 @@ msgstr "Nouveau %s" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Base Type" -msgstr "Changer le type de base" +msgstr "Type de base" #: editor/editor_resource_picker.cpp -#, fuzzy msgid "Edited Resource" -msgstr "Ajouter une ressource" +msgstr "Ressource modifiée" #: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp #: scene/gui/slider.cpp scene/gui/spin_box.cpp -#, fuzzy msgid "Editable" -msgstr "Élément modifiable" +msgstr "Modifiable" #: editor/editor_resource_picker.cpp editor/property_editor.cpp msgid "New Script" @@ -5365,9 +5310,8 @@ msgstr "" "Ajoutez un préréglage exécutable dans le menu d'exportation." #: editor/editor_run_native.cpp -#, fuzzy msgid "Project Run" -msgstr "Projet" +msgstr "Exécution du projet" #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." @@ -5394,34 +5338,32 @@ msgid "Did you forget the '_run' method?" msgstr "Avez-vous oublié la méthode « _run » ?" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor Language" -msgstr "Disposition de l'éditeur" +msgstr "Langue de l'Éditeur" #: editor/editor_settings.cpp -#, fuzzy msgid "Display Scale" -msgstr "Tout afficher" +msgstr "Échelle de l'affichage" #: editor/editor_settings.cpp msgid "Custom Display Scale" -msgstr "" +msgstr "Échelle personnalisé de l'affichage" #: editor/editor_settings.cpp msgid "Main Font Size" -msgstr "" +msgstr "Taille de la police principale" #: editor/editor_settings.cpp msgid "Code Font Size" -msgstr "" +msgstr "Taille de la police du code" #: editor/editor_settings.cpp msgid "Font Antialiased" -msgstr "" +msgstr "Police anticrénelée" #: editor/editor_settings.cpp msgid "Font Hinting" -msgstr "" +msgstr "Indication de police" #: editor/editor_settings.cpp msgid "Main Font" @@ -5429,7 +5371,7 @@ msgstr "Police Principale" #: editor/editor_settings.cpp msgid "Main Font Bold" -msgstr "" +msgstr "Principale police grasse" #: editor/editor_settings.cpp msgid "Code Font" @@ -5437,28 +5379,27 @@ msgstr "Police du Code" #: editor/editor_settings.cpp msgid "Dim Editor On Dialog Popup" -msgstr "" +msgstr "Assombrir l'éditeur à l'ouverture d'un dialogue" #: editor/editor_settings.cpp main/main.cpp msgid "Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Veille du Mode faible latence Processeur (µsec)" #: editor/editor_settings.cpp msgid "Unfocused Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Veille du mode d'utilisation faible du processeur quand inactif (µsec)" #: editor/editor_settings.cpp -#, fuzzy msgid "Separate Distraction Mode" -msgstr "Mode Sans Distraction" +msgstr "Mode distraction séparée" #: editor/editor_settings.cpp msgid "Automatically Open Screenshots" -msgstr "" +msgstr "Ouvrir automatiquement les captures d'écran" #: editor/editor_settings.cpp msgid "Max Array Dictionary Items Per Page" -msgstr "" +msgstr "Nombre maximum d'articles tableau de dictionnaire par page" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp @@ -5472,85 +5413,75 @@ msgstr "Préréglage" #: editor/editor_settings.cpp msgid "Icon And Font Color" -msgstr "" +msgstr "Couleur de police et d'icône" #: editor/editor_settings.cpp msgid "Base Color" msgstr "Couleur de Base" #: editor/editor_settings.cpp -#, fuzzy msgid "Accent Color" -msgstr "Prélever une couleur" +msgstr "Couleur d'accentuation" #: editor/editor_settings.cpp scene/resources/environment.cpp msgid "Contrast" -msgstr "" +msgstr "Contraste" #: editor/editor_settings.cpp msgid "Relationship Line Opacity" -msgstr "" +msgstr "Opacité des lignes de relation" #: editor/editor_settings.cpp -#, fuzzy msgid "Highlight Tabs" -msgstr "Enregistrement des lightmaps" +msgstr "Surligner les onglets" #: editor/editor_settings.cpp -#, fuzzy msgid "Border Size" -msgstr "Pixels de bordure" +msgstr "Taille de bordure" #: editor/editor_settings.cpp msgid "Use Graph Node Headers" -msgstr "" +msgstr "Utiliser les en-têtes de graphes des nÅ“uds" #: editor/editor_settings.cpp -#, fuzzy msgid "Additional Spacing" -msgstr "Bouclage de l’animation" +msgstr "Espacement supplémentaire" #: editor/editor_settings.cpp msgid "Custom Theme" msgstr "Thème Personnalisé" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Script Button" -msgstr "Molette bouton droit" +msgstr "Afficher le bouton script" #: editor/editor_settings.cpp -#, fuzzy msgid "Directories" -msgstr "Directions" +msgstr "Dossiers" #: editor/editor_settings.cpp -#, fuzzy msgid "Autoscan Project Path" -msgstr "Chemin du projet :" +msgstr "Scan auto du chemin du projet" #: editor/editor_settings.cpp msgid "Default Project Path" msgstr "Chemin du Projet par Défaut" #: editor/editor_settings.cpp -#, fuzzy msgid "On Save" -msgstr "Enregistrer" +msgstr "À l'enregistrement" #: editor/editor_settings.cpp -#, fuzzy msgid "Compress Binary Resources" -msgstr "Copier la ressource" +msgstr "Compresser les ressources binaires" #: editor/editor_settings.cpp msgid "Safe Save On Backup Then Rename" -msgstr "" +msgstr "Sauvegarde sécurisée lors de l'archivage avant de renommer" #: editor/editor_settings.cpp -#, fuzzy msgid "File Dialog" -msgstr "Dialogue XForm" +msgstr "Fenêtre de sélection de fichiers" #: editor/editor_settings.cpp msgid "Thumbnail Size" @@ -5558,7 +5489,7 @@ msgstr "Taille de la vignette" #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "S'attache" #: editor/editor_settings.cpp msgid "Scene Tree" @@ -5566,12 +5497,11 @@ msgstr "une arborescence, arbre des scènes" #: editor/editor_settings.cpp msgid "Start Create Dialog Fully Expanded" -msgstr "" +msgstr "Lancer le dialogue de création complètement déplié" #: editor/editor_settings.cpp -#, fuzzy msgid "Always Show Folders" -msgstr "Toujours afficher la grille" +msgstr "Toujours afficher les dossiers" #: editor/editor_settings.cpp msgid "Property Editor" @@ -5579,69 +5509,61 @@ msgstr "Éditeur de Propriétés" #: editor/editor_settings.cpp msgid "Auto Refresh Interval" -msgstr "" +msgstr "Intervalle d’autorafraîchissement" #: editor/editor_settings.cpp -#, fuzzy msgid "Subresource Hue Tint" -msgstr "Ressources secondaires" +msgstr "Teinte des sous-ressources" #: editor/editor_settings.cpp -#, fuzzy msgid "Color Theme" -msgstr "Thème de l'éditeur" +msgstr "Thème de couleurs" #: editor/editor_settings.cpp scene/3d/label_3d.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Line Spacing" -msgstr "" +msgstr "Espace entre les lignes" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Highlighting" -msgstr "Éclairage direct" +msgstr "Surlignage" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Syntax Highlighting" msgstr "Coloration syntaxique" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight All Occurrences" -msgstr "" +msgstr "Mettre en évidence toutes les occurrences" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight Current Line" -msgstr "" +msgstr "Mettre en évidence la ligne actuelle" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Highlight Type Safe Lines" -msgstr "" +msgstr "Surligner les lignes à types sûrs" #: editor/editor_settings.cpp -#, fuzzy msgid "Indent" -msgstr "Indenter vers la gauche" +msgstr "Indenter" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Auto Indent" msgstr "Indentation automatique" #: editor/editor_settings.cpp -#, fuzzy msgid "Convert Indent On Save" -msgstr "Convertir indentations en espaces" +msgstr "Convertir les indentations à l'enregistrement" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Draw Tabs" -msgstr "Appels de dessin :" +msgstr "Montrer les tabulations" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Draw Spaces" -msgstr "Appels de dessin :" +msgstr "Afficher les espaces" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp @@ -5652,75 +5574,75 @@ msgstr "Navigation" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Smooth Scrolling" -msgstr "" +msgstr "Défilement Doux" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "V Scroll Speed" -msgstr "" +msgstr "Vitesse du défilement vertical" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Minimap" -msgstr "Afficher l'origine" +msgstr "Afficher la minimap" #: editor/editor_settings.cpp msgid "Minimap Width" -msgstr "" +msgstr "Largeur de la mini-carte" #: editor/editor_settings.cpp msgid "Mouse Extra Buttons Navigate History" -msgstr "" +msgstr "Boutons additionnels de la souris déplacent dans l'historique" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "Sélection de la GridMap" +msgstr "Sélection glisser/déposer" + +#: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "Rester sur l’éditeur de script en sélectionnant un nÅ“ud" #: editor/editor_settings.cpp msgid "Appearance" -msgstr "" +msgstr "Apparence" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Show Line Numbers" msgstr "Afficher les Numéros de Ligne" #: editor/editor_settings.cpp -#, fuzzy msgid "Line Numbers Zero Padded" -msgstr "Numéro de ligne :" +msgstr "Numéros de lignes avec remplissage en zéros" #: editor/editor_settings.cpp msgid "Show Bookmark Gutter" -msgstr "" +msgstr "Montrer le bandeau de marque-page" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Breakpoint Gutter" -msgstr "Passer les points d'arrêt" +msgstr "Afficher le bandeau de points d’arrêt" #: editor/editor_settings.cpp msgid "Show Info Gutter" -msgstr "" +msgstr "Montrer le bandeau d'information" #: editor/editor_settings.cpp msgid "Code Folding" -msgstr "" +msgstr "Rétrécir le code" #: editor/editor_settings.cpp msgid "Word Wrap" -msgstr "" +msgstr "Retour à la ligne des mots" #: editor/editor_settings.cpp msgid "Show Line Length Guidelines" -msgstr "" +msgstr "Montrer les guides de longueur de ligne" #: editor/editor_settings.cpp msgid "Line Length Guideline Soft Column" -msgstr "" +msgstr "Colonne douce des guides de longueur de ligne" #: editor/editor_settings.cpp msgid "Line Length Guideline Hard Column" -msgstr "" +msgstr "Colonne dure des guides de longueur de ligne" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Script List" @@ -5728,66 +5650,64 @@ msgstr "Liste des Scripts" #: editor/editor_settings.cpp msgid "Show Members Overview" -msgstr "" +msgstr "Montrer l'ensemble des Membres" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Files" msgstr "Fichiers" #: editor/editor_settings.cpp -#, fuzzy msgid "Trim Trailing Whitespace On Save" -msgstr "Supprimer les espaces de fin de ligne" +msgstr "Retirer les espaces de fin de ligne à l'enregistrement" #: editor/editor_settings.cpp msgid "Autosave Interval Secs" -msgstr "" +msgstr "Intervalle entre les sauvegardes automatiques (en secondes)" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Restore Scripts On Load" -msgstr "" +msgstr "Restaurer les scripts au chargement" #: editor/editor_settings.cpp msgid "Auto Reload And Parse Scripts On Save" msgstr "" +"Recharger et parcourir les scripts automatiquement lors de la sauvegarde" #: editor/editor_settings.cpp msgid "Auto Reload Scripts On External Change" -msgstr "" +msgstr "Recharger automatiquement les scripts sur changement externe" #: editor/editor_settings.cpp -#, fuzzy msgid "Create Signal Callbacks" -msgstr "Forcer les replis du shader" +msgstr "Créer des rappels de signaux" #: editor/editor_settings.cpp msgid "Sort Members Outline Alphabetically" -msgstr "" +msgstr "Trier le contour des membres alphabétiquement" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Cursor" -msgstr "" +msgstr "Curseur" #: editor/editor_settings.cpp msgid "Scroll Past End Of File" -msgstr "" +msgstr "Défiler au-delà de la fin du fichier" #: editor/editor_settings.cpp msgid "Block Caret" -msgstr "" +msgstr "Caret bloc" #: editor/editor_settings.cpp msgid "Caret Blink" -msgstr "" +msgstr "Clignotement du caret" #: editor/editor_settings.cpp msgid "Caret Blink Speed" -msgstr "" +msgstr "Vitesse du clignotement du caret" #: editor/editor_settings.cpp -#, fuzzy msgid "Right Click Moves Caret" -msgstr "Clic droit pour ajouter un point" +msgstr "Clic droit déplace le caret" #: editor/editor_settings.cpp modules/gdscript/gdscript.cpp #: modules/gdscript/gdscript_editor.cpp @@ -5801,39 +5721,35 @@ msgstr "" #: editor/editor_settings.cpp msgid "Auto Brace Complete" -msgstr "" +msgstr "Complétion automatique des accolades" #: editor/editor_settings.cpp msgid "Code Complete Delay" -msgstr "" +msgstr "Délai d'auto-complétion du code" #: editor/editor_settings.cpp msgid "Put Callhint Tooltip Below Current Line" -msgstr "" +msgstr "Placer l'info-bulle d'appel sous la ligne actuelle" #: editor/editor_settings.cpp msgid "Callhint Tooltip Offset" -msgstr "" +msgstr "Décalage des info-bulles d'appel" #: editor/editor_settings.cpp -#, fuzzy msgid "Complete File Paths" -msgstr "Copier le chemin du nÅ“ud" +msgstr "Compléter les chemins de fichiers" #: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp -#, fuzzy msgid "Add Type Hints" -msgstr "Ajouter un type" +msgstr "Ajouter des indices de type" #: editor/editor_settings.cpp -#, fuzzy msgid "Use Single Quotes" -msgstr "Nouvelle Simple Tuile" +msgstr "Utiliser des simples guillemets" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Help Index" -msgstr "Afficher les aides" +msgstr "Afficher l'index d'aide" #: editor/editor_settings.cpp msgid "Help Font Size" @@ -5845,16 +5761,15 @@ msgstr "Taille de la police de l'aide de la source" #: editor/editor_settings.cpp msgid "Help Title Font Size" -msgstr "" +msgstr "Taille de la police du titre Aide" #: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp msgid "Grid Map" msgstr "Grille" #: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Pick Distance" -msgstr "Choisissez distance :" +msgstr "Choisissez la distance" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Preview Size" @@ -5862,39 +5777,34 @@ msgstr "Aperçu de la taille" #: editor/editor_settings.cpp msgid "Primary Grid Color" -msgstr "" +msgstr "Couleur de la grille principale" #: editor/editor_settings.cpp msgid "Secondary Grid Color" -msgstr "" +msgstr "Couleur de la grille secondaire" #: editor/editor_settings.cpp -#, fuzzy msgid "Selection Box Color" -msgstr "Sélection uniquement" +msgstr "Couleur de la boîte de sélection" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "3D Gizmos" -msgstr "Gadgets" +msgstr "Manipulateurs 3D" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Gizmo Colors" -msgstr "Couleurs d'émission" +msgstr "Couleurs des manipulateurs" #: editor/editor_settings.cpp -#, fuzzy msgid "Instanced" -msgstr "Instance" +msgstr "Instancié" #: editor/editor_settings.cpp modules/gltf/gltf_node.cpp #: scene/3d/physics_body.cpp -#, fuzzy msgid "Joint" -msgstr "Point" +msgstr "Jointure" #: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp @@ -5903,12 +5813,11 @@ msgstr "Point" #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Shape" -msgstr "" +msgstr "Forme" #: editor/editor_settings.cpp -#, fuzzy msgid "Primary Grid Steps" -msgstr "Pas de la grille :" +msgstr "Pas de la grille principale" #: editor/editor_settings.cpp msgid "Grid Size" @@ -5916,63 +5825,55 @@ msgstr "Taille de la Grille" #: editor/editor_settings.cpp msgid "Grid Division Level Max" -msgstr "" +msgstr "Niveau maximal de division de la grille" #: editor/editor_settings.cpp msgid "Grid Division Level Min" -msgstr "" +msgstr "Niveau minimal de division de la grille" #: editor/editor_settings.cpp msgid "Grid Division Level Bias" -msgstr "" +msgstr "Niveau de biais de la division de grille" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XZ Plane" -msgstr "Peinture GridMap" +msgstr "Plan XZ de la grille" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XY Plane" -msgstr "Peinture GridMap" +msgstr "Plan XY de la grille" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid YZ Plane" -msgstr "Peinture GridMap" +msgstr "Plan YZ de la grille" #: editor/editor_settings.cpp msgid "Default FOV" msgstr "FOV par défaut" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Near" -msgstr "Thème par défaut" +msgstr "Z proche par défaut" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Far" -msgstr "Défaut" +msgstr "Z distant par défaut" #: editor/editor_settings.cpp msgid "Lightmap Baking Number Of CPU Threads" -msgstr "" +msgstr "Nombre de fils CPU pour calculer les cartes de lumières" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Scheme" -msgstr "Mode Navigation" +msgstr "Schéma de navigation" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert Y Axis" -msgstr "Modifier l'axe Y" +msgstr "Inverser l'axe Y" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert X Axis" -msgstr "Modifier l'axe X" +msgstr "Inverser l'axe X" #: editor/editor_settings.cpp msgid "Zoom Style" @@ -5980,26 +5881,23 @@ msgstr "Style de Zoom" #: editor/editor_settings.cpp msgid "Emulate Numpad" -msgstr "" +msgstr "Émuler un pavé numérique" #: editor/editor_settings.cpp msgid "Emulate 3 Button Mouse" -msgstr "" +msgstr "Émuler souris à 3 boutons" #: editor/editor_settings.cpp -#, fuzzy msgid "Orbit Modifier" -msgstr "Trier par date de modification (moins récent au plus récent)" +msgstr "Modificateur d'orbite" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Modifier" -msgstr "Mode navigation" +msgstr "Modificateur panoramique" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Modifier" -msgstr "Modifié" +msgstr "Multiplicateur de Zoom" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Warped Mouse Panning" @@ -6012,11 +5910,11 @@ msgstr "Mode Navigation" #: editor/editor_settings.cpp msgid "Orbit Sensitivity" -msgstr "" +msgstr "Sensibilité de l'orbite" #: editor/editor_settings.cpp msgid "Orbit Inertia" -msgstr "" +msgstr "Inertie de l'orbite" #: editor/editor_settings.cpp msgid "Translation Inertia" @@ -6027,155 +5925,136 @@ msgid "Zoom Inertia" msgstr "Inertie du Zoom" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook" -msgstr "Vue libre haut" +msgstr "Vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Navigation Scheme" -msgstr "Créer un maillage de navigation" +msgstr "Schéma de navigation en vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Sensitivity" -msgstr "Vue libre gauche" +msgstr "Sensibilité de la vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Inertia" -msgstr "Vue libre gauche" +msgstr "Inertie de la vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Base Speed" -msgstr "Modificateur de vitesse de la vue libre" +msgstr "Vitesse de base de la vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Activation Modifier" -msgstr "Ralentissement de la vue libre" +msgstr "Modificateur d'activation de la vue libre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Speed Zoom Link" -msgstr "Modificateur de vitesse de la vue libre" +msgstr "Lien de zoom rapide de la vue libre" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Grid Color" msgstr "Couleur de la Grille" #: editor/editor_settings.cpp -#, fuzzy msgid "Guides Color" -msgstr "Prélever une couleur" +msgstr "Couleur des guides" #: editor/editor_settings.cpp -#, fuzzy msgid "Smart Snapping Line Color" -msgstr "Magnétisme intelligent" +msgstr "Couleur de ligne du magnétisme intelligent" #: editor/editor_settings.cpp msgid "Bone Width" -msgstr "" +msgstr "Largeur des os" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 1" -msgstr "Renommer l'item de couleur" +msgstr "Couleur d'os 1" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 2" -msgstr "Renommer l'item de couleur" +msgstr "Couleur d'os 2" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Selected Color" -msgstr "Configurer le profil sélectionné :" +msgstr "Couleur de l'os sélectionnée" #: editor/editor_settings.cpp msgid "Bone IK Color" -msgstr "" +msgstr "Couleur de cinématique inverse d'os" #: editor/editor_settings.cpp msgid "Bone Outline Color" -msgstr "" +msgstr "Couleur de contour d'os" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Outline Size" -msgstr "Taille du contour :" +msgstr "Taille du contour de l'os" #: editor/editor_settings.cpp msgid "Viewport Border Color" -msgstr "" +msgstr "Couleur de bordure de la fenêtre d'affichage" #: editor/editor_settings.cpp msgid "Constrain Editor View" -msgstr "" +msgstr "Restreindre la fenêtre d'Éditeur" #: editor/editor_settings.cpp msgid "Simple Panning" -msgstr "" +msgstr "Panoramique simple" #: editor/editor_settings.cpp msgid "Scroll To Pan" -msgstr "" +msgstr "Panoramique au défilement" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Speed" msgstr "Vitesse Panoramique" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Poly Editor" -msgstr "Éditeur UV de polygones 2D" +msgstr "Éditeur de polygones" #: editor/editor_settings.cpp msgid "Point Grab Radius" -msgstr "" +msgstr "Rayon de saisie par point" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Show Previous Outline" -msgstr "Plan précédent" +msgstr "Montrer le contour précédent" #: editor/editor_settings.cpp editor/scene_tree_dock.cpp -#, fuzzy msgid "Autorename Animation Tracks" -msgstr "Renommer l'animation" +msgstr "Renommer les pistes d'animation automatiquement" #: editor/editor_settings.cpp msgid "Default Create Bezier Tracks" -msgstr "" +msgstr "Créer pistes de Bézier par défaut" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Create Reset Tracks" -msgstr "Créer des pistes RESET" +msgstr "Créer pistes de réinitialisation par défaut" #: editor/editor_settings.cpp msgid "Onion Layers Past Color" -msgstr "" +msgstr "Couleur des couches d'oignon précedentes" #: editor/editor_settings.cpp msgid "Onion Layers Future Color" -msgstr "" +msgstr "Couleur des couches d'oignon suivantes" #: editor/editor_settings.cpp -#, fuzzy msgid "Visual Editors" -msgstr "Editeur de groupe" +msgstr "Éditeurs visuels" #: editor/editor_settings.cpp msgid "Minimap Opacity" -msgstr "" +msgstr "Opacité de la mini-carte" #: editor/editor_settings.cpp msgid "Window Placement" -msgstr "" +msgstr "Placement de la fenêtre" #: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp #: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp @@ -6184,18 +6063,16 @@ msgid "Rect" msgstr "Rect" #: editor/editor_settings.cpp -#, fuzzy msgid "Rect Custom Position" -msgstr "Définir la position de sortie de la courbe" +msgstr "Position du Rect personnalisée" #: editor/editor_settings.cpp platform/android/export/export_plugin.cpp msgid "Screen" -msgstr "" +msgstr "Écran" #: editor/editor_settings.cpp -#, fuzzy msgid "Auto Save" -msgstr "Coupe automatique" +msgstr "Sauvegarde auto" #: editor/editor_settings.cpp msgid "Save Before Running" @@ -6212,28 +6089,26 @@ msgstr "Hôte distant" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Remote Port" -msgstr "Supprimer un point" +msgstr "Port distant" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor SSL Certificates" -msgstr "Paramètres de l'éditeur" +msgstr "Certificats SSL de l’éditeur" #: editor/editor_settings.cpp msgid "HTTP Proxy" -msgstr "" +msgstr "Proxy HTTP" #: editor/editor_settings.cpp msgid "Host" -msgstr "" +msgstr "Hôte" #: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Port" -msgstr "" +msgstr "Port" #. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects. #: editor/editor_settings.cpp @@ -6247,37 +6122,35 @@ msgstr "Ordre de Tri" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Symbol Color" -msgstr "" +msgstr "Couleur de symbole" #: editor/editor_settings.cpp msgid "Keyword Color" -msgstr "" +msgstr "Couleur des mots-clés" #: editor/editor_settings.cpp msgid "Control Flow Keyword Color" -msgstr "" +msgstr "Couleur de mot clé de contrôle de flux" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Type Color" -msgstr "Changer le type de base" +msgstr "Couleur de base des types" #: editor/editor_settings.cpp msgid "Engine Type Color" -msgstr "" +msgstr "Couleur de type du moteur" #: editor/editor_settings.cpp msgid "User Type Color" -msgstr "" +msgstr "Couleur de type utilisateur" #: editor/editor_settings.cpp msgid "Comment Color" -msgstr "" +msgstr "Couleur des commentaires" #: editor/editor_settings.cpp -#, fuzzy msgid "String Color" -msgstr "Stockage du fichier :" +msgstr "Couleur des chaînes de caractères" #: editor/editor_settings.cpp platform/javascript/export/export.cpp #: platform/uwp/export/export.cpp @@ -6286,9 +6159,8 @@ msgid "Background Color" msgstr "Couleur d’Arrière-Plan" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Background Color" -msgstr "Couleur de fond invalide." +msgstr "Couleur d'arrière-plan de complétion" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -6316,23 +6188,20 @@ msgid "Line Number Color" msgstr "Couleur du Numéro de Ligne" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Safe Line Number Color" -msgstr "Numéro de ligne :" +msgstr "Couleur des nombres des lignes sûres" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Color" -msgstr "" +msgstr "Couleur du caret" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Caret Background Color" -msgstr "Couleur de fond invalide." +msgstr "Couleur d'arrière-plan de caret" #: editor/editor_settings.cpp -#, fuzzy msgid "Text Selected Color" -msgstr "Supprimer la selection" +msgstr "Couleur de texte sélectionné" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Selection Color" @@ -6340,7 +6209,7 @@ msgstr "Couleur de la Sélection" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Brace Mismatch Color" -msgstr "" +msgstr "Couleur des erreur de fermeture d'accolades" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Current Line Color" @@ -6348,26 +6217,23 @@ msgstr "Couleur de la Ligne Actuelle" #: editor/editor_settings.cpp msgid "Line Length Guideline Color" -msgstr "" +msgstr "Couleur du guide de longueur de ligne" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Word Highlighted Color" -msgstr "Coloration syntaxique" +msgstr "Couleur de surlignage des mots" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Number Color" -msgstr "" +msgstr "Couleur des nombres" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Function Color" -msgstr "Fonction" +msgstr "Couleur des fonctions" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Member Variable Color" -msgstr "Renommer la variable" +msgstr "Couleur des variables de membres" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -6375,32 +6241,28 @@ msgid "Mark Color" msgstr "Prélever une couleur" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Bookmark Color" -msgstr "Signets" +msgstr "Couleur des signets" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Breakpoint Color" -msgstr "Point d'arrêts" +msgstr "Couleur des point d'arrêts" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Executing Line Color" -msgstr "" +msgstr "Couleur de la ligne d’exécution" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Code Folding Color" -msgstr "" +msgstr "Couleur du repliage de code" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Color" -msgstr "Résultats de recherche" +msgstr "Couleur des résultats de recherche" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Border Color" -msgstr "Résultats de recherche" +msgstr "Couleur de bordure des résultats de recherche" #: editor/editor_spin_slider.cpp msgid "Hold %s to round to integers. Hold Shift for more precise changes." @@ -6413,9 +6275,8 @@ msgid "Flat" msgstr "Plat" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hide Slider" -msgstr "Mode collision" +msgstr "Cacher la barre de défilement" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -6714,7 +6575,7 @@ msgstr "" #: editor/fileserver/editor_file_server.cpp msgid "File Server" -msgstr "" +msgstr "Serveur de fichiers" #: editor/fileserver/editor_file_server.cpp #: editor/plugins/version_control_editor_plugin.cpp @@ -7087,11 +6948,11 @@ msgstr "Gérer les groupes" #: editor/import/editor_import_collada.cpp msgid "Collada" -msgstr "" +msgstr "Collada" #: editor/import/editor_import_collada.cpp msgid "Use Ambient" -msgstr "" +msgstr "Utiliser ambiant" #: editor/import/resource_importer_bitmask.cpp msgid "Create From" @@ -7100,7 +6961,7 @@ msgstr "Créer à Partir de" #: editor/import/resource_importer_bitmask.cpp #: servers/audio/effects/audio_effect_compressor.cpp msgid "Threshold" -msgstr "" +msgstr "Seuil" #: editor/import/resource_importer_csv_translation.cpp #: editor/import/resource_importer_layered_texture.cpp @@ -7112,7 +6973,7 @@ msgstr "Compresser" #: editor/import/resource_importer_csv_translation.cpp msgid "Delimiter" -msgstr "" +msgstr "Délimiteur" #: editor/import/resource_importer_layered_texture.cpp #, fuzzy @@ -7121,7 +6982,7 @@ msgstr "Correction de Couleur" #: editor/import/resource_importer_layered_texture.cpp msgid "No BPTC If RGB" -msgstr "" +msgstr "Pas de BPTC si RVB" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp @@ -7129,13 +6990,13 @@ msgstr "" #: scene/resources/material.cpp scene/resources/particles_material.cpp #: scene/resources/texture.cpp scene/resources/visual_shader.cpp msgid "Flags" -msgstr "" +msgstr "Paramètres" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp #: scene/resources/texture.cpp msgid "Repeat" -msgstr "" +msgstr "Répéter" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp @@ -7145,24 +7006,22 @@ msgstr "Filtre" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Mipmaps" -msgstr "Signaux" +msgstr "Mipmaps" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "Anisotropic" -msgstr "" +msgstr "Anisotrope" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "sRGB" -msgstr "" +msgstr "sRGB" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "Slices" -msgstr "Coupe automatique" +msgstr "Tranches" #: editor/import/resource_importer_layered_texture.cpp #: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp @@ -7179,30 +7038,25 @@ msgid "Vertical" msgstr "Vertical" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Generate Tangents" -msgstr "Générer des points" +msgstr "Générer les tangentes" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Scale Mesh" -msgstr "Mode mise à l'échelle" +msgstr "Échelle du maillage" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Offset Mesh" -msgstr "Décalage :" +msgstr "Décalage du maillage" #: editor/import/resource_importer_obj.cpp #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Octahedral Compression" -msgstr "Expression" +msgstr "Compression Octaédrique" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Optimize Mesh Flags" -msgstr "Optimiser les drapeaux de Mesh" +msgstr "Optimiser les paramètres du maillage" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" @@ -7258,9 +7112,8 @@ msgid "Root Name" msgstr "Nom de la Racine" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Scale" -msgstr "Mode mise à l'échelle" +msgstr "Échelle de la racine" #: editor/import/resource_importer_scene.cpp msgid "Custom Script" @@ -7272,16 +7125,15 @@ msgstr "Stockage" #: editor/import/resource_importer_scene.cpp msgid "Use Legacy Names" -msgstr "" +msgstr "Utiliser les noms hérités" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Materials" msgstr "Matériaux" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep On Reimport" -msgstr "Réimporter" +msgstr "Conserver à la réimportation" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Meshes" @@ -7293,47 +7145,40 @@ msgid "Ensure Tangents" msgstr "Modifier la tangente de courbes" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Light Baking" -msgstr "Précalculer les lightmaps" +msgstr "Pré-calculer les lumières" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Lightmap Texel Size" -msgstr "LightMap Bake" +msgstr "Taille des Texels dans la carte de lumières" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Skins" -msgstr "" +msgstr "Enveloppes" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Use Named Skins" -msgstr "Utiliser le magnétisme d'échelle" +msgstr "Utiliser les enveloppes nommées" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "External Files" -msgstr "Ouvrir un fichier" +msgstr "Fichiers externes" #: editor/import/resource_importer_scene.cpp msgid "Store In Subdir" -msgstr "" +msgstr "Stocker dans un sous-dossier" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Filter Script" msgstr "Filtrer les scripts" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep Custom Tracks" -msgstr "Transformation" +msgstr "Conserver les pistes personnalisées" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Optimizer" -msgstr "Optimiser" +msgstr "Optimiseur" #: editor/import/resource_importer_scene.cpp #: editor/plugins/item_list_editor_plugin.cpp main/main.cpp @@ -7347,9 +7192,8 @@ msgstr "Optimiser" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp #: scene/gui/rich_text_label.cpp scene/resources/curve.cpp #: scene/resources/environment.cpp scene/resources/material.cpp -#, fuzzy msgid "Enabled" -msgstr "Activer" +msgstr "Activé" #: editor/import/resource_importer_scene.cpp msgid "Max Linear Error" @@ -7360,17 +7204,14 @@ msgid "Max Angular Error" msgstr "Erreur Angulaire Max" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Angle" -msgstr "Valeur" +msgstr "Angle maximal" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Remove Unused Tracks" -msgstr "Supprimer la piste d’animation" +msgstr "Retirer les pistes inutilisées" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Clips" msgstr "Clips d'animation" @@ -7427,89 +7268,90 @@ msgid "" "%s: Texture detected as used as a normal map in 3D. Enabling red-green " "texture compression to reduce memory usage (blue channel is discarded)." msgstr "" +"%s : La texture a été utilisé comme carte de normales dans la 3D. Activation " +"de la compression rouge-verte pour réduire l'utilisation de la mémoire (le " +"canal bleu est désactivé)." #: editor/import/resource_importer_texture.cpp msgid "" "%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap " "generation and VRAM texture compression." msgstr "" +"%s : La texture a été détecter comme étant utilisé dans la 3D. Activation du " +"filtrage, de la répétition, de la génération de mipmap et de la compression " +"de la texture dans la mémoire vidéo." #: editor/import/resource_importer_texture.cpp msgid "2D, Detect 3D" -msgstr "" +msgstr "2D, Détecter la 3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "2D Pixel" -msgstr "Pixels pleins" +msgstr "Pixel 2D" #: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp msgid "Lossy Quality" -msgstr "" +msgstr "Mauvaise qualité" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "HDR Mode" -msgstr "Mode sélection" +msgstr "Mode HDR" #: editor/import/resource_importer_texture.cpp msgid "BPTC LDR" -msgstr "" +msgstr "BPTC LDR" #: editor/import/resource_importer_texture.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp #: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp msgid "Normal Map" -msgstr "" +msgstr "Carte de normales" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Process" -msgstr "Post-traitement" +msgstr "Processus" #: editor/import/resource_importer_texture.cpp msgid "Fix Alpha Border" -msgstr "" +msgstr "Corriger la bordure alpha" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Premult Alpha" -msgstr "Modifier le polygone" +msgstr "Alpha pré-multiplié" #: editor/import/resource_importer_texture.cpp msgid "Hdr As Srgb" -msgstr "" +msgstr "Hdr en tant que Srgb" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Invert Color" -msgstr "Vertex" +msgstr "Inverser la couleur" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Normal Map Invert Y" -msgstr "Échelle aléatoire :" +msgstr "Inverser l'axe Y de la carte de normales" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Size Limit" -msgstr "Limites" +msgstr "Limite de taille" #: editor/import/resource_importer_texture.cpp msgid "Detect 3D" -msgstr "" +msgstr "Détecter la 3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "SVG" -msgstr "HSV" +msgstr "SVG" #: editor/import/resource_importer_texture.cpp msgid "" "Warning, no suitable PC VRAM compression enabled in Project Settings. This " "texture will not display correctly on PC." msgstr "" +"Attention, aucune compression de la mémoire vidéo qui aille sur PC n'est " +"activé dans les paramètres du projet. Cette texture ne s'affichera pas " +"correctement sur PC." #: editor/import/resource_importer_texture_atlas.cpp msgid "Atlas File" @@ -7520,64 +7362,56 @@ msgid "Import Mode" msgstr "Mode d'Importation" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Crop To Region" -msgstr "Définir la région de la tuile" +msgstr "Rogner vers la région" #: editor/import/resource_importer_texture_atlas.cpp msgid "Trim Alpha Border From Region" -msgstr "" +msgstr "Rogner les bordures alpha de la région" #: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Force" -msgstr "Force-pousser" +msgstr "Force" #: editor/import/resource_importer_wav.cpp msgid "8 Bit" -msgstr "" +msgstr "8 Bit" #: editor/import/resource_importer_wav.cpp main/main.cpp #: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Mono" -msgstr "" +msgstr "Mono" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate" -msgstr "Mélanger le nÅ“ud" +msgstr "Taux maximal" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate Hz" -msgstr "Mélanger le nÅ“ud" +msgstr "Taux maximal en Hz" #: editor/import/resource_importer_wav.cpp msgid "Trim" -msgstr "" +msgstr "Rogner" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Normalize" -msgstr "Format" +msgstr "Normaliser" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Mode" -msgstr "Mode déplacement" +msgstr "Mode de bouclage" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Begin" -msgstr "Mode déplacement" +msgstr "Début de la boucle" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop End" -msgstr "Mode déplacement" +msgstr "Fin de la boucle" #: editor/import_defaults_editor.cpp msgid "Select Importer" @@ -7658,27 +7492,24 @@ msgid "Failed to load resource." msgstr "Impossible de charger la ressource." #: editor/inspector_dock.cpp -#, fuzzy msgid "Property Name Style" -msgstr "Nom du projet :" +msgstr "Style des noms de propriétés" #: editor/inspector_dock.cpp scene/gui/color_picker.cpp msgid "Raw" msgstr "Brut" #: editor/inspector_dock.cpp -#, fuzzy msgid "Capitalized" msgstr "Majuscule à chaque mot" #: editor/inspector_dock.cpp -#, fuzzy msgid "Localized" -msgstr "Localisation" +msgstr "Traduit" #: editor/inspector_dock.cpp msgid "Localization not available for current language." -msgstr "" +msgstr "La traduction n'est pas disponible pour la langue actuel." #: editor/inspector_dock.cpp msgid "Copy Properties" @@ -8229,9 +8060,8 @@ msgid "New" msgstr "Nouveau" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Paste As Reference" -msgstr "Référence de classe %s" +msgstr "Collé en tant que référence" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -8483,7 +8313,7 @@ msgstr "Mélange 1 :" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "X-Fade Time (s):" -msgstr "Durée du fondu (s) :" +msgstr "Durée du fondu croisé (s) :" #: editor/plugins/animation_tree_player_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp @@ -8561,7 +8391,7 @@ msgstr "Filtres…" #: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp msgid "Use Threads" -msgstr "" +msgstr "Utiliser le multitâche" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Contents:" @@ -8724,25 +8554,21 @@ msgid "Loading..." msgstr "Chargement..." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "First" msgstr "Premier" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Previous" msgstr "Précédent" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Next" msgstr "Suivant" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Last" msgstr "Dernier" @@ -8793,7 +8619,7 @@ msgstr "En période de test" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed to get repository configuration." -msgstr "" +msgstr "N'a pas réussi à récupérer la configuration du dépôt." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" @@ -9360,23 +9186,20 @@ msgid "View" msgstr "Affichage" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show" -msgstr "Afficher la grille" +msgstr "Afficher" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show When Snapping" -msgstr "Magnétisme intelligent" +msgstr "Afficher lors de la magnétisation" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Hide" -msgstr "" +msgstr "Cacher" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid" -msgstr "Basculer le mode" +msgstr "Activer/Désactiver la grille" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -9728,16 +9551,15 @@ msgstr "Dégradé édité" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap GradientTexture2D Fill Points" -msgstr "" +msgstr "Échanger les points de remplissage du GradientTexture2D" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap Gradient Fill Points" -msgstr "" +msgstr "Échanger les points de remplissage du dégradé" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid Snap" -msgstr "Basculer le mode" +msgstr "Activer/Désactiver le magnétisme de la grille" #: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp #: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp @@ -9756,13 +9578,12 @@ msgstr "Icône" #: editor/plugins/item_list_editor_plugin.cpp msgid "ID" -msgstr "" +msgstr "ID" #: editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separator" -msgstr "Séparation :" +msgstr "Séparateur" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" @@ -10006,7 +9827,6 @@ msgstr "" "%s" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "MeshLibrary" msgstr "Librairie de maillages" @@ -10031,14 +9851,12 @@ msgid "Update from Scene" msgstr "Mettre à jour depuis la scène" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply without Transforms" -msgstr "Appliquer la transformation du MeshInstance" +msgstr "Appliquer sans transformations" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply with Transforms" -msgstr "Appliquer la transformation du MeshInstance" +msgstr "Appliquer avec transformations" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." @@ -10569,7 +10387,7 @@ msgstr "Synchroniser les os avec le polygone" #: editor/plugins/ray_cast_2d_editor_plugin.cpp msgid "Set cast_to" -msgstr "" +msgstr "Définir cast_to" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" @@ -10900,57 +10718,51 @@ msgstr "Résultats de recherche" #: editor/plugins/script_editor_plugin.cpp msgid "Open Dominant Script On Scene Change" -msgstr "" +msgstr "Ouvrir le script principal lors du changement de scène" #: editor/plugins/script_editor_plugin.cpp msgid "External" -msgstr "" +msgstr "Externe" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Use External Editor" -msgstr "Déboguer avec un éditeur externe" +msgstr "Utiliser un éditeur externe" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Exec Path" -msgstr "Chemin d'exportation" +msgstr "Chemin d'exécution" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script Temperature Enabled" -msgstr "Sélectionner le fichier de modèles" +msgstr "Température de script activée" #: editor/plugins/script_editor_plugin.cpp msgid "Highlight Current Script" -msgstr "" +msgstr "Mettre en évidence le script actuel" #: editor/plugins/script_editor_plugin.cpp msgid "Script Temperature History Size" -msgstr "" +msgstr "Taille de l'historique des températures de script" #: editor/plugins/script_editor_plugin.cpp msgid "Current Script Background Color" msgstr "Couleur d'Arrière-Plan du Script Actuel" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Group Help Pages" -msgstr "Groupe sélectionné" +msgstr "Pages d'aide de groupe" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Sort Scripts By" -msgstr "Créer un script" +msgstr "Trier les scripts par" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "List Script Names As" -msgstr "Nom du script :" +msgstr "Lister les noms de scripts en tant que" #: editor/plugins/script_editor_plugin.cpp msgid "Exec Flags" -msgstr "" +msgstr "Paramètres d'exécution" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Scripts" @@ -11471,10 +11283,11 @@ msgid "(Not in GLES2)" msgstr "(Non disponible dans GLES2)" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "" "Debug draw modes are only available when using the GLES3 renderer, not GLES2." -msgstr "Non disponible quand le moteur de rendu GLES2 est utilisé." +msgstr "" +"Les modes de rendu de débogage ne sont disponibles qu'avec le moteur GLES3, " +"et pas GLES2." #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" @@ -11770,16 +11583,15 @@ msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Size" -msgstr "" +msgstr "Taille des manipulateurs" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Opacity" -msgstr "" +msgstr "Opacité des manipulateurs" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Show Viewport Rotation Gizmo" -msgstr "Verrouiller la rotation de la vue" +msgstr "Afficher le manipulateur de rotation dans le viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "Unnamed Gizmo" @@ -11832,9 +11644,8 @@ msgid "Invalid geometry, can't replace by mesh." msgstr "Géométrie invalide, impossible de remplacer par un maillage." #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Convert to MeshInstance2D" -msgstr "Convertir en Mesh2D" +msgstr "Convertir en MeshInstance2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't create polygon." @@ -11937,6 +11748,10 @@ msgid "New Animation" msgstr "Nouvelle animation" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "Filtrer les animations" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Vitesse :" @@ -12238,9 +12053,8 @@ msgstr "" "Fermer tout de même ?" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Type" -msgstr "Supprimer la tuile" +msgstr "Supprimer le type" #: editor/plugins/theme_editor_plugin.cpp msgid "" @@ -12285,14 +12099,12 @@ msgstr "" "thème." #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Add Theme Type" -msgstr "Ajouter un item de type" +msgstr "Ajouter un type de thème" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Theme Type" -msgstr "Retirer le dépôt distant" +msgstr "Supprimer un type de thème" #: editor/plugins/theme_editor_plugin.cpp msgid "Add Color Item" @@ -12409,9 +12221,8 @@ msgid "Select Another Theme Resource:" msgstr "Sélectionnez une autre ressource Theme :" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Theme Resource" -msgstr "Renommer une ressource" +msgstr "Ressource de thème" #: editor/plugins/theme_editor_plugin.cpp msgid "Another Theme" @@ -12467,12 +12278,10 @@ msgid "Add Item Type" msgstr "Ajouter un item de type" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Variation Base Type" -msgstr "Définir type de variable" +msgstr "Définir le type parent de la variation" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Base Type" msgstr "Changer le type de base" @@ -12496,12 +12305,16 @@ msgstr "Surcharge tous les items de type par défaut." #: editor/plugins/theme_editor_plugin.cpp msgid "Select the variation base type from a list of available types." msgstr "" +"Choisissez le type parent de la variation depuis la liste des types " +"disponibles." #: editor/plugins/theme_editor_plugin.cpp msgid "" "A type associated with a built-in class cannot be marked as a variation of " "another type." msgstr "" +"Un type affilié à une classe intégrée ne peut pas être marqué comme variante " +"d'un autre type." #: editor/plugins/theme_editor_plugin.cpp msgid "Theme:" @@ -12742,14 +12555,13 @@ msgid "Clear Transform" msgstr "Supprimer la transformation" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Tile Map" -msgstr "Peindre sur la TileMap" +msgstr "Carte de Tuiles" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Palette Min Width" -msgstr "" +msgstr "Largeur minimale de la palette" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -12757,40 +12569,33 @@ msgid "Palette Item H Separation" msgstr "Séparateur nommé" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Names" -msgstr "Afficher toutes les langues" +msgstr "Afficher les noms des tuiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Ids" -msgstr "Afficher les règles" +msgstr "Afficher les IDs des tuiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Sort Tiles By Name" -msgstr "Trier les fichiers" +msgstr "Trier les tuiles par nom" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Bucket Fill Preview" -msgstr "Remplissage du seau" +msgstr "Aperçu du remplissage" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Editor Side" -msgstr "Éditeur" +msgstr "Coté Éditeur" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Display Grid" -msgstr "Affichage des surimpressions" +msgstr "Afficher la grille" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Axis Color" -msgstr "Prélever une couleur" +msgstr "Couleur des axes" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Add Texture(s) to TileSet." @@ -13129,7 +12934,6 @@ msgid "This property can't be changed." msgstr "Cette propriété ne peut être changée." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Snap Options" msgstr "Options de magnétisme" @@ -13154,14 +12958,12 @@ msgstr "Pas" #: editor/plugins/tile_set_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separation" -msgstr "Séparation :" +msgstr "Séparation" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Tile" -msgstr "Sélectionner" +msgstr "Tuile sélectionné" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp @@ -13170,14 +12972,12 @@ msgstr "Sélectionner" #: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp #: scene/resources/material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Texture" -msgstr "Texte" +msgstr "Texture" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tex Offset" -msgstr "Décalage d’Octet" +msgstr "Décalage de texture" #: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp #: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp @@ -13187,79 +12987,64 @@ msgstr "Matériau" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Modulate" -msgstr "Peupler" +msgstr "Moduler" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Mode" -msgstr "Basculer le mode" +msgstr "Mode de tuile" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Autotile Bitmask Mode" -msgstr "Mode Bitmask" +msgstr "Mode de masque d'octet de tuile auto" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Size" -msgstr "Taille de Contour" +msgstr "Taille des sous-tuiles" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Spacing" -msgstr "Bouclage de l’animation" +msgstr "Espacement des sous-tuiles" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Occluder Offset" -msgstr "Créer un polygone occulteur" +msgstr "Décalage de l’occulteur" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation Offset" -msgstr "Mode Navigation" +msgstr "Décalage de la navigation" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Offset" -msgstr "Décalage :" +msgstr "Décalage de la forme" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Transform" -msgstr "Transformation" +msgstr "Transformation de la forme" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision" -msgstr "Collision" +msgstr "Collision sélectionné" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way" -msgstr "Sélection uniquement" +msgstr "Collision à sens unique de la sélection" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way Margin" -msgstr "Mode collision" +msgstr "Marge de collision à sens unique de la sélection" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Navigation" -msgstr "Navigation visible" +msgstr "Navigation sélectionnée" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Occlusion" -msgstr "Sélectionner" +msgstr "Occultation de la sélection" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tileset Script" -msgstr "Filtrer les scripts" +msgstr "Script de palette de tuiles" #: editor/plugins/tile_set_editor_plugin.cpp msgid "TileSet" @@ -14354,11 +14139,13 @@ msgstr "Exécutable" #: editor/project_export.cpp msgid "Export the project for all the presets defined." -msgstr "" +msgstr "Exporter le projet pour tous les préréglages définis." #: editor/project_export.cpp msgid "All presets must have an export path defined for Export All to work." msgstr "" +"Tous les préréglages doivent avoir un chemin d'exportation défini pour " +"pouvoir tous les exportés." #: editor/project_export.cpp msgid "Delete preset '%s'?" @@ -14471,53 +14258,48 @@ msgid "" "Note: Encryption key needs to be stored in the binary,\n" "you need to build the export templates from source." msgstr "" +"Note : La clé de cryptage doit être stocké dans le binaire,\n" +"vous devez compiler les modèles d'exportation depuis les sources." #: editor/project_export.cpp -#, fuzzy msgid "More Info..." -msgstr "Déplacer vers…" +msgstr "Plus d'informations..." #: editor/project_export.cpp -#, fuzzy msgid "Export PCK/Zip..." -msgstr "Exporter le PCK/ZIP" +msgstr "Exporter le PCK/ZIP..." #: editor/project_export.cpp -#, fuzzy msgid "Export Project..." -msgstr "Exporter le projet" +msgstr "Exporter le projet..." #: editor/project_export.cpp msgid "Export All" msgstr "Tout exporter" #: editor/project_export.cpp -#, fuzzy msgid "Choose an export mode:" -msgstr "Veuillez choisir un dossier vide." +msgstr "Choisissez un mode d'exportation :" #: editor/project_export.cpp -#, fuzzy msgid "Export All..." -msgstr "Tout exporter" +msgstr "Tout exporter..." #: editor/project_export.cpp editor/project_manager.cpp msgid "ZIP File" msgstr "Fichier ZIP" #: editor/project_export.cpp -#, fuzzy msgid "Godot Project Pack" -msgstr "Archive Godot" +msgstr "Pack de Projet Godot" #: editor/project_export.cpp msgid "Export templates for this platform are missing:" msgstr "Modèles d'exportation manquants pour cette plateforme :" #: editor/project_export.cpp -#, fuzzy msgid "Project Export" -msgstr "Fondateurs du projet" +msgstr "Exportation du projet" #: editor/project_export.cpp msgid "Manage Export Templates" @@ -14835,7 +14617,6 @@ msgstr "" #. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp -#, fuzzy msgctxt "Application" msgid "Project Manager" msgstr "Gestionnaire de projets" @@ -15552,7 +15333,7 @@ msgstr "Supprimer le nÅ“ud \"%s\" et ses enfants ?" #: editor/scene_tree_dock.cpp msgid "Delete node \"%s\"?" -msgstr "Supprimer le noeud \"%s\" ?" +msgstr "Supprimer le nÅ“ud \"%s\" ?" #: editor/scene_tree_dock.cpp msgid "" @@ -15644,17 +15425,15 @@ msgstr "Rendre local" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp msgid "Another node already uses this unique name in the scene." -msgstr "" +msgstr "Un autre NÅ“ud utilise ce nom unique dans la scène." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Enable Scene Unique Name" -msgstr "Nom unique" +msgstr "Activer le nom unique de la scène" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -#, fuzzy msgid "Disable Scene Unique Name" -msgstr "Nom unique" +msgstr "Désactiver le nom unique de la scène" #: editor/scene_tree_dock.cpp msgid "New Scene Root" @@ -15731,7 +15510,7 @@ msgstr "Ressources secondaires" #: editor/scene_tree_dock.cpp msgid "Access as Scene Unique Name" -msgstr "" +msgstr "Accéder en tant que nom unique de scène" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" @@ -15831,18 +15610,16 @@ msgid "Clear Inheritance? (No Undo!)" msgstr "Effacer l'héritage ? (Pas de retour en arrière !)" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Show Scene Tree Root Selection" -msgstr "Centrer sur la sélection" +msgstr "Afficher la sélection de la racine de la hiérarchie de la scène" #: editor/scene_tree_dock.cpp msgid "Derive Script Globals By Name" -msgstr "" +msgstr "Dériver les Globals de scripts par nom" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Use Favorites Root Selection" -msgstr "Encadrer la sélection" +msgstr "Utiliser la sélection racine des favoris" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" @@ -15870,6 +15647,9 @@ msgid "" "with the '%s' prefix in a node path.\n" "Click to disable this." msgstr "" +"Ce NÅ“ud est accessible de n'importe où dans la scène en le préfixant de '%s' " +"dans un chemin de NÅ“ud.\n" +"Cliquer pour désactiver cela." #: editor/scene_tree_editor.cpp msgid "" @@ -16156,21 +15936,20 @@ msgid "Stack Frames" msgstr "Pile des appels" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Filter stack variables" -msgstr "Filtrer les tuiles" +msgstr "Filtrer les variables de la pile" #: editor/script_editor_debugger.cpp msgid "Auto Switch To Remote Scene Tree" -msgstr "" +msgstr "Basculer automatiquement vers l'arborescence de scène distante" #: editor/script_editor_debugger.cpp msgid "Remote Scene Tree Refresh Interval" -msgstr "" +msgstr "Intervalle de rafraîchissement de l'arborescence distante" #: editor/script_editor_debugger.cpp msgid "Remote Inspect Refresh Interval" -msgstr "" +msgstr "Intervalle de rafraîchissement d'inspection distante" #: editor/script_editor_debugger.cpp msgid "Network Profiler" @@ -16269,7 +16048,7 @@ msgstr "Changer le rayon d'une lumière" #: editor/spatial_editor_gizmos.cpp msgid "Stream Player 3D" -msgstr "" +msgstr "Émetteur de flux 3D" #: editor/spatial_editor_gizmos.cpp msgid "Change AudioStreamPlayer3D Emission Angle" @@ -16279,7 +16058,7 @@ msgstr "Changer l'angle d'émission AudioStreamPlayer3D" #: platform/osx/export/export.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Camera" -msgstr "" +msgstr "Caméra" #: editor/spatial_editor_gizmos.cpp msgid "Change Camera FOV" @@ -16291,7 +16070,7 @@ msgstr "Changer la taille d'une caméra" #: editor/spatial_editor_gizmos.cpp msgid "Visibility Notifier" -msgstr "" +msgstr "Notifiant de visibilité" #: editor/spatial_editor_gizmos.cpp msgid "Change Notifier AABB" @@ -16302,23 +16081,20 @@ msgid "Change Particles AABB" msgstr "Changer particules AABB" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Reflection Probe" -msgstr "Sélectionnez une propriété" +msgstr "Sonde de Réflexion" #: editor/spatial_editor_gizmos.cpp msgid "Change Probe Extents" msgstr "Changer les ampleurs de la sonde" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "GI Probe" -msgstr "Créer sonde IG (Illumination Globale)" +msgstr "Sonde GI" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Baked Indirect Light" -msgstr "Éclairage indirect" +msgstr "Éclairage indirect pré-calculé" #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp msgid "Change Sphere Shape Radius" @@ -16349,57 +16125,52 @@ msgid "Change Ray Shape Length" msgstr "Changer la longueur d'une forme en rayon" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge" -msgstr "Mode Navigation" +msgstr "Bord de la Navigation" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge Disabled" -msgstr "Mode Navigation" +msgstr "Bord de la Navigation Désactivé" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid" -msgstr "Mode Navigation" +msgstr "Solide de navigation" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid Disabled" -msgstr "Mode Navigation" +msgstr "Solide de navigation désactivé" #: editor/spatial_editor_gizmos.cpp msgid "Joint Body A" -msgstr "" +msgstr "Jointure Corps A" #: editor/spatial_editor_gizmos.cpp msgid "Joint Body B" -msgstr "" +msgstr "Jointure Corps B" #: editor/spatial_editor_gizmos.cpp msgid "Room Edge" -msgstr "" +msgstr "Bord de la pièce" #: editor/spatial_editor_gizmos.cpp msgid "Room Overlap" -msgstr "" +msgstr "Chevauchement de salle" #: editor/spatial_editor_gizmos.cpp msgid "Set Room Point Position" msgstr "Définir la position du point de la pièce" #: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp -#, fuzzy msgid "Portal Margin" -msgstr "Définir la marge" +msgstr "Marge du portail" #: editor/spatial_editor_gizmos.cpp msgid "Portal Edge" -msgstr "" +msgstr "Bords du portail" #: editor/spatial_editor_gizmos.cpp msgid "Portal Arrow" -msgstr "" +msgstr "Flèche de portail" #: editor/spatial_editor_gizmos.cpp msgid "Set Portal Point Position" @@ -16407,18 +16178,16 @@ msgstr "Définir la position du point du Portal" #: editor/spatial_editor_gizmos.cpp msgid "Portal Front" -msgstr "" +msgstr "Avant du Portail" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Portal Back" -msgstr "Retourner" +msgstr "Arrière du Portail" #: editor/spatial_editor_gizmos.cpp scene/2d/light_occluder_2d.cpp #: scene/2d/tile_map.cpp -#, fuzzy msgid "Occluder" -msgstr "Mode Occlusion" +msgstr "Occulteur" #: editor/spatial_editor_gizmos.cpp msgid "Set Occluder Sphere Radius" @@ -16429,118 +16198,106 @@ msgid "Set Occluder Sphere Position" msgstr "Définir la position de la sphère de l'occulteur" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Set Occluder Polygon Point Position" -msgstr "Définir la position du point du Portal" +msgstr "Définir la position ponctuelle du polygone occulteur" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Set Occluder Hole Point Position" -msgstr "Définir la position du point de la courbe" +msgstr "Définir la position ponctuelle du trou occulteur" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Polygon Front" -msgstr "Créer un polygone occulteur" +msgstr "Avant du polygone occulteur" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Polygon Back" -msgstr "Créer un polygone occulteur" +msgstr "Arrière du polygone occulteur" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Occluder Hole" -msgstr "Créer un polygone occulteur" +msgstr "Trou occulteur" #: main/main.cpp msgid "Godot Physics" -msgstr "" +msgstr "Calculs de physique de Godot" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp msgid "Use BVH" -msgstr "" +msgstr "Utiliser BVH" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp -#, fuzzy msgid "BVH Collision Margin" -msgstr "Mode collision" +msgstr "Marge de collision BVH" #: main/main.cpp -#, fuzzy msgid "Crash Handler" -msgstr "Définir la poignée" +msgstr "Gestionnaire de Crash" #: main/main.cpp -#, fuzzy msgid "Multithreaded Server" -msgstr "Ensemble multi-nÅ“ud" +msgstr "Serveur à tâches parallèles" #: main/main.cpp msgid "RID Pool Prealloc" msgstr "" #: main/main.cpp -#, fuzzy msgid "Debugger stdout" -msgstr "Débogueur" +msgstr "Sortie standard du débogueur" #: main/main.cpp msgid "Max Chars Per Second" -msgstr "" +msgstr "Maximum de Caractères par seconde" #: main/main.cpp msgid "Max Messages Per Frame" -msgstr "" +msgstr "Maximum de messages par image" #: main/main.cpp msgid "Max Errors Per Second" -msgstr "" +msgstr "Maximum d'erreurs par seconde" #: main/main.cpp msgid "Max Warnings Per Second" -msgstr "" +msgstr "Maximum d'avertissements par secondes" #: main/main.cpp msgid "Flush stdout On Print" -msgstr "" +msgstr "Vider stdout à l'impression" #: main/main.cpp servers/visual_server.cpp msgid "Logging" -msgstr "" +msgstr "Journalisation" #: main/main.cpp msgid "File Logging" -msgstr "" +msgstr "Journalisation dans un fichier" #: main/main.cpp -#, fuzzy msgid "Enable File Logging" -msgstr "Activer le filtrage" +msgstr "Activer la journalisation dans un fichier" #: main/main.cpp -#, fuzzy msgid "Log Path" -msgstr "Copier le chemin" +msgstr "Chemin du Journal" #: main/main.cpp msgid "Max Log Files" -msgstr "" +msgstr "Maximum de fichiers journaux" #: main/main.cpp msgid "Driver" -msgstr "" +msgstr "Pilote" #: main/main.cpp -#, fuzzy msgid "Driver Name" -msgstr "Nom du script :" +msgstr "Nom du Pilote" #: main/main.cpp msgid "Fallback To GLES2" -msgstr "" +msgstr "Se replier sur GLES2" #: main/main.cpp msgid "Use Nvidia Rect Flicker Workaround" @@ -16548,52 +16305,47 @@ msgstr "" #: main/main.cpp msgid "DPI" -msgstr "" +msgstr "PPP" #: main/main.cpp msgid "Allow hiDPI" -msgstr "" +msgstr "Autoriser PPP élevé" #: main/main.cpp -#, fuzzy msgid "V-Sync" -msgstr "Synchroniser" +msgstr "Synchronisation Vertical" #: main/main.cpp -#, fuzzy msgid "Use V-Sync" -msgstr "Utiliser l’aimantation" +msgstr "Utiliser la Synchronisation Vertical" #: main/main.cpp msgid "Per Pixel Transparency" -msgstr "" +msgstr "Transparence par pixel" #: main/main.cpp msgid "Allowed" -msgstr "" +msgstr "Autorisé" #: main/main.cpp msgid "Intended Usage" -msgstr "" +msgstr "Usage prévu" #: main/main.cpp -#, fuzzy msgid "Framebuffer Allocation" -msgstr "Encadrer la sélection" +msgstr "Allocation du tampon d'image (Framebuffer)" #: main/main.cpp platform/uwp/os_uwp.cpp -#, fuzzy msgid "Energy Saving" -msgstr "Erreur d'enregistrement" +msgstr "Économie d'Énergie" #: main/main.cpp msgid "Threads" -msgstr "" +msgstr "Tâches Parallèles" #: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h -#, fuzzy msgid "Thread Model" -msgstr "Basculer le mode" +msgstr "Modèle de Parallélisme" #: main/main.cpp msgid "Thread Safe BVH" @@ -16601,29 +16353,25 @@ msgstr "" #: main/main.cpp msgid "Handheld" -msgstr "" +msgstr "Portable" #: main/main.cpp platform/javascript/export/export.cpp #: platform/uwp/export/export.cpp -#, fuzzy msgid "Orientation" -msgstr "Documentation en ligne" +msgstr "Orientation" #: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp #: scene/main/scene_tree.cpp scene/register_scene_types.cpp -#, fuzzy msgid "Common" -msgstr "Communauté" +msgstr "Commun" #: main/main.cpp -#, fuzzy msgid "Physics FPS" -msgstr "Image physique %" +msgstr "TPS de la physique" #: main/main.cpp -#, fuzzy msgid "Force FPS" -msgstr "Force-pousser" +msgstr "Forces les trames par seconde" #: main/main.cpp msgid "Enable Pause Aware Picking" @@ -16641,34 +16389,31 @@ msgstr "" #: main/main.cpp msgid "stdout" -msgstr "" +msgstr "Sortie Standard" #: main/main.cpp msgid "Print FPS" -msgstr "" +msgstr "Afficher les FPS" #: main/main.cpp msgid "Verbose stdout" -msgstr "" +msgstr "Détailler La Sortie Standard" #: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp -#, fuzzy msgid "Physics Interpolation" -msgstr "Mode d’interpolation" +msgstr "Interpolation de la physique" #: main/main.cpp -#, fuzzy msgid "Enable Warnings" -msgstr "Activer le filtrage" +msgstr "Activer les avertissements" #: main/main.cpp -#, fuzzy msgid "Frame Delay Msec" -msgstr "Encadrer la sélection" +msgstr "Délai des trames en millisecondes" #: main/main.cpp msgid "Low Processor Mode" -msgstr "" +msgstr "Mode Processeur Faible" #: main/main.cpp msgid "Delta Sync After Draw" @@ -16676,90 +16421,81 @@ msgstr "" #: main/main.cpp msgid "iOS" -msgstr "" +msgstr "iOS" #: main/main.cpp msgid "Hide Home Indicator" -msgstr "" +msgstr "Masquer l'indicateur d’accueil" #: main/main.cpp -#, fuzzy msgid "Input Devices" -msgstr "Tous les périphérique" +msgstr "Périphériques d'entrée" #: main/main.cpp -#, fuzzy msgid "Pointing" -msgstr "Point" +msgstr "Pointage" #: main/main.cpp msgid "Touch Delay" -msgstr "" +msgstr "Retard d'appui" #: main/main.cpp servers/visual_server.cpp msgid "GLES3" -msgstr "" +msgstr "GLES3" #: main/main.cpp servers/visual_server.cpp -#, fuzzy msgid "Shaders" -msgstr "Ombrage" +msgstr "Shaders" #: main/main.cpp -#, fuzzy msgid "Debug Shader Fallbacks" -msgstr "Forcer les replis du shader" +msgstr "Valeurs de repli du shader de débogage" #: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp #: scene/3d/world_environment.cpp scene/main/scene_tree.cpp #: scene/resources/world.cpp -#, fuzzy msgid "Environment" -msgstr "Voir environnement" +msgstr "Environnement" #: main/main.cpp msgid "Default Clear Color" -msgstr "" +msgstr "Couleur d'effacement par défaut" #: main/main.cpp msgid "Boot Splash" -msgstr "" +msgstr "Écran de démarrage" #: main/main.cpp -#, fuzzy msgid "Show Image" -msgstr "Afficher les os" +msgstr "Afficher l'image" #: main/main.cpp msgid "Image" -msgstr "" +msgstr "Image" #: main/main.cpp msgid "Fullsize" -msgstr "" +msgstr "Pleine taille" #: main/main.cpp scene/resources/dynamic_font.cpp -#, fuzzy msgid "Use Filter" -msgstr "Filtre :" +msgstr "Utiliser le filtrage" #: main/main.cpp scene/resources/style_box.cpp -#, fuzzy msgid "BG Color" -msgstr "Couleurs" +msgstr "Couleur d'arrière-plan" #: main/main.cpp -#, fuzzy msgid "macOS Native Icon" -msgstr "Définir l'icône de la tuile" +msgstr "Icône native de macOS" #: main/main.cpp msgid "Windows Native Icon" -msgstr "" +msgstr "Icône native de Windows" #: main/main.cpp msgid "Buffering" -msgstr "" +msgstr "Mise en mémoire tampon" #: main/main.cpp msgid "Agile Event Flushing" @@ -16767,40 +16503,35 @@ msgstr "" #: main/main.cpp msgid "Emulate Touch From Mouse" -msgstr "" +msgstr "Émuler le toucher tactile avec la souris" #: main/main.cpp msgid "Emulate Mouse From Touch" -msgstr "" +msgstr "Émuler la souris avec le toucher tactile" #: main/main.cpp -#, fuzzy msgid "Mouse Cursor" -msgstr "Bouton de souris" +msgstr "Curseur de la souris" #: main/main.cpp -#, fuzzy msgid "Custom Image" -msgstr "NÅ“ud Personnalisé" +msgstr "Image personnalisée" #: main/main.cpp msgid "Custom Image Hotspot" msgstr "" #: main/main.cpp -#, fuzzy msgid "Tooltip Position Offset" -msgstr "Décalage de la rotation :" +msgstr "Décalage de la position des info-bulles" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Debugger Agent" -msgstr "Débogueur" +msgstr "Agent du débogueur" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Wait For Debugger" -msgstr "Débogueur" +msgstr "Attendre le débogueur" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Wait Timeout" @@ -16808,53 +16539,48 @@ msgstr "Délai d'Attente" #: main/main.cpp msgid "Runtime" -msgstr "" +msgstr "Exécution" #: main/main.cpp msgid "Unhandled Exception Policy" -msgstr "" +msgstr "Politique d'exceptions non gérées" #: main/main.cpp -#, fuzzy msgid "Main Loop Type" -msgstr "Rechercher le type de nÅ“ud" +msgstr "Type de boucle principale" #: main/main.cpp scene/gui/texture_progress.cpp #: scene/gui/viewport_container.cpp -#, fuzzy msgid "Stretch" -msgstr "Actualiser" +msgstr "Étirement" #: main/main.cpp -#, fuzzy msgid "Aspect" -msgstr "Inspecteur" +msgstr "Aspect" #: main/main.cpp msgid "Shrink" -msgstr "" +msgstr "Rétrécissement" #: main/main.cpp scene/main/scene_tree.cpp msgid "Auto Accept Quit" -msgstr "" +msgstr "Accepter automatiquement la fermeture" #: main/main.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Quit On Go Back" -msgstr "Retourner" +msgstr "Quitter au retour" #: main/main.cpp scene/main/viewport.cpp -#, fuzzy msgid "Snap Controls To Pixels" -msgstr "Aimanter aux flancs du nÅ“ud" +msgstr "Aimanter les contrôles aux pixels" #: main/main.cpp msgid "Dynamic Fonts" -msgstr "" +msgstr "Polices Dynamiques" #: main/main.cpp msgid "Use Oversampling" -msgstr "" +msgstr "Utiliser le suréchantillonnage" #: modules/bullet/register_types.cpp modules/bullet/space_bullet.cpp msgid "Active Soft World" @@ -16881,35 +16607,30 @@ msgid "Change Torus Outer Radius" msgstr "Changer le rayon extérieur de la tour" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Operation" -msgstr "Options" +msgstr "Opération" #: modules/csg/csg_shape.cpp msgid "Calculate Tangents" -msgstr "" +msgstr "Calculer les Tangentes" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Use Collision" -msgstr "Collision" +msgstr "Utiliser les collisions" #: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp -#, fuzzy msgid "Collision Layer" -msgstr "Mode collision" +msgstr "Couche des collisions" #: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp #: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp #: scene/resources/navigation_mesh.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Mask" -msgstr "Mode collision" +msgstr "Masque de collisions" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Invert Faces" -msgstr "Modifier la casse" +msgstr "Inverses les faces" #: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp @@ -16927,57 +16648,50 @@ msgid "Radial Segments" msgstr "Segments radiaux" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Rings" -msgstr "Avertissements" +msgstr "Anneaux" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Smooth Faces" -msgstr "Progression douce" +msgstr "Adoucir les faces" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Sides" -msgstr "Afficher les guides" +msgstr "Côtés" #: modules/csg/csg_shape.cpp msgid "Cone" -msgstr "" +msgstr "Cone" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Inner Radius" -msgstr "Changer le rayon intérieur de la tour" +msgstr "Rayon intérieur" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Outer Radius" -msgstr "Changer le rayon extérieur de la tour" +msgstr "Rayon extérieur" #: modules/csg/csg_shape.cpp msgid "Ring Sides" -msgstr "" +msgstr "Côtés de l'anneau" #: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp #: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp #: scene/3d/collision_polygon.cpp -#, fuzzy msgid "Polygon" -msgstr "Polygones" +msgstr "Polygone" #: modules/csg/csg_shape.cpp msgid "Spin Degrees" -msgstr "" +msgstr "Degrés de tour" #: modules/csg/csg_shape.cpp msgid "Spin Sides" -msgstr "" +msgstr "Côtés du tour" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Node" -msgstr "Coller les nÅ“uds" +msgstr "Noeud de chemin" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16986,106 +16700,92 @@ msgstr "Créer un vertex interne" #: modules/csg/csg_shape.cpp msgid "Path Interval" -msgstr "" +msgstr "Intervalle de chemin" #: modules/csg/csg_shape.cpp msgid "Path Simplify Angle" -msgstr "" +msgstr "Simplification d'angle de chemin" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Rotation" -msgstr "Rotation aléatoire :" +msgstr "Rotation du chemin" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Local" -msgstr "Rendre local" +msgstr "Chemin local" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Continuous U" -msgstr "Continu" +msgstr "Chemin Continu U" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path U Distance" -msgstr "Choisissez distance :" +msgstr "Distance du chemin U" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Joined" -msgstr "Rotation aléatoire :" +msgstr "Chemin joint" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Compression Mode" -msgstr "Mode collision" +msgstr "Mode de compression" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Transfer Channel" -msgstr "Modification de la transformation" +msgstr "Canal de transfert" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Channel Count" -msgstr "Instance" +msgstr "Nombre de canaux" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Always Ordered" -msgstr "Toujours afficher la grille" +msgstr "Toujours ordonnée" #: modules/enet/networked_multiplayer_enet.cpp msgid "Server Relay" -msgstr "" +msgstr "Relais serveur" #: modules/enet/networked_multiplayer_enet.cpp msgid "DTLS Verify" -msgstr "" +msgstr "Vérification DTLS" #: modules/enet/networked_multiplayer_enet.cpp msgid "DTLS Hostname" -msgstr "" +msgstr "Nom de l'hôte DTLS" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Use DTLS" -msgstr "Utiliser l’aimantation" +msgstr "Utiliser DTLS" #: modules/fbx/editor_scene_importer_fbx.cpp msgid "FBX" -msgstr "" +msgstr "FBX" #: modules/fbx/editor_scene_importer_fbx.cpp msgid "Use FBX" -msgstr "" +msgstr "Utiliser FBX" #: modules/gdnative/gdnative.cpp msgid "Config File" msgstr "Fichier de Configuration" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Load Once" -msgstr "Charger une ressource" +msgstr "Charger une fois" #: modules/gdnative/gdnative.cpp #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Singleton" -msgstr "Squelette" +msgstr "Singleton" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Symbol Prefix" -msgstr "Préfixe :" +msgstr "Préfixe du symbole" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Reloadable" -msgstr "Recharger" +msgstr "Rechargeable" #: modules/gdnative/gdnative.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -17146,14 +16846,12 @@ msgid "Class Name" msgstr "Nom de la Classe" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Script Class" -msgstr "Nom du script :" +msgstr "Classe de Script" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Icon Path" -msgstr "Focaliser le chemin" +msgstr "Chemin de l'icône" #: modules/gdnative/register_types.cpp msgid "GDNative" @@ -17161,34 +16859,32 @@ msgstr "GDNative" #: modules/gdscript/editor/gdscript_highlighter.cpp #: modules/gdscript/gdscript.cpp -#, fuzzy msgid "GDScript" -msgstr "Script" +msgstr "GDScript" #: modules/gdscript/editor/gdscript_highlighter.cpp msgid "Function Definition Color" -msgstr "" +msgstr "Couleur de définition de fonction" #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Node Path Color" -msgstr "Copier le chemin du nÅ“ud" +msgstr "Couleur des chemins de nÅ“ud" #: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp msgid "Max Call Stack" -msgstr "" +msgstr "Maximum de la pile d'appel" #: modules/gdscript/gdscript.cpp msgid "Treat Warnings As Errors" -msgstr "" +msgstr "Traiter les avertissements comme des erreurs" #: modules/gdscript/gdscript.cpp msgid "Exclude Addons" -msgstr "" +msgstr "Exclure les extensions" #: modules/gdscript/gdscript.cpp msgid "Autocomplete Setters And Getters" -msgstr "" +msgstr "Auto-compléter les setters et les getters" #: modules/gdscript/gdscript_functions.cpp msgid "Step argument is zero!" @@ -17235,17 +16931,16 @@ msgid "Language Server" msgstr "Serveur de Langues" #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Enable Smart Resolve" -msgstr "Impossible à résoudre" +msgstr "Activer la résolution intelligente" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Show Native Symbols In Editor" -msgstr "" +msgstr "Afficher les symboles natifs dans l'éditeur" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Use Thread" -msgstr "" +msgstr "Utiliser le parallélisme" #: modules/gltf/editor_scene_exporter_gltf_plugin.cpp msgid "Export Mesh GLTF2" @@ -17256,37 +16951,32 @@ msgid "Export GLTF..." msgstr "Exporter en GLTF..." #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Buffer View" -msgstr "Vue de derrière" +msgstr "Vue du tampon" #: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp msgid "Byte Offset" msgstr "Décalage d’Octet" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Component Type" -msgstr "Composants" +msgstr "Type de composant" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Normalized" -msgstr "Format" +msgstr "Normalisé" #: modules/gltf/gltf_accessor.cpp msgid "Count" msgstr "Compte" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Min" -msgstr "Mio" +msgstr "Min" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Max" -msgstr "Mixer" +msgstr "Max" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17302,9 +16992,8 @@ msgid "Sparse Indices Byte Offset" msgstr "" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Sparse Indices Component Type" -msgstr "Analyse de la géométrie..." +msgstr "Type de composant d'indices épars" #: modules/gltf/gltf_accessor.cpp msgid "Sparse Values Buffer View" @@ -17315,14 +17004,12 @@ msgid "Sparse Values Byte Offset" msgstr "" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Buffer" -msgstr "Vue de derrière" +msgstr "Tampon" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Byte Length" -msgstr "Thème par défaut" +msgstr "Longueur de byte" #: modules/gltf/gltf_buffer_view.cpp msgid "Byte Stride" @@ -17354,19 +17041,17 @@ msgstr "Linéaire" #: scene/resources/environment.cpp scene/resources/material.cpp #: scene/resources/particles_material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Color" -msgstr "Couleurs" +msgstr "Couleur" #: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp #: scene/resources/environment.cpp msgid "Intensity" -msgstr "" +msgstr "Intensité" #: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Range" -msgstr "Changer" +msgstr "Plage" #: modules/gltf/gltf_light.cpp msgid "Inner Cone Angle" @@ -17382,14 +17067,12 @@ msgid "Blend Weights" msgstr "Précalculer les lightmaps" #: modules/gltf/gltf_mesh.cpp -#, fuzzy msgid "Instance Materials" -msgstr "Changements de matériau :" +msgstr "Matériaux d'instances" #: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp -#, fuzzy msgid "Parent" -msgstr "Re-parenter" +msgstr "Parent" #: modules/gltf/gltf_node.cpp #, fuzzy @@ -17398,78 +17081,71 @@ msgstr "Plateforme" #: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp msgid "Skin" -msgstr "" +msgstr "Enveloppe" #: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Translation" -msgstr "Traductions" +msgstr "Translation" #: modules/gltf/gltf_node.cpp -#, fuzzy msgid "Children" -msgstr "Enfants modifiables" +msgstr "Enfants" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints" -msgstr "Point" +msgstr "Jointures" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp msgid "Roots" -msgstr "" +msgstr "Racines" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp msgid "Unique Names" -msgstr "" +msgstr "Noms Uniques" #: modules/gltf/gltf_skeleton.cpp -#, fuzzy msgid "Godot Bone Node" -msgstr "Le nÅ“ud de la scène" +msgstr "NÅ“ud d'os de Godot" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Skin Root" -msgstr "Nouvelle racine de scène" +msgstr "Racine de l'enveloppe" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints Original" -msgstr "Focaliser l'origine" +msgstr "Jointure à l'original" #: modules/gltf/gltf_skin.cpp msgid "Inverse Binds" -msgstr "" +msgstr "Inverser les liens" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Non Joints" -msgstr "Déplacer la jointure" +msgstr "Non jointures" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Bone I" -msgstr "" +msgstr "Jointure I à os I" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Name" -msgstr "" +msgstr "Jointure I à nom" #: modules/gltf/gltf_skin.cpp msgid "Godot Skin" -msgstr "" +msgstr "Enveloppe Godot" #: modules/gltf/gltf_spec_gloss.cpp msgid "Diffuse Img" -msgstr "" +msgstr "Image Diffuse" #: modules/gltf/gltf_spec_gloss.cpp msgid "Diffuse Factor" -msgstr "" +msgstr "Facteur de diffusion" #: modules/gltf/gltf_spec_gloss.cpp msgid "Gloss Factor" -msgstr "" +msgstr "Facteur de brillance" #: modules/gltf/gltf_spec_gloss.cpp msgid "Specular Factor" @@ -17481,96 +17157,84 @@ msgstr "" #: modules/gltf/gltf_state.cpp msgid "Json" -msgstr "" +msgstr "Json" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Major Version" -msgstr "Version" +msgstr "Version majeure" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Minor Version" -msgstr "Version" +msgstr "Version mineure" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "GLB Data" -msgstr "Avec données" +msgstr "Données GLB" #: modules/gltf/gltf_state.cpp msgid "Use Named Skin Binds" -msgstr "" +msgstr "Utiliser les liens d'enveloppe par nom" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Buffer Views" -msgstr "Vue de derrière" +msgstr "Vues tampon" #: modules/gltf/gltf_state.cpp msgid "Accessors" -msgstr "" +msgstr "Accesseurs" #: modules/gltf/gltf_state.cpp msgid "Scene Name" msgstr "Nom de la Scène" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Root Nodes" -msgstr "Nom de nÅ“ud racine" +msgstr "NÅ“uds racines" #: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp -#, fuzzy msgid "Textures" -msgstr "Fonctionnalités" +msgstr "Textures" #: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp msgid "Images" -msgstr "" +msgstr "Images" #: modules/gltf/gltf_state.cpp msgid "Cameras" -msgstr "" +msgstr "Caméras" #: modules/gltf/gltf_state.cpp servers/visual_server.cpp -#, fuzzy msgid "Lights" -msgstr "Lumière" +msgstr "Lumières" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Unique Animation Names" -msgstr "Nom de la nouvelle animation :" +msgstr "Noms d'animations uniques" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeletons" -msgstr "Squelette" +msgstr "Squelettes" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeleton To Node" -msgstr "Sélectionner un nÅ“ud" +msgstr "Squelette vers nÅ“ud" #: modules/gltf/gltf_state.cpp msgid "Animations" msgstr "Animations" #: modules/gltf/gltf_texture.cpp -#, fuzzy msgid "Src Image" -msgstr "Afficher les os" +msgstr "Image source" #: modules/gridmap/grid_map.cpp msgid "Mesh Library" msgstr "Librairie de maillages" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Physics Material" -msgstr "Image physique %" +msgstr "Matériau physique" #: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp #, fuzzy @@ -17579,46 +17243,40 @@ msgstr "Précalculer les lightmaps" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp msgid "Cell" -msgstr "" +msgstr "Cellule" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Octant Size" -msgstr "Vue de devant" +msgstr "Taille d'octant" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center X" -msgstr "Centre" +msgstr "X du centre" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Y" -msgstr "Centre" +msgstr "Y du centre" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Z" -msgstr "Centre" +msgstr "Z du centre" #: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp #: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp #: scene/resources/material.cpp msgid "Mask" -msgstr "" +msgstr "Masque" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp -#, fuzzy msgid "Bake Navigation" -msgstr "Navigation" +msgstr "Pré-calculer la navigation" #: modules/gridmap/grid_map.cpp scene/2d/navigation_2d.cpp #: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp #: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp #: scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Navigation Layers" -msgstr "Mode Navigation" +msgstr "Calques de navigation" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Next Plane" @@ -17784,19 +17442,19 @@ msgstr "Précalculer les lightmaps" #: modules/lightmapper_cpu/register_types.cpp msgid "Low Quality Ray Count" -msgstr "" +msgstr "Nombre de rayons de basse qualité" #: modules/lightmapper_cpu/register_types.cpp msgid "Medium Quality Ray Count" -msgstr "" +msgstr "Nombre de rayons de qualité moyenne" #: modules/lightmapper_cpu/register_types.cpp msgid "High Quality Ray Count" -msgstr "" +msgstr "Nombre de rayons de haute qualité" #: modules/lightmapper_cpu/register_types.cpp msgid "Ultra Quality Ray Count" -msgstr "" +msgstr "Nombre de rayons de qualité extrême" #: modules/minimp3/audio_stream_mp3.cpp #: modules/minimp3/resource_importer_mp3.cpp @@ -17807,16 +17465,15 @@ msgstr "Décalage de Boucle" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Eye Height" -msgstr "" +msgstr "Hauteur de l’œil" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "IOD" msgstr "" #: modules/mobile_vr/mobile_vr_interface.cpp -#, fuzzy msgid "Display Width" -msgstr "Affichage en fil de fer" +msgstr "Afficher la largeur" #: modules/mobile_vr/mobile_vr_interface.cpp #, fuzzy @@ -17825,15 +17482,15 @@ msgstr "Afficher sans ombrage" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Oversample" -msgstr "" +msgstr "Suréchantillonner" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "K1" -msgstr "" +msgstr "K1" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "K2" -msgstr "" +msgstr "K2" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -17844,9 +17501,8 @@ msgid "Build Solution" msgstr "Compiler la solution" #: modules/mono/editor/csharp_project.cpp -#, fuzzy msgid "Auto Update Project" -msgstr "Projet sans titre" +msgstr "Mettre à jour le projet automatiquement" #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" @@ -17921,56 +17577,51 @@ msgstr "C'est fait !" #: modules/opensimplex/noise_texture.cpp msgid "Seamless" -msgstr "" +msgstr "Sans bord" #: modules/opensimplex/noise_texture.cpp -#, fuzzy msgid "As Normal Map" -msgstr "Échelle aléatoire :" +msgstr "En tant que carte de normales" #: modules/opensimplex/noise_texture.cpp msgid "Bump Strength" -msgstr "" +msgstr "Force du bossage" #: modules/opensimplex/noise_texture.cpp msgid "Noise" -msgstr "" +msgstr "Bruit" #: modules/opensimplex/noise_texture.cpp -#, fuzzy msgid "Noise Offset" -msgstr "Décalage de la grille :" +msgstr "Décalage du bruit" #: modules/opensimplex/open_simplex_noise.cpp msgid "Octaves" -msgstr "" +msgstr "Octaves" #: modules/opensimplex/open_simplex_noise.cpp msgid "Period" -msgstr "" +msgstr "Période" #: modules/opensimplex/open_simplex_noise.cpp -#, fuzzy msgid "Persistence" -msgstr "Perspective" +msgstr "Persistance" #: modules/opensimplex/open_simplex_noise.cpp msgid "Lacunarity" -msgstr "" +msgstr "Lacunarité" #: modules/regex/regex.cpp msgid "Subject" -msgstr "" +msgstr "Sujet" #: modules/regex/regex.cpp -#, fuzzy msgid "Names" -msgstr "Nom" +msgstr "Noms" #: modules/regex/regex.cpp -#, fuzzy msgid "Strings" -msgstr "Paramètres :" +msgstr "Paramètres" #: modules/upnp/upnp.cpp msgid "Discover Multicast If" @@ -17978,39 +17629,35 @@ msgstr "" #: modules/upnp/upnp.cpp msgid "Discover Local Port" -msgstr "" +msgstr "Révéler le port local" #: modules/upnp/upnp.cpp msgid "Discover IPv6" -msgstr "" +msgstr "Découvrir IPv6" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Description URL" -msgstr "Description" +msgstr "URL de description" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "Service Type" -msgstr "Définir type de variable" +msgstr "Type du service" #: modules/upnp/upnp_device.cpp msgid "IGD Control URL" -msgstr "" +msgstr "URL de contrôle IGD" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "IGD Service Type" -msgstr "Définir type de variable" +msgstr "Type de service IGD" #: modules/upnp/upnp_device.cpp msgid "IGD Our Addr" msgstr "" #: modules/upnp/upnp_device.cpp -#, fuzzy msgid "IGD Status" -msgstr "État" +msgstr "État IGD" #: modules/visual_script/visual_script.cpp msgid "" @@ -18051,9 +17698,8 @@ msgid "Stack overflow with stack depth:" msgstr "Débordement de pile avec profondeur de pile :" #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Visual Script" -msgstr "Rechercher VisualScript" +msgstr "Script graphique" #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" @@ -18389,9 +18035,8 @@ msgid "Return Enabled" msgstr "Exécutable" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Return Type" -msgstr "Retour" +msgstr "Type de retour" #: modules/visual_script/visual_script_flow_control.cpp #: scene/resources/visual_shader_nodes.cpp @@ -18439,7 +18084,6 @@ msgid "in order:" msgstr "dans l'ordre :" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Steps" msgstr "Pas" @@ -18461,9 +18105,8 @@ msgstr "Est-ce %s ?" #: modules/visual_script/visual_script_flow_control.cpp #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Base Script" -msgstr "Nouveau script" +msgstr "Script de base" #: modules/visual_script/visual_script_func_nodes.cpp msgid "On %s" @@ -18475,36 +18118,31 @@ msgstr "On Self" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Call Mode" -msgstr "Mode mise à l'échelle" +msgstr "Mode d'appel" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Basic Type" -msgstr "Changer le type de base" +msgstr "Type simple" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Node Path" -msgstr "Copier le chemin du nÅ“ud" +msgstr "Chemin de nÅ“ud" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Use Default Args" -msgstr "Réinitialiser" +msgstr "Utiliser les valeurs d'arguments par défaut" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Validate" msgstr "Valider" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "RPC Call Mode" -msgstr "Mode mise à l'échelle" +msgstr "Mode d'appel RPC" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Subtract %s" @@ -18543,14 +18181,12 @@ msgid "BitXor %s" msgstr "Ou-exclusif par bit %s" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Set Mode" -msgstr "Mode sélection" +msgstr "Définir le mode" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Assign Op" -msgstr "Assigner" +msgstr "Opérateur d'assignation" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp @@ -18567,9 +18203,8 @@ msgid "Base object is not a Node!" msgstr "L'objet de base n'est pas un nÅ“ud !" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Path does not lead to Node!" -msgstr "Le chemin ne mène pas au nÅ“ud !" +msgstr "Le chemin ne mène pas vers un nÅ“ud !" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." @@ -18585,9 +18220,8 @@ msgstr "Composer le tableau" #: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Operator" -msgstr "Itérateur" +msgstr "Opérateur" #: modules/visual_script/visual_script_nodes.cpp msgid "Invalid argument of type:" @@ -18602,9 +18236,8 @@ msgid "a if cond, else b" msgstr "a if cond, else b" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Var Name" -msgstr "Nom" +msgstr "Nom de variable" #: modules/visual_script/visual_script_nodes.cpp msgid "VariableGet not found in script:" @@ -18682,7 +18315,7 @@ msgstr "Sous-appel" #: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp msgid "Title" -msgstr "" +msgstr "Titre" #: modules/visual_script/visual_script_nodes.cpp msgid "Construct %s" @@ -18729,9 +18362,8 @@ msgid "%s sec(s)" msgstr "%s seconde(s)" #: modules/visual_script/visual_script_yield_nodes.cpp scene/main/timer.cpp -#, fuzzy msgid "Wait Time" -msgstr "Peindre la tuile" +msgstr "Temps d'attente" #: modules/visual_script/visual_script_yield_nodes.cpp msgid "WaitSignal" @@ -18746,81 +18378,72 @@ msgid "WaitInstanceSignal" msgstr "WaitInstanceSignal" #: modules/webrtc/webrtc_data_channel.cpp -#, fuzzy msgid "Write Mode" -msgstr "Mode prioritaire" +msgstr "Mode écriture" #: modules/webrtc/webrtc_data_channel.h msgid "WebRTC" -msgstr "" +msgstr "WebRTC" #: modules/webrtc/webrtc_data_channel.h msgid "Max Channel In Buffer (KB)" -msgstr "" +msgstr "Maximum de canal dans le tampon (Ko)" #: modules/websocket/websocket_client.cpp msgid "Verify SSL" -msgstr "" +msgstr "Vérifier la SSL" #: modules/websocket/websocket_client.cpp msgid "Trusted SSL Certificate" -msgstr "" +msgstr "Certificat SSL Fiable" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Client" -msgstr "Profileur réseau" +msgstr "Client WebSocket" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max In Buffer (KB)" -msgstr "Taille Maximale (KB)" +msgstr "Maximum tampon entrant (KB)" #: modules/websocket/websocket_macros.h msgid "Max In Packets" -msgstr "" +msgstr "Maximum de paquets entrant" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max Out Buffer (KB)" -msgstr "Taille Maximale (KB)" +msgstr "Maximum tampon sortant (KB)" #: modules/websocket/websocket_macros.h msgid "Max Out Packets" -msgstr "" +msgstr "Maximum de paquets sortant" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Server" -msgstr "Profileur réseau" +msgstr "Server WebSocket" #: modules/websocket/websocket_server.cpp msgid "Bind IP" -msgstr "" +msgstr "Lier IP" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "Private Key" -msgstr "Chemin de la clé privée SSH" +msgstr "Clé privée" #: modules/websocket/websocket_server.cpp platform/javascript/export/export.cpp msgid "SSL Certificate" -msgstr "" +msgstr "Certificat SSL" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "CA Chain" -msgstr "Effacer la chaîne IK" +msgstr "Chaîne d’autorité de certificat (CA)" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "Handshake Timeout" -msgstr "Délai dépassé." +msgstr "Délai de poignée de main expiré" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Session Mode" -msgstr "Mode Région" +msgstr "Mode de session" #: modules/webxr/webxr_interface.cpp msgid "Required Features" @@ -18835,18 +18458,17 @@ msgid "Requested Reference Space Types" msgstr "" #: modules/webxr/webxr_interface.cpp +#, fuzzy msgid "Reference Space Type" -msgstr "" +msgstr "Type de référentiel spatial" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Visibility State" -msgstr "Basculer la visibilité" +msgstr "État de la visibilité" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Bounds Geometry" -msgstr "Réessayer" +msgstr "Géométrie des limites" #: modules/webxr/webxr_interface.cpp #, fuzzy @@ -18855,7 +18477,7 @@ msgstr "Magnétisme intelligent" #: platform/android/export/export.cpp msgid "Android SDK Path" -msgstr "" +msgstr "Chemin du SDK Android" #: platform/android/export/export.cpp #, fuzzy @@ -18872,27 +18494,27 @@ msgstr "" #: platform/android/export/export.cpp msgid "Force System User" -msgstr "" +msgstr "Forcer l'utilisateur système" #: platform/android/export/export.cpp msgid "Shutdown ADB On Exit" -msgstr "" +msgstr "Fermer ADB à la sortie" #: platform/android/export/export_plugin.cpp msgid "Launcher Icons" -msgstr "" +msgstr "Icônes du lanceur" #: platform/android/export/export_plugin.cpp msgid "Main 192 X 192" -msgstr "" +msgstr "Principal 192 X 192" #: platform/android/export/export_plugin.cpp msgid "Adaptive Foreground 432 X 432" -msgstr "" +msgstr "Avant-Plan Adaptatif 432 X 432" #: platform/android/export/export_plugin.cpp msgid "Adaptive Background 432 X 432" -msgstr "" +msgstr "Arrière-Plan Adaptatif 432 X 432" #: platform/android/export/export_plugin.cpp msgid "Package name is missing." @@ -18924,18 +18546,16 @@ msgid "The package must have at least one '.' separator." msgstr "Le paquet doit comporter au moins un séparateur « . »." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Build" -msgstr "NÅ“ud Personnalisé" +msgstr "Construction personnalisé" #: platform/android/export/export_plugin.cpp msgid "Use Custom Build" -msgstr "" +msgstr "Utiliser une construction personnalisé" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Export Format" -msgstr "Chemin d'exportation" +msgstr "Format d'exportation" #: platform/android/export/export_plugin.cpp msgid "Min SDK" @@ -18943,12 +18563,11 @@ msgstr "Min SDK" #: platform/android/export/export_plugin.cpp msgid "Target SDK" -msgstr "Target SDK" +msgstr "SDK Cible" #: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp -#, fuzzy msgid "Architectures" -msgstr "Ajouter une entrée architecture" +msgstr "Architectures" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18956,51 +18575,44 @@ msgid "Keystore" msgstr "Débogueur" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Debug User" -msgstr "Débogueur" +msgstr "Utilisateur de débogage" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Debug Password" -msgstr "Mot de passe" +msgstr "Mot de passe de débogage" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Release User" -msgstr "Publication (release)" +msgstr "Utilisateur de publication (release)" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Release Password" -msgstr "Mot de passe" +msgstr "Mot de passe de publication" #: platform/android/export/export_plugin.cpp msgid "One Click Deploy" -msgstr "" +msgstr "Déploiement en un clic" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Clear Previous Install" -msgstr "Inspecter l'instance précédente" +msgstr "Nettoyer l'installation précédente" #: platform/android/export/export_plugin.cpp msgid "Code" -msgstr "" +msgstr "Code" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Package" -msgstr "Empaquetage" +msgstr "Paquetage" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp msgid "Unique Name" msgstr "Nom unique" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Signed" -msgstr "Signaux" +msgstr "Signé" #: platform/android/export/export_plugin.cpp msgid "Classify As Game" @@ -19008,22 +18620,19 @@ msgstr "Classer En Tant Que Jeu" #: platform/android/export/export_plugin.cpp msgid "Retain Data On Uninstall" -msgstr "" +msgstr "Conserver les données lors de la désinstallation" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Exclude From Recents" -msgstr "Supprimer des nÅ“uds" +msgstr "Exclure des récents" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Graphics" -msgstr "Décalage de la grille :" +msgstr "Graphismes" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "OpenGL Debug" -msgstr "Ouvrir" +msgstr "Débogage OpenGL" #: platform/android/export/export_plugin.cpp msgid "XR Features" @@ -19034,22 +18643,20 @@ msgid "XR Mode" msgstr "Mode XR" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Hand Tracking" -msgstr "Empaquetage" +msgstr "Suivi des mains" #: platform/android/export/export_plugin.cpp msgid "Hand Tracking Frequency" -msgstr "" +msgstr "Fréquence de suivi des mains" #: platform/android/export/export_plugin.cpp msgid "Passthrough" -msgstr "" +msgstr "Relais" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Immersive Mode" -msgstr "Mode prioritaire" +msgstr "Mode immersif" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -19072,18 +18679,16 @@ msgid "Support Xlarge" msgstr "Support" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "User Data Backup" -msgstr "Interface utilisateur" +msgstr "Sauvegarde(backup) des données utilisateur" #: platform/android/export/export_plugin.cpp msgid "Allow" -msgstr "" +msgstr "Autoriser" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Command Line" -msgstr "Communauté" +msgstr "Ligne de commande" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp msgid "Extra Args" @@ -19096,22 +18701,19 @@ msgstr "Expression" #: platform/android/export/export_plugin.cpp msgid "Salt" -msgstr "" +msgstr "Sel" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Public Key" -msgstr "Chemin de la clé publique SSH" +msgstr "Clé Publique" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Permissions" -msgstr "Masque d'émission" +msgstr "Permissions" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Permissions" -msgstr "Jouer une scène personnalisée" +msgstr "Permissions Personnalisées" #: platform/android/export/export_plugin.cpp msgid "Select device from the list" @@ -19231,6 +18833,11 @@ msgid "" "Note that the singleton was also renamed from \"GodotPayments\" to " "\"GodotGooglePlayBilling\"." msgstr "" +"Le module \"GodotPaymentV3\" inclus dans les paramètres du projet à " +"\"android/modules\" est invalide (Changé dans Godot 3.2.2).\n" +"Remplacez-le avec le plugin tiers \"GodotGooglePlayBilling\".\n" +"Notez que ce singleton a aussi été renommé de \"GodotPayments\" en " +"\"GodotGooglePlayBilling\"." #: platform/android/export/export_plugin.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." @@ -19265,12 +18872,16 @@ msgstr "" #: platform/android/export/export_plugin.cpp msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid." msgstr "" +"\"Min SDK\" devrait être un nombre entier valide, mais \"%s\" n'est pas " +"valide." #: platform/android/export/export_plugin.cpp msgid "" "\"Min SDK\" cannot be lower than %d, which is the version needed by the " "Godot library." msgstr "" +"« Min SDK » ne peut être inférieur à %d, la version requise par la libraire " +"de Godot." #: platform/android/export/export_plugin.cpp msgid "" @@ -19283,12 +18894,16 @@ msgstr "" msgid "" "\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid." msgstr "" +"« SDK Cible » devrait être un nombre entier valide, mais « %s » n'en est pas " +"un." #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" %d is higher than the default version %d. This may work, but " "wasn't tested and may be unstable." msgstr "" +"« SDK Cible » %d est plus grande que la version par défaut %d. Cela pourrait " +"fonctionner, mais ça n'a pas été testé. Le résultat pourrait être instable." #: platform/android/export/export_plugin.cpp msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version." @@ -19298,20 +18913,17 @@ msgstr "" #: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Code Signing" -msgstr "Signaux" +msgstr "Signature du code" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "'apksigner' could not be found. Please check that the command is available " "in the Android SDK build-tools directory. The resulting %s is unsigned." msgstr "" -"Impossible de trouver 'apksigner'.\n" -"Veuillez vérifier que la commande est disponible dans le dossier build-tools " -"du SDK Android.\n" -"Le paquet sortant %s est non signé." +"Impossible de trouver 'apksigner'. Veuillez vérifier que la commande est " +"disponible dans le dossier build-tools du SDK Android. Le %s resultant n'est " +"pas signé." #: platform/android/export/export_plugin.cpp msgid "Signing debug %s..." @@ -19326,9 +18938,8 @@ msgid "Could not find keystore, unable to export." msgstr "Impossible de trouver le keystore, impossible d'exporter." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not start apksigner executable." -msgstr "Impossible de démarrer le sous-processus !" +msgstr "Impossible de le programme apksigner." #: platform/android/export/export_plugin.cpp msgid "'apksigner' returned with error #%d" @@ -19365,9 +18976,8 @@ msgstr "" "*.apk." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Unsupported export format!" -msgstr "Format d'export non supporté !\n" +msgstr "Format d'export non supporté !" #: platform/android/export/export_plugin.cpp msgid "" @@ -19379,28 +18989,24 @@ msgstr "" "menu 'Projet'." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Android build version mismatch: Template installed: %s, Godot version: %s. " "Please reinstall Android build template from 'Project' menu." msgstr "" -"La version d'Android ne correspond pas :\n" -" Modèle installé : %s\n" -" Version Godot : %s\n" -"Veuillez réinstaller la version d'Android depuis le menu 'Projet'." +"La version compilée d'Android ne correspond pas : Modèle type installé : %s, " +"Version de Godot : %s. Veuillez réinstaller le modèle type de compilation " +"d'Android depuis le menu 'Projet'." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Unable to overwrite res://android/build/res/*.xml files with project name." msgstr "" "Impossible d'écraser les fichiers res://android/build/res/*.xml avec le nom " -"du projet" +"du projet." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle\n" +msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle." #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -19411,15 +19017,13 @@ msgid "Building Android Project (gradle)" msgstr "Construire le Project Android (gradle)" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Building of Android project failed, check output for the error. " "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" "La construction du projet Android a échoué, vérifiez la sortie pour " -"l'erreur.\n" -"Sinon, visitez docs.godotengine.org pour la documentation de construction " -"Android." +"l'erreur. Sinon, visitez docs.godotengine.org pour la documentation de " +"construction Android." #: platform/android/export/export_plugin.cpp msgid "Moving output" @@ -19434,41 +19038,38 @@ msgstr "" "du projet gradle pour les journaux." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Package not found: \"%s\"." -msgstr "Paquet non trouvé : %s" +msgstr "Paquet non trouvé : \"%s\"." #: platform/android/export/export_plugin.cpp msgid "Creating APK..." msgstr "Création de l'APK..." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not find template APK to export: \"%s\"." msgstr "" -"Impossible de trouver le modèle de l'APK à exporter :\n" -"%s" +"La construction du projet Android a échoué, vérifiez la sortie pour " +"l'erreur. Sinon, visitez docs.godotengine.org pour la documentation de " +"construction Android." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Missing libraries in the export template for the selected architectures: %s. " "Please build a template with all required libraries, or uncheck the missing " "architectures in the export preset." msgstr "" "Bibliothèques manquantes dans le modèle d'exportation pour les architectures " -"sélectionnées : %s.\n" -"Veuillez construire un modèle avec toutes les bibliothèques requises, ou " -"désélectionner les architectures manquantes dans le préréglage d'exportation." +"sélectionnées : %s. Veuillez construire un modèle avec toutes les " +"bibliothèques requises, ou désélectionner les architectures manquantes dans " +"le préréglage d'exportation." #: platform/android/export/export_plugin.cpp msgid "Adding files..." msgstr "Ajout de fichiers..." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files." -msgstr "Impossible d'exporter les fichiers du projet" +msgstr "Impossible d'exporter les fichiers du projet." #: platform/android/export/export_plugin.cpp msgid "Aligning APK..." @@ -19492,188 +19093,176 @@ msgstr "" #: platform/iphone/export/export.cpp msgid "iPhone 2436 X 1125" -msgstr "" +msgstr "iPhone 2436 X 1125" #: platform/iphone/export/export.cpp msgid "iPhone 2208 X 1242" -msgstr "" +msgstr "iPhone 2208 X 1242" #: platform/iphone/export/export.cpp msgid "iPad 1024 X 768" -msgstr "" +msgstr "iPad 1024 X 768" #: platform/iphone/export/export.cpp msgid "iPad 2048 X 1536" -msgstr "" +msgstr "iPad 2048 X 1536" #: platform/iphone/export/export.cpp msgid "Portrait Launch Screens" -msgstr "" +msgstr "Écrans de lancement en mode portrait" #: platform/iphone/export/export.cpp msgid "iPhone 640 X 960" -msgstr "" +msgstr "iPhone 640 X 960" #: platform/iphone/export/export.cpp msgid "iPhone 640 X 1136" -msgstr "" +msgstr "iPhone 640 X 1136" #: platform/iphone/export/export.cpp msgid "iPhone 750 X 1334" -msgstr "" +msgstr "iPhone 750 X 1334" #: platform/iphone/export/export.cpp msgid "iPhone 1125 X 2436" -msgstr "" +msgstr "iPhone 1125 X 2436" #: platform/iphone/export/export.cpp msgid "iPad 768 X 1024" -msgstr "" +msgstr "iPad 768 X 1024" #: platform/iphone/export/export.cpp msgid "iPad 1536 X 2048" -msgstr "" +msgstr "iPad 1536 X 2048" #: platform/iphone/export/export.cpp msgid "iPhone 1242 X 2208" -msgstr "" +msgstr "iPhone 1242 X 2208" #: platform/iphone/export/export.cpp msgid "App Store Team ID" -msgstr "" +msgstr "ID de groupe de l'App Store" #: platform/iphone/export/export.cpp msgid "Provisioning Profile UUID Debug" -msgstr "" +msgstr "UUID de provisionnement de profils en débogage" #: platform/iphone/export/export.cpp msgid "Code Sign Identity Debug" -msgstr "" +msgstr "Identité de signature de code en débogage" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Export Method Debug" -msgstr "Exporter avec debug" +msgstr "Méthode d'exportation en débogage" #: platform/iphone/export/export.cpp msgid "Provisioning Profile UUID Release" -msgstr "" +msgstr "UUID de provisionnement de profils en publication" #: platform/iphone/export/export.cpp msgid "Code Sign Identity Release" -msgstr "" +msgstr "Identité de signature de code en publication" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Export Method Release" -msgstr "Mode d'exportation :" +msgstr "Méthode d'exportation en publication" #: platform/iphone/export/export.cpp msgid "Targeted Device Family" -msgstr "" +msgstr "Famille de système ciblée" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp msgid "Info" -msgstr "" +msgstr "Info" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp msgid "Identifier" msgstr "Identifiant" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Signature" -msgstr "Signaux" +msgstr "Signature" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Short Version" -msgstr "Version" +msgstr "Version courte" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Copyright" -msgstr "En haut à droite" +msgstr "Copyright" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Capabilities" -msgstr "Coller les propriétés" +msgstr "Capacités" #: platform/iphone/export/export.cpp msgid "Access Wi-Fi" msgstr "Accès Wi-Fi" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Push Notifications" -msgstr "Rotation aléatoire :" +msgstr "Notifications Push" #: platform/iphone/export/export.cpp -#, fuzzy msgid "User Data" -msgstr "Interface utilisateur" +msgstr "Données Utilisateur" #: platform/iphone/export/export.cpp msgid "Accessible From Files App" -msgstr "" +msgstr "Accessible depuis l'application Files" #: platform/iphone/export/export.cpp msgid "Accessible From iTunes Sharing" -msgstr "" +msgstr "Accessible depuis le partage iTunes" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Privacy" -msgstr "Chemin de la clé privée SSH" +msgstr "Confidentialité" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Camera Usage Description" -msgstr "Description" +msgstr "Description d'utilisation de la caméra" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Microphone Usage Description" -msgstr "Description des propriétés" +msgstr "Description d'utilisation du microphone" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Photolibrary Usage Description" -msgstr "Description des propriétés" +msgstr "Description d'utilisation de la bibliothèque d'image" #: platform/iphone/export/export.cpp msgid "iPhone 120 X 120" -msgstr "" +msgstr "iPhone 120 X 120" #: platform/iphone/export/export.cpp msgid "iPhone 180 X 180" -msgstr "" +msgstr "iPhone 180 X 180" #: platform/iphone/export/export.cpp msgid "iPad 76 X 76" -msgstr "" +msgstr "iPad 76 X 76" #: platform/iphone/export/export.cpp msgid "iPad 152 X 152" -msgstr "" +msgstr "iPad 152 X 152" #: platform/iphone/export/export.cpp msgid "iPad 167 X 167" -msgstr "" +msgstr "iPad 167 X 167" #: platform/iphone/export/export.cpp msgid "App Store 1024 X 1024" -msgstr "" +msgstr "App Store 1024 X 1024" #: platform/iphone/export/export.cpp msgid "Spotlight 40 X 40" -msgstr "" +msgstr "Projecteur 40 X 40" #: platform/iphone/export/export.cpp msgid "Spotlight 80 X 80" -msgstr "" +msgstr "Projecteur 80 X 80" #: platform/iphone/export/export.cpp msgid "Storyboard" @@ -19684,40 +19273,33 @@ msgid "Use Launch Screen Storyboard" msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Image Scale Mode" -msgstr "Mode mise à l'échelle" +msgstr "Mode de mise à l'échelle d'image" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom Image @2x" -msgstr "NÅ“ud Personnalisé" +msgstr "Image personnalisée @2x" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom Image @3x" -msgstr "NÅ“ud Personnalisé" +msgstr "Image personnalisée @3x" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Use Custom BG Color" -msgstr "NÅ“ud Personnalisé" +msgstr "Utiliser la couleur d'arrière-plan personnalisée" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Custom BG Color" -msgstr "NÅ“ud Personnalisé" +msgstr "Couleur d'arrière-plan personnalisée" #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp -#, fuzzy msgid "Prepare Templates" -msgstr "Gérer les modèles" +msgstr "Préparer les modèles" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Export template not found." -msgstr "Modèle de version personnalisée introuvable." +msgstr "Modèle d'exportation introuvable." #: platform/iphone/export/export.cpp msgid "App Store Team ID not specified - cannot configure the project." @@ -19740,29 +19322,24 @@ msgid "Run exported HTML in the system's default browser." msgstr "Exécutez le HTML exporté dans le navigateur par défaut du système." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not open template for export: \"%s\"." -msgstr "Impossible d'ouvrir le modèle pour exportation :" +msgstr "Impossible d'ouvrir le modèle pour exportation : « %s »." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Invalid export template: \"%s\"." -msgstr "Modèle d'exportation non valide :" +msgstr "Modèle d'exportation invalide : « %s »." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not write file: \"%s\"." -msgstr "Impossible d'écrire le fichier :" +msgstr "Impossible d'écrire le fichier : « %s »." #: platform/javascript/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Icon Creation" -msgstr "Définir la marge" +msgstr "Création de l'icône" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read file: \"%s\"." -msgstr "Impossible de lire le fichier :" +msgstr "Impossible de lire le fichier : «%s »." #: platform/javascript/export/export.cpp msgid "PWA" @@ -19773,36 +19350,32 @@ msgid "Variant" msgstr "Variant" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Export Type" -msgstr "Exporter" +msgstr "Type d'exportation" #: platform/javascript/export/export.cpp -#, fuzzy msgid "VRAM Texture Compression" -msgstr "Expression" +msgstr "Compression des textures dans la mémoire vidéo" #: platform/javascript/export/export.cpp msgid "For Desktop" -msgstr "" +msgstr "Pour PC" #: platform/javascript/export/export.cpp msgid "For Mobile" -msgstr "" +msgstr "Pour Mobile" #: platform/javascript/export/export.cpp msgid "HTML" -msgstr "" +msgstr "HTML" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Export Icon" -msgstr "Développer tout" +msgstr "Icône d'exportation" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Custom HTML Shell" -msgstr "NÅ“ud Personnalisé" +msgstr "Shell HTML personnalisé" #: platform/javascript/export/export.cpp msgid "Head Include" @@ -19810,72 +19383,67 @@ msgstr "" #: platform/javascript/export/export.cpp msgid "Canvas Resize Policy" -msgstr "" +msgstr "Politique de redimensionnement du canevas" #: platform/javascript/export/export.cpp msgid "Focus Canvas On Start" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Experimental Virtual Keyboard" -msgstr "Filtrer les signaux" +msgstr "Clavier virtuel expérimental" #: platform/javascript/export/export.cpp msgid "Progressive Web App" -msgstr "" +msgstr "Application web progressive" #: platform/javascript/export/export.cpp msgid "Offline Page" -msgstr "" +msgstr "Page hors ligne" #: platform/javascript/export/export.cpp msgid "Icon 144 X 144" -msgstr "" +msgstr "Icône 144 X 144" #: platform/javascript/export/export.cpp msgid "Icon 180 X 180" -msgstr "" +msgstr "Icône 180 X 180" #: platform/javascript/export/export.cpp msgid "Icon 512 X 512" -msgstr "" +msgstr "Icône 512 X 512" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read HTML shell: \"%s\"." -msgstr "Impossible de lire le shell HTML :" +msgstr "Impossible de lire le shell HTML : « %s »." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not create HTTP server directory: %s." -msgstr "Impossible de créer le répertoire du serveur HTTP :" +msgstr "Impossible de créer le répertoire du serveur HTTP : %s." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Error starting HTTP server: %d." -msgstr "Erreur de démarrage du serveur HTTP :" +msgstr "Erreur de démarrage du serveur HTTP : %d." #: platform/javascript/export/export.cpp msgid "Web" -msgstr "" +msgstr "Web" #: platform/javascript/export/export.cpp msgid "HTTP Host" -msgstr "" +msgstr "Hôte HTTP" #: platform/javascript/export/export.cpp msgid "HTTP Port" -msgstr "" +msgstr "Port HTTP" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Use SSL" -msgstr "Utiliser l’aimantation" +msgstr "Utiliser SSL" #: platform/javascript/export/export.cpp msgid "SSL Key" -msgstr "" +msgstr "Clé SSL" #: platform/osx/export/codesign.cpp msgid "Can't get filesystem access." @@ -19903,7 +19471,7 @@ msgstr "Échec de création du sous-dossier « %s »." #: platform/osx/export/codesign.cpp msgid "Failed to extract thin binary." -msgstr "" +msgstr "Échec lors de l'extraction du binaire." #: platform/osx/export/codesign.cpp msgid "Invalid binary format." @@ -19914,18 +19482,16 @@ msgid "Already signed!" msgstr "Déjà signé !" #: platform/osx/export/codesign.cpp -#, fuzzy msgid "Failed to process nested resources." -msgstr "Impossible de charger la ressource." +msgstr "Le traitement des ressources imbriquées a échoué." #: platform/osx/export/codesign.cpp msgid "Failed to create _CodeSignature subfolder." -msgstr "" +msgstr "Échec lors de la création du sous-dossier _CodeSignature." #: platform/osx/export/codesign.cpp -#, fuzzy msgid "Failed to get CodeResources hash." -msgstr "Impossible de charger la ressource." +msgstr "La récupération du hachage de CodeResources a échouée." #: platform/osx/export/codesign.cpp platform/osx/export/export.cpp #, fuzzy @@ -19938,94 +19504,84 @@ msgstr "Fichier exécutable invalide." #: platform/osx/export/codesign.cpp msgid "Can't resize signature load command." -msgstr "" +msgstr "Impossible de redimensionner la commande de chargement des signatures." #: platform/osx/export/codesign.cpp msgid "Failed to create fat binary." -msgstr "" +msgstr "Échec lors de la création du binaire." #: platform/osx/export/codesign.cpp msgid "Unknown bundle type." -msgstr "" +msgstr "Type de paquet inconnu." #: platform/osx/export/codesign.cpp msgid "Unknown object type." msgstr "Type d'objet inconnu." #: platform/osx/export/export.cpp -#, fuzzy msgid "App Category" -msgstr "Catégorie :" +msgstr "Catégorie de l'application" #: platform/osx/export/export.cpp msgid "High Res" -msgstr "" +msgstr "Haute Résolution" #: platform/osx/export/export.cpp -#, fuzzy msgid "Location Usage Description" -msgstr "Description" +msgstr "Description d'utilisation de la géolocalisation" #: platform/osx/export/export.cpp msgid "Address Book Usage Description" -msgstr "" +msgstr "Description d'utilisation du carnet d'adresse" #: platform/osx/export/export.cpp -#, fuzzy msgid "Calendar Usage Description" -msgstr "Description" +msgstr "Description d'utilisation du calendrier" #: platform/osx/export/export.cpp -#, fuzzy msgid "Photos Library Usage Description" -msgstr "Description des propriétés" +msgstr "Description d'utilisation de la bibliothèque photo" #: platform/osx/export/export.cpp -#, fuzzy msgid "Desktop Folder Usage Description" -msgstr "Descriptions des méthodes" +msgstr "Description d'utilisation du dossier Bureau" #: platform/osx/export/export.cpp -#, fuzzy msgid "Documents Folder Usage Description" -msgstr "Descriptions des méthodes" +msgstr "Description d'utilisation du dossier Documents" #: platform/osx/export/export.cpp msgid "Downloads Folder Usage Description" -msgstr "" +msgstr "Description d'utilisation du dossier Téléchargements" #: platform/osx/export/export.cpp msgid "Network Volumes Usage Description" -msgstr "" +msgstr "Description d'utilisation des disques réseau" #: platform/osx/export/export.cpp msgid "Removable Volumes Usage Description" -msgstr "" +msgstr "Description d'utilisation des disques amovibles" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Codesign" -msgstr "NÅ“ud" +msgstr "Signature du code" #: platform/osx/export/export.cpp platform/uwp/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Identity" -msgstr "Indenter vers la gauche" +msgstr "Identité" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Timestamp" -msgstr "Temps" +msgstr "Horodatage" #: platform/osx/export/export.cpp msgid "Hardened Runtime" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Replace Existing Signature" -msgstr "Remplacer dans les fichiers" +msgstr "Remplacer la signature existante" #: platform/osx/export/export.cpp #, fuzzy @@ -20033,13 +19589,12 @@ msgid "Entitlements" msgstr "Gadgets" #: platform/osx/export/export.cpp -#, fuzzy msgid "Custom File" -msgstr "NÅ“ud Personnalisé" +msgstr "Fichier personnalisé" #: platform/osx/export/export.cpp msgid "Allow JIT Code Execution" -msgstr "" +msgstr "Autoriser l'exécution du code JIT" #: platform/osx/export/export.cpp msgid "Allow Unsigned Executable Memory" @@ -20050,65 +19605,57 @@ msgid "Allow Dyld Environment Variables" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Disable Library Validation" -msgstr "Bouton désactivé" +msgstr "Désactiver la validation des librairies" #: platform/osx/export/export.cpp -#, fuzzy msgid "Audio Input" -msgstr "Ajouter une entrée" +msgstr "Entrée Audio" #: platform/osx/export/export.cpp msgid "Address Book" -msgstr "" +msgstr "Carnet d'Adresses" #: platform/osx/export/export.cpp msgid "Calendars" -msgstr "" +msgstr "Calendrier" #: platform/osx/export/export.cpp -#, fuzzy msgid "Photos Library" -msgstr "Bibliothèque d'exportation" +msgstr "Bibliothèque de photos" #: platform/osx/export/export.cpp -#, fuzzy msgid "Apple Events" -msgstr "Ajouter évènement" +msgstr "Événements Apple" #: platform/osx/export/export.cpp -#, fuzzy msgid "Debugging" msgstr "Débogage" #: platform/osx/export/export.cpp msgid "App Sandbox" -msgstr "" +msgstr "Bac à sable de l'application" #: platform/osx/export/export.cpp -#, fuzzy msgid "Network Server" -msgstr "Profileur réseau" +msgstr "Serveur réseau" #: platform/osx/export/export.cpp -#, fuzzy msgid "Network Client" -msgstr "Profileur réseau" +msgstr "Client réseau" #: platform/osx/export/export.cpp -#, fuzzy msgid "Device USB" -msgstr "Périphérique" +msgstr "Périphérique USB" #: platform/osx/export/export.cpp msgid "Device Bluetooth" -msgstr "" +msgstr "Périphérique Bluetooth" #: platform/osx/export/export.cpp #, fuzzy msgid "Files Downloads" -msgstr "Télécharger" +msgstr "Téléchargement de fichiers" #: platform/osx/export/export.cpp #, fuzzy @@ -20126,9 +19673,8 @@ msgid "Files Movies" msgstr "Filtrer les tuiles" #: platform/osx/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Custom Options" -msgstr "Options de bus" +msgstr "Options personnalisées" #: platform/osx/export/export.cpp #, fuzzy @@ -20137,31 +19683,27 @@ msgstr "Localisation" #: platform/osx/export/export.cpp msgid "Apple ID Name" -msgstr "" +msgstr "Nom Apple ID" #: platform/osx/export/export.cpp -#, fuzzy msgid "Apple ID Password" -msgstr "Mot de passe" +msgstr "Mot de passe Apple ID" #: platform/osx/export/export.cpp msgid "Apple Team ID" msgstr "Apple Team ID" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open icon file \"%s\"." -msgstr "Impossible d'exporter les fichiers du projet" +msgstr "Impossible d'ouvrir le fichier d'icône \"%s\"." #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start xcrun executable." -msgstr "Impossible de démarrer le sous-processus !" +msgstr "Impossible de démarrer le sous-processus." #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization failed." -msgstr "Localisation" +msgstr "Notarisation échouée." #: platform/osx/export/export.cpp msgid "Notarization request UUID: \"%s\"" @@ -20172,22 +19714,30 @@ msgid "" "The notarization process generally takes less than an hour. When the process " "is completed, you'll receive an email." msgstr "" +"Le processus de certification prend généralement moins d'une heure. Quand le " +"processus sera achevé, vous recevrez un e-mail." #: platform/osx/export/export.cpp msgid "" "You can check progress manually by opening a Terminal and running the " "following command:" msgstr "" +"Vous pouvez contrôler la progression manuellement en ouvrant un Terminal et " +"en exécutant la commande suivante :" #: platform/osx/export/export.cpp msgid "" "Run the following command to staple the notarization ticket to the exported " "application (optional):" msgstr "" +"Exécutez la commande suivante pour lier le ticket de certification avec " +"l'application exporté (optionnel) :" #: platform/osx/export/export.cpp msgid "Timestamping is not compatible with ad-hoc signature, and was disabled!" msgstr "" +"L'horodatage n'est pas compatible avec la signature ad-hoc et a été " +"désactivé !" #: platform/osx/export/export.cpp msgid "" @@ -20200,71 +19750,73 @@ msgstr "" #: platform/osx/export/export.cpp msgid "Built-in CodeSign require regex module." -msgstr "" +msgstr "CodeSign intégré nécessite le module regex." #: platform/osx/export/export.cpp msgid "" "Could not start codesign executable, make sure Xcode command line tools are " "installed." msgstr "" +"Ne peut lancer l'exécutable codesign, vérifiez que les outils en ligne de " +"commande de Xcode sont installés." #: platform/osx/export/export.cpp platform/windows/export/export.cpp msgid "No identity found." msgstr "Aucune identité trouvée." #: platform/osx/export/export.cpp -#, fuzzy msgid "Cannot sign file %s." -msgstr "Erreur lors de l'enregistrement du fichier : %s" +msgstr "Impossible de signer le fichier %s." #: platform/osx/export/export.cpp msgid "Relative symlinks are not supported, exported \"%s\" might be broken!" msgstr "" +"Les liens symboliques relatifs ne sont pas supportés, « %s » pourrait être " +"cassé !" #: platform/osx/export/export.cpp -#, fuzzy msgid "DMG Creation" -msgstr "Directions" +msgstr "Création du DMG" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start hdiutil executable." -msgstr "Impossible de démarrer le sous-processus !" +msgstr "Impossible de démarrer le programme hdiutil." #: platform/osx/export/export.cpp msgid "`hdiutil create` failed - file exists." -msgstr "" +msgstr "`hdiutil create` a échoué - le fichier existe." #: platform/osx/export/export.cpp msgid "`hdiutil create` failed." -msgstr "" +msgstr "`hdiutil create` a échoué." #: platform/osx/export/export.cpp -#, fuzzy msgid "Creating app bundle" -msgstr "Création de l'aperçu" +msgstr "Création du paquet d'application" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not find template app to export: \"%s\"." -msgstr "Impossible de trouver le modèle de l'application à exporter :" +msgstr "Impossible de trouver le modèle de l'application à exporter : \"%s\"." #: platform/osx/export/export.cpp -#, fuzzy msgid "Invalid export format." -msgstr "Modèle d'exportation non valide :" +msgstr "Format d'export invalide." #: platform/osx/export/export.cpp msgid "" "Relative symlinks are not supported on this OS, the exported project might " "be broken!" msgstr "" +"Les liens symboliques relatifs ne sont pas supportés sur ce système " +"d'exploitation, le projet exporté pourrait être cassé !" #: platform/osx/export/export.cpp msgid "" "Requested template binary \"%s\" not found. It might be missing from your " "template archive." msgstr "" +"Le binaire modèle requis « %s » n'a pas été trouvé. Il doit être absent de " +"votre archive de modèles." #: platform/osx/export/export.cpp msgid "Making PKG" @@ -20275,10 +19827,13 @@ msgid "" "Ad-hoc signed applications require the 'Disable Library Validation' " "entitlement to load dynamic libraries." msgstr "" +"La signature d'applications ad-hoc nécessite la permission \"Désactiver la " +"validation de bibliothèque\" pour pouvoir charger dynamiquement les " +"bibliothèques." #: platform/osx/export/export.cpp msgid "Code signing bundle" -msgstr "" +msgstr "Paquet de signature du code" #: platform/osx/export/export.cpp msgid "Making DMG" @@ -20286,7 +19841,7 @@ msgstr "Création du DMG" #: platform/osx/export/export.cpp msgid "Code signing DMG" -msgstr "" +msgstr "DMG de signature du code" #: platform/osx/export/export.cpp msgid "Making ZIP" @@ -20297,20 +19852,20 @@ msgid "" "Notarization requires the app to be archived first, select the DMG or ZIP " "export format instead." msgstr "" +"La certification nécessite que l'application soit préalablement archivé. " +"Sélectionnez le format d'exportation DMG ou ZIP à la place." #: platform/osx/export/export.cpp msgid "Sending archive for notarization" -msgstr "" +msgstr "Envoi de l'archive pour la certification" #: platform/osx/export/export.cpp -#, fuzzy msgid "ZIP Creation" -msgstr "Projet" +msgstr "Création ZIP" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open file to read from path \"%s\"." -msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle\n" +msgstr "Impossible d'ouvrir le fichier à lire au chemin \"%s\"." #: platform/osx/export/export.cpp msgid "Invalid bundle identifier:" @@ -20321,26 +19876,32 @@ msgid "" "Warning: Built-in \"codesign\" is selected in the Editor Settings. Code " "signing is limited to ad-hoc signature only." msgstr "" +"Attention : Le « codesign » embarqué est sélectionné dans les paramètres de " +"l'éditeur. La signature du code se limite à la signature ad-hoc seulement." #: platform/osx/export/export.cpp msgid "" "Warning: Xcode command line tools are not installed, using built-in " "\"codesign\". Code signing is limited to ad-hoc signature only." msgstr "" +"Attention : Les outils en ligne de commande de Xcode ne sont pas installés, " +"utilisation du « codesign » embarqué. La signature du code se limite à la " +"signature ad-hoc seulement." #: platform/osx/export/export.cpp msgid "Notarization: Notarization with an ad-hoc signature is not supported." msgstr "" +"Certification : La certification avec une signature ad-hoc n'est pas " +"supporté." #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization: Code signing is required for notarization." -msgstr "Certification : signature du code requise." +msgstr "" +"Notarisation : La signature du code est nécessaire pour la notarisation." #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization: Hardened runtime is required for notarization." -msgstr "Certification : exécution renforcée requise." +msgstr "Notarisation : exécution renforcée nécessaire pour la notarisation." #: platform/osx/export/export.cpp #, fuzzy @@ -20360,12 +19921,17 @@ msgid "" "Warning: Notarization is disabled. The exported project will be blocked by " "Gatekeeper if it's downloaded from an unknown source." msgstr "" +"Attention : La certification est désactivé. Le projet exporté sera bloqué " +"par Gatekeeper si il est téléchargé depuis une source inconnue." #: platform/osx/export/export.cpp msgid "" "Code signing is disabled. The exported project will not run on Macs with " "enabled Gatekeeper and Apple Silicon powered Macs." msgstr "" +"La signature du code est désactivé. Le projet exporté ne fonctionnera pas " +"sur les Macs avec Gatekeeper activé et sous les Macs fonctionnant sous Apple " +"Silicon." #: platform/osx/export/export.cpp msgid "" @@ -20377,12 +19943,17 @@ msgstr "" msgid "" "Timestamping is not compatible with ad-hoc signature, and will be disabled!" msgstr "" +"L'horodatage n'est pas compatible avec la signature ad-hoc et a été " +"désactivé !" #: platform/osx/export/export.cpp msgid "" "Warning: Notarization is not supported from this OS. The exported project " "will be blocked by Gatekeeper if it's downloaded from an unknown source." msgstr "" +"Attention : La certification n'est pas compatible avec ce système " +"d'exploitation. Le projet exporté sera bloqué par Gatekeeper si il est " +"téléchargé depuis une source inconnue." #: platform/osx/export/export.cpp msgid "" @@ -20432,21 +20003,19 @@ msgstr "" #: platform/osx/export/export.cpp msgid "macOS" -msgstr "" +msgstr "macOS" #: platform/osx/export/export.cpp msgid "Force Builtin Codesign" -msgstr "" +msgstr "Forcer CodeSign intégré" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Architecture" -msgstr "Ajouter une entrée architecture" +msgstr "Architecture" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Display Name" -msgstr "Tout afficher" +msgstr "Afficher le nom" #: platform/uwp/export/export.cpp msgid "Short Name" @@ -20454,118 +20023,107 @@ msgstr "Nom Abrégé" #: platform/uwp/export/export.cpp msgid "Publisher" -msgstr "" +msgstr "Publicateur" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Publisher Display Name" -msgstr "Nom d'affichage d'éditeur du paquet invalide." +msgstr "Nom d'affichage de l'éditeur du paquet" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Product GUID" -msgstr "GUID produit invalide." +msgstr "GUID du produit" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Publisher GUID" -msgstr "Effacé Guides" +msgstr "GUID du publicateur" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Signing" -msgstr "Signaux" +msgstr "Signature" #: platform/uwp/export/export.cpp msgid "Certificate" msgstr "Certificat" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Algorithm" -msgstr "Débogueur" +msgstr "Algorithme" #: platform/uwp/export/export.cpp msgid "Major" -msgstr "" +msgstr "Majeur" #: platform/uwp/export/export.cpp msgid "Minor" -msgstr "" +msgstr "Mineur" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Build" -msgstr "Mode Règle" +msgstr "Build" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Revision" -msgstr "Expression" +msgstr "Révision" #: platform/uwp/export/export.cpp msgid "Landscape" -msgstr "" +msgstr "Paysage" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Portrait" -msgstr "Retourner les Portals" +msgstr "Portrait" #: platform/uwp/export/export.cpp msgid "Landscape Flipped" -msgstr "" +msgstr "Paysage Inversé" #: platform/uwp/export/export.cpp msgid "Portrait Flipped" -msgstr "" +msgstr "Portrait Inversé" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Store Logo" -msgstr "Mode mise à l'échelle" +msgstr "Logo du magasin" #: platform/uwp/export/export.cpp msgid "Square 44 X 44 Logo" -msgstr "" +msgstr "Logo 44 X 44 Carré" #: platform/uwp/export/export.cpp msgid "Square 71 X 71 Logo" -msgstr "" +msgstr "Logo 71 X 71 Carré" #: platform/uwp/export/export.cpp msgid "Square 150 X 150 Logo" -msgstr "" +msgstr "Logo 150 X 150 Carré" #: platform/uwp/export/export.cpp msgid "Square 310 X 310 Logo" -msgstr "" +msgstr "Logo 310 X 310 Carré" #: platform/uwp/export/export.cpp msgid "Wide 310 X 150 Logo" -msgstr "" +msgstr "Logo 310 X 150 Large" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Splash Screen" -msgstr "Appels de dessin :" +msgstr "Écran de chargement" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Tiles" -msgstr "Fichier" +msgstr "Tuiles" #: platform/uwp/export/export.cpp msgid "Show Name On Square 150 X 150" -msgstr "" +msgstr "Afficher le nom sur le carré 150 X 150" #: platform/uwp/export/export.cpp msgid "Show Name On Wide 310 X 150" -msgstr "" +msgstr "Afficher le nom sur le large 310 X 150" #: platform/uwp/export/export.cpp msgid "Show Name On Square 310 X 310" -msgstr "" +msgstr "Afficher le nom sur le carré 310 X 310" #: platform/uwp/export/export.cpp msgid "Invalid package short name." @@ -20634,34 +20192,31 @@ msgstr "" #: platform/uwp/export/export.cpp msgid "UWP" -msgstr "" +msgstr "UWP" #: platform/uwp/export/export.cpp platform/windows/export/export.cpp -#, fuzzy msgid "Signtool" -msgstr "Signaux" +msgstr "Signtool" #: platform/uwp/export/export.cpp msgid "Debug Certificate" -msgstr "" +msgstr "Certificat de Débogage" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Debug Algorithm" -msgstr "Débogueur" +msgstr "Algorithme de débogage" #: platform/windows/export/export.cpp -#, fuzzy msgid "Failed to rename temporary file \"%s\"." -msgstr "Impossible de supprimer le fichier temporaire :" +msgstr "Impossible de renommer le fichier temporaire \"%s\"." #: platform/windows/export/export.cpp msgid "Identity Type" -msgstr "" +msgstr "Type d'identité" #: platform/windows/export/export.cpp msgid "Timestamp Server URL" -msgstr "" +msgstr "URL du serveur d'horodatage" #: platform/windows/export/export.cpp #, fuzzy @@ -20669,14 +20224,12 @@ msgid "Digest Algorithm" msgstr "Débogueur" #: platform/windows/export/export.cpp -#, fuzzy msgid "Modify Resources" -msgstr "Copier la ressource" +msgstr "Modifier les ressources" #: platform/windows/export/export.cpp -#, fuzzy msgid "File Version" -msgstr "Version" +msgstr "Version de fichier" #: platform/windows/export/export.cpp msgid "Product Version" @@ -20691,18 +20244,16 @@ msgid "Product Name" msgstr "Nom du produit" #: platform/windows/export/export.cpp -#, fuzzy msgid "File Description" -msgstr "Description" +msgstr "Description de fichier" #: platform/windows/export/export.cpp msgid "Trademarks" -msgstr "" +msgstr "Marques Déposées" #: platform/windows/export/export.cpp -#, fuzzy msgid "Resources Modification" -msgstr "Rotation aléatoire :" +msgstr "Modification de ressources" #: platform/windows/export/export.cpp #, fuzzy @@ -20717,59 +20268,52 @@ msgstr "Impossible de trouver le keystore, impossible d'exporter." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "L'outil « rcedit » doit être configuré dans les préférences de l'éditeur " "(Exporter > Windows > Rcedit) for modifier l'icône ou les informations de " "l'application." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +msgid "rcedit failed to modify executable: %s." +msgstr "rcedit n'a pas réussi à modifier l'exécutable : %s." #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find signtool executable at \"%s\"." -msgstr "Impossible de trouver le keystore, impossible d'exporter." +msgstr "Impossible de trouver l’exécutable signtool à \"%s\"." #: platform/windows/export/export.cpp -#, fuzzy msgid "Could not find osslsigncode executable at \"%s\"." -msgstr "Impossible de trouver le keystore, impossible d'exporter." +msgstr "Impossible de trouver l’exécutable osslsigncode à \"%s\"." #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid identity type." -msgstr "Identifiant invalide :" +msgstr "Type d'identité invalide." #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid timestamp server." -msgstr "Nom invalide." +msgstr "Server d'horodatage invalide." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "L'outil « rcedit » doit être configuré dans les préférences de l'éditeur " "(Exporter > Windows > Rcedit) for modifier l'icône ou les informations de " "l'application." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +msgid "Signtool failed to sign executable: %s." +msgstr "La signature de l’exécutable avec Signtool a échoué : %s." #: platform/windows/export/export.cpp -#, fuzzy msgid "Failed to remove temporary file \"%s\"." -msgstr "Impossible de supprimer le fichier temporaire :" +msgstr "Impossible de supprimer le fichier temporaire \"%s\"." #: platform/windows/export/export.cpp msgid "" @@ -20794,7 +20338,7 @@ msgstr "Version du produit invalide :" #: platform/windows/export/export.cpp msgid "Windows executables cannot be >= 4 GiB." -msgstr "" +msgstr "Les exécutables Windows ne peuvent pas peser >= 4Gio." #: platform/windows/export/export.cpp platform/x11/export/export.cpp #, fuzzy @@ -20803,38 +20347,37 @@ msgstr "Fichier exécutable invalide." #: platform/windows/export/export.cpp platform/x11/export/export.cpp msgid "Executable file header corrupted." -msgstr "" +msgstr "Entête du fichier exécutable corrompue." #: platform/windows/export/export.cpp platform/x11/export/export.cpp msgid "Executable \"pck\" section not found." -msgstr "" +msgstr "Section \"pck\" de l’exécutable non trouvée." #: platform/windows/export/export.cpp -#, fuzzy msgid "Windows" -msgstr "Nouvelle Fenêtre" +msgstr "Windows" #: platform/windows/export/export.cpp msgid "Rcedit" -msgstr "" +msgstr "Rcedit" #: platform/windows/export/export.cpp msgid "Osslsigncode" -msgstr "" +msgstr "Osslsigncode" #: platform/windows/export/export.cpp msgid "Wine" -msgstr "" +msgstr "Wine" #: platform/x11/export/export.cpp msgid "32-bit executables cannot have embedded data >= 4 GiB." msgstr "" +"les exécutables 32 bits ne peuvent pas contenir de données pesant >= 4Gio." #: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Frames" -msgstr "Image %" +msgstr "Trames" #: scene/2d/animated_sprite.cpp msgid "" @@ -20846,71 +20389,61 @@ msgstr "" #: scene/2d/animated_sprite.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Speed Scale" -msgstr "Mode mise à l'échelle" +msgstr "Échelle de vitesse" #: scene/2d/animated_sprite.cpp scene/2d/audio_stream_player_2d.cpp #: scene/3d/audio_stream_player_3d.cpp scene/3d/sprite_3d.cpp #: scene/audio/audio_stream_player.cpp -#, fuzzy msgid "Playing" -msgstr "Jouer" +msgstr "En train de jouer" #: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Centered" -msgstr "Centre" +msgstr "Centré" #: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp msgid "Flip H" -msgstr "" +msgstr "Miroir H" #: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp msgid "Flip V" -msgstr "" +msgstr "Miroir V" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Monitoring" -msgstr "Moniteur" +msgstr "Observation" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Monitorable" -msgstr "Moniteur" +msgstr "Observable" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Physics Overrides" -msgstr "Redéfinition" +msgstr "Redéfinitions de physique" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Space Override" -msgstr "Redéfinition" +msgstr "Redéfinition d'espace" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Point" -msgstr "Générer des points" +msgstr "Gravité ponctuelle" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Distance Scale" -msgstr "WaitInstanceSignal" +msgstr "Échelle de distance de gravité" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Gravity Vec" -msgstr "Aperçu par défaut" +msgstr "Vecteur de gravité" #: scene/2d/area_2d.cpp scene/2d/cpu_particles_2d.cpp scene/3d/area.cpp #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp msgid "Gravity" -msgstr "" +msgstr "Gravité" #: scene/2d/area_2d.cpp scene/3d/area.cpp #, fuzzy @@ -20922,38 +20455,33 @@ msgid "Angular Damp" msgstr "" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Audio Bus" -msgstr "Ajouter un bus audio" +msgstr "Bus audio" #: scene/2d/area_2d.cpp scene/3d/area.cpp -#, fuzzy msgid "Override" msgstr "Redéfinition" #: scene/2d/audio_stream_player_2d.cpp scene/audio/audio_stream_player.cpp #: scene/gui/video_player.cpp servers/audio/effects/audio_effect_amplify.cpp -#, fuzzy msgid "Volume dB" -msgstr "Volume" +msgstr "Volume (dB)" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp #: servers/audio/effects/audio_effect_pitch_shift.cpp -#, fuzzy msgid "Pitch Scale" -msgstr "Mode mise à l'échelle" +msgstr "Échelle de pitch" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp -#, fuzzy msgid "Autoplay" -msgstr "Activer/désactiver la lecture automatique" +msgstr "Lecture automatique" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp msgid "Stream Paused" -msgstr "" +msgstr "Diffusion en pause" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/3d/light.cpp scene/3d/reflection_probe.cpp @@ -20963,34 +20491,29 @@ msgid "Max Distance" msgstr "Distance Maximale" #: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Attenuation" -msgstr "Animation" +msgstr "Atténuation" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp -#, fuzzy msgid "Bus" -msgstr "Ajouter un bus" +msgstr "Bus" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp msgid "Area Mask" -msgstr "" +msgstr "Masque de zone" #: scene/2d/back_buffer_copy.cpp -#, fuzzy msgid "Copy Mode" -msgstr "Copier les nÅ“uds" +msgstr "Mode copie" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Anchor Mode" -msgstr "Mode Icône" +msgstr "Mode ancre" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Rotating" -msgstr "Pas de la rotation :" +msgstr "En rotation" #: scene/2d/camera_2d.cpp scene/2d/listener_2d.cpp scene/3d/camera.cpp #: scene/3d/listener.cpp scene/animation/animation_blend_tree.cpp @@ -20998,14 +20521,12 @@ msgid "Current" msgstr "Actuel" #: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom" msgstr "Zoomer" #: scene/2d/camera_2d.cpp scene/main/canvas_layer.cpp -#, fuzzy msgid "Custom Viewport" -msgstr "1 vue" +msgstr "Vue personnalisée" #: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp #: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp @@ -21016,26 +20537,23 @@ msgstr "Mode déplacement" #: scene/2d/camera_2d.cpp msgid "Limit" -msgstr "" +msgstr "Limite" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp -#, fuzzy msgid "Left" -msgstr "En haut à gauche" +msgstr "Gauche" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp -#, fuzzy msgid "Right" -msgstr "Lumière" +msgstr "Droite" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/dynamic_font.cpp scene/resources/style_box.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Bottom" -msgstr "En bas à gauche" +msgstr "Bas" #: scene/2d/camera_2d.cpp #, fuzzy @@ -21043,9 +20561,8 @@ msgid "Smoothed" msgstr "Progression douce" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Margin" -msgstr "Définir la marge" +msgstr "Afficher les marges" #: scene/2d/camera_2d.cpp #, fuzzy @@ -21064,27 +20581,24 @@ msgstr "Progression douce" #: scene/2d/camera_2d.cpp msgid "H" -msgstr "" +msgstr "H" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "V" -msgstr "UV" +msgstr "V" #: scene/2d/camera_2d.cpp #, fuzzy msgid "Drag Margin" -msgstr "Définir la marge" +msgstr "Tirer la marge" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Screen" -msgstr "Appels de dessin :" +msgstr "Afficher l'écran" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Limits" -msgstr "Appels de dessin :" +msgstr "Afficher les limites" #: scene/2d/camera_2d.cpp #, fuzzy @@ -21093,43 +20607,37 @@ msgstr "Définir la marge" #: scene/2d/canvas_item.cpp scene/resources/environment.cpp #: scene/resources/material.cpp -#, fuzzy msgid "Blend Mode" -msgstr "NÅ“ud Blend2" +msgstr "Mode mélange" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Light Mode" -msgstr "Étendu à Droite" +msgstr "Mode de lumière" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Particles Animation" -msgstr "Particules" +msgstr "Animation de particules" #: scene/2d/canvas_item.cpp msgid "Particles Anim H Frames" -msgstr "" +msgstr "Trames d'animation H de particules" #: scene/2d/canvas_item.cpp msgid "Particles Anim V Frames" -msgstr "" +msgstr "Trames d'animation V de particules" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Particles Anim Loop" -msgstr "Particules" +msgstr "Boucle d'animation de particules" #: scene/2d/canvas_item.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Visibility" -msgstr "Basculer la visibilité" +msgstr "Visibilité" #: scene/2d/canvas_item.cpp scene/3d/spatial.cpp scene/gui/progress_bar.cpp #: scene/gui/rich_text_effect.cpp scene/main/canvas_layer.cpp -#, fuzzy msgid "Visible" -msgstr "Basculer la visibilité" +msgstr "Visible" #: scene/2d/canvas_item.cpp #, fuzzy @@ -21138,22 +20646,20 @@ msgstr "Peupler" #: scene/2d/canvas_item.cpp msgid "Show Behind Parent" -msgstr "" +msgstr "Montrer derrière le parent" #: scene/2d/canvas_item.cpp -#, fuzzy msgid "Show On Top" -msgstr "Afficher l'origine" +msgstr "Montrer au dessus" #: scene/2d/canvas_item.cpp scene/2d/light_occluder_2d.cpp #: scene/2d/tile_map.cpp -#, fuzzy msgid "Light Mask" -msgstr "LightMap Bake" +msgstr "Masque de lumières" #: scene/2d/canvas_item.cpp msgid "Use Parent Material" -msgstr "" +msgstr "Utiliser le matériau du parent" #: scene/2d/canvas_modulate.cpp msgid "" @@ -21175,9 +20681,8 @@ msgstr "" "qu'enfant pour définir sa forme." #: scene/2d/collision_object_2d.cpp -#, fuzzy msgid "Pickable" -msgstr "Sélectionner une tuile" +msgstr "Déplaçable" #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -21209,29 +20714,27 @@ msgstr "" msgid "" "The One Way Collision property will be ignored when the parent is an Area2D." msgstr "" +"La propriété Collision à sens unique est ignorée lorsque le parent est un " +"Area2D." #: scene/2d/collision_polygon_2d.cpp -#, fuzzy msgid "Build Mode" -msgstr "Mode Règle" +msgstr "Mode construction" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp #: scene/3d/collision_polygon.cpp scene/3d/collision_shape.cpp #: scene/animation/animation_node_state_machine.cpp scene/gui/base_button.cpp #: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Disabled" -msgstr "Item désactivé" +msgstr "Désactivé" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp -#, fuzzy msgid "One Way Collision" -msgstr "Créer le polygone de collision" +msgstr "Collision à sens unique" #: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp -#, fuzzy msgid "One Way Collision Margin" -msgstr "Créer le polygone de collision" +msgstr "marge de collision à sens unique" #: scene/2d/collision_shape_2d.cpp msgid "" @@ -21270,31 +20773,28 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Emitting" -msgstr "Paramètres :" +msgstr "Émet" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Lifetime" -msgstr "" +msgstr "Durée de vie" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp -#, fuzzy msgid "One Shot" -msgstr "NÅ“ud one-shot" +msgstr "Jouer une fois" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Preprocess" -msgstr "Post-traitement" +msgstr "Pré-traitement" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Explosiveness" -msgstr "" +msgstr "Explovisité" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21304,13 +20804,12 @@ msgstr "Aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Lifetime Randomness" -msgstr "" +msgstr "Aléatoire de durée de vie" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Fixed FPS" -msgstr "Voir Images par secondes" +msgstr "FPS fixes" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21324,20 +20823,18 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Local Coords" -msgstr "Projets locaux" +msgstr "Coordonnées locales" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Draw Order" -msgstr "" +msgstr "Ordre de rendu" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Emission Shape" -msgstr "Masque d'émission" +msgstr "Forme d'émission" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21350,63 +20847,55 @@ msgid "Rect Extents" msgstr "Gadgets" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp -#, fuzzy msgid "Normals" -msgstr "Format" +msgstr "Normales" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Align Y" -msgstr "Assigner" +msgstr "Aligner axe Y" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Direction" -msgstr "Directions" +msgstr "Direction" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp #: servers/audio/effects/audio_effect_reverb.cpp msgid "Spread" -msgstr "" +msgstr "Propagation" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Initial Velocity" -msgstr "Initialiser" +msgstr "Vélocité initiale" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Velocity Random" -msgstr "Vue de l'orbite vers la droite" +msgstr "Vélocité aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Angular Velocity" -msgstr "" +msgstr "Vélocité angulaire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Velocity Curve" -msgstr "Vue de l'orbite vers la droite" +msgstr "Courbe de vélocité" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Orbit Velocity" -msgstr "Vue de l'orbite vers la droite" +msgstr "Vélocité d'orbite" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Linear Accel" -msgstr "Linéaire" +msgstr "Accélération linéaire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21416,23 +20905,22 @@ msgstr "Accel" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Accel Random" -msgstr "" +msgstr "Accélération aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Accel Curve" -msgstr "Scinder la courbe" +msgstr "Courbe d’accélération" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Radial Accel" -msgstr "" +msgstr "Accélération radiale" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Tangential Accel" -msgstr "" +msgstr "Accélération tangentielle" #: scene/2d/cpu_particles_2d.cpp scene/2d/joints_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/physics_body.cpp @@ -21440,39 +20928,37 @@ msgstr "" #: scene/resources/particles_material.cpp #: servers/audio/effects/audio_effect_reverb.cpp msgid "Damping" -msgstr "" +msgstr "Amortissement" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Damping Random" -msgstr "" +msgstr "Amortissement aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Damping Curve" -msgstr "Scinder la courbe" +msgstr "Courbe d'amortissement" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp #: scene/resources/particles_material.cpp msgid "Angle" -msgstr "" +msgstr "Angle" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Angle Random" -msgstr "" +msgstr "Angle aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Angle Curve" -msgstr "Fermer la courbe" +msgstr "Courbe d'angle" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #, fuzzy msgid "Scale Amount" -msgstr "Quantité :" +msgstr "Valeur d'échelle" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp msgid "Scale Amount Random" @@ -21485,14 +20971,13 @@ msgstr "Agrandir/Rétrécir à partir du curseur" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Color Ramp" -msgstr "Couleurs" +msgstr "Dégradé de couleurs" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp msgid "Color Initial Ramp" -msgstr "" +msgstr "Dégradé de couleurs initial" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21511,33 +20996,28 @@ msgstr "Variation aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Variation Curve" -msgstr "Séparation :" +msgstr "Courbe de variation" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Speed Random" -msgstr "Mode mise à l'échelle" +msgstr "Vitesse aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Speed Curve" -msgstr "Scinder la courbe" +msgstr "Courbe de vitesse" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Offset Random" -msgstr "Décalage :" +msgstr "Décalage de l'aléatoire" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Offset Curve" -msgstr "Fermer la courbe" +msgstr "Courbe de décalage" #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be PhysicsBody2Ds" @@ -21560,39 +21040,35 @@ msgid "Node A and Node B must be different PhysicsBody2Ds" msgstr "Node A et Node B doivent être des PhysicsBody2D différents" #: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Node A" -msgstr "NÅ“ud" +msgstr "NÅ“ud A" #: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Node B" -msgstr "NÅ“ud" +msgstr "NÅ“ud B" #: scene/2d/joints_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp #: scene/resources/environment.cpp msgid "Bias" -msgstr "" +msgstr "Biais" #: scene/2d/joints_2d.cpp -#, fuzzy msgid "Disable Collision" -msgstr "Bouton désactivé" +msgstr "Désactiver les collisions" #: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Softness" -msgstr "" +msgstr "Douceur" #: scene/2d/joints_2d.cpp scene/resources/animation.cpp #: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp msgid "Length" -msgstr "" +msgstr "Longueur" #: scene/2d/joints_2d.cpp -#, fuzzy msgid "Initial Offset" -msgstr "Initialiser" +msgstr "Décalage initial" #: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp msgid "Rest Length" @@ -21600,7 +21076,7 @@ msgstr "" #: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp scene/3d/vehicle_body.cpp msgid "Stiffness" -msgstr "" +msgstr "Rigidité" #: scene/2d/light_2d.cpp msgid "" @@ -21611,57 +21087,50 @@ msgstr "" "« Texture »." #: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp -#, fuzzy msgid "Editor Only" -msgstr "Éditeur" +msgstr "Éditeur seulement" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Texture Scale" -msgstr "RegionDeTexture" +msgstr "Échelle de texture" #: scene/2d/light_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/light.cpp scene/resources/environment.cpp #: scene/resources/material.cpp scene/resources/sky.cpp msgid "Energy" -msgstr "" +msgstr "Énergie" #: scene/2d/light_2d.cpp msgid "Z Min" -msgstr "" +msgstr "Minimum Z" #: scene/2d/light_2d.cpp msgid "Z Max" -msgstr "" +msgstr "Maximum Z" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Layer Min" -msgstr "Changer la taille d'une caméra" +msgstr "Calque min" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Layer Max" -msgstr "Calque" +msgstr "Calque max" #: scene/2d/light_2d.cpp msgid "Item Cull Mask" msgstr "" #: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Shadow" -msgstr "Ombrage" +msgstr "Ombre" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Buffer Size" -msgstr "Vue de derrière" +msgstr "Taille de tampon" #: scene/2d/light_2d.cpp -#, fuzzy msgid "Gradient Length" -msgstr "Dégradé édité" +msgstr "Longueur du dégradé" #: scene/2d/light_2d.cpp #, fuzzy @@ -21669,9 +21138,8 @@ msgid "Filter Smooth" msgstr "Filtrer les méthodes" #: scene/2d/light_occluder_2d.cpp -#, fuzzy msgid "Closed" -msgstr "Fermer" +msgstr "Fermé" #: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp #, fuzzy @@ -21692,37 +21160,32 @@ msgstr "" "polygone." #: scene/2d/line_2d.cpp -#, fuzzy msgid "Width Curve" -msgstr "Scinder la courbe" +msgstr "Courbe de largeur" #: scene/2d/line_2d.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Default Color" -msgstr "Défaut" +msgstr "Couleur par défaut" #: scene/2d/line_2d.cpp scene/resources/texture.cpp msgid "Fill" -msgstr "" +msgstr "Remplissage" #: scene/2d/line_2d.cpp scene/resources/texture.cpp -#, fuzzy msgid "Gradient" -msgstr "Dégradé édité" +msgstr "Dégradé" #: scene/2d/line_2d.cpp -#, fuzzy msgid "Texture Mode" -msgstr "RegionDeTexture" +msgstr "Mode de texture" #: scene/2d/line_2d.cpp msgid "Capping" -msgstr "" +msgstr "Capuchonnement" #: scene/2d/line_2d.cpp -#, fuzzy msgid "Joint Mode" -msgstr "Mode Icône" +msgstr "Mode de jointure" #: scene/2d/line_2d.cpp #, fuzzy @@ -21730,14 +21193,12 @@ msgid "Begin Cap Mode" msgstr "Mode Région" #: scene/2d/line_2d.cpp -#, fuzzy msgid "End Cap Mode" -msgstr "Mode d'aimantation :" +msgstr "Mode du capuchon de fin" #: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Border" -msgstr "dans l'ordre :" +msgstr "Bordure" #: scene/2d/line_2d.cpp msgid "Sharp Limit" @@ -21745,13 +21206,12 @@ msgstr "" #: scene/2d/line_2d.cpp msgid "Round Precision" -msgstr "" +msgstr "Précision de l’arrondissement" #: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp #: scene/resources/dynamic_font.cpp -#, fuzzy msgid "Antialiased" -msgstr "Initialiser" +msgstr "Anticrénelé" #: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp #, fuzzy @@ -21762,12 +21222,11 @@ msgstr "Multiplier %s" #: scene/3d/navigation.cpp scene/animation/root_motion_view.cpp #: scene/resources/world_2d.cpp servers/physics_2d/physics_2d_server_sw.cpp msgid "Cell Size" -msgstr "" +msgstr "Taille des Cellules" #: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp -#, fuzzy msgid "Edge Connection Margin" -msgstr "Modifier la connexion :" +msgstr "Marge de connexion des bords" #: scene/2d/navigation_2d.cpp msgid "" @@ -21775,43 +21234,42 @@ msgid "" "will be removed in a future version. Use 'Navigation2DServer.map_get_path()' " "instead." msgstr "" +"Le nÅ“ud « Navigation2D » et « Navigation2D.get_simple_path() » sont " +"obsolètes et seront supprimés dans une future version. Utilisez « " +"Navigation2DServer.map_get_path() » à la place." #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp #, fuzzy msgid "Pathfinding" -msgstr "Liaison" +msgstr "Pathfinding" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Path Desired Distance" -msgstr "Choisissez distance :" +msgstr "Distance souhaitée du chemin" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Target Desired Distance" -msgstr "" +msgstr "Distance Désirée de la Cible" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Path Max Distance" -msgstr "Choisissez distance :" +msgstr "Distance maximale du chemin" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance" -msgstr "Options avancées" +msgstr "Évitement" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance Enabled" -msgstr "Activer" +msgstr "Évitement activé" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Neighbor Dist" -msgstr "" +msgstr "Distance des voisins" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Max Neighbors" -msgstr "" +msgstr "Maximum de voisins" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp #, fuzzy @@ -21819,20 +21277,19 @@ msgid "Time Horizon" msgstr "Retourner horizontalement" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Max Speed" -msgstr "Vitesse :" +msgstr "Vitesse Max" #: scene/2d/navigation_agent_2d.cpp -#, fuzzy msgid "" "The NavigationAgent2D can be used only under a Node2D inheriting parent node." -msgstr "Le NavigationAgent2D ne peut être utilisé que sous un nÅ“ud Node2D." +msgstr "" +"Le NavigationAgent2D ne peut être utilisé que sous un nÅ“ud dont le parent " +"hérite de Node2D." #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp -#, fuzzy msgid "Estimate Radius" -msgstr "Changer le rayon extérieur de la tour" +msgstr "Estimer le rayon" #: scene/2d/navigation_obstacle_2d.cpp msgid "" @@ -21853,74 +21310,65 @@ msgstr "" #: scene/2d/navigation_polygon.cpp msgid "Navpoly" -msgstr "" +msgstr "Polygone de navigation" #: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Enter Cost" -msgstr "Centrée en bas" +msgstr "Coût d’entrée" #: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Travel Cost" -msgstr "Se déplacer" +msgstr "Coût de déplacement" #: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp #: scene/main/canvas_layer.cpp msgid "Rotation Degrees" msgstr "Degrés de Rotation" -#: scene/2d/node_2d.cpp -#, fuzzy +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" -msgstr "Constante globale" +msgstr "Rotation Globale" #: scene/2d/node_2d.cpp msgid "Global Rotation Degrees" msgstr "Degrés de Rotation Globale" #: scene/2d/node_2d.cpp -#, fuzzy msgid "Global Scale" -msgstr "Échelle aléatoire :" +msgstr "Échelle Globale" #: scene/2d/node_2d.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Global Transform" -msgstr "Conserver la transformation globale" +msgstr "Transformation Globale" #: scene/2d/node_2d.cpp -#, fuzzy msgid "Z As Relative" -msgstr "Alignement relatif" +msgstr "Z En tant que relatif" #: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Scroll" -msgstr "" +msgstr "Défilement" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Base Offset" -msgstr "Décalage :" +msgstr "Décalage de Base" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Base Scale" -msgstr "Utiliser le magnétisme d'échelle" +msgstr "Échelle de Base" #: scene/2d/parallax_background.cpp msgid "Limit Begin" -msgstr "" +msgstr "Début de la limite" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Limit End" -msgstr "À la fin" +msgstr "Fin de la limite" #: scene/2d/parallax_background.cpp msgid "Ignore Camera Zoom" -msgstr "" +msgstr "Ignorer le zoom de la Caméra" #: scene/2d/parallax_layer.cpp msgid "" @@ -21932,14 +21380,12 @@ msgstr "" #: scene/2d/parallax_layer.cpp scene/2d/physics_body_2d.cpp #: scene/3d/physics_body.cpp scene/3d/vehicle_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Motion" -msgstr "Action" +msgstr "Déplacement" #: scene/2d/parallax_layer.cpp -#, fuzzy msgid "Mirroring" -msgstr "Miroir" +msgstr "Effet de miroir" #: scene/2d/particles_2d.cpp msgid "" @@ -21983,19 +21429,17 @@ msgstr "" "Animation » activé." #: scene/2d/particles_2d.cpp -#, fuzzy msgid "Visibility Rect" -msgstr "Mode prioritaire" +msgstr "Zone de Visibilité" #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "Process Material" -msgstr "" +msgstr "Matériau" #: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp #: scene/resources/texture.cpp -#, fuzzy msgid "Curve" -msgstr "Scinder la courbe" +msgstr "Courbe" #: scene/2d/path_2d.cpp msgid "PathFollow2D only works when set as a child of a Path2D node." @@ -22004,63 +21448,55 @@ msgstr "" "d'un nÅ“ud de type Path2D." #: scene/2d/path_2d.cpp scene/3d/path.cpp -#, fuzzy msgid "Unit Offset" -msgstr "Décalage de la grille :" +msgstr "Décalage d'unité" #: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp -#, fuzzy msgid "H Offset" -msgstr "Décalage :" +msgstr "Décalage Horizontal" #: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp -#, fuzzy msgid "V Offset" -msgstr "Décalage :" +msgstr "Décalage Vertical" #: scene/2d/path_2d.cpp scene/3d/path.cpp msgid "Cubic Interp" -msgstr "" +msgstr "Interpolation Cubique" #: scene/2d/path_2d.cpp msgid "Lookahead" -msgstr "" +msgstr "Anticipation" #: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp -#, fuzzy msgid "Layers" -msgstr "Calque" +msgstr "Calques" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Constant Linear Velocity" -msgstr "Initialiser" +msgstr "Vélocité Linéaire Constante" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Constant Angular Velocity" -msgstr "Initialiser" +msgstr "Vélocité Angulaire Constante" #: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp #: scene/resources/physics_material.cpp -#, fuzzy msgid "Friction" -msgstr "Fonction" +msgstr "Friction" #: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp #: scene/resources/physics_material.cpp msgid "Bounce" -msgstr "" +msgstr "Rebond" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Physics Material Override" -msgstr "" +msgstr "Surcharge du Matériau Des Physiques" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: scene/resources/world.cpp scene/resources/world_2d.cpp -#, fuzzy msgid "Default Gravity" -msgstr "Aperçu par défaut" +msgstr "Gravité par Défaut" #: scene/2d/physics_body_2d.cpp msgid "" @@ -22074,81 +21510,72 @@ msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Mass" -msgstr "" +msgstr "Masse" #: scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Inertia" -msgstr "Vertical :" +msgstr "Inertie" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Weight" -msgstr "Lumière" +msgstr "Poids" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Gravity Scale" -msgstr "" +msgstr "Échelle de la Gravité" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Custom Integrator" -msgstr "NÅ“ud Personnalisé" +msgstr "Intégrateur personnalisé" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Continuous CD" -msgstr "Continu" +msgstr "Détection de collision continue" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Contacts Reported" -msgstr "" +msgstr "Contact Rapporté" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Contact Monitor" -msgstr "Prélever une couleur" +msgstr "Moniteur de Contact" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Sleeping" -msgstr "Magnétisme intelligent" +msgstr "Sommeil" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Can Sleep" -msgstr "Vitesse :" +msgstr "Peut Dormir" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Damp" -msgstr "" +msgstr "Atténuation" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Angular" -msgstr "" +msgstr "Angulaire" #: scene/2d/physics_body_2d.cpp msgid "Applied Forces" -msgstr "" +msgstr "Forces Appliquées" #: scene/2d/physics_body_2d.cpp msgid "Torque" -msgstr "" +msgstr "Torque" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Safe Margin" -msgstr "Définir la marge" +msgstr "Marge de sécurité" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Sync To Physics" msgstr "Synchroniser Avec La Physique" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Moving Platform" -msgstr "Déplacement du résultat" +msgstr "Plateforme mobile" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Apply Velocity On Leave" @@ -22158,71 +21585,61 @@ msgstr "" #: scene/3d/physics_body.cpp scene/gui/texture_button.cpp #: scene/resources/default_theme/default_theme.cpp #: scene/resources/line_shape_2d.cpp scene/resources/material.cpp -#, fuzzy msgid "Normal" -msgstr "Format" +msgstr "Normale" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Remainder" -msgstr "Moteur de rendu :" +msgstr "Reste" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Local Shape" -msgstr "Localisation" +msgstr "Forme Locale" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider" -msgstr "Mode collision" +msgstr "Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Collider ID" -msgstr "" +msgstr "ID Du Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider RID" -msgstr "RID invalide" +msgstr "RID Du Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider Shape" -msgstr "Mode collision" +msgstr "Forme Du Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Collider Shape Index" -msgstr "Mode collision" +msgstr "Index De La Forme Du Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collider Velocity" -msgstr "Vue de l'orbite vers la droite" +msgstr "Vélocité Du Collisionneur" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Collider Metadata" -msgstr "" +msgstr "Méta-Données Du Collisionneur" #: scene/2d/polygon_2d.cpp msgid "Invert" -msgstr "" +msgstr "Inverser" #: scene/2d/polygon_2d.cpp -#, fuzzy msgid "Vertex Colors" -msgstr "Vertex" +msgstr "Couleurs Des Sommets" #: scene/2d/polygon_2d.cpp -#, fuzzy msgid "Internal Vertex Count" -msgstr "Créer un vertex interne" +msgstr "Nombre de Sommet Interne" #: scene/2d/position_2d.cpp #, fuzzy @@ -22231,24 +21648,23 @@ msgstr "Gadgets" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp msgid "Exclude Parent" -msgstr "" +msgstr "Exclure Le Parent" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp -#, fuzzy msgid "Cast To" -msgstr "Créer un nÅ“ud Shader" +msgstr "Lancer vers" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp msgid "Collide With" -msgstr "" +msgstr "Collisionne Avec" #: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp msgid "Areas" -msgstr "" +msgstr "Zones" #: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp msgid "Bodies" -msgstr "" +msgstr "Corps" #: scene/2d/remote_transform_2d.cpp msgid "Path property must point to a valid Node2D node to work." @@ -22257,24 +21673,20 @@ msgstr "" "fonctionner." #: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp -#, fuzzy msgid "Remote Path" -msgstr "Supprimer un point" +msgstr "Chemin distant" #: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp -#, fuzzy msgid "Use Global Coordinates" -msgstr "Coordonnée suivante" +msgstr "Utiliser les coordonnées globales" #: scene/2d/skeleton_2d.cpp scene/3d/skeleton.cpp -#, fuzzy msgid "Rest" -msgstr "Redémarrer" +msgstr "Repos" #: scene/2d/skeleton_2d.cpp -#, fuzzy msgid "Default Length" -msgstr "Thème par défaut" +msgstr "Longueur par défaut" #: scene/2d/skeleton_2d.cpp msgid "This Bone2D chain should end at a Skeleton2D node." @@ -22295,16 +21707,15 @@ msgstr "" #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp msgid "Hframes" -msgstr "" +msgstr "Trames H" #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp msgid "Vframes" -msgstr "" +msgstr "Trames V" #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Frame Coords" -msgstr "Image %" +msgstr "Coordonnées de trame" #: scene/2d/sprite.cpp scene/resources/texture.cpp #, fuzzy @@ -22322,14 +21733,12 @@ msgstr "" "etc." #: scene/2d/tile_map.cpp -#, fuzzy msgid "Tile Set" -msgstr "TileSet" +msgstr "Palette de tuiles" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Quadrant Size" -msgstr "Changer la taille d'une caméra" +msgstr "Taille de quadrant" #: scene/2d/tile_map.cpp #, fuzzy @@ -22337,66 +21746,56 @@ msgid "Custom Transform" msgstr "Transformation" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Half Offset" -msgstr "Initialiser" +msgstr "Décalage de moitié" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Tile Origin" -msgstr "Afficher l'origine" +msgstr "Origine de la tuile" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Y Sort" -msgstr "Trier" +msgstr "Trier par Y" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Show Collision" -msgstr "Collision" +msgstr "Afficher la Collision" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Compatibility Mode" -msgstr "Mode prioritaire" +msgstr "Mode de Compatibilité" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Centered Textures" -msgstr "Fonctionnalités principales :" +msgstr "Textures Centrées" #: scene/2d/tile_map.cpp msgid "Cell Clip UV" msgstr "" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Use Parent" -msgstr "Mode collision" +msgstr "Utiliser le Parent" #: scene/2d/tile_map.cpp msgid "Use Kinematic" -msgstr "" +msgstr "Utiliser Kinematic" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Shape Centered" -msgstr "Aimanter au centre du nÅ“ud" +msgstr "Forme Centrée" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Shape Visible" -msgstr "Rendre visible" +msgstr "Forme Visible" #: scene/2d/touch_screen_button.cpp msgid "Passby Press" msgstr "" #: scene/2d/touch_screen_button.cpp -#, fuzzy msgid "Visibility Mode" -msgstr "Mode prioritaire" +msgstr "Mode de Visibilité" #: scene/2d/visibility_notifier_2d.cpp msgid "" @@ -22407,41 +21806,36 @@ msgstr "" "nÅ“ud racine de la scène éditée." #: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp -#, fuzzy msgid "Pause Animations" -msgstr "Coller l'animation" +msgstr "Mettre les animations en pause" #: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp msgid "Freeze Bodies" -msgstr "" +msgstr "Geler les corps" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Pause Particles" -msgstr "Particules" +msgstr "Mettre les particules en pause" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Pause Animated Sprites" -msgstr "Coller l'animation" +msgstr "Mettre les Sprites animés en pause" #: scene/2d/visibility_notifier_2d.cpp -#, fuzzy msgid "Process Parent" -msgstr "Activer la priorité" +msgstr "Parent du Processus" #: scene/2d/visibility_notifier_2d.cpp msgid "Physics Process Parent" -msgstr "" +msgstr "Parent du Processus Physique" #: scene/3d/area.cpp msgid "Reverb Bus" msgstr "" #: scene/3d/area.cpp -#, fuzzy msgid "Uniformity" -msgstr "Définir le nom de l'uniforme" +msgstr "Uniformité" #: scene/3d/arvr_nodes.cpp msgid "ARVRCamera must have an ARVROrigin node as its parent." @@ -22449,11 +21843,11 @@ msgstr "ARVRCamera doit avoir un nÅ“ud ARVROrigin comme parent." #: scene/3d/arvr_nodes.cpp msgid "Controller ID" -msgstr "" +msgstr "ID Du Contrôleur" #: scene/3d/arvr_nodes.cpp servers/arvr/arvr_positional_tracker.cpp msgid "Rumble" -msgstr "" +msgstr "Vibration" #: scene/3d/arvr_nodes.cpp msgid "ARVRController must have an ARVROrigin node as its parent." @@ -22489,48 +21883,44 @@ msgid "ARVROrigin requires an ARVRCamera child node." msgstr "ARVROrigin requiert un nÅ“ud enfant ARVRCamera." #: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp -#, fuzzy msgid "World Scale" -msgstr "Échelle aléatoire :" +msgstr "Échelle du Monde" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Attenuation Model" -msgstr "NÅ“ud d'animation" +msgstr "Modèle d’atténuation" #: scene/3d/audio_stream_player_3d.cpp msgid "Unit dB" -msgstr "" +msgstr "Unité (dB)" #: scene/3d/audio_stream_player_3d.cpp msgid "Unit Size" -msgstr "" +msgstr "Taille d’unité" #: scene/3d/audio_stream_player_3d.cpp msgid "Max dB" -msgstr "" +msgstr "Max (dB)" #: scene/3d/audio_stream_player_3d.cpp msgid "Out Of Range Mode" msgstr "" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Emission Angle" -msgstr "Couleurs d'émission" +msgstr "Angle d’émission" #: scene/3d/audio_stream_player_3d.cpp msgid "Degrees" msgstr "Degrés" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Filter Attenuation dB" -msgstr "Animation" +msgstr "Filtre d’atténuation (dB)" #: scene/3d/audio_stream_player_3d.cpp msgid "Attenuation Filter" -msgstr "" +msgstr "Filtre d’atténuation" #: scene/3d/audio_stream_player_3d.cpp #: servers/audio/effects/audio_effect_chorus.cpp @@ -22540,14 +21930,12 @@ msgstr "" #: scene/3d/audio_stream_player_3d.cpp #: servers/audio/effects/audio_effect_filter.cpp -#, fuzzy msgid "dB" -msgstr "o" +msgstr "dB" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Doppler" -msgstr "Activer l'effet Doppler" +msgstr "Doppler" #: scene/3d/audio_stream_player_3d.cpp #, fuzzy @@ -22557,7 +21945,7 @@ msgstr "Empaquetage" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/reflection_probe.cpp msgid "Interior" -msgstr "" +msgstr "Intérieur" #: scene/3d/baked_lightmap.cpp msgid "Finding meshes and lights" @@ -22592,69 +21980,59 @@ msgstr "Gadgets" #: scene/3d/baked_lightmap.cpp msgid "Tweaks" -msgstr "" +msgstr "Ajustements" #: scene/3d/baked_lightmap.cpp msgid "Bounces" -msgstr "" +msgstr "Rebonds" #: scene/3d/baked_lightmap.cpp msgid "Bounce Indirect Energy" -msgstr "" +msgstr "Énergie indirecte de rebond" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Use Denoiser" -msgstr "Filtre :" +msgstr "Utiliser un filtre anti-bruit" #: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp msgid "Use HDR" -msgstr "" +msgstr "Utiliser HDR" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Use Color" -msgstr "Couleurs" +msgstr "Utiliser la couleur" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Default Texels Per Unit" -msgstr "Thème par défaut" +msgstr "Texels par unité par défaut" #: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp -#, fuzzy msgid "Atlas" -msgstr "Nouvel Atlas" +msgstr "Atlas" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Generate" -msgstr "Général" +msgstr "Générer" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Max Size" -msgstr "Taille :" +msgstr "Taille maximale" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Sky" -msgstr "NÅ“ud Personnalisé" +msgstr "Ciel personnalisé" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Sky Rotation Degrees" -msgstr "Rotation de %s degrés." +msgstr "Degrés de rotation du ciel personnalisé" #: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp -#, fuzzy msgid "Custom Color" -msgstr "NÅ“ud Personnalisé" +msgstr "Couleur personnalisée" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Energy" -msgstr "Déplacer effet de transport" +msgstr "Énergie personnalisée" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -22662,27 +22040,24 @@ msgid "Min Light" msgstr "Indenter vers la droite" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp -#, fuzzy msgid "Propagation" -msgstr "Navigation" +msgstr "Propagation" #: scene/3d/baked_lightmap.cpp msgid "Image Path" -msgstr "" +msgstr "Chemin de l'image" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Light Data" -msgstr "Avec données" +msgstr "Données de lumière" #: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Bone Name" -msgstr "Nom de nÅ“ud :" +msgstr "Nom de l'os" #: scene/3d/camera.cpp msgid "Keep Aspect" -msgstr "" +msgstr "Garder l'aspect" #: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp msgid "Cull Mask" @@ -22694,36 +22069,32 @@ msgid "Doppler Tracking" msgstr "Piste de propriété" #: scene/3d/camera.cpp -#, fuzzy msgid "Projection" -msgstr "Projet" +msgstr "Projection" #: scene/3d/camera.cpp msgid "FOV" -msgstr "" +msgstr "Champ de vision" #: scene/3d/camera.cpp -#, fuzzy msgid "Frustum Offset" -msgstr "Décalage de la grille :" +msgstr "Décalage du Tronc" #: scene/3d/camera.cpp -#, fuzzy msgid "Near" -msgstr "Au plus proche" +msgstr "Plan proche" #: scene/3d/camera.cpp msgid "Far" -msgstr "" +msgstr "Plan éloigné" #: scene/3d/camera.cpp scene/3d/collision_polygon.cpp scene/3d/spring_arm.cpp #: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp #: scene/resources/shape.cpp scene/resources/style_box.cpp #: scene/resources/texture.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp -#, fuzzy msgid "Margin" -msgstr "Définir la marge" +msgstr "Marge" #: scene/3d/camera.cpp #, fuzzy @@ -22813,48 +22184,40 @@ msgid "Box Extents" msgstr "Gadgets" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Radius" -msgstr "Masque d'émission" +msgstr "Rayon de l'anneau" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Inner Radius" -msgstr "Changer le rayon intérieur de la tour" +msgstr "Rayon intérieur de l'anneau" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Height" -msgstr "Rotation vers la droite" +msgstr "Hauteur de l'anneau" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Ring Axis" -msgstr "Avertissements" +msgstr "Axe de l'anneau" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Rotate Y" -msgstr "Rotation" +msgstr "Rotation Y" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp -#, fuzzy msgid "Disable Z" -msgstr "Item désactivé" +msgstr "Désactiver axe Z" #: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp msgid "Flatness" -msgstr "" +msgstr "Platitude" #: scene/3d/cull_instance.cpp servers/visual_server.cpp -#, fuzzy msgid "Portals" -msgstr "Retourner les Portals" +msgstr "Portails" #: scene/3d/cull_instance.cpp -#, fuzzy msgid "Portal Mode" -msgstr "Mode prioritaire" +msgstr "Mode portail" #: scene/3d/cull_instance.cpp msgid "Include In Bound" @@ -22865,9 +22228,8 @@ msgid "Allow Merging" msgstr "" #: scene/3d/cull_instance.cpp -#, fuzzy msgid "Autoplace Priority" -msgstr "Activer la priorité" +msgstr "Priorité d’auto-placement" #: scene/3d/gi_probe.cpp msgid "Plotting Meshes" @@ -22898,114 +22260,98 @@ msgstr "" #: scene/3d/gi_probe.cpp msgid "Subdiv" -msgstr "" +msgstr "Subdivision" #: scene/3d/gi_probe.cpp -#, fuzzy msgid "Dynamic Range" -msgstr "Bibliothèque dynamique" +msgstr "Plage dynamique" #: scene/3d/gi_probe.cpp scene/3d/light.cpp msgid "Normal Bias" -msgstr "" +msgstr "Biais normal" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp #: scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Pixel Size" -msgstr "Aimanter au pixel" +msgstr "Taille de pixel" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Billboard" -msgstr "Billboard" +msgstr "Panneau(Billboard)" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp -#, fuzzy msgid "Shaded" -msgstr "Ombrage" +msgstr "Ombré" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Double Sided" -msgstr "" +msgstr "Double face" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp msgid "No Depth Test" -msgstr "" +msgstr "Pas de test de profondeur" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp -#, fuzzy msgid "Fixed Size" -msgstr "Vue de devant" +msgstr "Taille fixe" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp msgid "Alpha Cut" -msgstr "" +msgstr "Coupe alpha" #: scene/3d/label_3d.cpp scene/resources/material.cpp msgid "Alpha Scissor Threshold" -msgstr "" +msgstr "Seuil des ciseaux d'alpha" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp -#, fuzzy msgid "Render Priority" -msgstr "Activer la priorité" +msgstr "Priorité de rendu" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Outline Render Priority" -msgstr "Activer la priorité" +msgstr "Priorité de rendu du contour" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Outline Modulate" -msgstr "Forcer la modulation blanche" +msgstr "Moduler le contour" #: scene/3d/label_3d.cpp scene/resources/default_theme/default_theme.cpp #: scene/resources/dynamic_font.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Font" -msgstr "Polices" +msgstr "Police" #: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Horizontal Alignment" -msgstr "Horizontal Activé" +msgstr "Alignement horizontal" #: scene/3d/label_3d.cpp -#, fuzzy msgid "Vertical Alignment" -msgstr "Filtrer les signaux" +msgstr "Alignement vertical" #: scene/3d/label_3d.cpp scene/gui/dialogs.cpp scene/gui/label.cpp -#, fuzzy msgid "Autowrap" -msgstr "AutoLoad" +msgstr "Retour à la ligne automatique" #: scene/3d/light.cpp -#, fuzzy msgid "Indirect Energy" -msgstr "Couleurs d'émission" +msgstr "Énergie indirecte" #: scene/3d/light.cpp -#, fuzzy msgid "Negative" -msgstr "GDNative" +msgstr "Négative" #: scene/3d/light.cpp scene/resources/material.cpp #: scene/resources/visual_shader.cpp -#, fuzzy msgid "Specular" -msgstr "Mode Règle" +msgstr "Spéculaire" #: scene/3d/light.cpp -#, fuzzy msgid "Bake Mode" -msgstr "Mode Bitmask" +msgstr "Mode de pré-calcul" #: scene/3d/light.cpp -#, fuzzy msgid "Contact" -msgstr "Prélever une couleur" +msgstr "Contact" #: scene/3d/light.cpp #, fuzzy @@ -23013,9 +22359,8 @@ msgid "Reverse Cull Face" msgstr "Réinitialiser le volume de bus" #: scene/3d/light.cpp servers/visual_server.cpp -#, fuzzy msgid "Directional Shadow" -msgstr "Directions" +msgstr "Ombre directionnelle" #: scene/3d/light.cpp #, fuzzy @@ -23033,9 +22378,8 @@ msgid "Split 3" msgstr "Divisé" #: scene/3d/light.cpp -#, fuzzy msgid "Blend Splits" -msgstr "Temps de mélange :" +msgstr "Mélanger les écarts" #: scene/3d/light.cpp #, fuzzy @@ -23043,23 +22387,20 @@ msgid "Bias Split Scale" msgstr "Utiliser le magnétisme d'échelle" #: scene/3d/light.cpp -#, fuzzy msgid "Depth Range" -msgstr "Profondeur" +msgstr "Plage de profondeur" #: scene/3d/light.cpp msgid "Omni" -msgstr "" +msgstr "Omnidirectionnelle" #: scene/3d/light.cpp -#, fuzzy msgid "Shadow Mode" -msgstr "Ombrage" +msgstr "Mode ombre" #: scene/3d/light.cpp -#, fuzzy msgid "Shadow Detail" -msgstr "Afficher par défaut" +msgstr "Détails d'ombre" #: scene/3d/light.cpp msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows." @@ -23069,21 +22410,19 @@ msgstr "" #: scene/3d/light.cpp msgid "Spot" -msgstr "" +msgstr "Spot" #: scene/3d/light.cpp -#, fuzzy msgid "Angle Attenuation" -msgstr "Animation" +msgstr "Atténuation d'angle" #: scene/3d/mesh_instance.cpp msgid "Software Skinning" msgstr "" #: scene/3d/mesh_instance.cpp -#, fuzzy msgid "Transform Normals" -msgstr "Transformation annulée." +msgstr "Transformer les normales" #: scene/3d/navigation.cpp msgid "" @@ -23091,45 +22430,44 @@ msgid "" "be removed in a future version. Use 'NavigationServer.map_get_path()' " "instead." msgstr "" +"Le nÅ“ud \"Navigation\" et \"Navigation.get_simple_path()\" sont obsolètes et " +"seront retires dans une version ultérieure. Utilisez plutôt " +"\"NavigationServer.map_get_path()\"." #: scene/3d/navigation.cpp scene/resources/curve.cpp -#, fuzzy msgid "Up Vector" -msgstr "Vecteur" +msgstr "Vecteur Haut" #: scene/3d/navigation.cpp -#, fuzzy msgid "Cell Height" -msgstr "En période de test" +msgstr "Hauteur de cellule" #: scene/3d/navigation_agent.cpp msgid "Agent Height Offset" -msgstr "" +msgstr "Décalage de hauteur de l'agent" #: scene/3d/navigation_agent.cpp -#, fuzzy msgid "Ignore Y" -msgstr "[Ignorer]" +msgstr "Ignorer Y" #: scene/3d/navigation_agent.cpp -#, fuzzy msgid "" "The NavigationAgent can be used only under a Spatial inheriting parent node." -msgstr "Le NavigationAgent ne peut être utilisé que sous un nÅ“ud spatial." +msgstr "" +"Le NavigationAgent ne peut être utilisé que sous un nÅ“ud parent héritant de " +"Spatial." #: scene/3d/navigation_mesh_instance.cpp scene/resources/mesh_library.cpp -#, fuzzy msgid "NavMesh" -msgstr "Calculer le NavMesh" +msgstr "NavMesh" #: scene/3d/navigation_obstacle.cpp -#, fuzzy msgid "" "The NavigationObstacle only serves to provide collision avoidance to a " "Spatial inheriting parent object." msgstr "" -"Un NavigationObstacle ne peut éviter les collisions qu'avec les nÅ“uds " -"Spatial." +"Le NavigationObstacle ne sert qu'à fournir l’évitement de collision qu'aux " +"objets dont les parents héritent de Spatial." #: scene/3d/occluder.cpp msgid "No shape is set." @@ -23180,19 +22518,16 @@ msgstr "" "Particles » activé." #: scene/3d/particles.cpp -#, fuzzy msgid "Visibility AABB" -msgstr "Basculer la visibilité" +msgstr "Visibilité AABB" #: scene/3d/particles.cpp -#, fuzzy msgid "Draw Passes" -msgstr "Appels de dessin :" +msgstr "Afficher les passes" #: scene/3d/particles.cpp -#, fuzzy msgid "Passes" -msgstr "Appels de dessin :" +msgstr "Passes" #: scene/3d/path.cpp msgid "PathFollow only works when set as a child of a Path node." @@ -23209,7 +22544,6 @@ msgstr "" "Vector » dans la ressource Curve de son parent Path." #: scene/3d/path.cpp -#, fuzzy msgid "Rotation Mode" msgstr "Mode rotation" @@ -23224,223 +22558,189 @@ msgstr "" "Modifiez la taille dans les formes de collision enfant à la place." #: scene/3d/physics_body.cpp -#, fuzzy msgid "Axis Lock" -msgstr "Axe" +msgstr "Verrouiller l'axe" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear X" -msgstr "Linéaire" +msgstr "X linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Y" -msgstr "Linéaire" +msgstr "Y linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Z" -msgstr "Linéaire" +msgstr "Z linéaire" #: scene/3d/physics_body.cpp msgid "Angular X" -msgstr "" +msgstr "X angulaire" #: scene/3d/physics_body.cpp msgid "Angular Y" -msgstr "" +msgstr "Y angulaire" #: scene/3d/physics_body.cpp msgid "Angular Z" -msgstr "" +msgstr "Z angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion X" -msgstr "Action" +msgstr "X mouvement" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion Y" -msgstr "Action" +msgstr "Y mouvement" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Motion Z" -msgstr "Action" +msgstr "Z mouvement" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Joint Constraints" -msgstr "Constantes" +msgstr "Restrictions de jointure" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Impulse Clamp" -msgstr "" +msgstr "Borner l'impulsion" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp -#, fuzzy msgid "Swing Span" -msgstr "Enregistrement de la scène" +msgstr "Ampleur de balancement" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "Twist Span" -msgstr "" +msgstr "Ampleur de torsion" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Relaxation" -msgstr "Séparation :" +msgstr "Relaxation" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Enabled" -msgstr "Filtrer les signaux" +msgstr "Limite angulaire activée" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Upper" -msgstr "Linéaire" +msgstr "Limite angulaire haute" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Lower" -msgstr "Erreur angulaire max. :" +msgstr "Limite angulaire basse" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Bias" -msgstr "Linéaire" +msgstr "Biais de limite angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Softness" -msgstr "Animation" +msgstr "Douceur de limite angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Relaxation" -msgstr "Animation" +msgstr "Relaxation de limite angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Upper" -msgstr "Linéaire" +msgstr "Limite linéaire haute" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Lower" -msgstr "Linéaire" +msgstr "Limite linéaire basse" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Softness" -msgstr "Linéaire" +msgstr "Douceur de limite linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Restitution" -msgstr "Linéaire" +msgstr "Restitution de limite linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Damping" -msgstr "Linéaire" +msgstr "Amortissement de limite linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Restitution" -msgstr "Animation" +msgstr "Restitution de limite angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Damping" -msgstr "Animation" +msgstr "Amortissement de limite angulaire" #: scene/3d/physics_body.cpp msgid "X" -msgstr "" +msgstr "X" #: scene/3d/physics_body.cpp msgid "Y" -msgstr "" +msgstr "Y" #: scene/3d/physics_body.cpp msgid "Z" -msgstr "" +msgstr "Z" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Limit Enabled" -msgstr "Linéaire" +msgstr "Limite linéaire active" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Enabled" -msgstr "Linéaire" +msgstr "Ressort linéaire actif" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Stiffness" -msgstr "Linéaire" +msgstr "Raideur du ressort linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Spring Damping" -msgstr "Linéaire" +msgstr "Amortissement de ressort linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Equilibrium Point" -msgstr "Linéaire" +msgstr "Point d’équilibre linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Restitution" -msgstr "Description" +msgstr "Restitution linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Linear Damping" -msgstr "Linéaire" +msgstr "Amortissement linéaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Restitution" -msgstr "Description" +msgstr "Restitution angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Damping" -msgstr "Animation" +msgstr "Amortissement angulaire" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp msgid "ERP" msgstr "" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Spring Enabled" -msgstr "Filtrer les signaux" +msgstr "Ressort angulaire actif" #: scene/3d/physics_body.cpp msgid "Angular Spring Stiffness" -msgstr "" +msgstr "Raideur de ressort angulaire" #: scene/3d/physics_body.cpp msgid "Angular Spring Damping" -msgstr "" +msgstr "Amortissement de ressort angulaire" #: scene/3d/physics_body.cpp msgid "Angular Equilibrium Point" -msgstr "" +msgstr "Point d’équilibre angulaire" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Body Offset" -msgstr "Décalage :" +msgstr "Décalage du corps" #: scene/3d/physics_joint.cpp msgid "Node A and Node B must be PhysicsBodies" @@ -23464,183 +22764,159 @@ msgstr "Node A et Node B doivent être des PhysicsBody différents" #: scene/3d/physics_joint.cpp msgid "Solver" -msgstr "" +msgstr "Résolveur" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Exclude Nodes" -msgstr "Supprimer des nÅ“uds" +msgstr "Exclure les nÅ“uds" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Params" -msgstr "Paramètre modifié :" +msgstr "Paramètres" #: scene/3d/physics_joint.cpp msgid "Angular Limit" -msgstr "" +msgstr "Limite angulaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper" -msgstr "Tout en majuscule" +msgstr "Haute" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower" -msgstr "Tout en minuscule" +msgstr "Basse" #: scene/3d/physics_joint.cpp msgid "Motor" -msgstr "" +msgstr "Moteur" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Target Velocity" -msgstr "Vue de l'orbite vers la droite" +msgstr "Vélocité cible" #: scene/3d/physics_joint.cpp msgid "Max Impulse" msgstr "Impulsion Maximale" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit" -msgstr "Linéaire" +msgstr "Limite linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper Distance" -msgstr "Choisissez distance :" +msgstr "Distance haute" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower Distance" -msgstr "Choisissez distance :" +msgstr "Distance basse" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Restitution" -msgstr "Description" +msgstr "Restitution" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motion" -msgstr "Initialiser" +msgstr "Mouvement linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Ortho" -msgstr "Orthogonale arrière" +msgstr "Ortho linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper Angle" -msgstr "Tout en majuscule" +msgstr "Angle supérieur" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower Angle" -msgstr "Tout en minuscule" +msgstr "Angle inférieur" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Angular Motion" -msgstr "Animation" +msgstr "Mouvement angulaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Angular Ortho" -msgstr "Erreur angulaire max. :" +msgstr "Ortho angulaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit X" -msgstr "Linéaire" +msgstr "X de la limite linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor X" -msgstr "Initialiser" +msgstr "X du moteur linéaire" #: scene/3d/physics_joint.cpp msgid "Force Limit" msgstr "Limite de Force" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring X" -msgstr "Linéaire" +msgstr "X du ressort linéaire" #: scene/3d/physics_joint.cpp msgid "Equilibrium Point" -msgstr "" +msgstr "Point d’équilibre" #: scene/3d/physics_joint.cpp msgid "Angular Limit X" -msgstr "" +msgstr "X de la limite angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Motor X" -msgstr "" +msgstr "X du moteur angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Spring X" -msgstr "" +msgstr "X du ressort angulaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit Y" -msgstr "Linéaire" +msgstr "Y de la limite linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor Y" -msgstr "Initialiser" +msgstr "Y du moteur linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring Y" -msgstr "Linéaire" +msgstr "Y du ressort linéaire" #: scene/3d/physics_joint.cpp msgid "Angular Limit Y" -msgstr "" +msgstr "Y de la limite angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Motor Y" -msgstr "" +msgstr "Y du moteur angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Spring Y" -msgstr "" +msgstr "Y du ressort angulaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Limit Z" -msgstr "Linéaire" +msgstr "Z de la limite linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Motor Z" -msgstr "Initialiser" +msgstr "Z du moteur linéaire" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Linear Spring Z" -msgstr "Linéaire" +msgstr "Z du ressort linéaire" #: scene/3d/physics_joint.cpp msgid "Angular Limit Z" -msgstr "" +msgstr "Z de la limite angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Motor Z" -msgstr "" +msgstr "Z du moteur angulaire" #: scene/3d/physics_joint.cpp msgid "Angular Spring Z" -msgstr "" +msgstr "Z du ressort angulaire" #: scene/3d/portal.cpp msgid "The RoomManager should not be a child or grandchild of a Portal." @@ -23660,21 +22936,19 @@ msgstr "Portail actif" #: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp msgid "Two Way" -msgstr "" +msgstr "Double sens" #: scene/3d/portal.cpp msgid "Linked Room" msgstr "Salle liée" #: scene/3d/portal.cpp -#, fuzzy msgid "Use Default Margin" -msgstr "Défaut" +msgstr "Utiliser les marges par défaut" #: scene/3d/proximity_group.cpp -#, fuzzy msgid "Group Name" -msgstr "Groupé" +msgstr "Nom de groupe" #: scene/3d/proximity_group.cpp msgid "Dispatch Mode" @@ -23685,42 +22959,36 @@ msgid "Grid Radius" msgstr "Rayon de la Grille" #: scene/3d/ray_cast.cpp -#, fuzzy msgid "Debug Shape" -msgstr "Débogueur" +msgstr "Forme de débogage" #: scene/3d/ray_cast.cpp scene/resources/style_box.cpp msgid "Thickness" -msgstr "" +msgstr "Épaisseur" #: scene/3d/reflection_probe.cpp scene/main/viewport.cpp -#, fuzzy msgid "Update Mode" -msgstr "Mode rotation" +msgstr "Mode de mise à jour" #: scene/3d/reflection_probe.cpp msgid "Origin Offset" msgstr "Décalage de la Grille" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Box Projection" -msgstr "Projet" +msgstr "Projection boîte" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Enable Shadows" -msgstr "Activer l'alignement" +msgstr "Activer les ombres" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Ambient Color" -msgstr "Prélever une couleur" +msgstr "Couleur ambiante" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Ambient Energy" -msgstr "Couleurs d'émission" +msgstr "Énergie ambiante" #: scene/3d/reflection_probe.cpp #, fuzzy @@ -24023,6 +23291,11 @@ msgstr "" "Modifiez les tailles dans les formes de collision enfants à la place." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transformation Globale" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -24096,9 +23369,8 @@ msgid "Use As Steering" msgstr "" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Wheel" -msgstr "Molette vers le haut." +msgstr "Molette" #: scene/3d/vehicle_body.cpp msgid "Roll Influence" @@ -24134,9 +23406,8 @@ msgid "Material Override" msgstr "Redéfinition" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Material Overlay" -msgstr "Changements de matériau :" +msgstr "Superposition de Matériau" #: scene/3d/visual_instance.cpp #, fuzzy @@ -24144,9 +23415,8 @@ msgid "Cast Shadow" msgstr "Créer un nÅ“ud Shader" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Extra Cull Margin" -msgstr "Arguments supplémentaires :" +msgstr "Marge supplémentaire de détermination des faces cachées" #: scene/3d/visual_instance.cpp #, fuzzy @@ -24218,14 +23488,12 @@ msgid "Mix Mode" msgstr "Mélanger le nÅ“ud" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Fadein Time" -msgstr "Durée du fondu (s) :" +msgstr "Durée du fondu entrant" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Fadeout Time" -msgstr "Durée du fondu (s) :" +msgstr "Durée du fondu sortant" #: scene/animation/animation_blend_tree.cpp msgid "Auto Restart" @@ -24240,9 +23508,8 @@ msgid "Delay" msgstr "" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Random Delay" -msgstr "Inclinaison aléatoire :" +msgstr "Retard aléatoire" #: scene/animation/animation_blend_tree.cpp #, fuzzy @@ -24250,9 +23517,8 @@ msgid "Add Amount" msgstr "Quantité" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Blend Amount" -msgstr "Quantité :" +msgstr "Quantité de mélange" #: scene/animation/animation_blend_tree.cpp #, fuzzy @@ -24266,9 +23532,8 @@ msgstr "Ajouter un port d'entrée" #: scene/animation/animation_blend_tree.cpp #: scene/animation/animation_node_state_machine.cpp -#, fuzzy msgid "Xfade Time" -msgstr "Durée du fondu (s) :" +msgstr "Durée du fondu croisé" #: scene/animation/animation_node_state_machine.cpp #, fuzzy @@ -24680,9 +23945,8 @@ msgid "Pass On Modal Close Click" msgstr "" #: scene/gui/control.cpp -#, fuzzy msgid "Size Flags" -msgstr "Taille :" +msgstr "Drapeaux de Taille" #: scene/gui/control.cpp #, fuzzy @@ -24734,9 +23998,8 @@ msgid "Scroll Offset" msgstr "Décalage du Défilement" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Snap Distance" -msgstr "Choisissez distance :" +msgstr "Distance d'arrondissage" #: scene/gui/graph_edit.cpp #, fuzzy @@ -24873,9 +24136,8 @@ msgid "Secret" msgstr "" #: scene/gui/line_edit.cpp -#, fuzzy msgid "Secret Character" -msgstr "Caractères valides :" +msgstr "Caractère secret" #: scene/gui/line_edit.cpp msgid "Expand To Text Length" @@ -24932,7 +24194,7 @@ msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Caret" -msgstr "" +msgstr "Caret" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" @@ -25109,9 +24371,8 @@ msgid "Meta Underlined" msgstr "" #: scene/gui/rich_text_label.cpp -#, fuzzy msgid "Tab Size" -msgstr "Taille :" +msgstr "Taille de tabulation" #: scene/gui/rich_text_label.cpp #, fuzzy @@ -25132,9 +24393,8 @@ msgid "Selection Enabled" msgstr "Sélection uniquement" #: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Override Selected Font Color" -msgstr "Configurer le profil sélectionné :" +msgstr "Remplacer la couleur de police sélectionnée" #: scene/gui/rich_text_label.cpp #, fuzzy @@ -25185,9 +24445,8 @@ msgid "Tick Count" msgstr "Prélever une couleur" #: scene/gui/slider.cpp -#, fuzzy msgid "Ticks On Borders" -msgstr "dans l'ordre :" +msgstr "Encoches aux bordures" #: scene/gui/spin_box.cpp msgid "Prefix" @@ -25198,9 +24457,8 @@ msgid "Suffix" msgstr "Suffixe" #: scene/gui/split_container.cpp -#, fuzzy msgid "Split Offset" -msgstr "Décalage de la grille :" +msgstr "Décalage des écarts" #: scene/gui/split_container.cpp scene/gui/tree.cpp #, fuzzy @@ -25217,9 +24475,8 @@ msgid "Tab Align" msgstr "" #: scene/gui/tab_container.cpp scene/gui/tabs.cpp -#, fuzzy msgid "Current Tab" -msgstr "Actuel :" +msgstr "Onglet actuel" #: scene/gui/tab_container.cpp #, fuzzy @@ -25261,9 +24518,8 @@ msgid "Breakpoint Gutter" msgstr "Passer les points d'arrêt" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Fold Gutter" -msgstr "Dossier :" +msgstr "Replier le bandeau" #: scene/gui/text_edit.cpp #, fuzzy @@ -25365,9 +24621,8 @@ msgid "Initial Angle" msgstr "Initialiser" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Fill Degrees" -msgstr "Rotation de %s degrés." +msgstr "Degrés remplis" #: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp #, fuzzy @@ -25473,9 +24728,8 @@ msgid "Max Redirects" msgstr "" #: scene/main/http_request.cpp -#, fuzzy msgid "Timeout" -msgstr "Délai dépassé." +msgstr "Délai dépassé" #: scene/main/node.cpp msgid "" @@ -25748,9 +25002,8 @@ msgid "Debug Draw" msgstr "Débogage" #: scene/main/viewport.cpp -#, fuzzy msgid "Render Target" -msgstr "Moteur de rendu :" +msgstr "Rendre la cible" #: scene/main/viewport.cpp msgid "V Flip" @@ -25923,9 +25176,8 @@ msgid "Font Color Disabled" msgstr "Âgrafe désactivée" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "H Separation" -msgstr "Séparation :" +msgstr "Séparation H" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26013,14 +25265,12 @@ msgid "Font Outline Modulate" msgstr "Forcer la modulation blanche" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Shadow Offset X" -msgstr "Décalage X de la grille :" +msgstr "Décalage X de l'ombre" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Shadow Offset Y" -msgstr "Décalage Y de la grille :" +msgstr "Décalage Y de l'ombre" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26078,14 +25328,12 @@ msgid "Space" msgstr "Scène principale" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Folded" -msgstr "Dossier :" +msgstr "Replié" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Fold" -msgstr "Dossier :" +msgstr "Replier" #: scene/resources/default_theme/default_theme.cpp msgid "Font Color Readonly" @@ -26204,14 +25452,12 @@ msgid "Close Highlight" msgstr "Éclairage direct" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Close H Offset" -msgstr "Décalage de la grille :" +msgstr "Fermer décalage H" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Close V Offset" -msgstr "Décalage de la grille :" +msgstr "Fermer décalage V" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26239,9 +25485,8 @@ msgid "Labeled Separator Right" msgstr "Séparateur nommé" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Separator" -msgstr "Opérateur de couleur." +msgstr "Séparateur de police" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26249,14 +25494,12 @@ msgid "Font Color Accel" msgstr "Renommer l'item de couleur" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Separator" -msgstr "Opérateur de couleur." +msgstr "Séparateur de couleur de police" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "V Separation" -msgstr "Séparation :" +msgstr "Séparation V" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26304,9 +25547,8 @@ msgid "Title Offset" msgstr "Décalage d’Octet" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Close Offset" -msgstr "Décalage de la grille :" +msgstr "Fermer de décalage" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26436,9 +25678,8 @@ msgid "Icon Margin" msgstr "Définir la marge" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Line Separation" -msgstr "Séparation :" +msgstr "Séparation de line" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26498,9 +25739,8 @@ msgid "Large" msgstr "Cible" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Folder" -msgstr "Dossier :" +msgstr "Dossier" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26538,9 +25778,8 @@ msgid "Label Width" msgstr "Étendu à Gauche" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Screen Picker" -msgstr "Opérateur d'écran." +msgstr "Sélecteur d'écran" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26601,14 +25840,12 @@ msgid "Mono Font" msgstr "Police Principale" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Table H Separation" -msgstr "Séparation :" +msgstr "Séparation H de table" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Table V Separation" -msgstr "Séparation :" +msgstr "Séparation V de table" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26773,7 +26010,7 @@ msgstr "Condition" #: scene/resources/environment.cpp msgid "Fog" -msgstr "" +msgstr "Brouillard" #: scene/resources/environment.cpp msgid "Sun Color" @@ -26869,14 +26106,12 @@ msgid "Max Steps" msgstr "Pas" #: scene/resources/environment.cpp -#, fuzzy msgid "Fade In" -msgstr "Fondu entrant (s) :" +msgstr "Fondu entrant" #: scene/resources/environment.cpp -#, fuzzy msgid "Fade Out" -msgstr "Fondu sortant (s) :" +msgstr "Fondu sortant" #: scene/resources/environment.cpp #, fuzzy @@ -26955,54 +26190,52 @@ msgstr "2" #: scene/resources/environment.cpp #: servers/audio/effects/audio_effect_chorus.cpp msgid "3" -msgstr "" +msgstr "3" #: scene/resources/environment.cpp #: servers/audio/effects/audio_effect_chorus.cpp msgid "4" -msgstr "" +msgstr "4" #: scene/resources/environment.cpp msgid "5" -msgstr "" +msgstr "5" #: scene/resources/environment.cpp msgid "6" -msgstr "" +msgstr "6" #: scene/resources/environment.cpp msgid "7" -msgstr "" +msgstr "7" #: scene/resources/environment.cpp msgid "Bloom" -msgstr "" +msgstr "Flou lumineux" #: scene/resources/environment.cpp msgid "HDR Threshold" -msgstr "" +msgstr "Seuil HDR" #: scene/resources/environment.cpp msgid "HDR Luminance Cap" -msgstr "" +msgstr "Limite de luminance HDR" #: scene/resources/environment.cpp -#, fuzzy msgid "HDR Scale" -msgstr "Mode mise à l'échelle" +msgstr "Échelle HDR" #: scene/resources/environment.cpp msgid "Bicubic Upscale" -msgstr "" +msgstr "Redimensionnement Bicubique" #: scene/resources/environment.cpp msgid "Adjustments" -msgstr "" +msgstr "Ajustements" #: scene/resources/environment.cpp -#, fuzzy msgid "Brightness" -msgstr "Lumière" +msgstr "Luminosité" #: scene/resources/environment.cpp msgid "Saturation" @@ -27010,22 +26243,19 @@ msgstr "Saturation" #: scene/resources/environment.cpp msgid "Color Correction" -msgstr "Correction de Couleur" +msgstr "Correction des couleurs" #: scene/resources/font.cpp -#, fuzzy msgid "Ascent" -msgstr "Récents :" +msgstr "Inclinaison" #: scene/resources/font.cpp -#, fuzzy msgid "Distance Field" -msgstr "Mode Sans Distraction" +msgstr "Champ de distance" #: scene/resources/gradient.cpp -#, fuzzy msgid "Raw Data" -msgstr "Profondeur" +msgstr "Données brutes" #: scene/resources/gradient.cpp msgid "Offsets" @@ -27033,62 +26263,55 @@ msgstr "Décalages" #: scene/resources/height_map_shape.cpp msgid "Map Width" -msgstr "" +msgstr "Largeur de la carte" #: scene/resources/height_map_shape.cpp -#, fuzzy msgid "Map Depth" -msgstr "Profondeur" +msgstr "Profondeur de la carte" #: scene/resources/height_map_shape.cpp -#, fuzzy msgid "Map Data" -msgstr "Profondeur" +msgstr "Données de la carte" #: scene/resources/line_shape_2d.cpp msgid "D" -msgstr "" +msgstr "D" #: scene/resources/material.cpp -#, fuzzy msgid "Next Pass" -msgstr "Plan suivant" +msgstr "Passe suivante" #: scene/resources/material.cpp msgid "Use Shadow To Opacity" msgstr "" #: scene/resources/material.cpp -#, fuzzy msgid "Unshaded" -msgstr "Afficher sans ombrage" +msgstr "Sans ombrage" #: scene/resources/material.cpp -#, fuzzy msgid "Vertex Lighting" -msgstr "Éclairage direct" +msgstr "Éclairage de sommet" #: scene/resources/material.cpp -#, fuzzy msgid "Use Point Size" -msgstr "Vue de devant" +msgstr "Utiliser la taille de point" #: scene/resources/material.cpp msgid "World Triplanar" -msgstr "" +msgstr "Monde Triplanaire" #: scene/resources/material.cpp msgid "Albedo Tex Force sRGB" -msgstr "" +msgstr "Forcer sRGB dans la texture d'albédo" #: scene/resources/material.cpp msgid "Do Not Receive Shadows" -msgstr "" +msgstr "Ne pas recevoir d'ombres" #: scene/resources/material.cpp -#, fuzzy msgid "Disable Ambient Light" -msgstr "Indenter vers la droite" +msgstr "Désactiver la lumière ambiante" #: scene/resources/material.cpp msgid "Ensure Correct Normals" @@ -27096,70 +26319,63 @@ msgstr "Assurer des Normales Correctes" #: scene/resources/material.cpp msgid "Albedo Tex MSDF" -msgstr "" +msgstr "Texture d'albédo MSDF" #: scene/resources/material.cpp -#, fuzzy msgid "Vertex Color" -msgstr "Vertex" +msgstr "Couleur de sommet" #: scene/resources/material.cpp msgid "Use As Albedo" -msgstr "" +msgstr "Utiliser comme albédo" #: scene/resources/material.cpp msgid "Is sRGB" -msgstr "" +msgstr "Est sRGB" #: scene/resources/material.cpp servers/visual_server.cpp msgid "Parameters" msgstr "Paramètres" #: scene/resources/material.cpp -#, fuzzy msgid "Diffuse Mode" -msgstr "Mode navigation" +msgstr "Mode diffus" #: scene/resources/material.cpp -#, fuzzy msgid "Specular Mode" -msgstr "Mode Règle" +msgstr "Mode spéculaire" #: scene/resources/material.cpp -#, fuzzy msgid "Depth Draw Mode" -msgstr "Mode d’interpolation" +msgstr "Mode de dessin en profondeur" #: scene/resources/material.cpp -#, fuzzy msgid "Line Width" -msgstr "Étendu à Gauche" +msgstr "Largeur de ligne" #: scene/resources/material.cpp -#, fuzzy msgid "Point Size" -msgstr "Vue de devant" +msgstr "Taille de point" #: scene/resources/material.cpp msgid "Billboard Mode" -msgstr "Mode billboard" +msgstr "Mode Billboard" #: scene/resources/material.cpp msgid "Billboard Keep Scale" -msgstr "Garder l'échelle du billboard" +msgstr "Garder l'échelle du Billboard" #: scene/resources/material.cpp msgid "Grow" -msgstr "" +msgstr "Croître" #: scene/resources/material.cpp -#, fuzzy msgid "Grow Amount" -msgstr "Quantité :" +msgstr "Quantité de croissance" #: scene/resources/material.cpp msgid "Use Alpha Scissor" -msgstr "" +msgstr "Utiliser la découpe alpha" #: scene/resources/material.cpp #, fuzzy @@ -27178,7 +26394,7 @@ msgstr "Image %" #: scene/resources/material.cpp msgid "Albedo" -msgstr "" +msgstr "Albédo" #: scene/resources/material.cpp msgid "Metallic" @@ -27204,7 +26420,7 @@ msgstr "" #: scene/resources/material.cpp msgid "Rim" -msgstr "Bordure" +msgstr "Bord" #: scene/resources/material.cpp #, fuzzy @@ -27328,9 +26544,8 @@ msgid "Color Format" msgstr "Format de Couleur" #: scene/resources/multimesh.cpp -#, fuzzy msgid "Transform Format" -msgstr "Transformation annulée." +msgstr "Format de transformation" #: scene/resources/multimesh.cpp msgid "Custom Data Format" @@ -27346,9 +26561,8 @@ msgid "Visible Instance Count" msgstr "" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Sampling" -msgstr "Mise à l'échelle :" +msgstr "Échantillonnage" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27356,9 +26570,8 @@ msgid "Partition Type" msgstr "Définir type de variable" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Parsed Geometry Type" -msgstr "Analyse de la géométrie..." +msgstr "Type de la géométrie analysée" #: scene/resources/navigation_mesh.cpp msgid "Source Geometry Mode" @@ -27415,9 +26628,8 @@ msgid "Details" msgstr "Afficher par défaut" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Sample Distance" -msgstr "Choisissez distance :" +msgstr "Échantillonner la distance" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27488,12 +26700,10 @@ msgid "Color Modifier" msgstr "Ralentissement de la vue libre" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Point Texture" -msgstr "Points d'Émission :" +msgstr "Texture ponctuelle" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Normal Texture" msgstr "Texture Normale" @@ -27525,9 +26735,8 @@ msgid "Absorbent" msgstr "" #: scene/resources/plane_shape.cpp -#, fuzzy msgid "Plane" -msgstr "Plan :" +msgstr "Plan" #: scene/resources/primitive_meshes.cpp #, fuzzy @@ -27601,9 +26810,8 @@ msgid "Bone" msgstr "Os" #: scene/resources/sky.cpp -#, fuzzy msgid "Radiance Size" -msgstr "Taille du contour :" +msgstr "Taille du rayonnement" #: scene/resources/sky.cpp msgid "Panorama" @@ -27895,9 +27103,8 @@ msgid "Default Cell Height" msgstr "En période de test" #: scene/resources/world.cpp scene/resources/world_2d.cpp -#, fuzzy msgid "Default Edge Connection Margin" -msgstr "Modifier la connexion :" +msgstr "Marge de connexion des bords par défaut" #: scene/resources/world_2d.cpp msgid "Canvas" @@ -28051,11 +27258,11 @@ msgstr "Ressource" #: servers/audio/effects/audio_effect_limiter.cpp msgid "Ceiling dB" -msgstr "" +msgstr "Plafond de dB" #: servers/audio/effects/audio_effect_limiter.cpp msgid "Threshold dB" -msgstr "" +msgstr "Seuil de dB" #: servers/audio/effects/audio_effect_limiter.cpp msgid "Soft Clip dB" @@ -28067,37 +27274,36 @@ msgstr "" #: servers/audio/effects/audio_effect_phaser.cpp msgid "Range Min Hz" -msgstr "" +msgstr "Borne inférieure de la plage (Hz)" #: servers/audio/effects/audio_effect_phaser.cpp msgid "Range Max Hz" -msgstr "" +msgstr "Borne supérieure de la plage (Hz)" #: servers/audio/effects/audio_effect_pitch_shift.cpp msgid "Oversampling" -msgstr "" +msgstr "Suréchantillonnage" #: servers/audio/effects/audio_effect_pitch_shift.cpp #: servers/audio/effects/audio_effect_spectrum_analyzer.cpp msgid "FFT Size" -msgstr "Taille FFT" +msgstr "Taille des FFTs" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Predelay" -msgstr "" +msgstr "Pré-retarder" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Msec" -msgstr "" +msgstr "Millisec" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Room Size" -msgstr "" +msgstr "Taille de la salle" #: servers/audio/effects/audio_effect_reverb.cpp -#, fuzzy msgid "High-pass" -msgstr "Contourner" +msgstr "Passe-haut" #: servers/audio/effects/audio_effect_spectrum_analyzer.cpp msgid "Tap Back Pos" @@ -28108,27 +27314,24 @@ msgid "Pan Pullout" msgstr "" #: servers/audio/effects/audio_effect_stereo_enhance.cpp -#, fuzzy msgid "Time Pullout (ms)" -msgstr "Délai dépassé." +msgstr "Temps de retrait (ms)" #: servers/audio/effects/audio_effect_stereo_enhance.cpp msgid "Surround" -msgstr "" +msgstr "Surround" #: servers/audio_server.cpp -#, fuzzy msgid "Enable Audio Input" -msgstr "Renommer le bus audio" +msgstr "Activer l’entrée audio" #: servers/audio_server.cpp -#, fuzzy msgid "Output Latency" -msgstr "Sortie" +msgstr "Latence de sortie" #: servers/audio_server.cpp msgid "Channel Disable Threshold dB" -msgstr "" +msgstr "Désactiver le seuil de dB du canal" #: servers/audio_server.cpp #, fuzzy @@ -28137,43 +27340,39 @@ msgstr "Changer le temps de mélange" #: servers/audio_server.cpp msgid "Video Delay Compensation (ms)" -msgstr "" +msgstr "Compensation de retard vidéo (ms)" #: servers/audio_server.cpp -#, fuzzy msgid "Bus Count" -msgstr "Ajouter un port d'entrée" +msgstr "Nombre de ports" #: servers/audio_server.cpp -#, fuzzy msgid "Capture Device" -msgstr "Capturer depuis Pixel" +msgstr "Périphérique de capture" #: servers/audio_server.cpp -#, fuzzy msgid "Global Rate Scale" -msgstr "Variable globale" +msgstr "Echelle de débit global" #: servers/camera/camera_feed.cpp msgid "Feed" -msgstr "" +msgstr "Flux" #: servers/camera/camera_feed.cpp -#, fuzzy msgid "Is Active" -msgstr "Perspective" +msgstr "Est active" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Sleep Threshold Linear" -msgstr "" +msgstr "Seuil linéaire de veille" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Sleep Threshold Angular" -msgstr "" +msgstr "Seuil angulaire de veille" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Time Before Sleep" -msgstr "" +msgstr "Temps avant veille" #: servers/physics_2d/physics_2d_server_sw.cpp msgid "BP Hash Table Size" @@ -28185,48 +27384,43 @@ msgstr "" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Inverse Mass" -msgstr "" +msgstr "Masse inverse" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Inverse Inertia" -msgstr "Vue libre gauche" +msgstr "Inertie inverse" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Total Angular Damp" -msgstr "" +msgstr "Amortissage angulaire total" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Total Linear Damp" -msgstr "Linéaire" +msgstr "Amortissage linéaire total" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Total Gravity" -msgstr "Aperçu par défaut" +msgstr "Gravité totale" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Linear Velocity" -msgstr "Initialiser" +msgstr "Vélocité linéaire" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Exclude" -msgstr "" +msgstr "Exclure" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Shape RID" -msgstr "" +msgstr "RID de forme" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collide With Bodies" -msgstr "Mode collision" +msgstr "Collisions avec les corps" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Collide With Areas" -msgstr "" +msgstr "Collisions avec les zones" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Motion Remainder" @@ -28468,14 +27662,12 @@ msgid "Use Software Skinning" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Ninepatch Mode" -msgstr "Mode d’interpolation" +msgstr "Mode Ninepatch" #: servers/visual_server.cpp -#, fuzzy msgid "OpenGL" -msgstr "Ouvrir" +msgstr "OpenGL" #: servers/visual_server.cpp msgid "Batching Send Null" @@ -28500,12 +27692,11 @@ msgstr "Traitement en lot" #: servers/visual_server.cpp msgid "Use Batching" -msgstr "" +msgstr "Utiliser le traitement en lot" #: servers/visual_server.cpp -#, fuzzy msgid "Use Batching In Editor" -msgstr "Mise à jour de l'éditeur" +msgstr "Utiliser le traitement en lot dans l'éditeur" #: servers/visual_server.cpp msgid "Single Rect Fallback" @@ -28529,7 +27720,7 @@ msgstr "Nombre Maximal d'Éléments Joints" #: servers/visual_server.cpp msgid "Batch Buffer Size" -msgstr "" +msgstr "Taille de tampon des lots" #: servers/visual_server.cpp msgid "Item Reordering Lookahead" @@ -28540,21 +27731,20 @@ msgid "Flash Batching" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Diagnose Frame" -msgstr "Coller une image" +msgstr "Diagnostiquer la trame" #: servers/visual_server.cpp msgid "GLES2" -msgstr "" +msgstr "GLES2" #: servers/visual_server.cpp msgid "Compatibility" -msgstr "" +msgstr "Compatibilité" #: servers/visual_server.cpp msgid "Disable Half Float" -msgstr "" +msgstr "Désactiver les demi Float" #: servers/visual_server.cpp #, fuzzy @@ -28562,31 +27752,28 @@ msgid "Enable High Float" msgstr "Activer la priorité" #: servers/visual_server.cpp -#, fuzzy msgid "Precision" -msgstr "Expression" +msgstr "Précision" #: servers/visual_server.cpp msgid "UV Contract" -msgstr "" +msgstr "Contraction UV" #: servers/visual_server.cpp msgid "UV Contract Amount" -msgstr "" +msgstr "Quantité de contraction UV" #: servers/visual_server.cpp -#, fuzzy msgid "Use Simple PVS" -msgstr "Utiliser le magnétisme d'échelle" +msgstr "Utiliser PVS simple" #: servers/visual_server.cpp msgid "PVS Logging" -msgstr "" +msgstr "Journal PVS" #: servers/visual_server.cpp -#, fuzzy msgid "Use Signals" -msgstr "Signaux" +msgstr "Utiliser les signaux" #: servers/visual_server.cpp #, fuzzy @@ -28605,27 +27792,24 @@ msgstr "Voir la suppression de l'occlusion" #: servers/visual_server.cpp msgid "Max Active Spheres" -msgstr "" +msgstr "Nombre maximum de sphères actives" #: servers/visual_server.cpp -#, fuzzy msgid "Max Active Polygons" -msgstr "Déplacer le polygone" +msgstr "Nombre maximum de polygones actifs" #: servers/visual_server.cpp -#, fuzzy msgid "Shader Compilation Mode" -msgstr "Mode d’interpolation" +msgstr "Mode de compilation des shaders" #: servers/visual_server.cpp msgid "Max Simultaneous Compiles" -msgstr "" +msgstr "Nombre de compilations simultanées" #: servers/visual_server.cpp msgid "Log Active Async Compiles Count" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Shader Cache Size (MB)" -msgstr "Changer la taille d'une caméra" +msgstr "Taille du cache de shader (Mo)" diff --git a/editor/translations/ga.po b/editor/translations/ga.po index 65ffebf3e5..87e005f5f3 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -450,6 +450,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2091,14 +2095,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Cuardach:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2154,8 +2159,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2715,8 +2720,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "CrannBeochan" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5300,6 +5306,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11289,6 +11299,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "CrannBeochan" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19438,14 +19453,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19466,14 +19480,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20453,7 +20466,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22332,6 +22345,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Athrú: " + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/gl.po b/editor/translations/gl.po index c8dd75ade3..29db0e8063 100644 --- a/editor/translations/gl.po +++ b/editor/translations/gl.po @@ -488,6 +488,10 @@ msgid "Pressure" msgstr "Axustes de Importación" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Axuste Relativo" @@ -2192,14 +2196,15 @@ msgstr "Favoritos:" msgid "Recent:" msgstr "Recente:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Buscar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Coincidencias:" @@ -2259,8 +2264,8 @@ msgstr "Buscar Recurso de Substitución:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2846,7 +2851,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Copiar Ruta do Nodo" #: editor/editor_export.cpp @@ -5652,6 +5657,10 @@ msgid "Drag And Drop Selection" msgstr "Encadrar Selección" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11900,6 +11909,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrar métodos" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocidade:" @@ -20536,15 +20550,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Extensión inválida." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20566,15 +20580,15 @@ msgstr "Nome inválido." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Extensión inválida." #: platform/windows/export/export.cpp #, fuzzy @@ -21645,7 +21659,7 @@ msgstr "Viaxe" msgid "Rotation Degrees" msgstr "Rotando % graos." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constante" @@ -23712,6 +23726,11 @@ msgstr "" "lugar." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transformación" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/he.po b/editor/translations/he.po index d37f806bb7..abaada7880 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -483,6 +483,10 @@ msgid "Pressure" msgstr "לחץ" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "GDNative" @@ -2163,14 +2167,15 @@ msgstr "מועדפי×:" msgid "Recent:" msgstr "××—×¨×•× ×™×:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "חיפוש:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "הת×מות:" @@ -2230,8 +2235,8 @@ msgstr "חיפוש מש×ב חלופי:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2802,7 +2807,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "העתקת × ×ª×™×‘ המפרק" #: editor/editor_export.cpp @@ -5567,6 +5572,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap מילוי הבחירה" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11955,6 +11964,11 @@ msgstr "×©× ×”× ×¤×©×” חדשה:" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy +msgid "Filter animations" +msgstr "מ××¤×™×™× ×™ פריט." + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy msgid "Speed:" msgstr "מהירות (FPS):" @@ -20693,15 +20707,15 @@ msgstr "×œ× × ×™×ª×Ÿ לפתוח ×ª×‘× ×™×ª לייצו×:" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "סיומת ×œ× ×—×•×§×™×ª." #: platform/windows/export/export.cpp #, fuzzy @@ -20725,15 +20739,15 @@ msgstr "×©× ×©×’×•×™." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "סיומת ×œ× ×—×•×§×™×ª." #: platform/windows/export/export.cpp #, fuzzy @@ -21808,7 +21822,7 @@ msgstr "טיול" msgid "Rotation Degrees" msgstr "הטיה של %s מעלות." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "קבוע" @@ -23890,6 +23904,11 @@ msgstr "" "×‘×ž×§×•× ×–×ת יש ×œ×©× ×•×ª ×ת גודל צורות ×”×”×ª× ×’×©×•×ª של הצ×צ××™×." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "התמרה" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 0e6bb551e4..e5a41404d0 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -466,6 +466,10 @@ msgid "Pressure" msgstr "पà¥à¤°à¥€à¤¸à¥‡à¤Ÿ" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2151,14 +2155,15 @@ msgstr "पसंदीदा:" msgid "Recent:" msgstr "हाल ही में किया:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "खोज:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "à¤à¤• जैसा:" @@ -2218,8 +2223,8 @@ msgstr "खोज रिपà¥à¤²à¥‡à¤¸à¤®à¥‡à¤‚ट संसाधन:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2799,8 +2804,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "खंड कौपी कीजिये" #: editor/editor_export.cpp #, fuzzy @@ -5572,6 +5578,10 @@ msgid "Drag And Drop Selection" msgstr "सà¤à¥€ खंड" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11756,6 +11766,11 @@ msgid "New Animation" msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨ लूप" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20295,15 +20310,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "गलत फॉणà¥à¤Ÿ का आकार |" #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20325,15 +20340,15 @@ msgstr "अमानà¥à¤¯ नाम." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "गलत फॉणà¥à¤Ÿ का आकार |" #: platform/windows/export/export.cpp #, fuzzy @@ -21363,7 +21378,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "कोनà¥à¤¸à¥à¤Ÿà¤¨à¥à¤Ÿ" @@ -23338,6 +23353,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "à¤à¤¨à¥€à¤®à¥‡à¤¶à¤¨ परिवरà¥à¤¤à¤¨ परिणत" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/hr.po b/editor/translations/hr.po index c1a9a444cc..e473c6556c 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -6,12 +6,13 @@ # Patik <patrikfs5@gmail.com>, 2019. # Nikola Bunjevac <nikola.bunjevac@gmail.com>, 2019, 2020. # LeoClose <leoclose575@gmail.com>, 2020, 2021. +# Filip <fhomolka@protonmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2021-08-13 19:05+0000\n" -"Last-Translator: LeoClose <leoclose575@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" +"Last-Translator: Filip <fhomolka@protonmail.com>\n" "Language-Team: Croatian <https://hosted.weblate.org/projects/godot-engine/" "godot/hr/>\n" "Language: hr\n" @@ -19,11 +20,11 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\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.8-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" -msgstr "" +msgstr "UpravljaÄki program za Tablet" #: core/bind/core_bind.cpp msgid "Clipboard" @@ -39,73 +40,77 @@ msgid "Exit Code" msgstr "" #: core/bind/core_bind.cpp -#, fuzzy msgid "V-Sync Enabled" -msgstr "Omogući" +msgstr "V-Sync Omogućen" #: core/bind/core_bind.cpp main/main.cpp msgid "V-Sync Via Compositor" -msgstr "" +msgstr "V-Sync preko Kompozitora" #: core/bind/core_bind.cpp main/main.cpp msgid "Delta Smoothing" -msgstr "" +msgstr "Delta Ublažavanje" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode" -msgstr "" +msgstr "NaÄin niske upotrebe procesora" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode Sleep (µsec)" -msgstr "" +msgstr "Stanje mirovanja u naÄinu koriÅ¡tenja niskog procesora (μsec)" #: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp msgid "Keep Screen On" -msgstr "" +msgstr "Zadrži zaslon ukljuÄenim" #: core/bind/core_bind.cpp -#, fuzzy msgid "Min Window Size" -msgstr "Glavna skripta:" +msgstr "Min. veliÄina prozora" #: core/bind/core_bind.cpp -#, fuzzy msgid "Max Window Size" -msgstr "Glavna skripta:" +msgstr "Maks. veliÄina prozora" #: core/bind/core_bind.cpp msgid "Screen Orientation" -msgstr "" +msgstr "Orijentacija zaslona" #: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp #: platform/uwp/os_uwp.cpp +#, fuzzy msgid "Window" -msgstr "" +msgstr "Prozor" #: core/bind/core_bind.cpp core/project_settings.cpp +#, fuzzy msgid "Borderless" -msgstr "" +msgstr "Bez obruba" #: core/bind/core_bind.cpp +#, fuzzy msgid "Per Pixel Transparency Enabled" -msgstr "" +msgstr "Omogućena prozirnost po pikselu" #: core/bind/core_bind.cpp core/project_settings.cpp +#, fuzzy msgid "Fullscreen" -msgstr "" +msgstr "Cijeli zaslon" #: core/bind/core_bind.cpp +#, fuzzy msgid "Maximized" -msgstr "" +msgstr "Maksimiziran" #: core/bind/core_bind.cpp +#, fuzzy msgid "Minimized" -msgstr "" +msgstr "Minimiziran" #: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp #: scene/gui/graph_node.cpp +#, fuzzy msgid "Resizable" -msgstr "" +msgstr "Mogućnost promjene veliÄine" #: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp #: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp @@ -114,7 +119,7 @@ msgstr "" #: scene/resources/default_theme/default_theme.cpp #, fuzzy msgid "Position" -msgstr "Stvori" +msgstr "Pozicija" #: core/bind/core_bind.cpp core/project_settings.cpp editor/editor_settings.cpp #: main/main.cpp modules/gridmap/grid_map.cpp @@ -125,8 +130,9 @@ msgstr "Stvori" #: scene/resources/primitive_meshes.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp #: scene/resources/visual_shader.cpp servers/visual_server.cpp +#, fuzzy msgid "Size" -msgstr "" +msgstr "VeliÄina" #: core/bind/core_bind.cpp msgid "Endian Swap" @@ -135,25 +141,27 @@ msgstr "" #: core/bind/core_bind.cpp #, fuzzy msgid "Editor Hint" -msgstr "(Editor Onemogućen)" +msgstr "Savjet Urednika" #: core/bind/core_bind.cpp +#, fuzzy msgid "Print Error Messages" -msgstr "" +msgstr "Ispis poruka o pogreÅ¡kama" #: core/bind/core_bind.cpp #, fuzzy msgid "Iterations Per Second" -msgstr "NaÄin Interpolacije" +msgstr "Iteracije u sekundi" #: core/bind/core_bind.cpp +#, fuzzy msgid "Target FPS" -msgstr "" +msgstr "Ciljani FPS" #: core/bind/core_bind.cpp #, fuzzy msgid "Time Scale" -msgstr "Dubina" +msgstr "Vremenska skala" #: core/bind/core_bind.cpp main/main.cpp msgid "Physics Jitter Fix" @@ -465,6 +473,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2121,14 +2133,15 @@ msgstr "Favoriti:" msgid "Recent:" msgstr "Nedavno:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Pretraga:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Podudaranja:" @@ -2188,8 +2201,8 @@ msgstr "Traži zamjenu resursa:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2760,8 +2773,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Animacija" #: editor/editor_export.cpp #, fuzzy @@ -5391,6 +5405,10 @@ msgid "Drag And Drop Selection" msgstr "IzbriÅ¡i Odabir" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11475,6 +11493,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Obrisati Animaciju?" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19795,15 +19818,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Nevažeće ime." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -19825,15 +19848,15 @@ msgstr "Nevažeće ime." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Nevažeće ime." #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -20844,7 +20867,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22783,6 +22806,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Uredi Tranzicije..." + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index 5bfd5b0995..b35be76368 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -507,6 +507,10 @@ msgid "Pressure" msgstr "ElÅ‘re beállÃtott" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "RelatÃv Illesztés" @@ -2222,14 +2226,15 @@ msgstr "Kedvencek:" msgid "Recent:" msgstr "Legutóbbi:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Keresés:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Egyezések:" @@ -2289,8 +2294,8 @@ msgstr "Csere Forrás Keresése:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2867,7 +2872,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Node Útvonal Másolása" #: editor/editor_export.cpp @@ -5680,6 +5685,10 @@ msgid "Drag And Drop Selection" msgstr "Kijelölés Keretezése" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11929,6 +11938,11 @@ msgid "New Animation" msgstr "Új animáció" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Metódusok szűrése" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20496,15 +20510,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Érvénytelen kiterjesztés." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20526,15 +20540,15 @@ msgstr "Érvénytelen név." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Érvénytelen kiterjesztés." #: platform/windows/export/export.cpp #, fuzzy @@ -21595,7 +21609,7 @@ msgstr "Utazás" msgid "Rotation Degrees" msgstr "Forgatási Léptetés:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Ãllandó" @@ -23628,6 +23642,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Globális Transzformáció Megtartása" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/id.po b/editor/translations/id.po index 57c1a69e92..7d839357cd 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -26,7 +26,7 @@ # Ade Fikri Malihuddin <ade.fm97@gmail.com>, 2020. # zephyroths <ridho.hikaru@gmail.com>, 2020, 2021, 2022. # Richard Urban <redasuio1@gmail.com>, 2020. -# yusuf afandi <afandi.yusuf.04@gmail.com>, 2020. +# yusuf afandi <afandi.yusuf.04@gmail.com>, 2020, 2022. # Habib Rohman <revolusi147id@gmail.com>, 2020. # Hanz <hanzhaxors@gmail.com>, 2021. # Reza Almanda <rezaalmanda27@gmail.com>, 2021, 2022. @@ -39,13 +39,14 @@ # ProgrammerIndonesia 44 <elo.jhy@gmail.com>, 2022. # Rizky Ramadhan <rizkyterm@gmail.com>, 2022. # Primananda Kurnia <primakurnia71@gmail.com>, 2022. +# FellowMustard <rachmawanng33@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-05-15 09:38+0000\n" -"Last-Translator: Tsaqib Fadhlurrahman Soka <sokatsaqib@gmail.com>\n" +"PO-Revision-Date: 2022-07-31 18:34+0000\n" +"Last-Translator: ProgrammerIndonesia 44 <elo.jhy@gmail.com>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot/id/>\n" "Language: id\n" @@ -53,7 +54,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.13-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -426,9 +427,8 @@ msgid "Command" msgstr "Perintah" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (Secara fisik)" +msgstr "(Secara fisik)" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -481,6 +481,11 @@ msgid "Pressure" msgstr "Tekanan" #: core/os/input_event.cpp +#, fuzzy +msgid "Pen Inverted" +msgstr "Balik" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relatif" @@ -1201,7 +1206,7 @@ msgstr "Atur Pegangan" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp msgid "Stream" -msgstr "" +msgstr "Arus" #: editor/animation_track_editor.cpp #, fuzzy @@ -2153,14 +2158,15 @@ msgstr "Favorit:" msgid "Recent:" msgstr "Saat ini:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Cari:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Kecocokan:" @@ -2220,8 +2226,8 @@ msgstr "Cari Resource Pengganti:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2798,13 +2804,12 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Salin Lokasi Node" #: editor/editor_export.cpp -#, fuzzy msgid "Completed successfully." -msgstr "Paket Sukses Terpasang!" +msgstr "Sukses." #: editor/editor_export.cpp #, fuzzy @@ -3283,9 +3288,8 @@ msgid "Save a File" msgstr "Simpan sebuah File" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Access" -msgstr "Sukses!" +msgstr "Akses" #: editor/editor_file_dialog.cpp editor/editor_settings.cpp #, fuzzy @@ -5611,6 +5615,10 @@ msgid "Drag And Drop Selection" msgstr "Isi Seleksi GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "Penampilan" @@ -11844,6 +11852,11 @@ msgid "New Animation" msgstr "Animasi Baru" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filter method" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Kecepatan:" @@ -12366,9 +12379,8 @@ msgid "Available Node-based types:" msgstr "Profil yang Tersedia:" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Type name is empty!" -msgstr "Nama berkas kosong." +msgstr "Nama tipe kosong!" #: editor/plugins/theme_editor_plugin.cpp #, fuzzy @@ -19273,9 +19285,8 @@ msgid "Could not find keystore, unable to export." msgstr "Tidak dapat menemukan keystore, tidak bisa ekspor." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not start apksigner executable." -msgstr "Tidak dapat memulai subproses!" +msgstr "Tidak dapat memulai apksigner." #: platform/android/export/export_plugin.cpp msgid "'apksigner' returned with error #%d" @@ -19308,9 +19319,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension." msgstr "Nama berkas tidak valid! APK Android memerlukan ekstensi *.apk ." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Unsupported export format!" -msgstr "Format ekspor tidak didukung!\n" +msgstr "Format ekspor tidak didukung!" #: platform/android/export/export_plugin.cpp msgid "" @@ -19321,15 +19331,12 @@ msgstr "" "versinya. Silakan pasang ulang dari menu 'Proyek'." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Android build version mismatch: Template installed: %s, Godot version: %s. " "Please reinstall Android build template from 'Project' menu." msgstr "" -"Versi build Android tidak cocok:\n" -" Templat terpasang: %s\n" -" Versi Godot: %s\n" -"Silakan pasang ulang templat build Android dari menu 'Project'." +"Versi build Android tidak cocok: Templat terpasang: %s, Versi Godot: %s. " +"Silakan pasang ulang templat build Android dari menu 'Proyek'." #: platform/android/export/export_plugin.cpp msgid "" @@ -19337,9 +19344,8 @@ msgid "" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "Tidak dapat menyunting proyek gradle dalam lokasi proyek\n" +msgstr "Tidak dapat mengekspor file proyek ke dalam lokasi proyek gradle." #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -19350,13 +19356,12 @@ msgid "Building Android Project (gradle)" msgstr "Membangun Proyek Android (gradle)" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Building of Android project failed, check output for the error. " "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"Pembangunan proyek Android gagal, periksa output untuk galatnya.\n" -"Atau kunjungi docs.godotengine.org untuk dokumentasi build Android." +"Pembangunan proyek Android gagal, periksa output untuk galatnya. Atau " +"kunjungi docs.godotengine.org untuk dokumentasi build Android." #: platform/android/export/export_plugin.cpp msgid "Moving output" @@ -19381,11 +19386,8 @@ msgid "Creating APK..." msgstr "Membuat kontur..." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not find template APK to export: \"%s\"." -msgstr "" -"Tidak dapat menemukan contoh APK untuk ekspor:\n" -"%s" +msgstr "Tidak dapat menemukan contoh APK untuk ekspor: \"%s\"" #: platform/android/export/export_plugin.cpp msgid "" @@ -19544,9 +19546,8 @@ msgid "Capabilities" msgstr "Kapabilitas" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Access Wi-Fi" -msgstr "Sukses!" +msgstr "Akses Wi-Fi" #: platform/iphone/export/export.cpp #, fuzzy @@ -20094,9 +20095,8 @@ msgid "Could not open icon file \"%s\"." msgstr "Tidak dapat ekspor berkas proyek" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start xcrun executable." -msgstr "Tidak dapat memulai subproses!" +msgstr "Tidak dapat memulai subproses xcrun." #: platform/osx/export/export.cpp #, fuzzy @@ -20174,9 +20174,8 @@ msgid "DMG Creation" msgstr "Arah" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start hdiutil executable." -msgstr "Tidak dapat memulai subproses!" +msgstr "Tidak dapat memulai subproses hdiutil." #: platform/osx/export/export.cpp msgid "`hdiutil create` failed - file exists." @@ -20258,7 +20257,7 @@ msgstr "Proyeksi" #: platform/osx/export/export.cpp #, fuzzy msgid "Could not open file to read from path \"%s\"." -msgstr "Tidak dapat menyunting proyek gradle dalam lokasi proyek\n" +msgstr "Tidak dapat membuka file untuk membaca dari jalur \"%s\"." #: platform/osx/export/export.cpp msgid "Invalid bundle identifier:" @@ -20643,15 +20642,15 @@ msgstr "Tidak dapat menemukan keystore, tidak bisa ekspor." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Ekstensi tidak valid." #: platform/windows/export/export.cpp #, fuzzy @@ -20675,15 +20674,15 @@ msgstr "Nama tidak sah." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Ekstensi tidak valid." #: platform/windows/export/export.cpp #, fuzzy @@ -21753,7 +21752,7 @@ msgstr "Menjelajah" msgid "Rotation Degrees" msgstr "Derajat Putaran" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "Rotasi Global" @@ -23822,6 +23821,11 @@ msgstr "" "Ubah ukurannya melalui \"collision shape\"-anaknya saja." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transformasi Global" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "Matriks" @@ -24742,7 +24746,7 @@ msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Caret" -msgstr "" +msgstr "Tanda sisipan" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" @@ -25424,9 +25428,8 @@ msgid "Draw 2D Outlines" msgstr "Buat Garis Tepi" #: scene/main/scene_tree.cpp servers/visual_server.cpp -#, fuzzy msgid "Reflections" -msgstr "Arah" +msgstr "Refleksi" #: scene/main/scene_tree.cpp #, fuzzy @@ -26782,9 +26785,8 @@ msgstr "" #: scene/resources/environment.cpp #: servers/audio/effects/audio_effect_chorus.cpp -#, fuzzy msgid "2" -msgstr "2D" +msgstr "2" #: scene/resources/environment.cpp #: servers/audio/effects/audio_effect_chorus.cpp diff --git a/editor/translations/is.po b/editor/translations/is.po index d5353421d4..512c660eef 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -457,6 +457,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2136,14 +2140,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2199,8 +2204,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2762,8 +2767,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Fjarlægja val" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5377,6 +5383,10 @@ msgid "Drag And Drop Selection" msgstr "Allt úrvalið" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11440,6 +11450,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Stillið breyting á:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19710,14 +19725,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19738,14 +19752,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20739,7 +20752,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22640,6 +22653,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Breyta umbreytingu" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/it.po b/editor/translations/it.po index e693139e21..2c9f7eb6fe 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -69,13 +69,15 @@ # Federico Caprini <caprinifede@gmail.com>, 2022. # Alessandro Casalino <alessandro.casalino93@gmail.com>, 2022. # conecat <ilgrandemax190@gmail.com>, 2022. +# Gico2006 <gradaellig@protonmail.com>, 2022. +# ale piccia <picciatialessio2@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-04 05:16+0000\n" -"Last-Translator: conecat <ilgrandemax190@gmail.com>\n" +"PO-Revision-Date: 2022-07-31 18:34+0000\n" +"Last-Translator: Mirko <miknsop@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -83,7 +85,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -374,7 +376,6 @@ msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "Byte insufficienti per decodificarli o formato non valido." #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" msgstr "Input %d non valido (assente) nell'espressione" @@ -425,7 +426,7 @@ msgstr "Modalità Mouse" #: core/os/input.cpp msgid "Use Accumulated Input" -msgstr "Usa Input Accumulato" +msgstr "Usa Input Accumulati" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -472,6 +473,7 @@ msgid "Physical Scancode" msgstr "Scancode Fisico" #: core/os/input_event.cpp +#, fuzzy msgid "Unicode" msgstr "Unicode" @@ -508,6 +510,10 @@ msgid "Pressure" msgstr "Pressione" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativo" @@ -667,14 +673,12 @@ msgid "Always On Top" msgstr "Sempre In Primo Piano" #: core/project_settings.cpp -#, fuzzy msgid "Test Width" -msgstr "Larghezza Test" +msgstr "Test Larghezza" #: core/project_settings.cpp -#, fuzzy msgid "Test Height" -msgstr "Altezza Test" +msgstr "Test Altezza" #: core/project_settings.cpp editor/animation_track_editor.cpp #: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp @@ -709,14 +713,12 @@ msgid "Script Templates Search Path" msgstr "Percorso di Ricerca dei Template di Script" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "Autocaricamento all'Avvio" +msgstr "Caricamento automatico del controllo di versione all'avvio" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Plugin Name" -msgstr "Controllo della versione" +msgstr "Nome del plugin di controllo della versione" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -899,6 +901,7 @@ msgid "Modules" msgstr "Moduli" #: core/register_core_types.cpp +#, fuzzy msgid "TCP" msgstr "TCP" @@ -1206,14 +1209,12 @@ msgid "Type" msgstr "Tipo" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "Imposta Maniglia" +msgstr "In gestione" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out Handle" -msgstr "Imposta Maniglia" +msgstr "Non gestire" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp @@ -1402,19 +1403,16 @@ msgid "Stream:" msgstr "Stream" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "Riavvia (s):" +msgstr "inizia:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End (s):" -msgstr "Fade In (s):" +msgstr "finisci:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Clip:" -msgstr "Animazioni:" +msgstr "clip delle animazioni:" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -2117,6 +2115,7 @@ msgid "Are you sure you want to remove all connections from the \"%s\" signal?" msgstr "Sei sicuro di voler rimuovere tutte le connessioni dal segnale \"%s\"?" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp +#, fuzzy msgid "Signals" msgstr "Segnali" @@ -2169,14 +2168,15 @@ msgstr "Preferiti:" msgid "Recent:" msgstr "Recenti:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Cerca:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Corrispondenze:" @@ -2236,8 +2236,8 @@ msgstr "Cerca risorsa di rimpiazzo:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2246,7 +2246,7 @@ msgstr "Apri" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "proprietario di: %s (Totale: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2603,9 +2603,8 @@ msgid "There is no '%s' file." msgstr "File \"%s\" assente." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Layout:" -msgstr "Disposizione" +msgstr "" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." @@ -2815,7 +2814,7 @@ msgstr "Esportazione del progetto per la piattaforma:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Completato con errori." #: editor/editor_export.cpp @@ -2846,9 +2845,8 @@ msgid "Save PCK" msgstr "Salva PCK" #: editor/editor_export.cpp -#, fuzzy msgid "Cannot create file \"%s\"." -msgstr "Impossibile creare la cartella." +msgstr "impossibile creare il file \"%s\"." #: editor/editor_export.cpp #, fuzzy @@ -2856,9 +2854,8 @@ msgid "Failed to export project files." msgstr "Impossibile esportare i file del progetto" #: editor/editor_export.cpp -#, fuzzy msgid "Can't open file to read from path \"%s\"." -msgstr "Impossibile aprire il file in scrittura:" +msgstr "impossibile aprire file da leggere dalla path \"%s\"." #: editor/editor_export.cpp #, fuzzy @@ -5578,6 +5575,10 @@ msgid "Drag And Drop Selection" msgstr "Selezione GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "Aspetto" @@ -6997,6 +6998,7 @@ msgstr "Anisotropico" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp +#, fuzzy msgid "sRGB" msgstr "sRGB" @@ -11735,6 +11737,11 @@ msgid "New Animation" msgstr "Nuova Animazione" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Modalità di filtraggio" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocità :" @@ -18017,7 +18024,6 @@ msgid "Expression" msgstr "Espressione" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Return" msgstr "Ritorno" @@ -18677,7 +18683,6 @@ msgid "Hand Tracking Frequency" msgstr "" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Passthrough" msgstr "Passthrough" @@ -20333,15 +20338,15 @@ msgstr "Non è stato possibile trovare keystore, impossible esportare." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Estensione non valida." #: platform/windows/export/export.cpp #, fuzzy @@ -20365,15 +20370,15 @@ msgstr "Nome non valido." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Estensione non valida." #: platform/windows/export/export.cpp #, fuzzy @@ -20921,9 +20926,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Fixed FPS" -msgstr "Vedi FPS" +msgstr "FPS fisso" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21493,7 +21497,7 @@ msgstr "Spostamento" msgid "Rotation Degrees" msgstr "Rotazione in Gradi" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Costante" @@ -23642,6 +23646,11 @@ msgstr "" "Modifica invece la dimensione nelle forme di collisione figlie." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Mantieni Transform Globale" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -26403,7 +26412,6 @@ msgid "Sky Contribution" msgstr "Condizione" #: scene/resources/environment.cpp -#, fuzzy msgid "Fog" msgstr "Nebbia" @@ -26750,7 +26758,7 @@ msgstr "" #: scene/resources/material.cpp msgid "Is sRGB" -msgstr "" +msgstr "È sRGB" #: scene/resources/material.cpp servers/visual_server.cpp #, fuzzy @@ -26868,9 +26876,8 @@ msgid "Flowmap" msgstr "" #: scene/resources/material.cpp -#, fuzzy msgid "Ambient Occlusion" -msgstr "Occlusione" +msgstr "Occlusione ambientale" #: scene/resources/material.cpp msgid "Deep Parallax" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 3abcd5529f..60458e89df 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -487,6 +487,11 @@ msgid "Pressure" msgstr "圧力" #: core/os/input_event.cpp +#, fuzzy +msgid "Pen Inverted" +msgstr "å転" + +#: core/os/input_event.cpp msgid "Relative" msgstr "相対的" @@ -2175,14 +2180,15 @@ msgstr "ãŠæ°—ã«å…¥ã‚Š:" msgid "Recent:" msgstr "最近:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "検索:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "一致:" @@ -2242,8 +2248,8 @@ msgstr "ç½®æ›ã™ã‚‹ãƒªã‚½ãƒ¼ã‚¹ã‚’検索:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2816,7 +2822,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "ノードã®ãƒ‘スをコピー" #: editor/editor_export.cpp @@ -5577,6 +5583,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap ã®é¸æŠž" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "外観" @@ -11772,6 +11782,11 @@ msgid "New Animation" msgstr "æ–°è¦ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "メソッドを絞り込む" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "速度:" @@ -20447,15 +20462,15 @@ msgstr "ã‚ーストアãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "無効ãªå®Ÿè¡Œå¯èƒ½ãƒ•ァイルã§ã™ã€‚" #: platform/windows/export/export.cpp #, fuzzy @@ -20479,15 +20494,15 @@ msgstr "無効ãªåå‰ã§ã™ã€‚" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "無効ãªå®Ÿè¡Œå¯èƒ½ãƒ•ァイルã§ã™ã€‚" #: platform/windows/export/export.cpp #, fuzzy @@ -21573,7 +21588,7 @@ msgstr "トラベル" msgid "Rotation Degrees" msgstr "%s 度回転。" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "コンスタント" @@ -23711,6 +23726,11 @@ msgstr "" "代ã‚りã«ã€åã®è¡çªã‚·ã‚§ã‚¤ãƒ—ã®ã‚µã‚¤ã‚ºã‚’変更ã—ã¦ãã ã•ã„。" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ã‚°ãƒãƒ¼ãƒãƒ« ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ ã‚’ä¿æŒ" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 14599ca68e..2e6e0e70e7 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -466,6 +466,10 @@ msgid "Pressure" msgstr "ზუმის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ–ე დáƒáƒ§áƒ”ნებáƒ" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2191,14 +2195,15 @@ msgstr "სáƒáƒ§áƒ•áƒáƒ ლები:" msgid "Recent:" msgstr "ბáƒáƒšáƒ:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "ძებნáƒ:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "დáƒáƒ›áƒ—ხვევები:" @@ -2260,8 +2265,8 @@ msgstr "ჩáƒáƒ›áƒœáƒáƒªáƒ•ლებელი რესურსის ძიá #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2842,8 +2847,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "მáƒáƒœáƒ˜áƒ¨áƒ•ნის მáƒáƒ¨áƒáƒ ებáƒ" #: editor/editor_export.cpp #, fuzzy @@ -5506,6 +5512,10 @@ msgid "Drag And Drop Selection" msgstr "ყველრმáƒáƒœáƒ˜áƒ¨áƒœáƒ•áƒ" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11723,6 +11733,11 @@ msgid "New Animation" msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ áƒáƒžáƒ¢áƒ˜áƒ›áƒ˜áƒ–áƒáƒªáƒ˜áƒ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ფუნქციები:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20180,15 +20195,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20210,15 +20225,15 @@ msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ." #: platform/windows/export/export.cpp #, fuzzy @@ -21235,7 +21250,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "მუდმივი" @@ -23190,6 +23205,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ დáƒáƒ¥áƒ›áƒœáƒ˜áƒ¡ ცვლილებáƒ" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/km.po b/editor/translations/km.po index 32175987ef..522cb30363 100644 --- a/editor/translations/km.po +++ b/editor/translations/km.po @@ -440,6 +440,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2067,14 +2071,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2130,8 +2135,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2690,8 +2695,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transform" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5265,6 +5271,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11236,6 +11246,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Key(s) ដែលបានជ្រើសស្ទួន" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19304,14 +19319,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19333,14 +19347,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20294,7 +20307,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22117,6 +22130,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transition" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 8800745e09..a91450dd41 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -477,6 +477,10 @@ msgid "Pressure" msgstr "ì••ë ¥" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "ìƒëŒ€ì " @@ -2119,14 +2123,15 @@ msgstr "ì¦ê²¨ì°¾ê¸°:" msgid "Recent:" msgstr "최근 기ë¡:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "검색:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "ì¼ì¹˜í•¨:" @@ -2186,8 +2191,8 @@ msgstr "대체 리소스 검색:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2756,7 +2761,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "íŒŒì¼ ê²½ë¡œ 완성" #: editor/editor_export.cpp @@ -5478,6 +5483,10 @@ msgid "Drag And Drop Selection" msgstr "그리드맵 ì„ íƒ" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "모습" @@ -11677,6 +11686,11 @@ msgid "New Animation" msgstr "새 ì• ë‹ˆë©”ì´ì…˜" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "메서드 í•„í„°" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "ì†ë„:" @@ -20406,15 +20420,15 @@ msgstr "keystore를 ì°¾ì„ ìˆ˜ 없어, 내보낼 수 없었습니다." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "ìž˜ëª»ëœ í™•ìž¥ìž." #: platform/windows/export/export.cpp #, fuzzy @@ -20438,15 +20452,15 @@ msgstr "올바르지 ì•Šì€ ì´ë¦„입니다." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "ìž˜ëª»ëœ í™•ìž¥ìž." #: platform/windows/export/export.cpp #, fuzzy @@ -21542,7 +21556,7 @@ msgstr "ì§„í–‰" msgid "Rotation Degrees" msgstr "%së„로 íšŒì „." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "ìƒìˆ˜" @@ -23666,6 +23680,11 @@ msgstr "" "ëŒ€ì‹ ìžì‹ ì½œë¦¬ì „ ëª¨ì–‘ì˜ í¬ê¸°ë¥¼ 변경하세요." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ì „ì— ë³€í˜• ìœ ì§€" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 51428b68f4..66891e3f0e 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -476,6 +476,10 @@ msgid "Pressure" msgstr "Atstatyti PriartinimÄ…" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2174,14 +2178,15 @@ msgstr "MÄ—gstamiausi:" msgid "Recent:" msgstr "Naujausi:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "IeÅ¡koti:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2237,8 +2242,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2801,8 +2806,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Panaikinti pasirinkimÄ…" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5483,6 +5489,10 @@ msgid "Drag And Drop Selection" msgstr "Visas Pasirinkimas" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11712,6 +11722,11 @@ msgid "New Animation" msgstr "Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrai..." + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20201,15 +20216,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Netinkamas Å¡rifto dydis." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20231,15 +20246,15 @@ msgstr "Netinkamas Å¡rifto dydis." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Netinkamas Å¡rifto dydis." #: platform/windows/export/export.cpp #, fuzzy @@ -21259,7 +21274,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstanta" @@ -23223,6 +23238,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Animacija: Pakeisti TransformacijÄ…" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/lv.po b/editor/translations/lv.po index 0d2e4afec9..c00e8d1a44 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -479,6 +479,10 @@ msgid "Pressure" msgstr "Sagatave" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2169,14 +2173,15 @@ msgstr "FavorÄ«ti:" msgid "Recent:" msgstr "Nesenie:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "MeklÄ“t:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "SakritÄ«bas:" @@ -2236,8 +2241,8 @@ msgstr "MeklÄ“t aizstÄjÄ“ja resursu:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2814,7 +2819,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "KopÄ“t mezgla ceļu" #: editor/editor_export.cpp @@ -5554,6 +5559,10 @@ msgid "Drag And Drop Selection" msgstr "Režģkartes izvÄ“le" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11640,6 +11649,11 @@ msgid "New Animation" msgstr "Jauna animÄcija" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "animÄcija" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20008,15 +20022,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "NederÄ«gs paplaÅ¡inÄjums." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20038,15 +20052,15 @@ msgstr "NederÄ«gs nosaukums." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "NederÄ«gs paplaÅ¡inÄjums." #: platform/windows/export/export.cpp #, fuzzy @@ -21083,7 +21097,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstante" @@ -23065,6 +23079,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "PÄreja eksistÄ“!" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/mk.po b/editor/translations/mk.po index b35fce0168..2d183ec609 100644 --- a/editor/translations/mk.po +++ b/editor/translations/mk.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" -"PO-Revision-Date: 2022-06-29 10:04+0000\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" "Last-Translator: Kristijan Fremen Velkovski <me@krisfremen.com>\n" "Language-Team: Macedonian <https://hosted.weblate.org/projects/godot-engine/" "godot/mk/>\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%10==1 ? 0 : 1;\n" -"X-Generator: Weblate 4.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -444,6 +444,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "GDNative(ГДДомороден)" @@ -1251,7 +1255,7 @@ msgstr "" #: editor/animation_track_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" -msgstr "" +msgstr "Фукнции:" #: editor/animation_track_editor.cpp msgid "Audio Clips:" @@ -1354,33 +1358,33 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Continuous" -msgstr "" +msgstr "Континуирана" #: editor/animation_track_editor.cpp msgid "Discrete" -msgstr "" +msgstr "ДиÑкретна" #: editor/animation_track_editor.cpp msgid "Trigger" -msgstr "" +msgstr "Чкрапало" #: editor/animation_track_editor.cpp scene/3d/baked_lightmap.cpp msgid "Capture" -msgstr "" +msgstr "Снимање" #: editor/animation_track_editor.cpp msgid "Nearest" -msgstr "" +msgstr "ÐајблиÑку" #: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp scene/2d/physics_body_2d.cpp #: scene/3d/physics_body.cpp msgid "Linear" -msgstr "" +msgstr "Линеарна" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "" +msgstr "Кубни" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" @@ -1458,7 +1462,7 @@ msgstr "" #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Create" -msgstr "" +msgstr "Создади" #: editor/animation_track_editor.cpp msgid "Anim Insert" @@ -1759,7 +1763,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Clean-Up" -msgstr "" +msgstr "ОчиÑти" #: editor/animation_track_editor.cpp msgid "Scale Ratio:" @@ -1836,7 +1840,7 @@ msgstr "" #: editor/code_editor.cpp msgid "Replace" -msgstr "" +msgstr "Замени" #: editor/code_editor.cpp msgid "Replace All" @@ -1849,7 +1853,7 @@ msgstr "" #: editor/code_editor.cpp editor/plugins/script_text_editor.cpp #: editor/plugins/text_editor.cpp msgid "Standard" -msgstr "" +msgstr "Стандардно" #: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" @@ -1875,7 +1879,7 @@ msgstr "" #: editor/code_editor.cpp modules/gdscript/gdscript.cpp msgid "Warnings" -msgstr "" +msgstr "Предупредувања" #: editor/code_editor.cpp msgid "Line and column numbers." @@ -1917,7 +1921,7 @@ msgstr "" #: editor/plugins/item_list_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp msgid "Add" -msgstr "" +msgstr "Додади" #: editor/connections_dialog.cpp editor/dependency_editor.cpp #: editor/groups_editor.cpp editor/plugins/animation_player_editor_plugin.cpp @@ -1927,7 +1931,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp #: editor/project_settings_editor.cpp msgid "Remove" -msgstr "" +msgstr "Избриши" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" @@ -1944,11 +1948,11 @@ msgstr "" #: editor/connections_dialog.cpp scene/3d/room_manager.cpp #: servers/visual_server.cpp msgid "Advanced" -msgstr "" +msgstr "Ðапредно" #: editor/connections_dialog.cpp msgid "Deferred" -msgstr "" +msgstr "Одложено" #: editor/connections_dialog.cpp msgid "" @@ -2076,14 +2080,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2139,8 +2144,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2699,7 +2704,7 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "" #: editor/editor_export.cpp @@ -5282,6 +5287,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11264,6 +11273,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "СвојÑтва на анимацијата." + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19349,14 +19363,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19378,14 +19391,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20345,7 +20357,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22175,6 +22187,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Ðнимација Промени Прелаз" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ml.po b/editor/translations/ml.po index b2f6c17059..7568bc881e 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -450,6 +450,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2086,14 +2090,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2149,8 +2154,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2710,8 +2715,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "ചലനം à´šàµà´±àµà´±àµ½" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5298,6 +5304,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11286,6 +11296,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "ചലനം à´šàµà´±àµà´±àµ½" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19388,14 +19403,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19417,14 +19431,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20389,7 +20402,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22247,6 +22260,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ചലനം à´šàµà´±àµà´±àµ½" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/mr.po b/editor/translations/mr.po index d9943d0a5e..4bdf5ba4fb 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -450,6 +450,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2087,14 +2091,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2150,8 +2155,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2710,8 +2715,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5288,6 +5294,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11274,6 +11284,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19389,14 +19404,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19418,14 +19432,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20406,7 +20419,7 @@ msgstr "पà¥à¤°à¤µà¤¾à¤¸" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22268,6 +22281,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "संकà¥à¤°à¤®à¤£: " + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ms.po b/editor/translations/ms.po index a1955bb027..61a60ad8fe 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -451,6 +451,10 @@ msgid "Pressure" msgstr "Tekanan" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relatif" @@ -2097,14 +2101,15 @@ msgstr "Kegemaran:" msgid "Recent:" msgstr "Terkini:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Cari:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Padanan:" @@ -2164,8 +2169,8 @@ msgstr "Cari Penggantian Sumber:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2740,8 +2745,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Salin Pilihan" #: editor/editor_export.cpp #, fuzzy @@ -5547,6 +5553,10 @@ msgid "Drag And Drop Selection" msgstr "Semua Pilihan" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11729,6 +11739,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Padam Animasi?" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20212,15 +20227,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Nama kumpulan tidak sah." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20242,15 +20257,15 @@ msgstr "Nama tidak sah." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Nama kumpulan tidak sah." #: platform/windows/export/export.cpp #, fuzzy @@ -21295,7 +21310,7 @@ msgstr "Perjalanan" msgid "Rotation Degrees" msgstr "Langkah Putaran:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Pemalar" @@ -23297,6 +23312,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Kosongkan Transformasi" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 11bf857f4b..542d5987ca 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -473,6 +473,10 @@ msgid "Pressure" msgstr "Trykk" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativ" @@ -2201,14 +2205,15 @@ msgstr "Favoritter:" msgid "Recent:" msgstr "Nylige:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Søk:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Treff:" @@ -2270,8 +2275,8 @@ msgstr "Søk Erstatningsressurs:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2871,7 +2876,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Kopier Node-bane" #: editor/editor_export.cpp @@ -5731,6 +5736,10 @@ msgid "Drag And Drop Selection" msgstr "Slett Valgte" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12211,6 +12220,11 @@ msgstr "Animasjon" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy +msgid "Filter animations" +msgstr "Lim inn Noder" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy msgid "Speed:" msgstr "Hastighet (FPS):" @@ -21035,15 +21049,15 @@ msgstr "Kunne ikke opprette mappe." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "MÃ¥ ha en gyldig filutvidelse." #: platform/windows/export/export.cpp #, fuzzy @@ -21067,15 +21081,15 @@ msgstr "Ugyldig navn." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "MÃ¥ ha en gyldig filutvidelse." #: platform/windows/export/export.cpp #, fuzzy @@ -22145,7 +22159,7 @@ msgstr "Reise" msgid "Rotation Degrees" msgstr "Roterer %s grader." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstant" @@ -24190,6 +24204,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Nullstill Transformasjon" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index def707ac8b..aaa0f38a1d 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -547,6 +547,10 @@ msgid "Pressure" msgstr "Voorinstellingen" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Relatief kleven" @@ -2266,14 +2270,15 @@ msgstr "Favorieten:" msgid "Recent:" msgstr "Onlangs:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Zoeken:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Overeenkomsten:" @@ -2333,8 +2338,8 @@ msgstr "Bronvervanging zoeken:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2911,7 +2916,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Knooppad kopiëren" #: editor/editor_export.cpp @@ -5724,6 +5729,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap-selectie vullen" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12064,6 +12073,11 @@ msgid "New Animation" msgstr "Nieuwe animatie" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filter methoden" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Snelheid:" @@ -20922,15 +20936,15 @@ msgstr "Kon template niet openen voor export:" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Ongeldige extentie." #: platform/windows/export/export.cpp #, fuzzy @@ -20954,15 +20968,15 @@ msgstr "Ongeldige naam." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Ongeldige extentie." #: platform/windows/export/export.cpp #, fuzzy @@ -22069,7 +22083,7 @@ msgstr "Verplaats" msgid "Rotation Degrees" msgstr "Roteren %s graden." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constante" @@ -24184,6 +24198,11 @@ msgstr "" "Verander in plaats daarvan de grootte van de onderliggende botsingsvormen." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Houd Globale Transformatie" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index 9fdaafae3e..3e4664c317 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -62,13 +62,14 @@ # Pixel Zone - Godot Engine Tutorials <karoltomaszewskimusic@gmail.com>, 2022. # DK0492 <doriankaczmarek28@gmail.com>, 2022. # Dawid Skubij <davidsd@tlen.pl>, 2022. +# kingofsponges <q.patex.q@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-05 23:51+0000\n" -"Last-Translator: Dawid Skubij <davidsd@tlen.pl>\n" +"PO-Revision-Date: 2022-08-04 06:38+0000\n" +"Last-Translator: kingofsponges <q.patex.q@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" "Language: pl\n" @@ -77,7 +78,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -270,7 +271,7 @@ msgstr "Sieć" #: core/io/file_access_network.cpp msgid "Remote FS" -msgstr "Zdalny System Plików" +msgstr "Zdalny System Plików" #: core/io/file_access_network.cpp msgid "Page Size" @@ -338,7 +339,7 @@ msgstr "CzÅ‚onek transmisji" #: core/io/stream_peer.cpp msgid "Big Endian" -msgstr "" +msgstr "Big endian" #: core/io/stream_peer.cpp msgid "Data Array" @@ -368,9 +369,8 @@ msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "NiewystarczajÄ…ca ilość bajtów dla bajtów dekodujÄ…cych lub zÅ‚y format." #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" -msgstr "NiewÅ‚aÅ›ciwe dane %i (nie przekazane) w wyrażeniu" +msgstr "NiewÅ‚aÅ›ciwe dane %d (nie przekazane) w wyrażeniu" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -415,14 +415,12 @@ msgid "Max Size (KB)" msgstr "Maks. rozmiar (KB)" #: core/os/input.cpp -#, fuzzy msgid "Mouse Mode" -msgstr "Tryb przesuwania" +msgstr "Tryb myszki" #: core/os/input.cpp -#, fuzzy msgid "Use Accumulated Input" -msgstr "UsuÅ„ WejÅ›cie" +msgstr "Użyj skumulowanego wejÅ›cia" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -450,9 +448,8 @@ msgid "Command" msgstr "Command" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (fizyczny)" +msgstr "Fizyczny" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -502,11 +499,15 @@ msgstr "Pochylenie" #: core/os/input_event.cpp msgid "Pressure" -msgstr "CiÅ›nienie" +msgstr "Nacisk" + +#: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Odwrócone pióro" #: core/os/input_event.cpp msgid "Relative" -msgstr "Relatywny" +msgstr "WzglÄ™dny" #: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp @@ -641,9 +642,8 @@ msgstr "WÅ‚asna nazwa katalogu użytkownika" #: core/project_settings.cpp main/main.cpp #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #: platform/uwp/os_uwp.cpp -#, fuzzy msgid "Display" -msgstr "Pokaż wszystko" +msgstr "WyÅ›wietlanie" #: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp #: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp @@ -657,23 +657,20 @@ msgstr "Szerokość" #: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp #: scene/resources/font.cpp scene/resources/navigation_mesh.cpp #: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp -#, fuzzy msgid "Height" -msgstr "ÅšwiatÅ‚o" +msgstr "Wysokość" #: core/project_settings.cpp msgid "Always On Top" msgstr "Zawsze na wierzchu" #: core/project_settings.cpp -#, fuzzy msgid "Test Width" -msgstr "RozciÄ…gnij po lewej" +msgstr "Szerokość testowa" #: core/project_settings.cpp -#, fuzzy msgid "Test Height" -msgstr "Testowanie" +msgstr "Wysokość testowa" #: core/project_settings.cpp editor/animation_track_editor.cpp #: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp @@ -696,9 +693,8 @@ msgid "Main Run Args" msgstr "Główne argumenty włączania" #: core/project_settings.cpp -#, fuzzy msgid "Scene Naming" -msgstr "Åšcieżka sceny:" +msgstr "Nazywanie scen" #: core/project_settings.cpp msgid "Search In File Extensions" @@ -709,14 +705,12 @@ msgid "Script Templates Search Path" msgstr "Åšcieżka wyszukiwania szablonów skryptów" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "Automatyczne Å‚adowanie podczas uruchamiania" +msgstr "Automatyczne Å‚adowanie kontroli wersji podczas uruchamiania" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Plugin Name" -msgstr "Kontrola wersji" +msgstr "Nazwa wtyczki kontroli wersji" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -1201,7 +1195,7 @@ msgstr "IloÅ›c:" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp msgid "Args" -msgstr "" +msgstr "Argumenty" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp @@ -1225,7 +1219,7 @@ msgstr "Ustaw uchwyt" #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp msgid "Stream" -msgstr "" +msgstr "StrumieÅ„" #: editor/animation_track_editor.cpp #, fuzzy @@ -2173,14 +2167,15 @@ msgstr "Ulubione:" msgid "Recent:" msgstr "Ostatnie:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Szukaj:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "PasujÄ…ce:" @@ -2240,8 +2235,8 @@ msgstr "Szukaj zastÄ™pczego zasobu:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2250,7 +2245,7 @@ msgstr "Otwórz" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "WÅ‚aÅ›ciciele: %s (Suma: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2810,11 +2805,11 @@ msgstr "Wybierz" #: editor/editor_export.cpp msgid "Project export for platform:" -msgstr "" +msgstr "Eksportowanie projektu dla platformy:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Skopiuj Å›cieżkÄ™ wÄ™zÅ‚a" #: editor/editor_export.cpp @@ -2840,14 +2835,12 @@ msgid "Packing" msgstr "Pakowanie" #: editor/editor_export.cpp -#, fuzzy msgid "Save PCK" -msgstr "Zapisz jako" +msgstr "Zapisz plik PCK" #: editor/editor_export.cpp -#, fuzzy msgid "Cannot create file \"%s\"." -msgstr "Nie można utworzyć katalogu." +msgstr "Nie można utworzyć pliku \"%s\"." #: editor/editor_export.cpp #, fuzzy @@ -5505,7 +5498,7 @@ msgstr "Miniatura..." #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "Doki" #: editor/editor_settings.cpp #, fuzzy @@ -5626,6 +5619,10 @@ msgid "Drag And Drop Selection" msgstr "Wybór GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "WyglÄ…d" @@ -7123,7 +7120,7 @@ msgstr "" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "sRGB" -msgstr "" +msgstr "sRGB" #: editor/import/resource_importer_layered_texture.cpp #, fuzzy @@ -7441,7 +7438,7 @@ msgstr "" #: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp #: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp msgid "Normal Map" -msgstr "" +msgstr "Mapa normalnych" #: editor/import/resource_importer_texture.cpp #, fuzzy @@ -9851,7 +9848,7 @@ msgstr "Utwórz obrys" #: scene/resources/multimesh.cpp scene/resources/primitive_meshes.cpp #: scene/resources/texture.cpp msgid "Mesh" -msgstr "Siatka" +msgstr "Mesh" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -11899,6 +11896,11 @@ msgid "New Animation" msgstr "Nowa animacja" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtruj metody" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Szybkość:" @@ -17095,9 +17097,8 @@ msgstr "GDNative" #: modules/gdscript/editor/gdscript_highlighter.cpp #: modules/gdscript/gdscript.cpp -#, fuzzy msgid "GDScript" -msgstr "Skrypt" +msgstr "GDScript" #: modules/gdscript/editor/gdscript_highlighter.cpp msgid "Function Definition Color" @@ -19304,9 +19305,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension." msgstr "NieprawidÅ‚owa nazwa pliku! APK Androida wymaga rozszerzenia *.apk." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Unsupported export format!" -msgstr "NieobsÅ‚ugiwany format eksportu!\n" +msgstr "NieobsÅ‚ugiwany format eksportu!" #: platform/android/export/export_plugin.cpp msgid "" @@ -19336,9 +19336,8 @@ msgstr "" "projektu" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "Nie udaÅ‚o siÄ™ eksportować plików projektu do projektu gradle\n" +msgstr "Nie udaÅ‚o siÄ™ eksportować plików projektu do projektu gradle." #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -20267,9 +20266,8 @@ msgid "ZIP Creation" msgstr "Projekt" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open file to read from path \"%s\"." -msgstr "Nie udaÅ‚o siÄ™ eksportować plików projektu do projektu gradle\n" +msgstr "Nie udaÅ‚o siÄ™ otworzyć pliku do odczytu ze Å›cieżki \"%s\"." #: platform/osx/export/export.cpp msgid "Invalid bundle identifier:" @@ -20689,17 +20687,17 @@ msgstr "Nie udaÅ‚o siÄ™ znaleźć keystore, nie można eksportować." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "NarzÄ™dzie rcedit musi być skonfigurowane w Ustawieniach edytora (Eksport > " "Windows > Rcedit), aby zmienić ikonÄ™ lub dane informacji o aplikacji." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Niepoprawny plik wykonywalny." #: platform/windows/export/export.cpp #, fuzzy @@ -20724,17 +20722,17 @@ msgstr "NiewÅ‚aÅ›ciwa nazwa." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "NarzÄ™dzie rcedit musi być skonfigurowane w Ustawieniach edytora (Eksport > " "Windows > Rcedit), aby zmienić ikonÄ™ lub dane informacji o aplikacji." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Niepoprawny plik wykonywalny." #: platform/windows/export/export.cpp #, fuzzy @@ -21255,26 +21253,23 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp -#, fuzzy msgid "One Shot" -msgstr "Jednorazowy WÄ™zeÅ‚" +msgstr "Wyemituj raz" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Preprocess" -msgstr "Przetwarzanie koÅ„cowe" +msgstr "Przetwarzanie wstÄ™pne" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Explosiveness" -msgstr "" +msgstr "Wybuchowość" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Randomness" -msgstr "Losowy restart (s):" +msgstr "Losowość" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21849,7 +21844,7 @@ msgstr "Przejdź" msgid "Rotation Degrees" msgstr "Obracanie o %s stopni." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "StaÅ‚a globalna" @@ -21963,9 +21958,8 @@ msgstr "" "\"Particles Animation\"." #: scene/2d/particles_2d.cpp -#, fuzzy msgid "Visibility Rect" -msgstr "Tryb priorytetów" +msgstr "ProstokÄ…t widocznoÅ›ci" #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "Process Material" @@ -24000,6 +23994,11 @@ msgstr "" "Zamiast tego, zmieÅ„ rozmiary ksztaÅ‚tów kolizji w wÄ™zÅ‚ach podrzÄ™dnych." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Zachowaj globalnÄ… transformacjÄ™" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -24916,7 +24915,7 @@ msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Caret" -msgstr "" +msgstr "Karetka" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index d0e041aba9..4c073f8542 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -470,6 +470,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2161,14 +2165,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2224,8 +2229,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2794,7 +2799,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Forge yer Node!" #: editor/editor_export.cpp @@ -5470,6 +5475,10 @@ msgid "Drag And Drop Selection" msgstr "Yar, Blow th' Selected Down!" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11701,6 +11710,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Paste yer Node" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20249,15 +20263,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Yer Calligraphy be wrongly sized." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20279,15 +20293,15 @@ msgstr "Yer Calligraphy be wrongly sized." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Yer Calligraphy be wrongly sized." #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -21300,7 +21314,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Rename Variable" @@ -23249,6 +23263,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Change yer Anim Transform" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/pt.po b/editor/translations/pt.po index edbc6971fb..f284e0ece8 100644 --- a/editor/translations/pt.po +++ b/editor/translations/pt.po @@ -24,13 +24,15 @@ # Renu <ifpilucas@gmail.com>, 2022. # El_ExpertPlayer <xpertnathan37@gmail.com>, 2022. # Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>, 2022. +# Ednaldo Pereira Confia <filat51823@storypo.com>, 2022. +# Zé Beato Página Oficial <zebeato@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-06-29 10:04+0000\n" -"Last-Translator: Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" +"Last-Translator: Zé Beato Página Oficial <zebeato@gmail.com>\n" "Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/" "godot/pt/>\n" "Language: pt\n" @@ -38,7 +40,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -463,6 +465,10 @@ msgid "Pressure" msgstr "Pressione" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativo" @@ -2104,14 +2110,15 @@ msgstr "Favoritos:" msgid "Recent:" msgstr "Recente:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Procurar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Correspondências:" @@ -2171,8 +2178,8 @@ msgstr "Procurar Recurso de substituição:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2293,7 +2300,6 @@ msgstr "Desenvolvedor-chefe" #. TRANSLATORS: This refers to a job title. #: editor/editor_about.cpp -#, fuzzy msgctxt "Job Title" msgid "Project Manager" msgstr "Gestor de Projetos" @@ -2540,9 +2546,8 @@ msgid "There is no '%s' file." msgstr "Não existe ficheiro '%s'." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Layout:" -msgstr "Esquema" +msgstr "Esquema:" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." @@ -2591,9 +2596,8 @@ msgid "Create a new Bus Layout." msgstr "Criar um novo Modelo de Barramento." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Audio Bus Layout" -msgstr "Abrir Modelo de barramento de áudio" +msgstr "Modelo de barramento de áudio" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -2751,17 +2755,16 @@ msgstr "Exportação do projeto para plataforma:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." -msgstr "Copiar Caminho do Nó" +msgid "Completed with warnings." +msgstr "ConcluÃdo com erros." #: editor/editor_export.cpp msgid "Completed successfully." -msgstr "Completado com sucesso." +msgstr "ConcluÃdo com sucesso." #: editor/editor_export.cpp -#, fuzzy msgid "Failed." -msgstr "Falhou:" +msgstr "Falhou." #: editor/editor_export.cpp msgid "Storing File:" @@ -2931,9 +2934,8 @@ msgid "The given export path doesn't exist." msgstr "O caminho de exportação não existe:" #: editor/editor_export.cpp platform/javascript/export/export.cpp -#, fuzzy msgid "Template file not found: \"%s\"." -msgstr "Ficheiro Modelo não encontrado:" +msgstr "Ficheiro Modelo não encontrado" #: editor/editor_export.cpp #, fuzzy @@ -5538,6 +5540,10 @@ msgid "Drag And Drop Selection" msgstr "Seleção de GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "Aparência" @@ -11721,6 +11727,11 @@ msgid "New Animation" msgstr "Nova Animação" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Métodos de filtro" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocidade:" @@ -20398,15 +20409,15 @@ msgstr "Incapaz de encontrar keystore e exportar." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Extensão inválida." #: platform/windows/export/export.cpp #, fuzzy @@ -20430,15 +20441,15 @@ msgstr "Nome inválido." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Extensão inválida." #: platform/windows/export/export.cpp #, fuzzy @@ -21543,7 +21554,7 @@ msgstr "Viagem" msgid "Rotation Degrees" msgstr "Graus de Rotação" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constante Global" @@ -23681,6 +23692,11 @@ msgstr "" "Em vez disso, mude o tamanho das formas de colisão filhas." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Manter Transformação Global" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 41301db983..84a5ac45c3 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -127,7 +127,7 @@ # Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>, 2021. # jak3z <jose_renato06@outlook.com>, 2021. # Henrique Darko <henridark00@gmail.com>, 2021. -# Cearaj <pmoraisleal@gmail.com>, 2021. +# Cearaj <pmoraisleal@gmail.com>, 2021, 2022. # Alefy San <alefyferreiradeoliveira@outlook.com>, 2021. # Joel Gomes da Silva <joelgomes1994@hotmail.com>, 2021, 2022. # Orangotango De tanga <luizinho0045@gmail.com>, 2021. @@ -141,13 +141,16 @@ # José Miranda Neto <dodimi95@gmail.com>, 2022. # lucas rossy brasil coelho <lucasrossy270@gmail.com>, 2022. # Kaycke <kaycke@ymail.com>, 2022. +# Ednaldo Pereira Confia <filat51823@storypo.com>, 2022. +# Mauricio <mauricio.fidalgo1@gmail.com>, 2022. +# Felipe Kinoshita <kinofhek@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2022-06-29 10:04+0000\n" -"Last-Translator: Douglas Leão <djlsplays@gmail.com>\n" +"PO-Revision-Date: 2022-08-04 06:38+0000\n" +"Last-Translator: Felipe Kinoshita <kinofhek@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -155,7 +158,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -360,7 +363,7 @@ msgstr "Página lida adiante" #: core/io/http_client.cpp msgid "Blocking Mode Enabled" -msgstr "Modo de bloqueio ativado" +msgstr "Modo de Bloqueio Ativado" #: core/io/http_client.cpp msgid "Connection" @@ -524,9 +527,8 @@ msgid "Command" msgstr "Comando" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (FÃsico)" +msgstr "FÃsico" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -579,6 +581,10 @@ msgid "Pressure" msgstr "Pressão" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Caneta Invertida (\"Borracha\")" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativo" @@ -715,7 +721,6 @@ msgstr "Nome do Diretório de Usuário Personalizado" #: core/project_settings.cpp main/main.cpp #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #: platform/uwp/os_uwp.cpp -#, fuzzy msgid "Display" msgstr "Exibição" @@ -739,14 +744,12 @@ msgid "Always On Top" msgstr "Sempre no topo" #: core/project_settings.cpp -#, fuzzy msgid "Test Width" msgstr "Largura de teste" #: core/project_settings.cpp -#, fuzzy msgid "Test Height" -msgstr "Teste de altura" +msgstr "Altura de teste" #: core/project_settings.cpp editor/animation_track_editor.cpp #: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp @@ -781,9 +784,8 @@ msgid "Script Templates Search Path" msgstr "Caminho de Pesquisa de Modelos de Script" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "Carregamento Automático na Inicialização" +msgstr "Carregamento Automático do Controle de Versão na Inicialização" #: core/project_settings.cpp msgid "Version Control Plugin Name" @@ -1091,9 +1093,8 @@ msgstr "Encaixe inteligente" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Use GPU Pixel Snap" -msgstr "Usar Encaixe de Pixel" +msgstr "Usar Encaixe de Pixels da GPU" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp @@ -1120,7 +1121,7 @@ msgstr "Máximo de luzes renderizáveis" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Reflections" -msgstr "Reflexões máximas renderizáveis" +msgstr "Máximo de Reflexões Renderizáveis" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Lights Per Object" @@ -1278,14 +1279,12 @@ msgid "Type" msgstr "Tipo" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "Definir Manipulador" +msgstr "Manipulador de Entrada" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out Handle" -msgstr "Definir Manipulador" +msgstr "Manipulador de SaÃda" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp @@ -1296,11 +1295,11 @@ msgstr "Fluxo" #: editor/animation_track_editor.cpp msgid "Start Offset" -msgstr "Iniciar deslocamento" +msgstr "Deslocamento Inicial" #: editor/animation_track_editor.cpp msgid "End Offset" -msgstr "Terminar deslocamento" +msgstr "Deslocamento Final" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/import/resource_importer_scene.cpp @@ -1313,9 +1312,8 @@ msgid "Animation" msgstr "Animação" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing" -msgstr "Facilitar Entrada-SaÃda" +msgstr "Suavização" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" @@ -1450,32 +1448,28 @@ msgid "Type:" msgstr "Tipo:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "(Invalid, expected type: %s)" -msgstr "Template de exportação inválido:" +msgstr "(Inválido, tipo esperado: %s)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing:" -msgstr "Facilitar Entrada-SaÃda" +msgstr "Suavizar:" #: editor/animation_track_editor.cpp msgid "In-Handle:" -msgstr "Definir Manipulador:" +msgstr "Manipulador de Entrada:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out-Handle:" -msgstr "Definir Manipulador:" +msgstr "Manipulador de SaÃda:" #: editor/animation_track_editor.cpp msgid "Stream:" msgstr "Transmissão:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "InÃcio(s):" +msgstr "InÃcio (s):" #: editor/animation_track_editor.cpp msgid "End (s):" @@ -1571,9 +1565,8 @@ msgid "Editors" msgstr "Editores" #: editor/animation_track_editor.cpp editor/editor_settings.cpp -#, fuzzy msgid "Confirm Insert Track" -msgstr "Inserir Trilha e Chave na Anim" +msgstr "Confirmar Inserção de Trilha" #. TRANSLATORS: %s will be replaced by a phrase describing the target of track. #: editor/animation_track_editor.cpp @@ -2114,7 +2107,7 @@ msgstr "" #: editor/connections_dialog.cpp scene/resources/texture.cpp msgid "Oneshot" -msgstr "Oneshot" +msgstr "Só Uma Vez" #: editor/connections_dialog.cpp msgid "Disconnects the signal after its first emission." @@ -2233,14 +2226,15 @@ msgstr "Favoritos:" msgid "Recent:" msgstr "Recente:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Pesquisar:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Correspondências:" @@ -2300,8 +2294,8 @@ msgstr "Buscar Recurso para Substituição:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2424,7 +2418,7 @@ msgstr "Desenvolvedor-chefe" #: editor/editor_about.cpp msgctxt "Job Title" msgid "Project Manager" -msgstr "Gerenciador de Projeto" +msgstr "Gestor de Projeto" #: editor/editor_about.cpp msgid "Developers" @@ -2667,9 +2661,8 @@ msgid "There is no '%s' file." msgstr "Não existe o arquivo '%s'." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Layout:" -msgstr "Layout" +msgstr "Layout:" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." @@ -2718,9 +2711,8 @@ msgid "Create a new Bus Layout." msgstr "Criar um novo Layout de Canais." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Audio Bus Layout" -msgstr "Abrir Layout de Canais de Ãudio" +msgstr "Layout de Canais de Ãudio" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -2876,7 +2868,8 @@ msgid "Project export for platform:" msgstr "Exportação do projeto para plataforma:" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "ConcluÃdo com erros." #: editor/editor_export.cpp @@ -2900,14 +2893,12 @@ msgid "Packing" msgstr "Empacotando" #: editor/editor_export.cpp -#, fuzzy msgid "Save PCK" -msgstr "Salvar Como" +msgstr "Salvar PCK" #: editor/editor_export.cpp -#, fuzzy msgid "Cannot create file \"%s\"." -msgstr "Não foi possÃvel criar a pasta." +msgstr "Não foi possÃvel criar arquivo \"%s\"." #: editor/editor_export.cpp msgid "Failed to export project files." @@ -2918,9 +2909,8 @@ msgid "Can't open file to read from path \"%s\"." msgstr "Não é possÃvel abrir arquivo para leitura a partir do caminho \"%s\"." #: editor/editor_export.cpp -#, fuzzy msgid "Save ZIP" -msgstr "Salvar Como" +msgstr "Salvar ZIP" #: editor/editor_export.cpp msgid "" @@ -3002,12 +2992,11 @@ msgstr "64 Bits" #: editor/editor_export.cpp msgid "Embed PCK" -msgstr "Incorporar PCK" +msgstr "PCK Incorporado" #: editor/editor_export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Texture Format" -msgstr "Região da Textura" +msgstr "Formato da Textura" #: editor/editor_export.cpp msgid "BPTC" @@ -3026,9 +3015,8 @@ msgid "ETC2" msgstr "ETC2" #: editor/editor_export.cpp -#, fuzzy msgid "No BPTC Fallbacks" -msgstr "Forçar Fallbacks do Shader" +msgstr "Sem Fallbacks para imagens BPTC" #: editor/editor_export.cpp platform/android/export/export_plugin.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -3040,12 +3028,11 @@ msgstr "Modelo customizado de depuração não encontrado." #: 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 "Template customizado de release não encontrado." +msgstr "Modelo customizado de lançamento não encontrado." #: editor/editor_export.cpp -#, fuzzy msgid "Prepare Template" -msgstr "Gerenciar Templates" +msgstr "Preparar Modelo" #: editor/editor_export.cpp platform/osx/export/export.cpp msgid "The given export path doesn't exist." @@ -3061,9 +3048,8 @@ msgstr "Falha ao copiar o modelo de exportação." #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp -#, fuzzy msgid "PCK Embedding" -msgstr "Preenchimento" +msgstr "Incorporação de PCK" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." @@ -3278,9 +3264,8 @@ msgid "Manage Editor Feature Profiles" msgstr "Gerenciar perfis de recurso do editor" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Default Feature Profile" -msgstr "Perfil de funcionalidade do Godot" +msgstr "Perfil de funcionalidade Padrão" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -3686,9 +3671,8 @@ msgid "Property:" msgstr "Propriedade:" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp -#, fuzzy msgid "Label" -msgstr "Valor" +msgstr "Rótulo" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp #: scene/resources/default_theme/default_theme.cpp @@ -4072,18 +4056,16 @@ msgid "Quick Open Script..." msgstr "Abrir Script Rapidamente..." #: editor/editor_node.cpp -#, fuzzy msgid "Save & Reload" -msgstr "Salvar e Reiniciar" +msgstr "Salvar & Recarregar" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to '%s' before reloading?" -msgstr "Salvar alterações em '%s' antes de fechar?" +msgstr "Salvar alterações em '%s' antes de recarregar?" #: editor/editor_node.cpp msgid "Save & Close" -msgstr "Salvar e Fechar" +msgstr "Salvar & Fechar" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" @@ -4198,9 +4180,8 @@ msgid "Open Project Manager?" msgstr "Abrir Gerenciador de Projetos?" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to the following scene(s) before reloading?" -msgstr "Salvar alterações na(s) seguinte(s) cena(s) antes de sair?" +msgstr "Salvar alterações na(s) seguinte(s) cena(s) antes de recarregar?" #: editor/editor_node.cpp msgid "Save & Quit" @@ -4406,13 +4387,12 @@ msgid "Scene Tabs" msgstr "Abas de Cena" #: editor/editor_node.cpp -#, fuzzy msgid "Always Show Close Button" -msgstr "Sempre Mostrar Grade" +msgstr "Sempre Exibir o Botão de Fechar" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Resize If Many Tabs" -msgstr "Redimensionar se houver muitas guias" +msgstr "Redimensionar se Houver Muitas Guias" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Minimum Width" @@ -4423,9 +4403,8 @@ msgid "Output" msgstr "SaÃda" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Always Clear Output On Play" -msgstr "Limpar SaÃda" +msgstr "Sempre limpar saÃda ao jogar" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Open Output On Play" @@ -4440,19 +4419,16 @@ msgid "Save On Focus Loss" msgstr "Salvar em caso de perda de foco" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Save Each Scene On Quit" -msgstr "Salvar Ramo como Cena" +msgstr "Salvar cada cena ao sair" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Quit Confirmation" -msgstr "Visualizar Informações" +msgstr "Confirmação de saÃda" #: editor/editor_node.cpp -#, fuzzy msgid "Show Update Spinner" -msgstr "Ocultar Spinner de Atualização" +msgstr "Mostrar Spinner de Atualização" #: editor/editor_node.cpp msgid "Update Continuously" @@ -4479,18 +4455,16 @@ msgid "Inspector" msgstr "Inspetor" #: editor/editor_node.cpp -#, fuzzy msgid "Default Property Name Style" -msgstr "Caminho Padrão do Projeto" +msgstr "Estilo de Nome de Propriedade Padrão" #: editor/editor_node.cpp msgid "Default Float Step" msgstr "Passo de ponto flutuante padrão" #: editor/editor_node.cpp scene/gui/tree.cpp -#, fuzzy msgid "Disable Folding" -msgstr "Botão Desativado" +msgstr "Desativar Dobragem" #: editor/editor_node.cpp msgid "Auto Unfold Foreign Scenes" @@ -4502,21 +4476,19 @@ msgstr "Edição Horizontal do Vector2" #: editor/editor_node.cpp msgid "Horizontal Vector Types Editing" -msgstr "" +msgstr "Edição Horizontal de Tipos de Vetor" #: editor/editor_node.cpp -#, fuzzy msgid "Open Resources In Current Inspector" -msgstr "Abrir no inspetor" +msgstr "Abrir Recursos no Inspetor Atual" #: editor/editor_node.cpp -#, fuzzy msgid "Resources To Open In New Inspector" -msgstr "Abrir no inspetor" +msgstr "Recursos para abrir em Novo Inspetor" #: editor/editor_node.cpp msgid "Default Color Picker Mode" -msgstr "" +msgstr "Modo de Seletor de Cores Padrão" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Version Control" @@ -5127,7 +5099,7 @@ msgstr "Tempo Médio (ms)" #: editor/editor_profiler.cpp msgid "Frame %" -msgstr "Frame %" +msgstr "Quadro %" #: editor/editor_profiler.cpp msgid "Physics Frame %" @@ -5172,12 +5144,11 @@ msgstr "Depurador" #: editor/editor_profiler.cpp msgid "Profiler Frame History Size" -msgstr "" +msgstr "Tamanho de histórico disponÃvel no \"Profiler\"" #: editor/editor_profiler.cpp -#, fuzzy msgid "Profiler Frame Max Functions" -msgstr "Renomear Função" +msgstr "Máximo de funções por quadro no \"Profiler\"" #: editor/editor_properties.cpp msgid "Edit Text:" @@ -5310,20 +5281,17 @@ msgstr "Novo %s" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Base Type" -msgstr "Mudar Tipo Base" +msgstr "Tipo Base" #: editor/editor_resource_picker.cpp -#, fuzzy msgid "Edited Resource" -msgstr "Adicionar Recurso" +msgstr "Recurso Editado" #: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp #: scene/gui/slider.cpp scene/gui/spin_box.cpp -#, fuzzy msgid "Editable" -msgstr "Item Editável" +msgstr "Editável" #: editor/editor_resource_picker.cpp editor/property_editor.cpp msgid "New Script" @@ -5349,9 +5317,8 @@ msgstr "" "predefinição existente como executável." #: editor/editor_run_native.cpp -#, fuzzy msgid "Project Run" -msgstr "Projeto" +msgstr "Executar Projeto" #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." @@ -5378,73 +5345,68 @@ msgid "Did you forget the '_run' method?" msgstr "Você esqueceu o método '_run'?" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor Language" -msgstr "Layout do Editor" +msgstr "Linguagem do Editor" #: editor/editor_settings.cpp -#, fuzzy msgid "Display Scale" -msgstr "Exibir Tudo" +msgstr "Escala de Exibição" #: editor/editor_settings.cpp msgid "Custom Display Scale" -msgstr "" +msgstr "Escala de Exibição Customizada" #: editor/editor_settings.cpp msgid "Main Font Size" -msgstr "" +msgstr "Tamanho de Fonte Principal" #: editor/editor_settings.cpp msgid "Code Font Size" -msgstr "" +msgstr "Tamanho de Fonte (Tipo) no Código" #: editor/editor_settings.cpp msgid "Font Antialiased" -msgstr "" +msgstr "Fonte Com Serrilhado Suavizado" #: editor/editor_settings.cpp msgid "Font Hinting" -msgstr "" +msgstr "Suavização de Fonte" #: editor/editor_settings.cpp -#, fuzzy msgid "Main Font" -msgstr "Cena Principal" +msgstr "Fonte Principal" #: editor/editor_settings.cpp msgid "Main Font Bold" -msgstr "" +msgstr "Fonte Principal (Negrito)" #: editor/editor_settings.cpp -#, fuzzy msgid "Code Font" -msgstr "Adicionar Ponto de Nó" +msgstr "Fonte para Código" #: editor/editor_settings.cpp msgid "Dim Editor On Dialog Popup" -msgstr "" +msgstr "Escurecer o Editor ao Abir Janela Popup" #: editor/editor_settings.cpp main/main.cpp msgid "Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Tempo de Espera em Modo de Hibernação (µseg)" #: editor/editor_settings.cpp msgid "Unfocused Low Processor Mode Sleep (µsec)" -msgstr "" +msgstr "Tempo de Espera em Modo de Hibernação Quando Fora de Foco (µseg)" #: editor/editor_settings.cpp -#, fuzzy msgid "Separate Distraction Mode" -msgstr "Modo Sem Distrações" +msgstr "Modo \"Sem Distrações\" Desacoplado" #: editor/editor_settings.cpp msgid "Automatically Open Screenshots" -msgstr "" +msgstr "Abrir Capturas de Tela Automaticamente" #: editor/editor_settings.cpp msgid "Max Array Dictionary Items Per Page" -msgstr "" +msgstr "Máximo de Itens em Arrays Dicionários Por Página" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp @@ -5458,59 +5420,51 @@ msgstr "Predefinição" #: editor/editor_settings.cpp msgid "Icon And Font Color" -msgstr "" +msgstr "Cor da Fonte e do Ãcone" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Color" -msgstr "Cores" +msgstr "Cor Base" #: editor/editor_settings.cpp -#, fuzzy msgid "Accent Color" -msgstr "Escolher Cor" +msgstr "Cor de Destaque" #: editor/editor_settings.cpp scene/resources/environment.cpp msgid "Contrast" -msgstr "" +msgstr "Contraste" #: editor/editor_settings.cpp msgid "Relationship Line Opacity" -msgstr "" +msgstr "Opacidade da Linha de Relacionamento" #: editor/editor_settings.cpp -#, fuzzy msgid "Highlight Tabs" -msgstr "Salvando mapas de luz" +msgstr "Abas de Destaque" #: editor/editor_settings.cpp -#, fuzzy msgid "Border Size" -msgstr "Pixels de Borda" +msgstr "Tamanho da Borda" #: editor/editor_settings.cpp msgid "Use Graph Node Headers" -msgstr "" +msgstr "Utilizar Cabeçalhos de Nós para Gráficos" #: editor/editor_settings.cpp -#, fuzzy msgid "Additional Spacing" -msgstr "Loop da Animação" +msgstr "Espaçamento Adicional" #: editor/editor_settings.cpp -#, fuzzy msgid "Custom Theme" -msgstr "Tema do Editor" +msgstr "Tema Personalizado" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Script Button" -msgstr "Botão direito da roda" +msgstr "Botão de Exibir Script" #: editor/editor_settings.cpp -#, fuzzy msgid "Directories" -msgstr "Direções" +msgstr "Diretórios" #: editor/editor_settings.cpp msgid "Autoscan Project Path" @@ -5521,23 +5475,20 @@ msgid "Default Project Path" msgstr "Caminho Padrão do Projeto" #: editor/editor_settings.cpp -#, fuzzy msgid "On Save" -msgstr "Salvar" +msgstr "Ao Salvar" #: editor/editor_settings.cpp -#, fuzzy msgid "Compress Binary Resources" -msgstr "Copiar Recurso" +msgstr "Comprimir Recursos Binários" #: editor/editor_settings.cpp msgid "Safe Save On Backup Then Rename" -msgstr "" +msgstr "Salvar de Forma Segura Como Backup e Então Renomear" #: editor/editor_settings.cpp -#, fuzzy msgid "File Dialog" -msgstr "Diálogo XForm" +msgstr "Janela de Arquivo" #: editor/editor_settings.cpp msgid "Thumbnail Size" @@ -5545,82 +5496,73 @@ msgstr "Tamanho da Miniatura" #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "Docks" #: editor/editor_settings.cpp -#, fuzzy msgid "Scene Tree" -msgstr "Edição da Ãrvore de Cena" +msgstr "Ãrvore de Cena" #: editor/editor_settings.cpp msgid "Start Create Dialog Fully Expanded" -msgstr "" +msgstr "Iniciar Dialogo de Criação Expandido por Completo" #: editor/editor_settings.cpp -#, fuzzy msgid "Always Show Folders" -msgstr "Sempre Mostrar Grade" +msgstr "Sempre Exibir Pastas" #: editor/editor_settings.cpp -#, fuzzy msgid "Property Editor" -msgstr "Editor de Grupos" +msgstr "Editor de Propriedades" #: editor/editor_settings.cpp msgid "Auto Refresh Interval" -msgstr "" +msgstr "Intervalo de Atualização Automática" #: editor/editor_settings.cpp -#, fuzzy msgid "Subresource Hue Tint" -msgstr "Sub-Recursos" +msgstr "Tom de Coloração para Sub-Recursos" #: editor/editor_settings.cpp -#, fuzzy msgid "Color Theme" -msgstr "Tema do Editor" +msgstr "Tema de Cores" #: editor/editor_settings.cpp scene/3d/label_3d.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Line Spacing" -msgstr "" +msgstr "Espaçamento de Linha" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Highlighting" -msgstr "Iluminação direta" +msgstr "Destacando" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Syntax Highlighting" -msgstr "Realce de sintaxe" +msgstr "Destaque de Sintaxe" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight All Occurrences" -msgstr "" +msgstr "Destaque de Todas as Ocorrências" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight Current Line" -msgstr "" +msgstr "Destaque da Linha Atual" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Highlight Type Safe Lines" -msgstr "" +msgstr "Destaque de Linhas de Tipo Seguro" #: editor/editor_settings.cpp -#, fuzzy msgid "Indent" -msgstr "Recuar Esquerda" +msgstr "Indentar" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Auto Indent" msgstr "Auto Recuar" #: editor/editor_settings.cpp -#, fuzzy msgid "Convert Indent On Save" -msgstr "Converter recuo para espaços" +msgstr "Converter Indentação Ao Salvar" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Draw Tabs" @@ -5639,144 +5581,139 @@ msgstr "Navegação" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Smooth Scrolling" -msgstr "" +msgstr "Rolagem Suave" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "V Scroll Speed" -msgstr "" +msgstr "Velocidade de Rolagem Vertical" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Minimap" -msgstr "Mostrar Origem" +msgstr "Exibir Mini-Mapa" #: editor/editor_settings.cpp msgid "Minimap Width" -msgstr "" +msgstr "Largura do Mini-Mapa" #: editor/editor_settings.cpp msgid "Mouse Extra Buttons Navigate History" -msgstr "" +msgstr "Botões Extra do Mouse Navegam o Histórico" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "Seleção Do GridMap" +msgstr "Seleção Arrasta e Solta" #: editor/editor_settings.cpp -msgid "Appearance" +msgid "Stay In Script Editor On Node Selected" msgstr "" +#: editor/editor_settings.cpp +msgid "Appearance" +msgstr "Aparência" + #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Show Line Numbers" msgstr "Mostrar Números de Linha" #: editor/editor_settings.cpp -#, fuzzy msgid "Line Numbers Zero Padded" -msgstr "Número da Linha:" +msgstr "Número das Linha Tem Espaçamento Com Zeros" #: editor/editor_settings.cpp msgid "Show Bookmark Gutter" -msgstr "" +msgstr "Exibir Espaçamento de Bookmark" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Breakpoint Gutter" -msgstr "Pular Breakpoints" +msgstr "Exibir Espaçamento de Pontos de Quebra" #: editor/editor_settings.cpp msgid "Show Info Gutter" -msgstr "" +msgstr "Exibir Espaçamento de Informações" #: editor/editor_settings.cpp msgid "Code Folding" -msgstr "" +msgstr "Dobramento de Código (Folding)" #: editor/editor_settings.cpp msgid "Word Wrap" -msgstr "" +msgstr "Quebra de Linhas" #: editor/editor_settings.cpp msgid "Show Line Length Guidelines" -msgstr "" +msgstr "Exibir Guia de Tamanho de Linhas" #: editor/editor_settings.cpp msgid "Line Length Guideline Soft Column" -msgstr "" +msgstr "Tamanho de Linha Guia em Coluna Suave" #: editor/editor_settings.cpp msgid "Line Length Guideline Hard Column" -msgstr "" +msgstr "Tamanho de Linha Guia em Coluna RÃgida" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script List" -msgstr "Editor de Script" +msgstr "Lista de Scripts" #: editor/editor_settings.cpp msgid "Show Members Overview" -msgstr "" +msgstr "Exibir Visão Geral de Membros" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Files" -msgstr "Arquivo" +msgstr "Arquivos" #: editor/editor_settings.cpp -#, fuzzy msgid "Trim Trailing Whitespace On Save" -msgstr "Apagar Espaços em Branco" +msgstr "Aparar Espaços em Branco de Fim de Linha ao Salvar" #: editor/editor_settings.cpp msgid "Autosave Interval Secs" -msgstr "" +msgstr "Intervalo de Salvamento Automático em Segundos" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Restore Scripts On Load" -msgstr "" +msgstr "Restaurar Scripts ao Carregar" #: editor/editor_settings.cpp msgid "Auto Reload And Parse Scripts On Save" -msgstr "" +msgstr "Ao Salvar Recarregar e Reinterpretar Scripts Automaticamente" #: editor/editor_settings.cpp msgid "Auto Reload Scripts On External Change" -msgstr "" +msgstr "Recarregar Scripts Automaticamente em Alterações Externas" #: editor/editor_settings.cpp -#, fuzzy msgid "Create Signal Callbacks" -msgstr "Forçar Fallbacks do Shader" +msgstr "Criar Sinal de Callback" #: editor/editor_settings.cpp msgid "Sort Members Outline Alphabetically" -msgstr "" +msgstr "Ordenar Prévia de Membros Automaticamente" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Cursor" -msgstr "" +msgstr "Cursor" #: editor/editor_settings.cpp msgid "Scroll Past End Of File" -msgstr "" +msgstr "Rolar Além do Fim do Arquivo" #: editor/editor_settings.cpp msgid "Block Caret" -msgstr "" +msgstr "Bloco Cursor" #: editor/editor_settings.cpp msgid "Caret Blink" -msgstr "" +msgstr "Piscar Cursor" #: editor/editor_settings.cpp msgid "Caret Blink Speed" -msgstr "" +msgstr "Velocidade de Piscar do Cursor" #: editor/editor_settings.cpp -#, fuzzy msgid "Right Click Moves Caret" -msgstr "Clique com o botão direito para adicionar o ponto" +msgstr "Botão Direito Move o Cursor" #: editor/editor_settings.cpp modules/gdscript/gdscript.cpp #: modules/gdscript/gdscript_editor.cpp @@ -5786,54 +5723,51 @@ msgstr "Conclusão" #: editor/editor_settings.cpp msgid "Idle Parse Delay" -msgstr "" +msgstr "Atraso Ocioso Para Interpretação" #: editor/editor_settings.cpp msgid "Auto Brace Complete" -msgstr "" +msgstr "Fechar Chaves Automaticamente" #: editor/editor_settings.cpp msgid "Code Complete Delay" -msgstr "" +msgstr "Atraso de Sugestão de Código" #: editor/editor_settings.cpp msgid "Put Callhint Tooltip Below Current Line" -msgstr "" +msgstr "Pôr Dica de Sugestão de Chamada na Linha Abaixo da Atual" #: editor/editor_settings.cpp msgid "Callhint Tooltip Offset" -msgstr "" +msgstr "Espaçamento de Dica de Sugestão de Chamada" #: editor/editor_settings.cpp -#, fuzzy msgid "Complete File Paths" -msgstr "Copiar Caminho do Nó" +msgstr "Concluir Caminhos de Arquivo" #: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp -#, fuzzy msgid "Add Type Hints" -msgstr "Adicionar Modelo" +msgstr "Adicionar Dicas de Tipo" #: editor/editor_settings.cpp msgid "Use Single Quotes" msgstr "Usar Aspas Simples" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Help Index" -msgstr "Mostrar auxiliadores" +msgstr "Exibir Ãndice de Ajuda" #: editor/editor_settings.cpp msgid "Help Font Size" -msgstr "" +msgstr "Tamanho da Fonte de Ajuda" #: editor/editor_settings.cpp msgid "Help Source Font Size" -msgstr "" +msgstr "Tamanho da Fonte de Ajuda Principal" #: editor/editor_settings.cpp msgid "Help Title Font Size" -msgstr "" +msgstr "Tamanho da Fonte de Ajuda para TÃtulos" #: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp msgid "Grid Map" @@ -5844,45 +5778,39 @@ msgid "Pick Distance" msgstr "Escolha a Distância" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Preview Size" -msgstr "Visualização" +msgstr "Tamanho da Prévia" #: editor/editor_settings.cpp msgid "Primary Grid Color" -msgstr "" +msgstr "Cor Primária da Grade" #: editor/editor_settings.cpp msgid "Secondary Grid Color" -msgstr "" +msgstr "Cor Secundária da Grade" #: editor/editor_settings.cpp -#, fuzzy msgid "Selection Box Color" -msgstr "Selecionar Apenas" +msgstr "Cor da Caixa de Seleção" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "3D Gizmos" -msgstr "Gizmos" +msgstr "Gizmos 3D" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Gizmo Colors" -msgstr "Cores de Emissão" +msgstr "Cores do Gismo" #: editor/editor_settings.cpp -#, fuzzy msgid "Instanced" -msgstr "Instância" +msgstr "Instanciado" #: editor/editor_settings.cpp modules/gltf/gltf_node.cpp #: scene/3d/physics_body.cpp -#, fuzzy msgid "Joint" -msgstr "Ponto" +msgstr "Junção" #: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp @@ -5891,12 +5819,11 @@ msgstr "Ponto" #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Shape" -msgstr "" +msgstr "Form" #: editor/editor_settings.cpp -#, fuzzy msgid "Primary Grid Steps" -msgstr "Passo de grade:" +msgstr "Passadas para Grade Primária" #: editor/editor_settings.cpp msgid "Grid Size" @@ -5904,183 +5831,155 @@ msgstr "Tamanho da Grade" #: editor/editor_settings.cpp msgid "Grid Division Level Max" -msgstr "" +msgstr "NÃvel Máximo de Divisão de Grade" #: editor/editor_settings.cpp msgid "Grid Division Level Min" -msgstr "" +msgstr "NÃvel MÃnimo de Divisão da Grade" #: editor/editor_settings.cpp msgid "Grid Division Level Bias" -msgstr "" +msgstr "Tendência do NÃvel de Divisão da Grade" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XZ Plane" -msgstr "Pintura GridMap" +msgstr "Grade do Plano XZ" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XY Plane" -msgstr "Pintura GridMap" +msgstr "Grade do Plano XY" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid YZ Plane" -msgstr "Pintura GridMap" +msgstr "Grade do Plano YZ" #: editor/editor_settings.cpp -#, fuzzy msgid "Default FOV" -msgstr "Padrão" +msgstr "Campo de Visão (FOV) Padrão" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Near" -msgstr "Tema Padrão" +msgstr "Z Padrão Próximo" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Far" -msgstr "Padrão" +msgstr "Z Padrão Longe" #: editor/editor_settings.cpp msgid "Lightmap Baking Number Of CPU Threads" -msgstr "" +msgstr "Número de Threads de CPU para o Bake do Mapa de Luz" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Scheme" -msgstr "Modo Navegação" +msgstr "Esquema de Navegação" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert Y Axis" -msgstr "Eduitar Eixo Y" +msgstr "Inverter Eixo Y" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert X Axis" -msgstr "Editar Eixo X" +msgstr "Inverter Eixo X" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Style" -msgstr "Reduzir" +msgstr "Estilo de Zoom" #: editor/editor_settings.cpp msgid "Emulate Numpad" -msgstr "" +msgstr "Simular o Numpad" #: editor/editor_settings.cpp msgid "Emulate 3 Button Mouse" -msgstr "" +msgstr "Simular o Botão 3 Do Mouse" #: editor/editor_settings.cpp -#, fuzzy msgid "Orbit Modifier" -msgstr "Ordenar por Primeiro Modificado" +msgstr "Modificador de Órbita" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Modifier" -msgstr "Modo Panorâmico" +msgstr "Modificador de Panorâmica" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Modifier" -msgstr "Modificado" +msgstr "Modificador de Zoom" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Warped Mouse Panning" -msgstr "" +msgstr "Panorização Distorcida pelo Mouse" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Feel" -msgstr "Modo Navegação" +msgstr "Sensação de Navegação" #: editor/editor_settings.cpp msgid "Orbit Sensitivity" -msgstr "" +msgstr "Sensitividade de Órbita" #: editor/editor_settings.cpp msgid "Orbit Inertia" -msgstr "" +msgstr "Inercia de Órbita" #: editor/editor_settings.cpp -#, fuzzy msgid "Translation Inertia" -msgstr "Traduções" +msgstr "Inércia de Translação" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Inertia" -msgstr "Ampliar" +msgstr "Inércia de Zoom" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook" -msgstr "Visão Livre em Cima" +msgstr "Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Navigation Scheme" -msgstr "Criar Malha de Navegação" +msgstr "Esquema de Navegação de Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Sensitivity" -msgstr "Visão Livre na Esquerda" +msgstr "Sensibilidade de Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Inertia" -msgstr "Visão Livre na Esquerda" +msgstr "Inercia de Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Base Speed" -msgstr "Modificador de velocidade da Visão Livre" +msgstr "Velocidade Base de Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Activation Modifier" -msgstr "Modificador de velocidade lenta da Visão Livre" +msgstr "Modificador de Ativação de Visão Livre" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Speed Zoom Link" -msgstr "Modificador de velocidade da Visão Livre" +msgstr "Velocidade de Ligação do Visão Livre" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Grid Color" -msgstr "Escolher Cor" +msgstr "Cor da Grade" #: editor/editor_settings.cpp -#, fuzzy msgid "Guides Color" -msgstr "Escolher Cor" +msgstr "Cor Guia" #: editor/editor_settings.cpp -#, fuzzy msgid "Smart Snapping Line Color" -msgstr "Encaixe inteligente" +msgstr "Cor da Linha de Encaixe Inteligente" #: editor/editor_settings.cpp msgid "Bone Width" -msgstr "" +msgstr "Largura do Osso" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 1" -msgstr "Renomear Item de Cor" +msgstr "Cor de Osso 1" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 2" -msgstr "Renomear Item de Cor" +msgstr "Cor de Osso 2" #: editor/editor_settings.cpp msgid "Bone Selected Color" @@ -6088,11 +5987,11 @@ msgstr "Cor Selecionada do Osso" #: editor/editor_settings.cpp msgid "Bone IK Color" -msgstr "" +msgstr "Cor de Osso IK (cinemática inversa)" #: editor/editor_settings.cpp msgid "Bone Outline Color" -msgstr "" +msgstr "Cor de Contorno do Osso" #: editor/editor_settings.cpp msgid "Bone Outline Size" @@ -6100,103 +5999,93 @@ msgstr "Tamanho do Contorno do Osso" #: editor/editor_settings.cpp msgid "Viewport Border Color" -msgstr "" +msgstr "Cor da Borda de Viewport" #: editor/editor_settings.cpp msgid "Constrain Editor View" -msgstr "" +msgstr "Restringir Visão do Editor" #: editor/editor_settings.cpp msgid "Simple Panning" -msgstr "" +msgstr "Panoramização Simples" #: editor/editor_settings.cpp msgid "Scroll To Pan" -msgstr "" +msgstr "Rolar para Panoramizar" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Speed" -msgstr "Velocidade:" +msgstr "Velocidade da Panoramização" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Poly Editor" -msgstr "Editor UV de PolÃgonos 2D" +msgstr "Editor de PolÃgonos" #: editor/editor_settings.cpp msgid "Point Grab Radius" -msgstr "" +msgstr "Raio de Agarro ao Ponto" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Show Previous Outline" -msgstr "Plano Anterior" +msgstr "Exibir Prévia Anterior" #: editor/editor_settings.cpp editor/scene_tree_dock.cpp -#, fuzzy msgid "Autorename Animation Tracks" -msgstr "Renomear Animação" +msgstr "Renomear Automaticamente Faixa de Animação" #: editor/editor_settings.cpp msgid "Default Create Bezier Tracks" -msgstr "" +msgstr "Criar Faixa de Bezier por Padrão" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Create Reset Tracks" -msgstr "Criar RESET Track(s)" +msgstr "Criar Faixa RESET Por Padrão" #: editor/editor_settings.cpp msgid "Onion Layers Past Color" -msgstr "" +msgstr "Cor da Camada de Cebola Anterior" #: editor/editor_settings.cpp msgid "Onion Layers Future Color" -msgstr "" +msgstr "Cor da Camada de Cebola Posterior" #: editor/editor_settings.cpp -#, fuzzy msgid "Visual Editors" -msgstr "Editor de Grupos" +msgstr "Editores Visuais" #: editor/editor_settings.cpp msgid "Minimap Opacity" -msgstr "" +msgstr "Opacidade do Mini-Mapa" #: editor/editor_settings.cpp msgid "Window Placement" -msgstr "" +msgstr "Colocação da Janela" #: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp #: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp #: scene/gui/control.cpp -#, fuzzy msgid "Rect" -msgstr "Rect Completo" +msgstr "Retângulo" #: editor/editor_settings.cpp -#, fuzzy msgid "Rect Custom Position" -msgstr "Definir Posição de SaÃda da Curva" +msgstr "Posição Personalizada Do Retângulo" #: editor/editor_settings.cpp platform/android/export/export_plugin.cpp msgid "Screen" -msgstr "" +msgstr "Tela" #: editor/editor_settings.cpp -#, fuzzy msgid "Auto Save" -msgstr "Auto Fatiar" +msgstr "Salvar Automaticamente" #: editor/editor_settings.cpp msgid "Save Before Running" msgstr "Salvar Antes de Executar" #: editor/editor_settings.cpp -#, fuzzy msgid "Font Size" -msgstr "Visão Frontal" +msgstr "Tamanho da Fonte" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp @@ -6205,28 +6094,26 @@ msgstr "Hospedeiro Remoto" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Remote Port" -msgstr "Remover Ponto" +msgstr "Porta Remota" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor SSL Certificates" -msgstr "Configurações do Editor" +msgstr "Certificados SSL do Editor" #: editor/editor_settings.cpp msgid "HTTP Proxy" -msgstr "" +msgstr "Proxy HTTP" #: editor/editor_settings.cpp msgid "Host" -msgstr "" +msgstr "Hospedeiro" #: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Port" -msgstr "" +msgstr "Porta" #. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects. #: editor/editor_settings.cpp @@ -6240,32 +6127,31 @@ msgstr "Ordem de Classificação" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Symbol Color" -msgstr "" +msgstr "Cor do Simbolo" #: editor/editor_settings.cpp msgid "Keyword Color" -msgstr "" +msgstr "Cor de Palavra Chave" #: editor/editor_settings.cpp msgid "Control Flow Keyword Color" -msgstr "" +msgstr "Core de Palavra Chave de Controle de Fluxo" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Type Color" -msgstr "Mudar Tipo Base" +msgstr "Cor de Tipo Base" #: editor/editor_settings.cpp msgid "Engine Type Color" -msgstr "" +msgstr "Cor de Tipo da Engine" #: editor/editor_settings.cpp msgid "User Type Color" -msgstr "" +msgstr "Cor de Tipo Do Usuário" #: editor/editor_settings.cpp msgid "Comment Color" -msgstr "" +msgstr "Cor de Comentário" #: editor/editor_settings.cpp msgid "String Color" @@ -6282,26 +6168,24 @@ msgid "Completion Background Color" msgstr "Cor de Fundo de Acabamento" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Selected Color" -msgstr "Importar Selecionado" +msgstr "Cor de Sugestão Selecionada" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Existing Color" -msgstr "" +msgstr "Cor de Sugestão Existente" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Scroll Color" -msgstr "" +msgstr "Cor da Barra de Rolagem de Sugestão" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Font Color" -msgstr "" +msgstr "Cor da Fonte de Sugestão" #: editor/editor_settings.cpp -#, fuzzy msgid "Text Color" -msgstr "Próximo Chão" +msgstr "Cor do Texto" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Line Number Color" @@ -6313,86 +6197,75 @@ msgstr "Cor do Número da Linha Segura" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Color" -msgstr "" +msgstr "Cor do Cursor" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Background Color" msgstr "Cor de Fundo de Acentuação" #: editor/editor_settings.cpp -#, fuzzy msgid "Text Selected Color" -msgstr "Excluir Selecionados" +msgstr "Cor do Texto Selecionado" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Selection Color" -msgstr "Selecionar Apenas" +msgstr "Cor da Seleção" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Brace Mismatch Color" -msgstr "" +msgstr "Cor de Chave IncompatÃvel" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Current Line Color" -msgstr "Cena Atual" +msgstr "Cor da Linha Atual" #: editor/editor_settings.cpp msgid "Line Length Guideline Color" -msgstr "" +msgstr "Cor do Tamanho de Linha Guia" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Word Highlighted Color" -msgstr "Realce de sintaxe" +msgstr "Cor da Palavra em Destaque" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Number Color" -msgstr "" +msgstr "Cor de Número" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Function Color" -msgstr "Funções" +msgstr "Cor de Função" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Member Variable Color" -msgstr "Renomear Variável" +msgstr "Cor de Variável Membro" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Mark Color" -msgstr "Escolher Cor" +msgstr "Cor de Marcação" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Bookmark Color" -msgstr "Marcadores" +msgstr "Cor de Bookmark" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Breakpoint Color" -msgstr "Breakpoints" +msgstr "Cor de Ponto de Quebra" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Executing Line Color" -msgstr "" +msgstr "Cor da Linha em Execução" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Code Folding Color" -msgstr "" +msgstr "Cor da Dobradiça de Código" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Color" -msgstr "Pesquisar resultados" +msgstr "Cor do Resultado de Pesquisa" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Border Color" -msgstr "Pesquisar resultados" +msgstr "Cor da Borda do Resultado de Pesquisa" #: editor/editor_spin_slider.cpp msgid "Hold %s to round to integers. Hold Shift for more precise changes." @@ -6401,14 +6274,12 @@ msgstr "" "mais precisas." #: editor/editor_spin_slider.cpp scene/gui/button.cpp -#, fuzzy msgid "Flat" -msgstr "Plano 0" +msgstr "Raso" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hide Slider" -msgstr "Modo Colisão" +msgstr "Esconder Rolagem" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -6708,7 +6579,7 @@ msgstr "" #: editor/fileserver/editor_file_server.cpp msgid "File Server" -msgstr "" +msgstr "Servidor de Arquivos" #: editor/fileserver/editor_file_server.cpp #: editor/plugins/version_control_editor_plugin.cpp @@ -6776,6 +6647,11 @@ msgid "" "After renaming to an unknown extension, the file won't be shown in the " "editor anymore." msgstr "" +"Esta extensão de arquivo não é reconhecida pelo editor.\n" +"Se ainda assim você deseja renomear, utilize o explorador de arquivos do seu " +"sistema operacional.\n" +"Após renomear para uma extensão desconhecida, este arquivo não será mais " +"exibida pelo editor." #: editor/filesystem_dock.cpp msgid "" @@ -7076,43 +6952,40 @@ msgstr "Gerenciar Grupos" #: editor/import/editor_import_collada.cpp msgid "Collada" -msgstr "" +msgstr "Collada" #: editor/import/editor_import_collada.cpp msgid "Use Ambient" -msgstr "" +msgstr "Utilizar Ambient" #: editor/import/resource_importer_bitmask.cpp -#, fuzzy msgid "Create From" -msgstr "Criar Pasta" +msgstr "Criar à Partir de" #: editor/import/resource_importer_bitmask.cpp #: servers/audio/effects/audio_effect_compressor.cpp msgid "Threshold" -msgstr "" +msgstr "Limite" #: editor/import/resource_importer_csv_translation.cpp #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_scene.cpp #: editor/import/resource_importer_texture.cpp #: editor/import/resource_importer_wav.cpp scene/3d/gi_probe.cpp -#, fuzzy msgid "Compress" -msgstr "Componentes" +msgstr "Comprimir" #: editor/import/resource_importer_csv_translation.cpp msgid "Delimiter" -msgstr "" +msgstr "Delimitador" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "ColorCorrect" -msgstr "Correção de Cor" +msgstr "Corrigir as Cores" #: editor/import/resource_importer_layered_texture.cpp msgid "No BPTC If RGB" -msgstr "" +msgstr "Não utilizar BPTC se for RGB" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp @@ -7120,13 +6993,13 @@ msgstr "" #: scene/resources/material.cpp scene/resources/particles_material.cpp #: scene/resources/texture.cpp scene/resources/visual_shader.cpp msgid "Flags" -msgstr "" +msgstr "Sinalizadores" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp #: scene/resources/texture.cpp msgid "Repeat" -msgstr "" +msgstr "Repetir" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp @@ -7136,24 +7009,22 @@ msgstr "Filtro" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Mipmaps" -msgstr "Sinais" +msgstr "Mipmaps" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "Anisotropic" -msgstr "" +msgstr "Anisotrópico" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "sRGB" -msgstr "" +msgstr "sRGB" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "Slices" -msgstr "Auto Fatiar" +msgstr "Fatias" #: editor/import/resource_importer_layered_texture.cpp #: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp @@ -7170,14 +7041,12 @@ msgid "Vertical" msgstr "Vertical" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Generate Tangents" -msgstr "Gerar Pontos" +msgstr "Gerar Tangentes" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Scale Mesh" -msgstr "Modo de Escalonamento" +msgstr "Redimensionar Malha" #: editor/import/resource_importer_obj.cpp msgid "Offset Mesh" @@ -7185,14 +7054,12 @@ msgstr "Malha de Deslocamento" #: editor/import/resource_importer_obj.cpp #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Octahedral Compression" -msgstr "Expressão" +msgstr "Compressão Octaedral" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Optimize Mesh Flags" -msgstr "Sinalizadores de Tamanho" +msgstr "Otimizar Sinalizadores da Malha" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" @@ -7240,24 +7107,20 @@ msgid "Nodes" msgstr "Nós" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Type" -msgstr "Retornar" +msgstr "Tipo da Raiz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Name" -msgstr "Nome Remoto" +msgstr "Nome da Raiz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Scale" -msgstr "Escala" +msgstr "Escala da Raiz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Custom Script" -msgstr "Recortar Nós" +msgstr "Script Personalizado" #: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp msgid "Storage" @@ -7265,69 +7128,59 @@ msgstr "Armazenamento" #: editor/import/resource_importer_scene.cpp msgid "Use Legacy Names" -msgstr "" +msgstr "Utilizar Nomes Legados" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Materials" msgstr "Materiais" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep On Reimport" -msgstr "Reimportar" +msgstr "Manter ao Reimportar" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp -#, fuzzy msgid "Meshes" -msgstr "Malha" +msgstr "Malhas" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Ensure Tangents" -msgstr "Modificar Tangente da Curva" +msgstr "Garantir Tangentes" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Light Baking" -msgstr "Faça mapas de luz" +msgstr "Bake de Mapa de Luz" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Lightmap Texel Size" -msgstr "Faça mapas de luz" +msgstr "Tamanho do Texel no Mapa de Luz" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Skins" -msgstr "" +msgstr "Peles" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Use Named Skins" -msgstr "Usar Encaixe Escalar" +msgstr "Utilizar Peles com Nome" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "External Files" -msgstr "Abrir um Arquivo" +msgstr "Arquivos Externos" #: editor/import/resource_importer_scene.cpp msgid "Store In Subdir" -msgstr "" +msgstr "Salvar em Sub Diretório" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Filter Script" -msgstr "Filtrar scripts" +msgstr "Filtrar Script" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep Custom Tracks" -msgstr "Transformação" +msgstr "Manter Faixas Personalizadas" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Optimizer" -msgstr "Otimizar" +msgstr "Otimizador" #: editor/import/resource_importer_scene.cpp #: editor/plugins/item_list_editor_plugin.cpp main/main.cpp @@ -7341,9 +7194,8 @@ msgstr "Otimizar" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp #: scene/gui/rich_text_label.cpp scene/resources/curve.cpp #: scene/resources/environment.cpp scene/resources/material.cpp -#, fuzzy msgid "Enabled" -msgstr "Habilitar" +msgstr "Habilitado" #: editor/import/resource_importer_scene.cpp msgid "Max Linear Error" @@ -7354,19 +7206,16 @@ msgid "Max Angular Error" msgstr "Erro Angular Máximo" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Angle" -msgstr "Valor" +msgstr "Ângulo Máximo" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Remove Unused Tracks" -msgstr "Remover Trilha da Anim" +msgstr "Remover Faixas não Utilizadas" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Clips" -msgstr "Clipes de Animação" +msgstr "Clipes" #: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp @@ -7420,30 +7269,33 @@ msgid "" "%s: Texture detected as used as a normal map in 3D. Enabling red-green " "texture compression to reduce memory usage (blue channel is discarded)." msgstr "" +"%s: Foi detectado que a textura está sendo utilizada como mapa normal em 3D. " +"Habilitando a compressão vermelho/verde para reduzir o uso de memória (o " +"canal azul é descartado)." #: editor/import/resource_importer_texture.cpp msgid "" "%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap " "generation and VRAM texture compression." msgstr "" +"%s: Foi detectado que a textura está sendo utilizada em 3D. Habilitando a " +"filtro, repetir, geração de mipmap e compressão de textura VRAM." #: editor/import/resource_importer_texture.cpp msgid "2D, Detect 3D" -msgstr "" +msgstr "2D, Detecte 3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "2D Pixel" -msgstr "Pixels Sólidos" +msgstr "Pixel 2D" #: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp msgid "Lossy Quality" -msgstr "" +msgstr "Com Perda de Qualidade" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "HDR Mode" -msgstr "Modo de Seleção" +msgstr "Modo HDR" #: editor/import/resource_importer_texture.cpp msgid "BPTC LDR" @@ -7454,54 +7306,52 @@ msgstr "" #: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp #: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp msgid "Normal Map" -msgstr "" +msgstr "Mapa Normal" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Process" -msgstr "Pós-processamento" +msgstr "Processar" #: editor/import/resource_importer_texture.cpp msgid "Fix Alpha Border" -msgstr "" +msgstr "Corrigir Alpha da Borda" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Premult Alpha" -msgstr "Editar PolÃgono" +msgstr "" #: editor/import/resource_importer_texture.cpp msgid "Hdr As Srgb" -msgstr "" +msgstr "HDR como SRGB" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Invert Color" -msgstr "Vértice" +msgstr "Inverter Cor" #: editor/import/resource_importer_texture.cpp msgid "Normal Map Invert Y" msgstr "Inverter Y do Mapa Normal" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Size Limit" -msgstr "Limites" +msgstr "Limite de Tamanho" #: editor/import/resource_importer_texture.cpp msgid "Detect 3D" -msgstr "" +msgstr "Detectar 3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "SVG" -msgstr "HSV" +msgstr "SVG" #: editor/import/resource_importer_texture.cpp msgid "" "Warning, no suitable PC VRAM compression enabled in Project Settings. This " "texture will not display correctly on PC." msgstr "" +"Atenção, nenhuma forma adequada de Compressão VRAM para PC foi habilitada " +"nas Configurações do Projeto. Esta textura não será exibida corretamente em " +"PCs." #: editor/import/resource_importer_texture_atlas.cpp msgid "Atlas File" @@ -7512,64 +7362,56 @@ msgid "Import Mode" msgstr "Modo de Importação" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Crop To Region" -msgstr "Definir a região do Mosaico" +msgstr "Recortar para Região" #: editor/import/resource_importer_texture_atlas.cpp msgid "Trim Alpha Border From Region" -msgstr "" +msgstr "Aparar Borda Alfa da Região" #: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Force" -msgstr "Forçar Push" +msgstr "Forçar" #: editor/import/resource_importer_wav.cpp msgid "8 Bit" -msgstr "" +msgstr "8 Bits" #: editor/import/resource_importer_wav.cpp main/main.cpp #: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Mono" -msgstr "" +msgstr "Mono" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate" -msgstr "Nó Mix" +msgstr "Frequência Máxima" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate Hz" -msgstr "Nó Mix" +msgstr "Frequência Máxima Hz" #: editor/import/resource_importer_wav.cpp msgid "Trim" -msgstr "" +msgstr "Aparar" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Normalize" -msgstr "Formato" +msgstr "Normalizar" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Mode" -msgstr "Modo de Movimentação" +msgstr "Modo de Loop" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Begin" -msgstr "Modo de Movimentação" +msgstr "Inicio do Loop" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop End" -msgstr "Modo de Movimentação" +msgstr "Fim do Loop" #: editor/import_defaults_editor.cpp msgid "Select Importer" @@ -7657,18 +7499,16 @@ msgid "Raw" msgstr "Bruto" #: editor/inspector_dock.cpp -#, fuzzy msgid "Capitalized" -msgstr "Capitalizar" +msgstr "Capitalizado" #: editor/inspector_dock.cpp -#, fuzzy msgid "Localized" -msgstr "Localizar" +msgstr "Localizado" #: editor/inspector_dock.cpp msgid "Localization not available for current language." -msgstr "" +msgstr "Localização não disponÃvel para linguagem atual." #: editor/inspector_dock.cpp msgid "Copy Properties" @@ -8217,9 +8057,8 @@ msgid "New" msgstr "Novo" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Paste As Reference" -msgstr "%s Referência de Classes" +msgstr "Colar como Referência" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -8548,7 +8387,7 @@ msgstr "Filtros..." #: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp msgid "Use Threads" -msgstr "" +msgstr "Usar Threads" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Contents:" @@ -8711,25 +8550,21 @@ msgid "Loading..." msgstr "Carregando..." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "First" msgstr "Primeiro" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Previous" msgstr "Anterior" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Next" msgstr "Próximo" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Last" msgstr "Último" @@ -8780,7 +8615,7 @@ msgstr "Testando" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed to get repository configuration." -msgstr "" +msgstr "Falhou em obter o repositório de configuração." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" @@ -8840,7 +8675,7 @@ msgstr "Faça mapas de luz" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "LightMap Bake" -msgstr "" +msgstr "Bake de Mapa de Luz" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Select lightmap bake file:" @@ -9347,23 +9182,20 @@ msgid "View" msgstr "Visualizar" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show" -msgstr "Mostrar Grade" +msgstr "Exibir" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show When Snapping" -msgstr "Encaixe inteligente" +msgstr "Exibir ao Encaixar" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Hide" -msgstr "" +msgstr "Esconder" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid" -msgstr "Alternar Modo" +msgstr "Alternar Grade" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -9647,11 +9479,11 @@ msgstr "Plano 1" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease In" -msgstr "Ease In" +msgstr "Esmaecer de Entrada" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease Out" -msgstr "Ease Out" +msgstr "Esmaecer de SaÃda" #: editor/plugins/curve_editor_plugin.cpp msgid "Smoothstep" @@ -9715,16 +9547,15 @@ msgstr "Gradiente Editado" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap GradientTexture2D Fill Points" -msgstr "" +msgstr "Trocar Pontos de Preenchimento do GradientTexture2D" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap Gradient Fill Points" -msgstr "" +msgstr "Trocar Pontos de Preenchimento do Degradê" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid Snap" -msgstr "Alternar Modo" +msgstr "Alternar Encaixe da Grade" #: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp #: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp @@ -9743,13 +9574,12 @@ msgstr "Ãcone" #: editor/plugins/item_list_editor_plugin.cpp msgid "ID" -msgstr "" +msgstr "ID" #: editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separator" -msgstr "Separação:" +msgstr "Separador" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" @@ -9983,7 +9813,6 @@ msgstr "" "%s" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "MeshLibrary" msgstr "Biblioteca de Malhas" @@ -10008,14 +9837,12 @@ msgid "Update from Scene" msgstr "Atualizar a partir de Cena" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply without Transforms" -msgstr "Aplicar transformações da MeshInstance" +msgstr "Aplicar sem Transformações" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply with Transforms" -msgstr "Aplicar transformações da MeshInstance" +msgstr "Aplicar com Transformações" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." @@ -10507,7 +10334,7 @@ msgstr "Configurações da grade" #: editor/plugins/polygon_2d_editor_plugin.cpp modules/csg/csg_shape.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Snap" -msgstr "Snap" +msgstr "Encaixe" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" @@ -10543,7 +10370,7 @@ msgstr "Sincronizar Ossos ao PolÃgono" #: editor/plugins/ray_cast_2d_editor_plugin.cpp msgid "Set cast_to" -msgstr "" +msgstr "Definir cast_to" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" @@ -10874,48 +10701,43 @@ msgstr "Resultados de Pesquisa" #: editor/plugins/script_editor_plugin.cpp msgid "Open Dominant Script On Scene Change" -msgstr "" +msgstr "Abrir Script Dominante ao Mudar de Cena" #: editor/plugins/script_editor_plugin.cpp msgid "External" -msgstr "" +msgstr "Externo" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Use External Editor" -msgstr "Depurar com o Editor Externo" +msgstr "Utilizar Editor Externo" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Exec Path" -msgstr "Caminho de Exportação" +msgstr "Caminho de Execução" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script Temperature Enabled" -msgstr "Selecionar o Arquivo de Modelo" +msgstr "Temperatura de Script Habilitado" #: editor/plugins/script_editor_plugin.cpp msgid "Highlight Current Script" -msgstr "" +msgstr "Destacar Script Atual" #: editor/plugins/script_editor_plugin.cpp msgid "Script Temperature History Size" -msgstr "" +msgstr "Tamanho de Histórico de Temperatura de Script" #: editor/plugins/script_editor_plugin.cpp msgid "Current Script Background Color" msgstr "Cor de Fundo do Script Atual" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Group Help Pages" -msgstr "Agrupar Selecionados" +msgstr "Agrupar Páginas de Ajuda" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Sort Scripts By" -msgstr "Criar Script" +msgstr "Ordenar Scripts Por" #: editor/plugins/script_editor_plugin.cpp msgid "List Script Names As" @@ -10923,7 +10745,7 @@ msgstr "Listar Nomes de Script Como" #: editor/plugins/script_editor_plugin.cpp msgid "Exec Flags" -msgstr "" +msgstr "Sinalizadores de Execução" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Scripts" @@ -11007,7 +10829,7 @@ msgstr "Marcadores" #: editor/plugins/script_text_editor.cpp msgid "Breakpoints" -msgstr "Breakpoints" +msgstr "Pontos de Quebra" #: editor/plugins/script_text_editor.cpp #: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp @@ -11436,13 +11258,14 @@ msgstr "Pré-visualização Cinemática" #: editor/plugins/spatial_editor_plugin.cpp msgid "(Not in GLES2)" -msgstr "" +msgstr "(Não disponÃvel em GLES2)" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "" "Debug draw modes are only available when using the GLES3 renderer, not GLES2." -msgstr "Não disponÃvel ao usar o renderizador GLES2." +msgstr "" +"Modos de Debug draw só estão disponÃveis para uso com o renderizador GLES3. " +"GLES2 não suporta esta funcionalidade." #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" @@ -11737,16 +11560,15 @@ msgstr "Pós" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Size" -msgstr "" +msgstr "Tamanho do Gizmo Manipulador" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Opacity" -msgstr "" +msgstr "Opacidade do Gizmo Manipulador" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Show Viewport Rotation Gizmo" -msgstr "Bloquear Rotação da Visão" +msgstr "Exibir Gizmo de Rotação do Viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "Unnamed Gizmo" @@ -11798,9 +11620,8 @@ msgid "Invalid geometry, can't replace by mesh." msgstr "Geometria inválida, não é possÃvel substituir por malha." #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Convert to MeshInstance2D" -msgstr "Converter para Malha2D" +msgstr "Converter para MeshInstance2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't create polygon." @@ -11903,6 +11724,11 @@ msgid "New Animation" msgstr "Nova animação" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrar métodos" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Velocidade:" @@ -12200,9 +12026,8 @@ msgstr "" "Fechar mesmo assim?" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Type" -msgstr "Remover Telha" +msgstr "Remover Tipo" #: editor/plugins/theme_editor_plugin.cpp msgid "" @@ -12246,14 +12071,12 @@ msgstr "" "Adicione mais itens manualmente ou importe de outro tema." #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Add Theme Type" -msgstr "Adicionar Tipo de Item" +msgstr "Adicionar Tipo de Tema" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Theme Type" -msgstr "Remover remoto" +msgstr "Remover Tipo de Tema" #: editor/plugins/theme_editor_plugin.cpp msgid "Add Color Item" @@ -12368,9 +12191,8 @@ msgid "Select Another Theme Resource:" msgstr "Selecionar Outro Recurso de Tema:" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Theme Resource" -msgstr "Renomear Recurso" +msgstr "Recurso de Tema" #: editor/plugins/theme_editor_plugin.cpp msgid "Another Theme" @@ -12425,14 +12247,12 @@ msgid "Add Item Type" msgstr "Adicionar Tipo de Item" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Variation Base Type" -msgstr "Definir o Tipo da Variável" +msgstr "Definir Tipo de Variação Base" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Base Type" -msgstr "Mudar Tipo Base" +msgstr "Definir Tipo Base" #: editor/plugins/theme_editor_plugin.cpp msgid "Show Default" @@ -12454,12 +12274,15 @@ msgstr "Substituir todos os itens do modelo padrão." #: editor/plugins/theme_editor_plugin.cpp msgid "Select the variation base type from a list of available types." msgstr "" +"Selecione a variação do tipo base à partir da lista de tipos disponÃveis." #: editor/plugins/theme_editor_plugin.cpp msgid "" "A type associated with a built-in class cannot be marked as a variation of " "another type." msgstr "" +"Um tipo associado à uma classe padrão não pode ser marcada como variação de " +"outro tipo." #: editor/plugins/theme_editor_plugin.cpp msgid "Theme:" @@ -12697,14 +12520,13 @@ msgid "Clear Transform" msgstr "Limpar Transformação" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Tile Map" -msgstr "Pintar TileMap" +msgstr "Tile Map" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Palette Min Width" -msgstr "" +msgstr "Largura MÃnima de Paleta" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -12712,24 +12534,20 @@ msgid "Palette Item H Separation" msgstr "Separador Nomeado" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Names" -msgstr "Mostrar todos os Locales" +msgstr "Mostrar Nomes dos Tiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Ids" -msgstr "Mostrar Réguas" +msgstr "Mostrar Ids dos Tiles" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Sort Tiles By Name" -msgstr "Ordenar arquivos" +msgstr "Ordenar Tiles por Nome" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Bucket Fill Preview" -msgstr "Preenchimento de Balde" +msgstr "Pré-visualização do Preenchimento de Balde" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp @@ -12738,9 +12556,8 @@ msgid "Editor Side" msgstr "Editor" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Display Grid" -msgstr "Exibição Overdraw" +msgstr "Mostrar Grid" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -13106,14 +12923,12 @@ msgstr "Passo" #: editor/plugins/tile_set_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separation" -msgstr "Separação:" +msgstr "Separação" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Tile" -msgstr "Selecionar" +msgstr "Selecionar Tile" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp @@ -13122,9 +12937,8 @@ msgstr "Selecionar" #: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp #: scene/resources/material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Texture" -msgstr "Texto" +msgstr "Textura" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -13144,9 +12958,8 @@ msgid "Modulate" msgstr "Popular" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Mode" -msgstr "Alternar Modo" +msgstr "Modo de Tiles" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -13154,14 +12967,12 @@ msgid "Autotile Bitmask Mode" msgstr "Modo Bitmask" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Size" -msgstr "Tamanho do Contorno:" +msgstr "Tamanho do Sub TÃtulo" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Spacing" -msgstr "Loop da Animação" +msgstr "Espaçamento dos Subtiles" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -13169,24 +12980,20 @@ msgid "Occluder Offset" msgstr "Criar PolÃgono de Oclusão" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation Offset" -msgstr "Modo Navegação" +msgstr "Deslocamento da Navegação" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Offset" -msgstr "Deslocamento Base" +msgstr "Deslocamento da Forma" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Transform" -msgstr "Transformação" +msgstr "Transformação da Forma" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision" -msgstr "Colisão" +msgstr "Colisão Selecionada" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -13199,19 +13006,16 @@ msgid "Selected Collision One Way Margin" msgstr "Modo Colisão" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Navigation" -msgstr "Navegação VisÃvel" +msgstr "Navegação Selecionada" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Occlusion" -msgstr "Selecionar" +msgstr "Oclusão Selecionada" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tileset Script" -msgstr "Filtrar scripts" +msgstr "Scripts do Tileset" #: editor/plugins/tile_set_editor_plugin.cpp msgid "TileSet" @@ -13290,7 +13094,7 @@ msgstr "Selecione o caminho da chave privada SSH" #: editor/plugins/version_control_editor_plugin.cpp msgid "SSH Passphrase" -msgstr "SSH Passphrase" +msgstr "Senha SSH" #: editor/plugins/version_control_editor_plugin.cpp msgid "Detect new changes" @@ -14299,11 +14103,13 @@ msgstr "Executável" #: editor/project_export.cpp msgid "Export the project for all the presets defined." -msgstr "" +msgstr "Exportar o projeto para todos os presets definidos." #: editor/project_export.cpp msgid "All presets must have an export path defined for Export All to work." msgstr "" +"Todos os presets devem ter um caminho de exportação para que a " +"funcionalidade de Exportar Todos funcione." #: editor/project_export.cpp msgid "Delete preset '%s'?" @@ -14416,11 +14222,12 @@ msgid "" "Note: Encryption key needs to be stored in the binary,\n" "you need to build the export templates from source." msgstr "" +"Nota: Chaves de encriptação têm que ser salvas com o binário,\n" +"você precisa compilar os modelos de exportação à partir do código fonte." #: editor/project_export.cpp -#, fuzzy msgid "More Info..." -msgstr "Mover Para..." +msgstr "Mais Informações..." #: editor/project_export.cpp msgid "Export PCK/Zip..." @@ -14447,18 +14254,16 @@ msgid "ZIP File" msgstr "Arquivo ZIP" #: editor/project_export.cpp -#, fuzzy msgid "Godot Project Pack" -msgstr "Pacote de Jogos Godot" +msgstr "Pacote do Projeto Godot" #: editor/project_export.cpp msgid "Export templates for this platform are missing:" msgstr "Modelos de exportação para esta plataforma não foram encontrados:" #: editor/project_export.cpp -#, fuzzy msgid "Project Export" -msgstr "Fundadores do Projeto" +msgstr "Exportar Projeto" #: editor/project_export.cpp msgid "Manage Export Templates" @@ -14771,7 +14576,6 @@ msgstr "" #. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp -#, fuzzy msgctxt "Application" msgid "Project Manager" msgstr "Gerenciador de Projetos" @@ -15571,7 +15375,7 @@ msgstr "Tornar Local" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp msgid "Another node already uses this unique name in the scene." -msgstr "" +msgstr "Outro nó já está usando este nome único na cena atual." #: editor/scene_tree_dock.cpp #, fuzzy @@ -15657,7 +15461,7 @@ msgstr "Sub-Recursos" #: editor/scene_tree_dock.cpp msgid "Access as Scene Unique Name" -msgstr "" +msgstr "Acessar como Nome Único de Cena" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" @@ -15762,7 +15566,7 @@ msgstr "Seleção Central" #: editor/scene_tree_dock.cpp msgid "Derive Script Globals By Name" -msgstr "" +msgstr "Obter Globais de Script por Nome" #: editor/scene_tree_dock.cpp #, fuzzy @@ -15795,6 +15599,9 @@ msgid "" "with the '%s' prefix in a node path.\n" "Click to disable this." msgstr "" +"Este nó pode ser acessado em qualquer lugar na cena adicionando o prefixo " +"'%s' em um node path.\n" +"Clique para desabilitar esta funcionalidade." #: editor/scene_tree_editor.cpp msgid "" @@ -16087,15 +15894,15 @@ msgstr "Filtros do tile" #: editor/script_editor_debugger.cpp msgid "Auto Switch To Remote Scene Tree" -msgstr "" +msgstr "Mudar Automaticamente Para a Ãrvore de Cena Remota" #: editor/script_editor_debugger.cpp msgid "Remote Scene Tree Refresh Interval" -msgstr "" +msgstr "Intervalo de Atualização da Ãrvore Remota" #: editor/script_editor_debugger.cpp msgid "Remote Inspect Refresh Interval" -msgstr "" +msgstr "Intervalo de Atualização da Inspeção Remota" #: editor/script_editor_debugger.cpp msgid "Network Profiler" @@ -16193,7 +16000,7 @@ msgstr "Alterar Raio da Luz" #: editor/spatial_editor_gizmos.cpp msgid "Stream Player 3D" -msgstr "" +msgstr "Player de Stream 3D" #: editor/spatial_editor_gizmos.cpp msgid "Change AudioStreamPlayer3D Emission Angle" @@ -16203,7 +16010,7 @@ msgstr "Alterar o Ângulo de Emissão do AudioStreamPlayer3D" #: platform/osx/export/export.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Camera" -msgstr "" +msgstr "Câmera" #: editor/spatial_editor_gizmos.cpp msgid "Change Camera FOV" @@ -16215,7 +16022,7 @@ msgstr "Alterar Tamanho da Câmera" #: editor/spatial_editor_gizmos.cpp msgid "Visibility Notifier" -msgstr "" +msgstr "Notificador de Visibilidade" #: editor/spatial_editor_gizmos.cpp msgid "Change Notifier AABB" @@ -16273,9 +16080,8 @@ msgid "Change Ray Shape Length" msgstr "Alterar o Comprimento da Forma do Raio" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge" -msgstr "Modo Navegação" +msgstr "Bordas de Navegação" #: editor/spatial_editor_gizmos.cpp #, fuzzy @@ -16283,30 +16089,28 @@ msgid "Navigation Edge Disabled" msgstr "Modo Navegação" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid" -msgstr "Modo Navegação" +msgstr "Navegação Sólida" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Solid Disabled" -msgstr "Modo Navegação" +msgstr "Navegação Sólida Desabilitada" #: editor/spatial_editor_gizmos.cpp msgid "Joint Body A" -msgstr "" +msgstr "Corpo de Encaixe A" #: editor/spatial_editor_gizmos.cpp msgid "Joint Body B" -msgstr "" +msgstr "Corpo de Encaixe B" #: editor/spatial_editor_gizmos.cpp msgid "Room Edge" -msgstr "" +msgstr "Canto da Sala" #: editor/spatial_editor_gizmos.cpp msgid "Room Overlap" -msgstr "" +msgstr "Intercessão de Quarto" #: editor/spatial_editor_gizmos.cpp msgid "Set Room Point Position" @@ -16319,11 +16123,11 @@ msgstr "Definir Margem" #: editor/spatial_editor_gizmos.cpp msgid "Portal Edge" -msgstr "" +msgstr "Canto do Portal" #: editor/spatial_editor_gizmos.cpp msgid "Portal Arrow" -msgstr "" +msgstr "Seta do Portal" #: editor/spatial_editor_gizmos.cpp msgid "Set Portal Point Position" @@ -16331,7 +16135,7 @@ msgstr "Definir Posição Do Ponto Do Portal" #: editor/spatial_editor_gizmos.cpp msgid "Portal Front" -msgstr "" +msgstr "Frente do Portal" #: editor/spatial_editor_gizmos.cpp #, fuzzy @@ -16379,12 +16183,12 @@ msgstr "Criar PolÃgono de Oclusão" #: main/main.cpp msgid "Godot Physics" -msgstr "" +msgstr "Godot Physics" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp msgid "Use BVH" -msgstr "" +msgstr "Usar BVH" #: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp #: servers/visual/visual_server_scene.cpp @@ -16407,37 +16211,36 @@ msgid "RID Pool Prealloc" msgstr "" #: main/main.cpp -#, fuzzy msgid "Debugger stdout" -msgstr "Depurador" +msgstr "Depurador stdout" #: main/main.cpp msgid "Max Chars Per Second" -msgstr "" +msgstr "Máximo de Caracteres por Segundo" #: main/main.cpp msgid "Max Messages Per Frame" -msgstr "" +msgstr "Máximo de Mensagens por Quadro" #: main/main.cpp msgid "Max Errors Per Second" -msgstr "" +msgstr "Máximo de Erros por Segundo" #: main/main.cpp msgid "Max Warnings Per Second" -msgstr "" +msgstr "Máximo de Alertas Por Segundo" #: main/main.cpp msgid "Flush stdout On Print" -msgstr "" +msgstr "Limpar stdout ao Fazer Print" #: main/main.cpp servers/visual_server.cpp msgid "Logging" -msgstr "" +msgstr "Registrando Log" #: main/main.cpp msgid "File Logging" -msgstr "" +msgstr "Registrando Log de Arquivos" #: main/main.cpp #, fuzzy @@ -16451,11 +16254,11 @@ msgstr "Copiar Caminho" #: main/main.cpp msgid "Max Log Files" -msgstr "" +msgstr "Máximo Log de Arquivos" #: main/main.cpp msgid "Driver" -msgstr "" +msgstr "Driver" #: main/main.cpp msgid "Driver Name" @@ -16463,41 +16266,39 @@ msgstr "Nome do Driver" #: main/main.cpp msgid "Fallback To GLES2" -msgstr "" +msgstr "Utilizar GLES2 Como Fallback" #: main/main.cpp msgid "Use Nvidia Rect Flicker Workaround" -msgstr "" +msgstr "Utilizar a Gambiarra \"Nvidia Rect Flicker\"" #: main/main.cpp msgid "DPI" -msgstr "" +msgstr "DPI" #: main/main.cpp msgid "Allow hiDPI" -msgstr "" +msgstr "Permitir hiDPI" #: main/main.cpp -#, fuzzy msgid "V-Sync" -msgstr "Sincronizar" +msgstr "Sincronização Vertical (V-Sync)" #: main/main.cpp -#, fuzzy msgid "Use V-Sync" -msgstr "Use Encaixar" +msgstr "Usar Sincronização Vertical (V-Sync)" #: main/main.cpp msgid "Per Pixel Transparency" -msgstr "" +msgstr "Transparência por Pixel" #: main/main.cpp msgid "Allowed" -msgstr "" +msgstr "Permitido" #: main/main.cpp msgid "Intended Usage" -msgstr "" +msgstr "Intenção de Uso" #: main/main.cpp #, fuzzy @@ -16505,13 +16306,12 @@ msgid "Framebuffer Allocation" msgstr "Seleção de Frame" #: main/main.cpp platform/uwp/os_uwp.cpp -#, fuzzy msgid "Energy Saving" -msgstr "Erro ao salvar" +msgstr "Economia de Energia" #: main/main.cpp msgid "Threads" -msgstr "" +msgstr "Threads" #: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h #, fuzzy @@ -16524,19 +16324,17 @@ msgstr "" #: main/main.cpp msgid "Handheld" -msgstr "" +msgstr "Portátil (Handheld)" #: main/main.cpp platform/javascript/export/export.cpp #: platform/uwp/export/export.cpp -#, fuzzy msgid "Orientation" -msgstr "Documentação Online" +msgstr "Orientação" #: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp #: scene/main/scene_tree.cpp scene/register_scene_types.cpp -#, fuzzy msgid "Common" -msgstr "Comunidade" +msgstr "Comum" #: main/main.cpp #, fuzzy @@ -16544,35 +16342,34 @@ msgid "Physics FPS" msgstr "Frame de FÃsica %" #: main/main.cpp -#, fuzzy msgid "Force FPS" -msgstr "Forçar Push" +msgstr "Forçar FPS" #: main/main.cpp msgid "Enable Pause Aware Picking" -msgstr "" +msgstr "Habilitar Escolha que é Ciente à Pausas" #: main/main.cpp scene/gui/item_list.cpp scene/gui/popup_menu.cpp #: scene/gui/scroll_container.cpp scene/gui/text_edit.cpp scene/gui/tree.cpp #: scene/main/viewport.cpp scene/register_scene_types.cpp msgid "GUI" -msgstr "" +msgstr "GUI (Interface Gráfica de Usuário)" #: main/main.cpp msgid "Drop Mouse On GUI Input Disabled" -msgstr "" +msgstr "Desabilitar Mouse quando GUI Input estiver Desabilitad" #: main/main.cpp msgid "stdout" -msgstr "" +msgstr "stdout" #: main/main.cpp msgid "Print FPS" -msgstr "" +msgstr "Mostrar FPS" #: main/main.cpp msgid "Verbose stdout" -msgstr "" +msgstr "stdout Verboso" #: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp #, fuzzy @@ -16580,9 +16377,8 @@ msgid "Physics Interpolation" msgstr "Modo de Interpolação" #: main/main.cpp -#, fuzzy msgid "Enable Warnings" -msgstr "Habilitar Filtragem" +msgstr "Habilitar Avisos" #: main/main.cpp #, fuzzy @@ -16591,19 +16387,19 @@ msgstr "Seleção de Frame" #: main/main.cpp msgid "Low Processor Mode" -msgstr "" +msgstr "Modo Processamento Baixo" #: main/main.cpp msgid "Delta Sync After Draw" -msgstr "" +msgstr "Sincronizar Delta Após o Draw" #: main/main.cpp msgid "iOS" -msgstr "" +msgstr "iOS" #: main/main.cpp msgid "Hide Home Indicator" -msgstr "" +msgstr "Esconder Indicador de Home" #: main/main.cpp #, fuzzy @@ -16617,16 +16413,15 @@ msgstr "Ponto" #: main/main.cpp msgid "Touch Delay" -msgstr "" +msgstr "Atraso de Touch" #: main/main.cpp servers/visual_server.cpp msgid "GLES3" -msgstr "" +msgstr "GLES3" #: main/main.cpp servers/visual_server.cpp -#, fuzzy msgid "Shaders" -msgstr "Shader" +msgstr "Shaders" #: main/main.cpp #, fuzzy @@ -16636,30 +16431,28 @@ msgstr "Forçar Fallbacks do Shader" #: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp #: scene/3d/world_environment.cpp scene/main/scene_tree.cpp #: scene/resources/world.cpp -#, fuzzy msgid "Environment" -msgstr "Visualizar Ambiente" +msgstr "Ambiente" #: main/main.cpp msgid "Default Clear Color" -msgstr "" +msgstr "Cor de Limpeza Padrão" #: main/main.cpp msgid "Boot Splash" -msgstr "" +msgstr "Imagem de Exibição ao Iniciar" #: main/main.cpp -#, fuzzy msgid "Show Image" -msgstr "Mostrar Ossos" +msgstr "Mostrar Imagem" #: main/main.cpp msgid "Image" -msgstr "" +msgstr "Imagem" #: main/main.cpp msgid "Fullsize" -msgstr "" +msgstr "Tamanho Inteiro" #: main/main.cpp scene/resources/dynamic_font.cpp msgid "Use Filter" @@ -16671,13 +16464,12 @@ msgid "BG Color" msgstr "Cores" #: main/main.cpp -#, fuzzy msgid "macOS Native Icon" -msgstr "Definir Ãcone de telha" +msgstr "Ãcone Nativo macOS" #: main/main.cpp msgid "Windows Native Icon" -msgstr "" +msgstr "Ãcone Windows Nativo" #: main/main.cpp msgid "Buffering" @@ -16685,29 +16477,27 @@ msgstr "" #: main/main.cpp msgid "Agile Event Flushing" -msgstr "" +msgstr "Limpeza de Eventos Agil" #: main/main.cpp msgid "Emulate Touch From Mouse" -msgstr "" +msgstr "Simular Toque à Partir do Mouse" #: main/main.cpp msgid "Emulate Mouse From Touch" -msgstr "" +msgstr "Simular Mouse à Partir do Touch" #: main/main.cpp -#, fuzzy msgid "Mouse Cursor" -msgstr "Botão do Mouse" +msgstr "Cursor do Mouse" #: main/main.cpp -#, fuzzy msgid "Custom Image" -msgstr "Recortar Nós" +msgstr "Imagem Personalizada" #: main/main.cpp msgid "Custom Image Hotspot" -msgstr "" +msgstr "Imagem Personalizada de Hotspot" #: main/main.cpp msgid "Tooltip Position Offset" @@ -16719,9 +16509,8 @@ msgid "Debugger Agent" msgstr "Depurador" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Wait For Debugger" -msgstr "Depurador" +msgstr "Esperar pelo Depurador" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Wait Timeout" @@ -16729,11 +16518,11 @@ msgstr "Tempo Limite de Espera" #: main/main.cpp msgid "Runtime" -msgstr "" +msgstr "Tempo de Execução" #: main/main.cpp msgid "Unhandled Exception Policy" -msgstr "" +msgstr "Politica de Tratamento Exceções" #: main/main.cpp #, fuzzy @@ -16742,22 +16531,20 @@ msgstr "Localizar Tipo de Nó" #: main/main.cpp scene/gui/texture_progress.cpp #: scene/gui/viewport_container.cpp -#, fuzzy msgid "Stretch" -msgstr "Buscar" +msgstr "Esticar" #: main/main.cpp -#, fuzzy msgid "Aspect" -msgstr "Inspetor" +msgstr "Aspecto" #: main/main.cpp msgid "Shrink" -msgstr "" +msgstr "Encolher" #: main/main.cpp scene/main/scene_tree.cpp msgid "Auto Accept Quit" -msgstr "" +msgstr "Aceitar Sair Automaticamente" #: main/main.cpp scene/main/scene_tree.cpp #, fuzzy @@ -16771,15 +16558,15 @@ msgstr "Encaixar nos Lados do Nó" #: main/main.cpp msgid "Dynamic Fonts" -msgstr "" +msgstr "Fontes Dinâmicas" #: main/main.cpp msgid "Use Oversampling" -msgstr "" +msgstr "Utilizar Oversampling" #: modules/bullet/register_types.cpp modules/bullet/space_bullet.cpp msgid "Active Soft World" -msgstr "" +msgstr "Ativar Mundo Macio" #: modules/csg/csg_gizmos.cpp msgid "CSG" @@ -16802,35 +16589,30 @@ msgid "Change Torus Outer Radius" msgstr "Alterar Raio Externo do Toro" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Operation" -msgstr "Opções" +msgstr "Operação" #: modules/csg/csg_shape.cpp msgid "Calculate Tangents" -msgstr "" +msgstr "Calcular Tangentes" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Use Collision" -msgstr "Colisão" +msgstr "Usar Colisão" #: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp -#, fuzzy msgid "Collision Layer" -msgstr "Modo Colisão" +msgstr "Camada de Colisão" #: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp #: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp #: scene/resources/navigation_mesh.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Mask" -msgstr "Modo Colisão" +msgstr "Máscara de Colisão" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Invert Faces" -msgstr "Converter MaÃusculas/Minúsculas" +msgstr "Inverter Faces" #: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp #: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp @@ -16848,14 +16630,12 @@ msgid "Radial Segments" msgstr "Segmentos Radiais" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Rings" -msgstr "Avisos" +msgstr "Anéis" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Smooth Faces" -msgstr "Passo suave" +msgstr "Suavizar Faces" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16864,7 +16644,7 @@ msgstr "Mostrar Guias" #: modules/csg/csg_shape.cpp msgid "Cone" -msgstr "" +msgstr "Cone" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16878,27 +16658,25 @@ msgstr "Alterar Raio Externo do Toro" #: modules/csg/csg_shape.cpp msgid "Ring Sides" -msgstr "" +msgstr "Lados de Anel" #: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp #: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp #: scene/3d/collision_polygon.cpp -#, fuzzy msgid "Polygon" -msgstr "PolÃgonos" +msgstr "PolÃgono" #: modules/csg/csg_shape.cpp msgid "Spin Degrees" -msgstr "" +msgstr "Graus de Rotação" #: modules/csg/csg_shape.cpp msgid "Spin Sides" -msgstr "" +msgstr "Lados de Rotação" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Node" -msgstr "Colar Nós" +msgstr "Caminho do Nó" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16907,11 +16685,11 @@ msgstr "Criar Vertex Interno" #: modules/csg/csg_shape.cpp msgid "Path Interval" -msgstr "" +msgstr "Intervalo de Caminho" #: modules/csg/csg_shape.cpp msgid "Path Simplify Angle" -msgstr "" +msgstr "Ângulo de Simplificação de Caminho" #: modules/csg/csg_shape.cpp msgid "Path Rotation" @@ -16936,58 +16714,52 @@ msgid "Path Joined" msgstr "Caminho Unido" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Compression Mode" -msgstr "Modo Colisão" +msgstr "Modo de Compressão" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Transfer Channel" -msgstr "Alteração de Transformação" +msgstr "Transferir Canal" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Channel Count" -msgstr "Instância" +msgstr "Quantidade de Canais" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Always Ordered" -msgstr "Sempre Mostrar Grade" +msgstr "Sempre Ordenado" #: modules/enet/networked_multiplayer_enet.cpp msgid "Server Relay" -msgstr "" +msgstr "Retransmissor de Servidor" #: modules/enet/networked_multiplayer_enet.cpp msgid "DTLS Verify" -msgstr "" +msgstr "Virificar DTLS" #: modules/enet/networked_multiplayer_enet.cpp msgid "DTLS Hostname" -msgstr "" +msgstr "Nome de Host DTLS" #: modules/enet/networked_multiplayer_enet.cpp -#, fuzzy msgid "Use DTLS" -msgstr "Use Encaixar" +msgstr "Usar DTLS" #: modules/fbx/editor_scene_importer_fbx.cpp msgid "FBX" -msgstr "" +msgstr "FBX" #: modules/fbx/editor_scene_importer_fbx.cpp msgid "Use FBX" -msgstr "" +msgstr "Utilizar FBX" #: modules/gdnative/gdnative.cpp msgid "Config File" msgstr "Arquivo de Configuração" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Load Once" -msgstr "Carregar Recurso" +msgstr "Carregar Apenas uma Vez" #: modules/gdnative/gdnative.cpp #: modules/visual_script/visual_script_func_nodes.cpp @@ -17000,9 +16772,8 @@ msgid "Symbol Prefix" msgstr "Prefixo do SÃmbolo" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Reloadable" -msgstr "Recarregar" +msgstr "Recarregável" #: modules/gdnative/gdnative.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -17067,9 +16838,8 @@ msgid "Script Class" msgstr "Classe do Script" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Icon Path" -msgstr "Habilitar" +msgstr "Caminho para Ãcone" #: modules/gdnative/register_types.cpp msgid "GDNative" @@ -17082,7 +16852,7 @@ msgstr "GDScript" #: modules/gdscript/editor/gdscript_highlighter.cpp msgid "Function Definition Color" -msgstr "" +msgstr "Cor de Definição de Função" #: modules/gdscript/editor/gdscript_highlighter.cpp #, fuzzy @@ -17091,19 +16861,19 @@ msgstr "Copiar Caminho do Nó" #: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp msgid "Max Call Stack" -msgstr "" +msgstr "Tamanho Máximo da Pilha de Chamadas de Função" #: modules/gdscript/gdscript.cpp msgid "Treat Warnings As Errors" -msgstr "" +msgstr "Trate Alertas como Erros" #: modules/gdscript/gdscript.cpp msgid "Exclude Addons" -msgstr "" +msgstr "Excluir Addons" #: modules/gdscript/gdscript.cpp msgid "Autocomplete Setters And Getters" -msgstr "" +msgstr "Auto Completar Setters e Getters" #: modules/gdscript/gdscript_functions.cpp msgid "Step argument is zero!" @@ -17154,11 +16924,11 @@ msgstr "Não foi possÃvel resolver" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Show Native Symbols In Editor" -msgstr "" +msgstr "Exibir Simbolos Nativos no Editor" #: modules/gdscript/language_server/gdscript_language_server.cpp msgid "Use Thread" -msgstr "" +msgstr "Utilize Thread" #: modules/gltf/editor_scene_exporter_gltf_plugin.cpp msgid "Export Mesh GLTF2" @@ -17178,9 +16948,8 @@ msgid "Byte Offset" msgstr "Deslocamento do Byte" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Component Type" -msgstr "Componentes" +msgstr "Tipo do Componente" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17192,14 +16961,12 @@ msgid "Count" msgstr "Quantidade" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Min" -msgstr "MiB" +msgstr "Min" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Max" -msgstr "Misturar" +msgstr "Max" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17241,9 +17008,8 @@ msgid "Byte Stride" msgstr "" #: modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Indices" -msgstr "Todos os dispositivos" +msgstr "Ãndices" #: modules/gltf/gltf_camera.cpp msgid "FOV Size" @@ -17266,19 +17032,17 @@ msgstr "Linear" #: scene/resources/environment.cpp scene/resources/material.cpp #: scene/resources/particles_material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Color" -msgstr "Cores" +msgstr "Cor" #: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp #: scene/resources/environment.cpp msgid "Intensity" -msgstr "" +msgstr "Intensidade" #: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp -#, fuzzy msgid "Range" -msgstr "Alterar" +msgstr "Intervalo" #: modules/gltf/gltf_light.cpp msgid "Inner Cone Angle" @@ -17309,35 +17073,31 @@ msgstr "Plataforma" #: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp msgid "Skin" -msgstr "" +msgstr "Skin" #: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp -#, fuzzy msgid "Translation" -msgstr "Traduções" +msgstr "Tradução" #: modules/gltf/gltf_node.cpp -#, fuzzy msgid "Children" -msgstr "Filhos Editáveis" +msgstr "Filhos" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints" -msgstr "Ponto" +msgstr "Pontos" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp msgid "Roots" -msgstr "" +msgstr "RaÃzes" #: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp msgid "Unique Names" -msgstr "" +msgstr "Nomes Únicos" #: modules/gltf/gltf_skeleton.cpp -#, fuzzy msgid "Godot Bone Node" -msgstr "Nó TimeSeek" +msgstr "Nó de Osso Godot" #: modules/gltf/gltf_skin.cpp #, fuzzy @@ -17345,9 +17105,8 @@ msgid "Skin Root" msgstr "Nova Raiz de Cena" #: modules/gltf/gltf_skin.cpp -#, fuzzy msgid "Joints Original" -msgstr "Origem do Foco" +msgstr "Pontos Originais" #: modules/gltf/gltf_skin.cpp msgid "Inverse Binds" @@ -17392,12 +17151,11 @@ msgstr "" #: modules/gltf/gltf_state.cpp msgid "Json" -msgstr "" +msgstr "Json" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Major Version" -msgstr "Versão" +msgstr "Versão Importante" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17427,28 +17185,25 @@ msgid "Scene Name" msgstr "Nome da Cena" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Root Nodes" -msgstr "Nome do nó raiz" +msgstr "Nós RaÃzes" #: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp #: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp -#, fuzzy msgid "Textures" -msgstr "Funcionalidades" +msgstr "Texturas" #: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp msgid "Images" -msgstr "" +msgstr "Imagens" #: modules/gltf/gltf_state.cpp msgid "Cameras" -msgstr "" +msgstr "Câmeras" #: modules/gltf/gltf_state.cpp servers/visual_server.cpp -#, fuzzy msgid "Lights" -msgstr "Luz" +msgstr "Luzes" #: modules/gltf/gltf_state.cpp msgid "Unique Animation Names" @@ -17459,9 +17214,8 @@ msgid "Skeletons" msgstr "Esqueletos" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Skeleton To Node" -msgstr "Selecione um Nó" +msgstr "Esqueleto Para Nó" #: modules/gltf/gltf_state.cpp msgid "Animations" @@ -17488,7 +17242,7 @@ msgstr "Faça mapas de luz" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp msgid "Cell" -msgstr "" +msgstr "Célula" #: modules/gridmap/grid_map.cpp #, fuzzy @@ -17496,25 +17250,22 @@ msgid "Octant Size" msgstr "Visão Frontal" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center X" -msgstr "Centro" +msgstr "Centro X" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Y" -msgstr "Centro" +msgstr "Centro Y" #: modules/gridmap/grid_map.cpp -#, fuzzy msgid "Center Z" -msgstr "Centro" +msgstr "Centro Z" #: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp #: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp #: scene/resources/material.cpp msgid "Mask" -msgstr "" +msgstr "Máscara" #: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp #, fuzzy @@ -17525,9 +17276,8 @@ msgstr "Navegação" #: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp #: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp #: scene/3d/navigation_mesh_instance.cpp -#, fuzzy msgid "Navigation Layers" -msgstr "Modo Navegação" +msgstr "Camadas da Navegação" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Next Plane" @@ -17829,7 +17579,7 @@ msgstr "Pronto!" #: modules/opensimplex/noise_texture.cpp msgid "Seamless" -msgstr "" +msgstr "Sem Emenda" #: modules/opensimplex/noise_texture.cpp msgid "As Normal Map" @@ -17849,7 +17599,7 @@ msgstr "Deslocamento do RuÃdo" #: modules/opensimplex/open_simplex_noise.cpp msgid "Octaves" -msgstr "" +msgstr "Oitavas" #: modules/opensimplex/open_simplex_noise.cpp msgid "Period" @@ -17866,7 +17616,7 @@ msgstr "" #: modules/regex/regex.cpp msgid "Subject" -msgstr "" +msgstr "Sujeito" #: modules/regex/regex.cpp #, fuzzy @@ -18318,7 +18068,7 @@ msgstr "Iterador" #: modules/visual_script/visual_script_flow_control.cpp msgid "for (elem) in (input):" -msgstr "" +msgstr "para (elem) em (input):" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable:" @@ -18352,7 +18102,7 @@ msgstr "Switch" #: modules/visual_script/visual_script_flow_control.cpp msgid "'input' is:" -msgstr "" +msgstr "'input' é:" #: modules/visual_script/visual_script_flow_control.cpp msgid "Type Cast" @@ -18604,7 +18354,7 @@ msgstr "Chamadas" #: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp msgid "Title" -msgstr "" +msgstr "TÃtulo" #: modules/visual_script/visual_script_nodes.cpp #, fuzzy @@ -18683,7 +18433,7 @@ msgstr "Modo Prioridade" #: modules/webrtc/webrtc_data_channel.h msgid "WebRTC" -msgstr "" +msgstr "WebRTC" #: modules/webrtc/webrtc_data_channel.h #, fuzzy @@ -18917,7 +18667,7 @@ msgstr "Inspecionar a Instância Anterior" #: platform/android/export/export_plugin.cpp msgid "Code" -msgstr "" +msgstr "Código" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp #, fuzzy @@ -19010,7 +18760,7 @@ msgstr "Interface de Usuário" #: platform/android/export/export_plugin.cpp msgid "Allow" -msgstr "" +msgstr "Permitir" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp #, fuzzy @@ -19028,7 +18778,7 @@ msgstr "Expressão" #: platform/android/export/export_plugin.cpp msgid "Salt" -msgstr "" +msgstr "Sal" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -19323,10 +19073,8 @@ msgstr "" "do projeto" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "" -"Não foi possÃvel exportar os arquivos do projeto ao projeto do gradle\n" +msgstr "Não foi possÃvel exportar os arquivos do projeto ao projeto do gradle" #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -19410,19 +19158,19 @@ msgstr "" #: platform/iphone/export/export.cpp msgid "iPhone 2436 X 1125" -msgstr "" +msgstr "IPhone 2436 X 1125" #: platform/iphone/export/export.cpp msgid "iPhone 2208 X 1242" -msgstr "" +msgstr "iPhone 2208 X 1242" #: platform/iphone/export/export.cpp msgid "iPad 1024 X 768" -msgstr "" +msgstr "iPad 1024 X 768" #: platform/iphone/export/export.cpp msgid "iPad 2048 X 1536" -msgstr "" +msgstr "iPad 2048 X 1536" #: platform/iphone/export/export.cpp msgid "Portrait Launch Screens" @@ -19430,31 +19178,31 @@ msgstr "" #: platform/iphone/export/export.cpp msgid "iPhone 640 X 960" -msgstr "" +msgstr "iPhone 640 X 960" #: platform/iphone/export/export.cpp msgid "iPhone 640 X 1136" -msgstr "" +msgstr "iPhone 640 X 1136" #: platform/iphone/export/export.cpp msgid "iPhone 750 X 1334" -msgstr "" +msgstr "iPhone 750 X 1334" #: platform/iphone/export/export.cpp msgid "iPhone 1125 X 2436" -msgstr "" +msgstr "iPhone 1125 X 2436" #: platform/iphone/export/export.cpp msgid "iPad 768 X 1024" -msgstr "" +msgstr "iPad 768 X 1024" #: platform/iphone/export/export.cpp msgid "iPad 1536 X 2048" -msgstr "" +msgstr "iPad 1536 X 2048" #: platform/iphone/export/export.cpp msgid "iPhone 1242 X 2208" -msgstr "" +msgstr "iPhone 1242 X 2208" #: platform/iphone/export/export.cpp msgid "App Store Team ID" @@ -19491,7 +19239,7 @@ msgstr "" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp msgid "Info" -msgstr "" +msgstr "Informação" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp msgid "Identifier" @@ -19561,23 +19309,23 @@ msgstr "Descrições da Propriedade" #: platform/iphone/export/export.cpp msgid "iPhone 120 X 120" -msgstr "" +msgstr "iPhone 120 X 120" #: platform/iphone/export/export.cpp msgid "iPhone 180 X 180" -msgstr "" +msgstr "iPhone 180 X 180" #: platform/iphone/export/export.cpp msgid "iPad 76 X 76" -msgstr "" +msgstr "iPad 76 X 76" #: platform/iphone/export/export.cpp msgid "iPad 152 X 152" -msgstr "" +msgstr "iPad 152 X 152" #: platform/iphone/export/export.cpp msgid "iPad 167 X 167" -msgstr "" +msgstr "iPad 167 X 167" #: platform/iphone/export/export.cpp msgid "App Store 1024 X 1024" @@ -19661,14 +19409,12 @@ msgid "Could not open template for export: \"%s\"." msgstr "Não foi possÃvel abrir o modelo para exportação: \"%s\"." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Invalid export template: \"%s\"." -msgstr "Template de exportação inválido:" +msgstr "Template de exportação inválido: \"%s\"." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not write file: \"%s\"." -msgstr "Não foi possÃvel escrever o arquivo:" +msgstr "Não foi possÃvel escrever o arquivo: \"%s\"." #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #, fuzzy @@ -19681,7 +19427,7 @@ msgstr "Não foi possÃvel ler o arquivo: \"%s\"." #: platform/javascript/export/export.cpp msgid "PWA" -msgstr "" +msgstr "PWA" #: platform/javascript/export/export.cpp msgid "Variant" @@ -19699,15 +19445,15 @@ msgstr "Expressão" #: platform/javascript/export/export.cpp msgid "For Desktop" -msgstr "" +msgstr "Para Desktop" #: platform/javascript/export/export.cpp msgid "For Mobile" -msgstr "" +msgstr "Para Mobile" #: platform/javascript/export/export.cpp msgid "HTML" -msgstr "" +msgstr "HTML" #: platform/javascript/export/export.cpp #, fuzzy @@ -19728,8 +19474,9 @@ msgid "Canvas Resize Policy" msgstr "" #: platform/javascript/export/export.cpp +#, fuzzy msgid "Focus Canvas On Start" -msgstr "" +msgstr "Focar Canvas ao Iniciar" #: platform/javascript/export/export.cpp #, fuzzy @@ -19738,11 +19485,11 @@ msgstr "Filtrar sinais" #: platform/javascript/export/export.cpp msgid "Progressive Web App" -msgstr "" +msgstr "Progressive Web App" #: platform/javascript/export/export.cpp msgid "Offline Page" -msgstr "" +msgstr "Página Offline" #: platform/javascript/export/export.cpp msgid "Icon 144 X 144" @@ -19761,9 +19508,8 @@ msgid "Could not read HTML shell: \"%s\"." msgstr "Não foi possÃvel ler o shell HTML: \"%s\"." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not create HTTP server directory: %s." -msgstr "Não foi possÃvel criar o diretório do servidor HTTP:" +msgstr "Não foi possÃvel criar o diretório do servidor HTTP: \"%s\"." #: platform/javascript/export/export.cpp msgid "Error starting HTTP server: %d." @@ -19771,7 +19517,7 @@ msgstr "Erro ao iniciar o servidor HTTP: %d." #: platform/javascript/export/export.cpp msgid "Web" -msgstr "" +msgstr "Web" #: platform/javascript/export/export.cpp msgid "HTTP Host" @@ -19788,7 +19534,7 @@ msgstr "Use Encaixar" #: platform/javascript/export/export.cpp msgid "SSL Key" -msgstr "" +msgstr "Chave SSL" #: platform/osx/export/codesign.cpp msgid "Can't get filesystem access." @@ -19828,7 +19574,7 @@ msgstr "Caminho base inválido." #: platform/osx/export/codesign.cpp msgid "Already signed!" -msgstr "" +msgstr "Já assinado!" #: platform/osx/export/codesign.cpp #, fuzzy @@ -19868,7 +19614,7 @@ msgstr "" #: platform/osx/export/codesign.cpp msgid "Unknown object type." -msgstr "" +msgstr "Tipo de objeto desconhecido." #: platform/osx/export/export.cpp msgid "App Category" @@ -19876,7 +19622,7 @@ msgstr "Categoria do Aplicativo" #: platform/osx/export/export.cpp msgid "High Res" -msgstr "" +msgstr "Alta Resolução" #: platform/osx/export/export.cpp #, fuzzy @@ -19956,7 +19702,7 @@ msgstr "Recortar Nós" #: platform/osx/export/export.cpp msgid "Allow JIT Code Execution" -msgstr "" +msgstr "Permitir Execução de Código JIT" #: platform/osx/export/export.cpp msgid "Allow Unsigned Executable Memory" @@ -19978,7 +19724,7 @@ msgstr "Adicionar Entrada" #: platform/osx/export/export.cpp msgid "Address Book" -msgstr "" +msgstr "Contatos" #: platform/osx/export/export.cpp msgid "Calendars" @@ -20020,7 +19766,7 @@ msgstr "Dispositivo" #: platform/osx/export/export.cpp msgid "Device Bluetooth" -msgstr "" +msgstr "Bluetooth do Dispositivo" #: platform/osx/export/export.cpp #, fuzzy @@ -20092,6 +19838,8 @@ msgid "" "You can check progress manually by opening a Terminal and running the " "following command:" msgstr "" +"Você pode verificar o progresso manualmente abrindo um Terminal e rodando o " +"seguinte comando:" #: platform/osx/export/export.cpp msgid "" @@ -20121,6 +19869,8 @@ msgid "" "Could not start codesign executable, make sure Xcode command line tools are " "installed." msgstr "" +"Não foi possÃvel iniciar o executável codesign, tenha certeza que as " +"utilidades de linha de comando do Xcode estão instaladas." #: platform/osx/export/export.cpp platform/windows/export/export.cpp #, fuzzy @@ -20181,7 +19931,7 @@ msgstr "" #: platform/osx/export/export.cpp msgid "Making PKG" -msgstr "" +msgstr "Criando PKG" #: platform/osx/export/export.cpp msgid "" @@ -20195,7 +19945,7 @@ msgstr "" #: platform/osx/export/export.cpp msgid "Making DMG" -msgstr "" +msgstr "Criando DMG" #: platform/osx/export/export.cpp msgid "Code signing DMG" @@ -20203,7 +19953,7 @@ msgstr "" #: platform/osx/export/export.cpp msgid "Making ZIP" -msgstr "" +msgstr "Criando ZIP" #: platform/osx/export/export.cpp msgid "" @@ -20366,7 +20116,7 @@ msgstr "Nome Curto" #: platform/uwp/export/export.cpp msgid "Publisher" -msgstr "" +msgstr "Publicadora" #: platform/uwp/export/export.cpp msgid "Publisher Display Name" @@ -20414,7 +20164,7 @@ msgstr "Revisão" #: platform/uwp/export/export.cpp msgid "Landscape" -msgstr "" +msgstr "Paisagem" #: platform/uwp/export/export.cpp #, fuzzy @@ -20423,11 +20173,11 @@ msgstr "Inverter Horizontalmente" #: platform/uwp/export/export.cpp msgid "Landscape Flipped" -msgstr "" +msgstr "Paisagem Invertido" #: platform/uwp/export/export.cpp msgid "Portrait Flipped" -msgstr "" +msgstr "Retrato Invertido" #: platform/uwp/export/export.cpp #, fuzzy @@ -20529,7 +20279,7 @@ msgstr "Dimensões inválidas da tela de abertura (deve ser 620x300)." #: platform/uwp/export/export.cpp msgid "UWP" -msgstr "" +msgstr "UWP" #: platform/uwp/export/export.cpp platform/windows/export/export.cpp #, fuzzy @@ -20546,13 +20296,13 @@ msgid "Debug Algorithm" msgstr "Depurador" #: platform/windows/export/export.cpp -#, fuzzy msgid "Failed to rename temporary file \"%s\"." -msgstr "Não é possÃvel remover o arquivo temporário:" +msgstr "Falha ao renomear arquivo temporário \"%s\"." #: platform/windows/export/export.cpp +#, fuzzy msgid "Identity Type" -msgstr "" +msgstr "Tipo de Identidade" #: platform/windows/export/export.cpp msgid "Timestamp Server URL" @@ -20592,7 +20342,7 @@ msgstr "Descrição" #: platform/windows/export/export.cpp msgid "Trademarks" -msgstr "" +msgstr "Marca Registrada (Trademarks)" #: platform/windows/export/export.cpp #, fuzzy @@ -20611,15 +20361,15 @@ msgstr "O keystore não foi encontrado, não foi possÃvel exportar." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Extensão inválida." #: platform/windows/export/export.cpp #, fuzzy @@ -20642,15 +20392,15 @@ msgstr "Nome Inválido." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Extensão inválida." #: platform/windows/export/export.cpp msgid "Failed to remove temporary file \"%s\"." @@ -20698,7 +20448,7 @@ msgstr "Nova Janela" #: platform/windows/export/export.cpp msgid "Rcedit" -msgstr "" +msgstr "Rcedit" #: platform/windows/export/export.cpp msgid "Osslsigncode" @@ -20897,7 +20647,7 @@ msgstr "Modo de Movimentação" #: scene/2d/camera_2d.cpp msgid "Limit" -msgstr "" +msgstr "Limite" #: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp @@ -21197,7 +20947,7 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Drawing" -msgstr "" +msgstr "Desenhando" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21208,7 +20958,7 @@ msgstr "Projetos Locais" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp msgid "Draw Order" -msgstr "" +msgstr "Ordem de Desenho" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21265,7 +21015,7 @@ msgstr "Velocidade" #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Angular Velocity" -msgstr "" +msgstr "Velocidade Angular" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21334,7 +21084,7 @@ msgstr "Dvidir Curva" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp #: scene/resources/particles_material.cpp msgid "Angle" -msgstr "" +msgstr "Ângulo" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21460,7 +21210,7 @@ msgstr "" #: scene/2d/joints_2d.cpp scene/resources/animation.cpp #: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp msgid "Length" -msgstr "" +msgstr "Comprimento" #: scene/2d/joints_2d.cpp #, fuzzy @@ -21496,7 +21246,7 @@ msgstr "Região da Textura" #: scene/3d/light.cpp scene/resources/environment.cpp #: scene/resources/material.cpp scene/resources/sky.cpp msgid "Energy" -msgstr "" +msgstr "Energia" #: scene/2d/light_2d.cpp msgid "Z Min" @@ -21574,7 +21324,7 @@ msgstr "Padrão" #: scene/2d/line_2d.cpp scene/resources/texture.cpp msgid "Fill" -msgstr "" +msgstr "Preencher" #: scene/2d/line_2d.cpp scene/resources/texture.cpp #, fuzzy @@ -21730,7 +21480,7 @@ msgstr "Viagem" msgid "Rotation Degrees" msgstr "Graus de Rotação" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "Rotação Global" @@ -21919,7 +21669,7 @@ msgstr "" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Mass" -msgstr "" +msgstr "Massa" #: scene/2d/physics_body_2d.cpp msgid "Inertia" @@ -21968,7 +21718,7 @@ msgstr "Úmido" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Angular" -msgstr "" +msgstr "Angular" #: scene/2d/physics_body_2d.cpp msgid "Applied Forces" @@ -22081,15 +21831,15 @@ msgstr "Criar Nó Shader" #: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp msgid "Collide With" -msgstr "" +msgstr "Colidir com" #: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp msgid "Areas" -msgstr "" +msgstr "Ãreas" #: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp msgid "Bodies" -msgstr "" +msgstr "Corpos" #: scene/2d/remote_transform_2d.cpp msgid "Path property must point to a valid Node2D node to work." @@ -22331,15 +22081,15 @@ msgstr "Nó de Animação" #: scene/3d/audio_stream_player_3d.cpp msgid "Unit dB" -msgstr "" +msgstr "Unidade dB" #: scene/3d/audio_stream_player_3d.cpp msgid "Unit Size" -msgstr "" +msgstr "Tamanho da Unidade" #: scene/3d/audio_stream_player_3d.cpp msgid "Max dB" -msgstr "" +msgstr "Max dB" #: scene/3d/audio_stream_player_3d.cpp msgid "Out Of Range Mode" @@ -22387,7 +22137,7 @@ msgstr "Empacotando" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp #: scene/3d/reflection_probe.cpp msgid "Interior" -msgstr "" +msgstr "Interior" #: scene/3d/baked_lightmap.cpp msgid "Finding meshes and lights" @@ -22438,7 +22188,7 @@ msgstr "Usar Redutor de RuÃdo" #: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp msgid "Use HDR" -msgstr "" +msgstr "Usar HDR" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -22537,7 +22287,7 @@ msgstr "Mais próximo" #: scene/3d/camera.cpp msgid "Far" -msgstr "" +msgstr "Longe" #: scene/3d/camera.cpp scene/3d/collision_polygon.cpp scene/3d/spring_arm.cpp #: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp @@ -22789,9 +22539,8 @@ msgid "Font" msgstr "Fontes" #: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Horizontal Alignment" -msgstr "Horizontal:" +msgstr "Alinhamento Horizontal" #: scene/3d/label_3d.cpp #, fuzzy @@ -22902,6 +22651,8 @@ msgid "" "be removed in a future version. Use 'NavigationServer.map_get_path()' " "instead." msgstr "" +"O nó 'Navigation' e 'Navigation.get_simple_path()' estão depreciados e serão " +"removidos em versões futuras. Use 'NavigationServer.map_get_path()' no lugar." #: scene/3d/navigation.cpp scene/resources/curve.cpp #, fuzzy @@ -23156,15 +22907,15 @@ msgstr "Animação" #: scene/3d/physics_body.cpp msgid "X" -msgstr "" +msgstr "X" #: scene/3d/physics_body.cpp msgid "Y" -msgstr "" +msgstr "Y" #: scene/3d/physics_body.cpp msgid "Z" -msgstr "" +msgstr "Z" #: scene/3d/physics_body.cpp #, fuzzy @@ -23481,7 +23232,7 @@ msgstr "Depurador" #: scene/3d/ray_cast.cpp scene/resources/style_box.cpp msgid "Thickness" -msgstr "" +msgstr "Espessura" #: scene/3d/reflection_probe.cpp scene/main/viewport.cpp #, fuzzy @@ -23588,7 +23339,7 @@ msgstr "Só Deve existir um RoomManager na SceneTree." #: scene/3d/room_manager.cpp msgid "Main" -msgstr "" +msgstr "Principal" #: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp #: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp @@ -23808,8 +23559,13 @@ msgstr "" "Altere o tamanho em formas de colisão de crianças." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Manter Transformação Global" + +#: scene/3d/spatial.cpp msgid "Matrix" -msgstr "" +msgstr "Matriz" #: scene/3d/spatial.cpp #, fuzzy @@ -23827,7 +23583,7 @@ msgstr "" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp msgid "Opacity" -msgstr "" +msgstr "Opacidade" #: scene/3d/sprite_3d.cpp scene/resources/material.cpp msgid "Transparent" @@ -23926,9 +23682,8 @@ msgid "Cast Shadow" msgstr "Criar Nó Shader" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Extra Cull Margin" -msgstr "Argumentos de Chamada Extras:" +msgstr "Margem de Descarte Extra" #: scene/3d/visual_instance.cpp #, fuzzy @@ -23950,9 +23705,8 @@ msgstr "" #: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp #: scene/resources/material.cpp -#, fuzzy msgid "Min Distance" -msgstr "Escolha uma Distância:" +msgstr "Distância MÃnima" #: scene/3d/visual_instance.cpp msgid "Min Hysteresis" @@ -23999,33 +23753,28 @@ msgid "Mix Mode" msgstr "Nó Mix" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Fadein Time" -msgstr "Tempo do X-Fade (s):" +msgstr "Tempo de Esmaecer de Entrada" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Fadeout Time" -msgstr "Tempo do X-Fade (s):" +msgstr "Tempo de Esmaecer de SaÃda" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Auto Restart" -msgstr "ReinÃcio Automático:" +msgstr "ReinÃcio Automático" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Autorestart" -msgstr "ReinÃcio Automático:" +msgstr "ReinÃcio Automático" #: scene/animation/animation_blend_tree.cpp msgid "Delay" -msgstr "" +msgstr "Atraso" #: scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Random Delay" -msgstr "Inclinação aleatória:" +msgstr "Atraso Aleatório" #: scene/animation/animation_blend_tree.cpp #, fuzzy @@ -24049,9 +23798,8 @@ msgstr "Adicionar porta de entrada" #: scene/animation/animation_blend_tree.cpp #: scene/animation/animation_node_state_machine.cpp -#, fuzzy msgid "Xfade Time" -msgstr "Tempo do X-Fade (s):" +msgstr "Tempo do Esmaecer Cruzado" #: scene/animation/animation_node_state_machine.cpp #, fuzzy @@ -24084,7 +23832,7 @@ msgstr "Adicionar Animação" #: scene/animation/animation_player.cpp msgid "Reset On Save" -msgstr "" +msgstr "Redefinir ao Salvar" #: scene/animation/animation_player.cpp #, fuzzy @@ -24097,9 +23845,8 @@ msgid "Current Animation Position" msgstr "Adicionar ponto de Animação" #: scene/animation/animation_player.cpp -#, fuzzy msgid "Playback Options" -msgstr "Opções da Classe:" +msgstr "Opções de Playback" #: scene/animation/animation_player.cpp #, fuzzy @@ -24142,9 +23889,8 @@ msgid "The AnimationPlayer root node is not a valid node." msgstr "O nó raiz do AnimationPlayer não é um nó válido." #: scene/animation/animation_tree.cpp -#, fuzzy msgid "Tree Root" -msgstr "Criar nó raiz:" +msgstr "Nó Raiz" #: scene/animation/animation_tree.cpp #, fuzzy @@ -24254,7 +24000,7 @@ msgstr "Modo de Seleção" #: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp msgid "Alignment" -msgstr "" +msgstr "Alinhamento" #: scene/gui/base_button.cpp #, fuzzy @@ -24292,11 +24038,11 @@ msgstr "Copiar Texto" #: scene/gui/button.cpp scene/gui/label.cpp scene/gui/line_edit.cpp #: scene/gui/spin_box.cpp msgid "Align" -msgstr "" +msgstr "Alinhar" #: scene/gui/button.cpp msgid "Icon Align" -msgstr "" +msgstr "Alinhamento do Ãcone" #: scene/gui/button.cpp #, fuzzy @@ -24400,14 +24146,12 @@ msgid "Grow Direction" msgstr "Direções" #: scene/gui/control.cpp scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Min Size" -msgstr "Tamanho do Contorno:" +msgstr "Tamanho MÃnimo" #: scene/gui/control.cpp -#, fuzzy msgid "Pivot Offset" -msgstr "Deslocamento da Grade:" +msgstr "Deslocamento do Pivô" #: scene/gui/control.cpp #, fuzzy @@ -24455,7 +24199,7 @@ msgstr "Anterior" #: scene/gui/control.cpp msgid "Mouse" -msgstr "" +msgstr "Mouse" #: scene/gui/control.cpp msgid "Default Cursor Shape" @@ -24481,7 +24225,7 @@ msgstr "Propriedades do Tema" #: scene/gui/dialogs.cpp msgid "Window Title" -msgstr "" +msgstr "TÃtulo da Janela" #: scene/gui/dialogs.cpp #, fuzzy @@ -24515,14 +24259,12 @@ msgid "Right Disconnects" msgstr "Desconectar" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Scroll Offset" -msgstr "Deslocamento da Grade:" +msgstr "Deslocamento da Rolagem" #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Snap Distance" -msgstr "Escolha uma Distância:" +msgstr "Distância de Encaixe" #: scene/gui/graph_edit.cpp #, fuzzy @@ -24547,7 +24289,7 @@ msgstr "Mostrar Ossos" #: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Minimap" -msgstr "" +msgstr "Mini-Mapa" #: scene/gui/graph_edit.cpp msgid "Enable grid minimap." @@ -24620,9 +24362,8 @@ msgid "Fixed Column Width" msgstr "" #: scene/gui/item_list.cpp -#, fuzzy msgid "Icon Scale" -msgstr "Escala aleatória:" +msgstr "Escala de Ãcone" #: scene/gui/item_list.cpp #, fuzzy @@ -24635,9 +24376,8 @@ msgid "V Align" msgstr "Atribuir" #: scene/gui/label.cpp scene/gui/rich_text_label.cpp -#, fuzzy msgid "Visible Characters" -msgstr "Caracteres válidos:" +msgstr "Caracteres Visiveis" #: scene/gui/label.cpp scene/gui/rich_text_label.cpp #, fuzzy @@ -24661,9 +24401,8 @@ msgid "Secret" msgstr "" #: scene/gui/line_edit.cpp -#, fuzzy msgid "Secret Character" -msgstr "Caracteres válidos:" +msgstr "Caracteres Secretos" #: scene/gui/line_edit.cpp msgid "Expand To Text Length" @@ -24720,20 +24459,19 @@ msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Caret" -msgstr "" +msgstr "Circunflexo" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" -msgstr "" +msgstr "Piscar" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Blink Speed" -msgstr "Velocidade:" +msgstr "Velocidade de Piscar" #: scene/gui/link_button.cpp msgid "Underline" -msgstr "" +msgstr "Sublinhado" #: scene/gui/menu_button.cpp #, fuzzy @@ -24816,9 +24554,8 @@ msgid "Allow Search" msgstr "Pesquisar" #: scene/gui/progress_bar.cpp -#, fuzzy msgid "Percent" -msgstr "Recente:" +msgstr "Porcentagem" #: scene/gui/range.cpp msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0." @@ -24878,9 +24615,8 @@ msgid "Absolute Index" msgstr "Auto Recuar" #: scene/gui/rich_text_effect.cpp -#, fuzzy msgid "Elapsed Time" -msgstr "Tempos de Mistura:" +msgstr "Tempo Decorrido" #: scene/gui/rich_text_effect.cpp #, fuzzy @@ -24888,9 +24624,8 @@ msgid "Env" msgstr "Fim" #: scene/gui/rich_text_effect.cpp -#, fuzzy msgid "Character" -msgstr "Caracteres válidos:" +msgstr "Caractere" #: scene/gui/rich_text_label.cpp msgid "BBCode" @@ -24901,9 +24636,8 @@ msgid "Meta Underlined" msgstr "" #: scene/gui/rich_text_label.cpp -#, fuzzy msgid "Tab Size" -msgstr "Tamanho:" +msgstr "Tamanho da Tabulação" #: scene/gui/rich_text_label.cpp #, fuzzy @@ -24924,9 +24658,8 @@ msgid "Selection Enabled" msgstr "Selecionar Apenas" #: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Override Selected Font Color" -msgstr "Configurar Perfil Selecionado:" +msgstr "Sobrescrever Cor da Fonte Selecionada" #: scene/gui/rich_text_label.cpp #, fuzzy @@ -24954,9 +24687,8 @@ msgid "Follow Focus" msgstr "Popular SuperfÃcie" #: scene/gui/scroll_container.cpp -#, fuzzy msgid "Horizontal Enabled" -msgstr "Horizontal:" +msgstr "Horizontal Habilitado" #: scene/gui/scroll_container.cpp #, fuzzy @@ -24977,24 +24709,20 @@ msgid "Tick Count" msgstr "Escolher Cor" #: scene/gui/slider.cpp -#, fuzzy msgid "Ticks On Borders" -msgstr "Renomear pasta:" +msgstr "Pontos Nas Bordas" #: scene/gui/spin_box.cpp -#, fuzzy msgid "Prefix" -msgstr "Prefixo:" +msgstr "Prefixo" #: scene/gui/spin_box.cpp -#, fuzzy msgid "Suffix" -msgstr "Sufixo:" +msgstr "Sufixo" #: scene/gui/split_container.cpp -#, fuzzy msgid "Split Offset" -msgstr "Deslocamento da Grade:" +msgstr "Deslocamento de Divisão" #: scene/gui/split_container.cpp scene/gui/tree.cpp #, fuzzy @@ -25011,9 +24739,8 @@ msgid "Tab Align" msgstr "" #: scene/gui/tab_container.cpp scene/gui/tabs.cpp -#, fuzzy msgid "Current Tab" -msgstr "Atual:" +msgstr "Aba Atual" #: scene/gui/tab_container.cpp #, fuzzy @@ -25055,9 +24782,8 @@ msgid "Breakpoint Gutter" msgstr "Pular Breakpoints" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Fold Gutter" -msgstr "Pasta:" +msgstr "Espaçamento de Dobra" #: scene/gui/text_edit.cpp #, fuzzy @@ -25075,19 +24801,16 @@ msgid "Wrap Enabled" msgstr "Habilitar" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Scroll Vertical" -msgstr "Vertical:" +msgstr "Scroll Vertical" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Scroll Horizontal" -msgstr "Horizontal:" +msgstr "Scroll Horizontal" #: scene/gui/text_edit.cpp -#, fuzzy msgid "Draw" -msgstr "Chamadas de Desenho:" +msgstr "Desenhar" #: scene/gui/text_edit.cpp #, fuzzy @@ -25145,9 +24868,8 @@ msgid "Progress Offset" msgstr "" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Fill Mode" -msgstr "Modo Panorâmico:" +msgstr "Modo de Preenchimento" #: scene/gui/texture_progress.cpp scene/resources/material.cpp msgid "Tint" @@ -25215,9 +24937,8 @@ msgid "Hide Folding" msgstr "Botão Desativado" #: scene/gui/tree.cpp -#, fuzzy msgid "Hide Root" -msgstr "Criar nó raiz:" +msgstr "Esconder Raiz" #: scene/gui/tree.cpp msgid "Drop Mode Flags" @@ -25230,7 +24951,7 @@ msgstr "Adicionar Faixa" #: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp msgid "Paused" -msgstr "" +msgstr "Pausado" #: scene/gui/video_player.cpp #, fuzzy @@ -25315,19 +25036,16 @@ msgid "Filename" msgstr "Renomear" #: scene/main/node.cpp -#, fuzzy msgid "Owner" -msgstr "Donos De:" +msgstr "Dono" #: scene/main/node.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Multiplayer" -msgstr "Definir Múltiplos:" +msgstr "Multijogador" #: scene/main/node.cpp -#, fuzzy msgid "Custom Multiplayer" -msgstr "Definir Múltiplos:" +msgstr "Multijogador Personalizado" #: scene/main/node.cpp #, fuzzy @@ -25360,17 +25078,16 @@ msgstr "Nova Raiz de Cena" #: scene/main/scene_tree.cpp msgid "Root" -msgstr "" +msgstr "Raiz" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Multiplayer Poll" -msgstr "Definir Múltiplos:" +msgstr "" #: scene/main/scene_tree.cpp scene/resources/mesh_library.cpp #: scene/resources/shape_2d.cpp msgid "Shapes" -msgstr "" +msgstr "Formas" #: scene/main/scene_tree.cpp msgid "Shape Color" @@ -25404,9 +25121,8 @@ msgid "Reflections" msgstr "Reflexões" #: scene/main/scene_tree.cpp -#, fuzzy msgid "Atlas Size" -msgstr "Tamanho do Contorno:" +msgstr "Tamanho do Atlas" #: scene/main/scene_tree.cpp msgid "Atlas Subdiv" @@ -25418,7 +25134,7 @@ msgstr "" #: scene/main/scene_tree.cpp msgid "Use FXAA" -msgstr "" +msgstr "Usar FXAA" #: scene/main/scene_tree.cpp msgid "Use Debanding" @@ -25426,7 +25142,7 @@ msgstr "" #: scene/main/scene_tree.cpp scene/main/viewport.cpp msgid "HDR" -msgstr "" +msgstr "HDR" #: scene/main/scene_tree.cpp scene/main/viewport.cpp msgid "Use 32 BPC Depth" @@ -25464,9 +25180,8 @@ msgstr "" "Timer para tempos de espera muito baixos." #: scene/main/timer.cpp -#, fuzzy msgid "Autostart" -msgstr "ReinÃcio Automático:" +msgstr "InÃcio Automático" #: scene/main/viewport.cpp #, fuzzy @@ -25492,7 +25207,7 @@ msgstr "" #: scene/main/viewport.cpp msgid "ARVR" -msgstr "" +msgstr "ARVR" #: scene/main/viewport.cpp #, fuzzy @@ -25505,11 +25220,11 @@ msgstr "" #: scene/main/viewport.cpp scene/resources/world_2d.cpp msgid "World" -msgstr "" +msgstr "Mundo" #: scene/main/viewport.cpp msgid "World 2D" -msgstr "" +msgstr "Mundo 2D" #: scene/main/viewport.cpp #, fuzzy @@ -25523,7 +25238,7 @@ msgstr "Alterar Valor da Entrada" #: scene/main/viewport.cpp msgid "FXAA" -msgstr "" +msgstr "FXAA" #: scene/main/viewport.cpp #, fuzzy @@ -25541,8 +25256,9 @@ msgid "Keep 3D Linear" msgstr "Linear Esquerda" #: scene/main/viewport.cpp +#, fuzzy msgid "Render Direct To Screen" -msgstr "" +msgstr "Renderizar Diretamente para a Tela" #: scene/main/viewport.cpp #, fuzzy @@ -25550,9 +25266,8 @@ msgid "Debug Draw" msgstr "Depuração" #: scene/main/viewport.cpp -#, fuzzy msgid "Render Target" -msgstr "Renderizador:" +msgstr "Alvo do Renderizador" #: scene/main/viewport.cpp msgid "V Flip" @@ -25660,7 +25375,7 @@ msgstr "Navegação" #: scene/register_scene_types.cpp msgid "Use hiDPI" -msgstr "" +msgstr "Usar hiDPI" #: scene/register_scene_types.cpp #, fuzzy @@ -25680,12 +25395,11 @@ msgstr "Nó Mix" #: scene/resources/audio_stream_sample.cpp msgid "Stereo" -msgstr "" +msgstr "Stereo" #: scene/resources/concave_polygon_shape_2d.cpp -#, fuzzy msgid "Segments" -msgstr "Argumentos da Cena Principal:" +msgstr "Segmentos" #: scene/resources/curve.cpp #, fuzzy @@ -25698,7 +25412,7 @@ msgstr "" #: scene/resources/default_theme/default_theme.cpp msgid "Panel" -msgstr "" +msgstr "Painel" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25726,9 +25440,8 @@ msgid "Font Color Disabled" msgstr "Corte Desabilitado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "H Separation" -msgstr "Separação:" +msgstr "Separação Horizontal" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25737,7 +25450,7 @@ msgstr "Loop da Animação" #: scene/resources/default_theme/default_theme.cpp msgid "Arrow" -msgstr "" +msgstr "Seta" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25816,14 +25529,12 @@ msgid "Font Outline Modulate" msgstr "Forçar Módulo Branco" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Shadow Offset X" -msgstr "Deslocamento da Grade X:" +msgstr "Deslocamento da Sombra em X" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Shadow Offset Y" -msgstr "Deslocamento da Grade Y:" +msgstr "Deslocamento da Sombra em Y" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25881,14 +25592,12 @@ msgid "Space" msgstr "Cena Principal" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Folded" -msgstr "Pasta:" +msgstr "Dobrado" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Fold" -msgstr "Pasta:" +msgstr "Dobrar" #: scene/resources/default_theme/default_theme.cpp msgid "Font Color Readonly" @@ -26056,9 +25765,8 @@ msgid "Font Color Separator" msgstr "Separador de Cor da Fonte" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "V Separation" -msgstr "Separação:" +msgstr "Separação Vertical" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26111,9 +25819,8 @@ msgid "Close Offset" msgstr "Deslocamento do RuÃdo" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Port Offset" -msgstr "Deslocamento da Grade:" +msgstr "Deslocamento de Porta" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26223,14 +25930,12 @@ msgid "Draw Guides" msgstr "Mostrar Guias" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Scroll Border" -msgstr "Vertical:" +msgstr "Borda da Barra de Rolagem" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Scroll Speed" -msgstr "Deslocamento da Grade:" +msgstr "Velocidade de Rolagem" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26238,9 +25943,8 @@ msgid "Icon Margin" msgstr "Definir Margem" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Line Separation" -msgstr "Separação:" +msgstr "Separação de Linha" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26259,7 +25963,7 @@ msgstr "Item Desativado" #: scene/resources/default_theme/default_theme.cpp msgid "Menu" -msgstr "" +msgstr "Menu" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26300,9 +26004,8 @@ msgid "Large" msgstr "Destino" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Folder" -msgstr "Pasta:" +msgstr "Pasta" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26394,7 +26097,7 @@ msgstr "Cena Principal" #: scene/resources/default_theme/default_theme.cpp msgid "Bold Italics Font" -msgstr "" +msgstr "Fonte Negrito Itálica" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26402,14 +26105,12 @@ msgid "Mono Font" msgstr "Cena Principal" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Table H Separation" -msgstr "Separação:" +msgstr "Separação Horizontal da Tabela" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Table V Separation" -msgstr "Separação:" +msgstr "Separação Vertical da Tabela" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26438,11 +26139,11 @@ msgstr "Auto Fatiar" #: scene/resources/default_theme/default_theme.cpp msgid "Minus" -msgstr "" +msgstr "Menos" #: scene/resources/default_theme/default_theme.cpp msgid "More" -msgstr "" +msgstr "Mais" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26502,9 +26203,8 @@ msgid "Font Path" msgstr "Habilitar" #: scene/resources/dynamic_font.cpp -#, fuzzy msgid "Outline Size" -msgstr "Tamanho do Contorno:" +msgstr "Tamanho do Contorno" #: scene/resources/dynamic_font.cpp #, fuzzy @@ -26517,14 +26217,12 @@ msgid "Use Mipmaps" msgstr "Sinais" #: scene/resources/dynamic_font.cpp -#, fuzzy msgid "Extra Spacing" -msgstr "Opções Extra:" +msgstr "Espaçamento Extra" #: scene/resources/dynamic_font.cpp -#, fuzzy msgid "Char" -msgstr "Caracteres válidos:" +msgstr "Caractere" #: scene/resources/dynamic_font.cpp #, fuzzy @@ -26537,7 +26235,7 @@ msgstr "" #: scene/resources/environment.cpp scene/resources/sky.cpp msgid "Sky" -msgstr "" +msgstr "Céu" #: scene/resources/environment.cpp #, fuzzy @@ -26550,9 +26248,8 @@ msgid "Sky Orientation" msgstr "Documentação Online" #: scene/resources/environment.cpp -#, fuzzy msgid "Sky Rotation" -msgstr "Passo de Rotação:" +msgstr "Rotação do Céu" #: scene/resources/environment.cpp msgid "Sky Rotation Degrees" @@ -26581,14 +26278,12 @@ msgid "Fog" msgstr "Névoa" #: scene/resources/environment.cpp -#, fuzzy msgid "Sun Color" -msgstr "Armazenando Arquivo:" +msgstr "Cor do Sol" #: scene/resources/environment.cpp -#, fuzzy msgid "Sun Amount" -msgstr "Quantidade:" +msgstr "Quantidade do Sol" #: scene/resources/environment.cpp #, fuzzy @@ -26652,7 +26347,7 @@ msgstr "Exportação" #: scene/resources/environment.cpp msgid "White" -msgstr "" +msgstr "Branco" #: scene/resources/environment.cpp msgid "Auto Exposure" @@ -26677,14 +26372,12 @@ msgid "Max Steps" msgstr "Passo" #: scene/resources/environment.cpp -#, fuzzy msgid "Fade In" -msgstr "[i]Fade In[/i](s):" +msgstr "Esmaecer de Entrada" #: scene/resources/environment.cpp -#, fuzzy msgid "Fade Out" -msgstr "[i]Fade Out[/i](s):" +msgstr "Esmaecer de SaÃda" #: scene/resources/environment.cpp #, fuzzy @@ -26697,12 +26390,11 @@ msgstr "Rugosidade" #: scene/resources/environment.cpp msgid "SSAO" -msgstr "" +msgstr "SSAO" #: scene/resources/environment.cpp -#, fuzzy msgid "Radius 2" -msgstr "Raio:" +msgstr "Raio 2" #: scene/resources/environment.cpp msgid "Intensity 2" @@ -26720,7 +26412,7 @@ msgstr "Depuração do Canal UV" #: scene/resources/environment.cpp msgid "Blur" -msgstr "" +msgstr "Blur" #: scene/resources/environment.cpp msgid "Edge Sharpness" @@ -26731,9 +26423,8 @@ msgid "DOF Far Blur" msgstr "" #: scene/resources/environment.cpp scene/resources/material.cpp -#, fuzzy msgid "Distance" -msgstr "Escolha uma Distância:" +msgstr "Distância" #: scene/resources/environment.cpp msgid "Transition" @@ -26816,18 +26507,16 @@ msgid "Brightness" msgstr "Luz" #: scene/resources/environment.cpp -#, fuzzy msgid "Saturation" -msgstr "Separação:" +msgstr "Separação" #: scene/resources/environment.cpp msgid "Color Correction" msgstr "Correção de Cor" #: scene/resources/font.cpp -#, fuzzy msgid "Ascent" -msgstr "Recente:" +msgstr "Subida" #: scene/resources/font.cpp #, fuzzy @@ -26840,9 +26529,8 @@ msgid "Raw Data" msgstr "Profundidade" #: scene/resources/gradient.cpp -#, fuzzy msgid "Offsets" -msgstr "Deslocamento:" +msgstr "Deslocamentos" #: scene/resources/height_map_shape.cpp msgid "Map Width" @@ -26922,7 +26610,7 @@ msgstr "" #: scene/resources/material.cpp msgid "Is sRGB" -msgstr "" +msgstr "É sRGB" #: scene/resources/material.cpp servers/visual_server.cpp msgid "Parameters" @@ -26968,9 +26656,8 @@ msgid "Grow" msgstr "Crescer" #: scene/resources/material.cpp -#, fuzzy msgid "Grow Amount" -msgstr "Quantidade:" +msgstr "Quantidade de Crescimento" #: scene/resources/material.cpp msgid "Use Alpha Scissor" @@ -27125,7 +26812,7 @@ msgstr "Faça mapas de luz" #: scene/resources/mesh.cpp scene/resources/primitive_meshes.cpp msgid "Custom AABB" -msgstr "" +msgstr "AABB Personalizado" #: scene/resources/mesh_library.cpp #, fuzzy @@ -27159,9 +26846,8 @@ msgid "Visible Instance Count" msgstr "" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Sampling" -msgstr "Escala:" +msgstr "Mostragem" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27182,12 +26868,11 @@ msgstr "Origem do Nome do Grupo" #: scene/resources/navigation_mesh.cpp msgid "Cells" -msgstr "" +msgstr "Células" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Agents" -msgstr "Argumentos da Cena Principal:" +msgstr "Agentes" #: scene/resources/navigation_mesh.cpp msgid "Max Climb" @@ -27209,7 +26894,7 @@ msgstr "Fundir a partir de Cena" #: scene/resources/navigation_mesh.cpp msgid "Edges" -msgstr "" +msgstr "Arestas" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27226,9 +26911,8 @@ msgid "Details" msgstr "Detalhe" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Sample Distance" -msgstr "Escolha uma Distância:" +msgstr "Distância de Amostra" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27298,9 +26982,8 @@ msgid "Color Modifier" msgstr "Modificador de velocidade lenta da Visão Livre" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Point Texture" -msgstr "Pontos de Emissão:" +msgstr "Textura de Ponto" #: scene/resources/particles_material.cpp msgid "Normal Texture" @@ -27317,9 +27000,8 @@ msgid "Point Count" msgstr "Adicionar porta de entrada" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Scale Random" -msgstr "Razão de Escala:" +msgstr "Randomização de Escala" #: scene/resources/particles_material.cpp #, fuzzy @@ -27335,9 +27017,8 @@ msgid "Absorbent" msgstr "" #: scene/resources/plane_shape.cpp -#, fuzzy msgid "Plane" -msgstr "Plano:" +msgstr "Plano" #: scene/resources/primitive_meshes.cpp #, fuzzy @@ -27361,9 +27042,8 @@ msgid "Subdivide Depth" msgstr "" #: scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Top Radius" -msgstr "Raio:" +msgstr "Raio do Topo" #: scene/resources/primitive_meshes.cpp #, fuzzy @@ -27412,13 +27092,12 @@ msgid "Bone" msgstr "Ossos" #: scene/resources/sky.cpp -#, fuzzy msgid "Radiance Size" -msgstr "Tamanho do Contorno:" +msgstr "Tamanho da Radiância" #: scene/resources/sky.cpp msgid "Panorama" -msgstr "" +msgstr "Panorama" #: scene/resources/sky.cpp #, fuzzy @@ -27426,9 +27105,8 @@ msgid "Top Color" msgstr "Próximo Chão" #: scene/resources/sky.cpp -#, fuzzy msgid "Horizon Color" -msgstr "Armazenando Arquivo:" +msgstr "Cor do Horizonte" #: scene/resources/sky.cpp #, fuzzy @@ -27452,7 +27130,7 @@ msgstr "Substituir" #: scene/resources/sky.cpp msgid "Longitude" -msgstr "" +msgstr "Longitude" #: scene/resources/sky.cpp msgid "Angle Min" @@ -27487,7 +27165,7 @@ msgstr "" #: scene/resources/style_box.cpp msgid "Anti Aliasing" -msgstr "" +msgstr "Anti Aliasing" #: scene/resources/style_box.cpp msgid "Grow Begin" @@ -27537,9 +27215,8 @@ msgid "Lossy Storage Quality" msgstr "Capturar" #: scene/resources/texture.cpp -#, fuzzy msgid "From" -msgstr "Modo Panorâmico:" +msgstr "À Partir de" #: scene/resources/texture.cpp #, fuzzy @@ -27743,9 +27420,8 @@ msgid "Audio Stream" msgstr "Item Rádio" #: servers/audio/audio_stream.cpp -#, fuzzy msgid "Random Pitch" -msgstr "Inclinação aleatória:" +msgstr "Timbre Aleatório" #: servers/audio/effects/audio_effect_capture.cpp #: servers/audio/effects/audio_effect_spectrum_analyzer.cpp @@ -27761,21 +27437,21 @@ msgstr "" #: servers/audio/effects/audio_effect_delay.cpp #: servers/audio/effects/audio_effect_reverb.cpp msgid "Dry" -msgstr "" +msgstr "Seco" #: servers/audio/effects/audio_effect_chorus.cpp #: servers/audio/effects/audio_effect_reverb.cpp msgid "Wet" -msgstr "" +msgstr "Molhado" #: servers/audio/effects/audio_effect_chorus.cpp msgid "Voice" -msgstr "" +msgstr "Voz" #: servers/audio/effects/audio_effect_chorus.cpp #: servers/audio/effects/audio_effect_delay.cpp msgid "Delay (ms)" -msgstr "" +msgstr "Atraso (ms)" #: servers/audio/effects/audio_effect_chorus.cpp #: servers/audio/effects/audio_effect_phaser.cpp @@ -27790,23 +27466,22 @@ msgstr "Profundidade" #: servers/audio/effects/audio_effect_chorus.cpp #: servers/audio/effects/audio_effect_delay.cpp msgid "Level dB" -msgstr "" +msgstr "NÃvel dB" #: servers/audio/effects/audio_effect_chorus.cpp #: servers/audio/effects/audio_effect_delay.cpp #: servers/audio/effects/audio_effect_panner.cpp -#, fuzzy msgid "Pan" -msgstr "Plano:" +msgstr "Panoramizar" #: servers/audio/effects/audio_effect_compressor.cpp #: servers/audio/effects/audio_effect_filter.cpp msgid "Gain" -msgstr "" +msgstr "Ganho" #: servers/audio/effects/audio_effect_compressor.cpp msgid "Attack (µs)" -msgstr "" +msgstr "Ataque (µs)" #: servers/audio/effects/audio_effect_compressor.cpp #, fuzzy @@ -27843,7 +27518,7 @@ msgstr "Ignorar" #: servers/audio/effects/audio_effect_distortion.cpp msgid "Pre Gain" -msgstr "" +msgstr "Pré Ganho" #: servers/audio/effects/audio_effect_distortion.cpp msgid "Keep Hf Hz" @@ -27851,7 +27526,7 @@ msgstr "" #: servers/audio/effects/audio_effect_distortion.cpp msgid "Drive" -msgstr "" +msgstr "Drive" #: servers/audio/effects/audio_effect_distortion.cpp #, fuzzy @@ -27893,21 +27568,20 @@ msgstr "" #: servers/audio/effects/audio_effect_pitch_shift.cpp #: servers/audio/effects/audio_effect_spectrum_analyzer.cpp -#, fuzzy msgid "FFT Size" -msgstr "Tamanho:" +msgstr "Tamanho FFT" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Predelay" -msgstr "" +msgstr "Pré Atraso" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Msec" -msgstr "" +msgstr "Msec" #: servers/audio/effects/audio_effect_reverb.cpp msgid "Room Size" -msgstr "" +msgstr "Tamanho da Sala" #: servers/audio/effects/audio_effect_reverb.cpp #, fuzzy @@ -27990,9 +27664,8 @@ msgid "Time Before Sleep" msgstr "" #: servers/physics_2d/physics_2d_server_sw.cpp -#, fuzzy msgid "BP Hash Table Size" -msgstr "Tamanho:" +msgstr "Tamanho da \"BP Hash Table\"" #: servers/physics_2d/physics_2d_server_sw.cpp msgid "Large Object Surface Threshold In Cells" @@ -28365,7 +28038,7 @@ msgstr "" #: servers/visual_server.cpp msgid "Compatibility" -msgstr "" +msgstr "Compatibilidade" #: servers/visual_server.cpp msgid "Disable Half Float" diff --git a/editor/translations/ro.po b/editor/translations/ro.po index cdd11f3980..a78712c6ba 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -477,6 +477,10 @@ msgid "Pressure" msgstr "Presiune" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Relativ" @@ -2182,14 +2186,15 @@ msgstr "Favorite:" msgid "Recent:" msgstr "Recent:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "CautaÈ›i:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Potriviri:" @@ -2249,8 +2254,8 @@ msgstr "CautaÈ›i ÃŽnlocuitor Resursă:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2831,8 +2836,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Copiază SelecÈ›ia" #: editor/editor_export.cpp #, fuzzy @@ -5629,6 +5635,10 @@ msgid "Drag And Drop Selection" msgstr "Toată selecÈ›ia" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12020,6 +12030,11 @@ msgid "New Animation" msgstr "AnimaÈ›ie" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Metode de filtrare" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20725,15 +20740,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Trebuie să utilizaÅ£i o extensie valida." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20755,15 +20770,15 @@ msgstr "Nume nevalid." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Trebuie să utilizaÅ£i o extensie valida." #: platform/windows/export/export.cpp #, fuzzy @@ -21815,7 +21830,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "Pas RotaÈ›ie:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Permanent" @@ -23840,6 +23855,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Anim Schimbare transformare" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 84762459c8..1df1d87308 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -85,7 +85,7 @@ # kyanukovich <ianu0001@algonquinlive.com>, 2020. # Ron788 <ustinov200511@gmail.com>, 2020. # Daniel <dan.ef1999@gmail.com>, 2020. -# NeoLan Qu <it.bulla@mail.ru>, 2020. +# NeoLan Qu <it.bulla@mail.ru>, 2020, 2022. # Nikita Epifanov <nikgreens@protonmail.com>, 2020. # Cube Show <griiv.06@gmail.com>, 2020. # Roman Tolkachyov <roman@tolkachyov.name>, 2020. @@ -117,13 +117,15 @@ # FuzzMix <fmwolfiechad@gmail.com>, 2022. # Jasuse <jasusemaele@gmail.com>, 2022. # Vadim Mitroshkin <Vadim7540@yandex.ru>, 2022. +# Maksim Marchukov <mar.maksim63@gmail.com>, 2022. +# Slava Beloglazov <slavathedeveloper@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-03 00:44+0000\n" -"Last-Translator: Vadim Mitroshkin <Vadim7540@yandex.ru>\n" +"PO-Revision-Date: 2022-07-26 01:55+0000\n" +"Last-Translator: NeoLan Qu <it.bulla@mail.ru>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -132,7 +134,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -506,7 +508,7 @@ msgstr "Command" #: core/os/input_event.cpp #, fuzzy msgid "Physical" -msgstr " (ФизичеÑкаÑ)" +msgstr "(ФизичеÑкаÑ)" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -559,6 +561,10 @@ msgid "Pressure" msgstr "Давление" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Перо Инвертировано" + +#: core/os/input_event.cpp msgid "Relative" msgstr "ОтноÑительный" @@ -1239,9 +1245,8 @@ msgid "Value" msgstr "Значение" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Arg Count" -msgstr "КоличеÑтво" +msgstr "КоличеÑтво Ðргументов" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp @@ -1432,24 +1437,22 @@ msgid "(Invalid, expected type: %s)" msgstr "(Ðеверный, ожидаемый тип: %s)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing:" -msgstr "Переход Ð’-ИЗ" +msgstr "Переход Ð’-ИЗ:" #: editor/animation_track_editor.cpp #, fuzzy msgid "In-Handle:" -msgstr "Задать обработчик" +msgstr "Обработчик Ввода:" #: editor/animation_track_editor.cpp #, fuzzy msgid "Out-Handle:" -msgstr "Задать обработчик" +msgstr "Обработчик Вывода:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Stream:" -msgstr "Поток" +msgstr "Поток:" #: editor/animation_track_editor.cpp msgid "Start (s):" @@ -2210,14 +2213,15 @@ msgstr "Избранное:" msgid "Recent:" msgstr "Ðедавнее:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "ПоиÑк:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "СовпадениÑ:" @@ -2277,8 +2281,8 @@ msgstr "Ðайти заменÑемый реÑурÑ:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2287,7 +2291,7 @@ msgstr "Открыть" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Владельцы: %s (Ð’Ñего: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2337,9 +2341,8 @@ msgid "Fix Dependencies" msgstr "ИÑправить завиÑимоÑти" #: editor/dependency_editor.cpp -#, fuzzy msgid "Errors loading!" -msgstr "Ошибки загружаютÑÑ!" +msgstr "Ошибки при загрузке!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" @@ -2846,17 +2849,16 @@ msgstr "Выбрать" #: editor/editor_export.cpp msgid "Project export for platform:" -msgstr "" +msgstr "ÐкÑпорт проекта Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ñ‹:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." -msgstr "Завершать пути файлов" +msgid "Completed with warnings." +msgstr "Завершено Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸." #: editor/editor_export.cpp -#, fuzzy msgid "Completed successfully." -msgstr "Пакет уÑпешно уÑтановлен!" +msgstr "Завершено без ошибок." #: editor/editor_export.cpp #, fuzzy @@ -2876,9 +2878,8 @@ msgid "Packing" msgstr "Упаковывание" #: editor/editor_export.cpp -#, fuzzy msgid "Save PCK" -msgstr "Сохранить как" +msgstr "Сохранить PCK" #: editor/editor_export.cpp #, fuzzy @@ -2905,16 +2906,16 @@ msgid "" "Target platform requires 'ETC' texture compression for GLES2. Enable 'Import " "Etc' in Project Settings." msgstr "" -"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует Ñжатие текÑтур «ETC» Ð´Ð»Ñ GLES2. Включите «Import " -"Etc» в ÐаÑтройках проекта." +"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует Ñжатие текÑтур «ETC» Ð´Ð»Ñ GLES2. Включите " +"«Импортировать Etc» в ÐаÑтройках Проекта." #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC2' texture compression for GLES3. Enable " "'Import Etc 2' in Project Settings." msgstr "" -"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» Ð´Ð»Ñ GLES2. Включите " -"«Import Etc 2» в ÐаÑтройках проекта." +"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» Ð´Ð»Ñ GLES3. Включите " +"«Импортировать Etc 2» в ÐаÑтройках Проекта." #: editor/editor_export.cpp msgid "" @@ -2924,8 +2925,8 @@ msgid "" "Enabled'." msgstr "" "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует ÑÐ¶Ð°Ñ‚Ð¸Ñ Ñ‚ÐµÐºÑтур «ETC» Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ñ‚Ð° драйвера к GLES2.\n" -"Включите «Import Etc» в ÐаÑтройках проекта или отключите «Driver Fallback " -"Enabled»." +"Включите «Импортировать Etc» в ÐаÑтройках проекта или отключите «Driver " +"Fallback Enabled»." #: editor/editor_export.cpp msgid "" @@ -2941,7 +2942,8 @@ msgid "" "Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings." msgstr "" "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» или «PVRTC» Ð´Ð»Ñ GLES3. " -"Включите «Import Etc 2» или «Import Pvrtc» в ÐаÑтройках проекта." +"Включите «Импортировать Etc 2» или «Импортировать Pvrtc» в ÐаÑтройках " +"Проекта." #: editor/editor_export.cpp msgid "" @@ -5599,6 +5601,10 @@ msgid "Drag And Drop Selection" msgstr "Выделение Ñетки" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "Внешний вид" @@ -7252,12 +7258,17 @@ msgid "" "%s: Texture detected as used as a normal map in 3D. Enabling red-green " "texture compression to reduce memory usage (blue channel is discarded)." msgstr "" +"%s: Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ñ‚ÐµÐºÑтура иÑпользуетÑÑ ÐºÐ°Ðº карта нормалей в 3D. Включено краÑно-" +"зелёное Ñжатие текÑтуры Ð´Ð»Ñ ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð¼Ñти (Ñиний канал " +"отбраÑываетÑÑ)." #: editor/import/resource_importer_texture.cpp msgid "" "%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap " "generation and VRAM texture compression." msgstr "" +"%s: ТекÑтура иÑпользуетÑÑ Ð² 3D. Включена фильтрациÑ, повторение и Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ " +"mipmap-карт, а также VRAM Ñжатие текÑтуры." #: editor/import/resource_importer_texture.cpp msgid "2D, Detect 3D" @@ -11694,6 +11705,11 @@ msgid "New Animation" msgstr "ÐÐ¾Ð²Ð°Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Фильтр методов" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "СкороÑть:" @@ -15356,7 +15372,7 @@ msgstr "Сделать локальным" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp msgid "Another node already uses this unique name in the scene." -msgstr "Ð˜Ð¼Ñ ÑƒÐ·Ð»Ð° уже иÑпользовано в Ñцене" +msgstr "Данное уникальное Ð¸Ð¼Ñ ÑƒÐ¶Ðµ иÑпользовано у другого узла в Ñцене." #: editor/scene_tree_dock.cpp msgid "Enable Scene Unique Name" @@ -15789,9 +15805,8 @@ msgid "Attach Node Script" msgstr "Прикрепить Ñкрипт" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote %s:" -msgstr "Удаленный " +msgstr "Удаленный %s:" #: editor/script_editor_debugger.cpp msgid "Bytes:" @@ -16769,7 +16784,7 @@ msgstr "Выключен GDNative Ñинглтон" #: modules/gdnative/gdnative_library_singleton_editor.cpp #, fuzzy msgid "Libraries:" -msgstr "Библиотеки: " +msgstr "Библиотеки:" #: modules/gdnative/nativescript/nativescript.cpp msgid "Class Name" @@ -17045,7 +17060,7 @@ msgstr "СфокуÑироватьÑÑ Ð½Ð° начале координат" #: modules/gltf/gltf_skin.cpp msgid "Inverse Binds" -msgstr "" +msgstr "Инвертировать СвÑзи" #: modules/gltf/gltf_skin.cpp #, fuzzy @@ -17054,11 +17069,11 @@ msgstr "Передвинуть ÑуÑтав" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Bone I" -msgstr "" +msgstr "Узел I к КоÑти I" #: modules/gltf/gltf_skin.cpp msgid "Joint I To Name" -msgstr "" +msgstr "Узел I К Имени" #: modules/gltf/gltf_skin.cpp msgid "Godot Skin" @@ -17074,7 +17089,7 @@ msgstr "Диффузный фактор" #: modules/gltf/gltf_spec_gloss.cpp msgid "Gloss Factor" -msgstr "" +msgstr "КоÑфф. ГлÑнца" #: modules/gltf/gltf_spec_gloss.cpp #, fuzzy @@ -17623,9 +17638,8 @@ msgstr "" "памÑти! ИÑправьте узел пожалуйÑта." #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Node returned an invalid sequence output:" -msgstr "Узел вернул ошибочную поÑледовательноÑть: " +msgstr "Узел вернул ошибочный вывод поÑледовательноÑти:" #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" @@ -17635,7 +17649,7 @@ msgstr "" #: modules/visual_script/visual_script.cpp #, fuzzy msgid "Stack overflow with stack depth:" -msgstr "Переполнение Ñтека Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð¾Ð¹ Ñтека: " +msgstr "Переполнение Ñтека Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð¾Ð¹ Ñтека:" #: modules/visual_script/visual_script.cpp msgid "Visual Script" @@ -18004,7 +18018,7 @@ msgstr "Ð´Ð»Ñ (Ñлемент) в (вход):" #: modules/visual_script/visual_script_flow_control.cpp #, fuzzy msgid "Input type not iterable:" -msgstr "Входной тип не итерируемый: " +msgstr "Входной тип не итерируемый:" #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid" @@ -18013,7 +18027,7 @@ msgstr "Итератор Ñтал недейÑтвительным" #: modules/visual_script/visual_script_flow_control.cpp #, fuzzy msgid "Iterator became invalid:" -msgstr "Итератор Ñтал недейÑтвительным: " +msgstr "Итератор Ñтал недейÑтвительным:" #: modules/visual_script/visual_script_flow_control.cpp msgid "Sequence" @@ -18167,14 +18181,12 @@ msgid "Operator" msgstr "Оператор" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Invalid argument of type:" -msgstr ": ÐедопуÑтимый аргумент типа: " +msgstr "ÐедопуÑтимый аргумент типа:" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Invalid arguments:" -msgstr ": ÐедопуÑтимые аргументы: " +msgstr "ÐедопуÑтимые аргументы:" #: modules/visual_script/visual_script_nodes.cpp msgid "a if cond, else b" @@ -18185,14 +18197,13 @@ msgid "Var Name" msgstr "Ð˜Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "VariableGet not found in script:" -msgstr "VariableGet не найден в Ñкрипте: " +msgstr "VariableGet отÑутÑтвует в Ñкрипте:" #: modules/visual_script/visual_script_nodes.cpp #, fuzzy msgid "VariableSet not found in script:" -msgstr "VariableSet не найден в Ñкрипте: " +msgstr "VariableSet не найден в Ñкрипте:" #: modules/visual_script/visual_script_nodes.cpp msgid "Preload" @@ -18329,7 +18340,7 @@ msgstr "Режим запиÑи" #: modules/webrtc/webrtc_data_channel.h msgid "WebRTC" -msgstr "" +msgstr "WebRTC" #: modules/webrtc/webrtc_data_channel.h #, fuzzy @@ -18345,36 +18356,32 @@ msgid "Trusted SSL Certificate" msgstr "Доверенный SSL-Ñертификат" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Client" -msgstr "Сетевой узел" +msgstr "Клиент WebSocket" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max In Buffer (KB)" -msgstr "МакÑимальный размер (КБ)" +msgstr "МакÑимальный Входной Буфер (КБ)" #: modules/websocket/websocket_macros.h msgid "Max In Packets" -msgstr "" +msgstr "МакÑимальные ВходÑщие Пакеты" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "Max Out Buffer (KB)" -msgstr "МакÑимальный размер (КБ)" +msgstr "МакÑимальный Буфер Вывода (КБ)" #: modules/websocket/websocket_macros.h msgid "Max Out Packets" -msgstr "" +msgstr "МакÑимальный Вывод Пакетов" #: modules/websocket/websocket_macros.h -#, fuzzy msgid "WebSocket Server" -msgstr "Сетевой узел" +msgstr "Сервер WebSocket" #: modules/websocket/websocket_server.cpp msgid "Bind IP" -msgstr "" +msgstr "ПривÑзать IP" #: modules/websocket/websocket_server.cpp msgid "Private Key" @@ -18398,14 +18405,12 @@ msgid "Session Mode" msgstr "Режим ÑеÑÑии" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Required Features" -msgstr "Ðеобходимые функции" +msgstr "Ðеобходимые Компоненты" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Optional Features" -msgstr "Дополнительные функции" +msgstr "Дополнительные Компоненты" #: modules/webxr/webxr_interface.cpp msgid "Requested Reference Space Types" @@ -18416,9 +18421,8 @@ msgid "Reference Space Type" msgstr "" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Visibility State" -msgstr "Переключить видимоÑть" +msgstr "ВидимоÑть" #: modules/webxr/webxr_interface.cpp #, fuzzy @@ -18426,9 +18430,8 @@ msgid "Bounds Geometry" msgstr "Повторить" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "XR Standard Mapping" -msgstr "Ð˜Ð½Ñ‚ÐµÐ»Ð»ÐµÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзка" +msgstr "Стандартный Маппинг XR" #: platform/android/export/export.cpp msgid "Android SDK Path" @@ -18457,19 +18460,19 @@ msgstr "Выключение ADB при выходе" #: platform/android/export/export_plugin.cpp msgid "Launcher Icons" -msgstr "" +msgstr "Иконки Лаунчера" #: platform/android/export/export_plugin.cpp msgid "Main 192 X 192" -msgstr "" +msgstr "ОÑÐ½Ð¾Ð²Ð½Ð°Ñ 192 X 192" #: platform/android/export/export_plugin.cpp msgid "Adaptive Foreground 432 X 432" -msgstr "" +msgstr "Ðдаптивный Передний Фон 432 X 432" #: platform/android/export/export_plugin.cpp msgid "Adaptive Background 432 X 432" -msgstr "" +msgstr "Ðдаптивный Задний Фон 432 X 432" #: platform/android/export/export_plugin.cpp msgid "Package name is missing." @@ -18496,39 +18499,32 @@ msgid "The package must have at least one '.' separator." msgstr "Пакет должен иметь Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один разделитель «.»." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Build" -msgstr "ИÑпользовать ÑобÑтвенную директорию данных пользователÑ" +msgstr "ÐаÑÑ‚Ñ€Ð°Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð¡Ð±Ð¾Ñ€ÐºÐ°" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Use Custom Build" -msgstr "ИÑпользовать ÑобÑтвенную директорию данных пользователÑ" +msgstr "ИÑпользовать ÐаÑтраиваемую Сборку" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Export Format" -msgstr "Путь ÑкÑпорта" +msgstr "Формат ÐкÑпорта" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Min SDK" -msgstr "Минимальный размер" +msgstr "Min SDK" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Target SDK" -msgstr "Целевой FPS" +msgstr "Целевой SDK" #: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp -#, fuzzy msgid "Architectures" -msgstr "Добавить поле архитектуры" +msgstr "Ðрхитектуры" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Keystore" -msgstr "Отладочное хранилище ключей" +msgstr "Хранилище ключей" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18552,31 +18548,27 @@ msgstr "Пароль" #: platform/android/export/export_plugin.cpp msgid "One Click Deploy" -msgstr "" +msgstr "Развёртывание в Один Клик" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Clear Previous Install" -msgstr "ОÑмотреть предыдущий ÑкземплÑÑ€" +msgstr "ОчиÑтить Предыдущую УÑтановку" #: platform/android/export/export_plugin.cpp msgid "Code" msgstr "Код" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Package" -msgstr "Упаковывание" +msgstr "Пакет" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Unique Name" -msgstr "Уникальные имена" +msgstr "Уникальное ИмÑ" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Signed" -msgstr "Сигнал" +msgstr "ПодпиÑано" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18886,14 +18878,12 @@ msgid "Code Signing" msgstr "ПодпиÑÑŒ кода DMG" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "'apksigner' could not be found. Please check that the command is available " "in the Android SDK build-tools directory. The resulting %s is unsigned." msgstr "" -"Ðе удалоÑÑŒ найти команду «apksigner».\n" -"ПожалуйÑта, проверьте наличие программы в каталоге Android SDK build-tools.\n" -"Результат %s не подпиÑан." +"Ðе удалоÑÑŒ найти «apksigner». ПожалуйÑта, убедитеÑÑŒ в наличии команды в " +"каталоге build-tools Android SDK. Результирующий %s не подпиÑан." #: platform/android/export/export_plugin.cpp msgid "Signing debug %s..." @@ -18908,9 +18898,8 @@ msgid "Could not find keystore, unable to export." msgstr "Ðе удалоÑÑŒ найти хранилище ключей, невозможно ÑкÑпортировать." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not start apksigner executable." -msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!" +msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл apksigner." #: platform/android/export/export_plugin.cpp msgid "'apksigner' returned with error #%d" @@ -18941,9 +18930,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension." msgstr "Ðеверное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°! Android APK требует раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ *.apk." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Unsupported export format!" -msgstr "Ðеподдерживаемый формат ÑкÑпорта!\n" +msgstr "Ðеподдерживаемый формат ÑкÑпорта!" #: platform/android/export/export_plugin.cpp msgid "" @@ -18954,15 +18942,12 @@ msgstr "" "не ÑущеÑтвует. ПожалуйÑта, переуÑтановите из меню «Проект»." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Android build version mismatch: Template installed: %s, Godot version: %s. " "Please reinstall Android build template from 'Project' menu." msgstr "" -"ÐеÑоответÑтвие верÑии Ñборки Android:\n" -" УÑтановлен шаблон: %s\n" -" ВерÑÐ¸Ñ Godot: %s\n" -"ПожалуйÑта, переуÑтановите шаблон Ñборки Android из меню «Проект»." +"ÐеÑоответÑтвие верÑии Ñборки Android: УÑтановлен шаблон: %s, верÑÐ¸Ñ Godot: " +"%s. ПожалуйÑта, переуÑтановите шаблон Ñборки Android из меню «Проект»." #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18972,9 +18957,8 @@ msgstr "" "Ðевозможно перезапиÑать файлы res://android/build/res/*.xml Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ проекта" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle\n" +msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle." #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -18985,14 +18969,13 @@ msgid "Building Android Project (gradle)" msgstr "Сборка проекта Android (gradle)" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Building of Android project failed, check output for the error. " "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"Сборка проекта Android не удалаÑÑŒ, проверьте вывод на ошибки.\n" -"Также поÑетите docs.godotengine.org Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ð¸ по Ñборке " -"Android." +"Сборка Android проекта не удалаÑÑŒ, проверьте вывод на ошибки. Ð’Ñ‹ также " +"можете поÑетить docs.godotengine.org Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ð¸ по Ñборке " +"Ð´Ð»Ñ Android." #: platform/android/export/export_plugin.cpp msgid "Moving output" @@ -19016,22 +18999,18 @@ msgid "Creating APK..." msgstr "Создание APK..." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not find template APK to export: \"%s\"." -msgstr "" -"Ðе удалоÑÑŒ найти шаблон APK Ð´Ð»Ñ ÑкÑпорта:\n" -"%s" +msgstr "Ðе удалоÑÑŒ найти шаблон APK Ð´Ð»Ñ ÑкÑпорта: \"%s\"." #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Missing libraries in the export template for the selected architectures: %s. " "Please build a template with all required libraries, or uncheck the missing " "architectures in the export preset." msgstr "" -"Ð’ шаблоне ÑкÑпорта отÑутÑтвуют библиотеки Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… архитектур: %s.\n" -"ПожалуйÑта, Ñоздайте шаблон Ñо вÑеми необходимыми библиотеками или Ñнимите " -"флажки Ñ Ð¾Ñ‚ÑутÑтвующих архитектур в преÑете ÑкÑпорта." +"Ð’ шаблоне ÑкÑпорта отÑутÑтвуют библиотеки Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… архитектур: %s. " +"ПожалуйÑта, поÑтройте шаблон Ñо вÑеми необходимыми библиотеками или Ñнимите " +"флажки Ñ Ð¾Ñ‚ÑутÑтвующих архитектур в предуÑтановках ÑкÑпорта." #: platform/android/export/export_plugin.cpp msgid "Adding files..." @@ -19721,9 +19700,8 @@ msgid "Could not open icon file \"%s\"." msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start xcrun executable." -msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!" +msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл xcrun." #: platform/osx/export/export.cpp #, fuzzy @@ -19807,9 +19785,8 @@ msgid "DMG Creation" msgstr "Ðаправление" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start hdiutil executable." -msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!" +msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл hdiutil." #: platform/osx/export/export.cpp msgid "`hdiutil create` failed - file exists." @@ -19896,9 +19873,8 @@ msgid "ZIP Creation" msgstr "ПроекциÑ" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open file to read from path \"%s\"." -msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle\n" +msgstr "Ðе удалоÑÑŒ открыть файл Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿Ð¾ пути \"%s\"." #: platform/osx/export/export.cpp msgid "Invalid bundle identifier:" @@ -20305,17 +20281,17 @@ msgstr "Ðе удалоÑÑŒ найти хранилище ключей, нево #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "ИнÑтрумент rcedit должен быть наÑтроен в ÐаÑтройках редактора (Export > " "Windows > Rcedit) Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ° или информационных данных приложениÑ." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "ÐедопуÑтимый иÑполнÑемый файл." #: platform/windows/export/export.cpp #, fuzzy @@ -20340,17 +20316,17 @@ msgstr "ÐедопуÑтимое имÑ." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "ИнÑтрумент rcedit должен быть наÑтроен в ÐаÑтройках редактора (Export > " "Windows > Rcedit) Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ° или информационных данных приложениÑ." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "ÐедопуÑтимый иÑполнÑемый файл." #: platform/windows/export/export.cpp #, fuzzy @@ -21425,7 +21401,7 @@ msgstr "ПеремеÑтитÑÑ" msgid "Rotation Degrees" msgstr "ГрадуÑÑ‹ вращениÑ" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "Глобальный поворот" @@ -22935,11 +22911,11 @@ msgstr "" #: scene/3d/physics_body.cpp msgid "Angular Spring Damping" -msgstr "" +msgstr "Угловое Затухание Пружины" #: scene/3d/physics_body.cpp msgid "Angular Equilibrium Point" -msgstr "" +msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ Ð¢Ð¾Ñ‡ÐºÐ° РавновеÑиÑ" #: scene/3d/physics_body.cpp #, fuzzy @@ -22968,7 +22944,7 @@ msgstr "Узел Ри Узел Ð’ должны быть различными о #: scene/3d/physics_joint.cpp msgid "Solver" -msgstr "" +msgstr "Разрешитель" #: scene/3d/physics_joint.cpp #, fuzzy @@ -22982,7 +22958,7 @@ msgstr "Параметры" #: scene/3d/physics_joint.cpp msgid "Angular Limit" -msgstr "" +msgstr "Угловой Предел" #: scene/3d/physics_joint.cpp #, fuzzy @@ -22996,7 +22972,7 @@ msgstr "нижний региÑтр" #: scene/3d/physics_joint.cpp msgid "Motor" -msgstr "" +msgstr "Мотор" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23080,11 +23056,11 @@ msgstr "МежÑтрочный интервал" #: scene/3d/physics_joint.cpp msgid "Equilibrium Point" -msgstr "" +msgstr "Точка РавновеÑиÑ" #: scene/3d/physics_joint.cpp msgid "Angular Limit X" -msgstr "" +msgstr "X Углового Предела" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23093,7 +23069,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть" #: scene/3d/physics_joint.cpp msgid "Angular Spring X" -msgstr "" +msgstr "X Угловой Пружины" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23112,7 +23088,7 @@ msgstr "МежÑтрочный интервал" #: scene/3d/physics_joint.cpp msgid "Angular Limit Y" -msgstr "" +msgstr "Y Углового Предела" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23121,7 +23097,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть" #: scene/3d/physics_joint.cpp msgid "Angular Spring Y" -msgstr "" +msgstr "Y Угловой Пружины" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23140,7 +23116,7 @@ msgstr "МежÑтрочный интервал" #: scene/3d/physics_joint.cpp msgid "Angular Limit Z" -msgstr "" +msgstr "Z Углового Предела" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23149,7 +23125,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть" #: scene/3d/physics_joint.cpp msgid "Angular Spring Z" -msgstr "" +msgstr "Z Угловой Пружины" #: scene/3d/portal.cpp msgid "The RoomManager should not be a child or grandchild of a Portal." @@ -23169,7 +23145,7 @@ msgstr "Портал активен" #: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp msgid "Two Way" -msgstr "" +msgstr "Ð’ обе Стороны" #: scene/3d/portal.cpp msgid "Linked Room" @@ -23531,6 +23507,11 @@ msgstr "" "shapes)." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Глобальное преобразование" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -27779,14 +27760,12 @@ msgid "Import S3TC" msgstr "Импорт" #: servers/visual_server.cpp -#, fuzzy msgid "Import ETC" -msgstr "Импорт" +msgstr "Импортировать ETC" #: servers/visual_server.cpp -#, fuzzy msgid "Import ETC2" -msgstr "Импорт" +msgstr "Импортировать ETC2" #: servers/visual_server.cpp #, fuzzy diff --git a/editor/translations/si.po b/editor/translations/si.po index ae1abeaa5a..8ce2d1d628 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -454,6 +454,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2116,14 +2120,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2179,8 +2184,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2740,8 +2745,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "à·à·Šâ€à¶»à·’à¶:" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5341,6 +5347,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11388,6 +11398,11 @@ msgid "New Animation" msgstr "සජීවීකරණ පුනරà·à·€à¶»à·Šà¶®à¶±à¶º" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "à·à·Šâ€à¶»à·’à¶:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19606,14 +19621,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19635,14 +19649,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20628,7 +20641,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "" @@ -22539,6 +22552,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Anim පරිවර්à¶à¶±à¶º වෙනස් කරන්න" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 6e20ee48da..7cba3886ba 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -493,6 +493,10 @@ msgid "Pressure" msgstr "Preset" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "PrichytiÅ¥ RelatÃvne" @@ -2200,14 +2204,15 @@ msgstr "Obľúbené:" msgid "Recent:" msgstr "Nedávne:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "HľadaÅ¥:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Zhody:" @@ -2267,8 +2272,8 @@ msgstr "HľadaÅ¥ Náhradný Zdroj:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2849,8 +2854,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "SkopÃrovaÅ¥ Výber" #: editor/editor_export.cpp #, fuzzy @@ -5654,6 +5660,10 @@ msgid "Drag And Drop Selection" msgstr "VÅ¡etky vybrané" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11959,6 +11969,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filter:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20648,15 +20663,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Nesprávna veľkosÅ¥ pÃsma." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20678,15 +20693,15 @@ msgstr "Neplatný Názov." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Nesprávna veľkosÅ¥ pÃsma." #: platform/windows/export/export.cpp #, fuzzy @@ -21746,7 +21761,7 @@ msgstr "CestovaÅ¥" msgid "Rotation Degrees" msgstr "Krok Rotácie:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "KonÅ¡tant" @@ -23771,6 +23786,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "PreložiÅ¥ Preloženie:" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 43eb784a39..ceb21aa750 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -466,6 +466,10 @@ msgid "Pressure" msgstr "Prednastavitev..." #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Pripni Relativno" @@ -2219,14 +2223,15 @@ msgstr "Priljubljene:" msgid "Recent:" msgstr "Nedavni:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Iskanje:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Zadetki:" @@ -2288,8 +2293,8 @@ msgstr "Iskanje Nadomestnih Virov:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2882,8 +2887,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Odstrani izbrano" #: editor/editor_export.cpp #, fuzzy @@ -5725,6 +5731,10 @@ msgid "Drag And Drop Selection" msgstr "GridMap IzbriÅ¡i Izbor" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12179,6 +12189,11 @@ msgid "New Animation" msgstr "Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Lastnosti objekta." + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20947,15 +20962,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Uporabiti moraÅ¡ valjavno razÅ¡iritev." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20977,15 +20992,15 @@ msgstr "Neveljavno ime." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Uporabiti moraÅ¡ valjavno razÅ¡iritev." #: platform/windows/export/export.cpp #, fuzzy @@ -22040,7 +22055,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "Rotacijski Korak:" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstanta" @@ -24060,6 +24075,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Preoblikovanje" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sq.po b/editor/translations/sq.po index b11dc2f46f..af72b686b9 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -478,6 +478,10 @@ msgid "Pressure" msgstr "Ngarko Gabimet" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2158,14 +2162,15 @@ msgstr "Të Preferuarat:" msgid "Recent:" msgstr "Të fundit:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Kërko:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Përputhjet:" @@ -2227,8 +2232,8 @@ msgstr "Kërko Resursin Zëvendësues:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2819,8 +2824,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Animacionet:" #: editor/editor_export.cpp #, fuzzy @@ -5661,6 +5667,10 @@ msgid "Drag And Drop Selection" msgstr "Fshi të Selektuarat" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11882,6 +11892,11 @@ msgid "New Animation" msgstr "Animacionin i Ri" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Nyjet filtruese" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20418,15 +20433,15 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Duhet të perdorësh një shtesë të lejuar." #: platform/windows/export/export.cpp msgid "Could not find signtool executable at \"%s\"." @@ -20448,15 +20463,15 @@ msgstr "Emër i palejuar." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Duhet të perdorësh një shtesë të lejuar." #: platform/windows/export/export.cpp #, fuzzy @@ -21475,7 +21490,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstantet" @@ -23425,6 +23440,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Binari i Transformimeve 3D" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index e4a0475e3f..4231d62c6b 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -494,6 +494,10 @@ msgid "Pressure" msgstr "ПоÑтавке" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "Залепи релативно" @@ -2329,14 +2333,15 @@ msgstr "Омиљене:" msgid "Recent:" msgstr "ЧеÑте:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Тражи:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Подударање:" @@ -2398,8 +2403,8 @@ msgstr "Потражи замену за реÑурÑ:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2998,7 +3003,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Копирај Путању Чвора" #: editor/editor_export.cpp @@ -5974,6 +5979,10 @@ msgid "Drag And Drop Selection" msgstr "МапаМреже ИÑпуни Одабрано" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12749,6 +12758,11 @@ msgstr "Ðнимација" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy +msgid "Filter animations" +msgstr "Филтрирај методе" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy msgid "Speed:" msgstr "Брзина (FPS):" @@ -22348,15 +22362,15 @@ msgstr "ÐеуÑпешно отварање нацрта за извоз:" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Мора Ñе кориÑтити важећа екÑтензија." #: platform/windows/export/export.cpp #, fuzzy @@ -22380,15 +22394,15 @@ msgstr "Ðеважеће име." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Мора Ñе кориÑтити важећа екÑтензија." #: platform/windows/export/export.cpp #, fuzzy @@ -23499,7 +23513,7 @@ msgstr "Путуј" msgid "Rotation Degrees" msgstr "Ротација за %s Ñтепени." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "КонÑтантан" @@ -25648,6 +25662,11 @@ msgstr "" "рада." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Сачувај Глобалну ТранÑформу" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 9bbc31e19a..b898108402 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -463,6 +463,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2133,14 +2137,15 @@ msgstr "Omiljeno:" msgid "Recent:" msgstr "Nedavno:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Pretraga:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Podudaranja:" @@ -2200,8 +2205,8 @@ msgstr "Traži Resurs Zamene:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2764,8 +2769,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Kopiraj OznaÄeno" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5360,6 +5366,10 @@ msgid "Drag And Drop Selection" msgstr "Sve sekcije" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11394,6 +11404,11 @@ msgid "New Animation" msgstr "Nova Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Animacija" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19695,14 +19710,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19724,14 +19738,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20735,7 +20748,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Kontanta" @@ -22675,6 +22688,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Animacija Promjeni Transformaciju" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index 010299e2cf..9fd6b9bf67 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -14,7 +14,7 @@ # Mattias Münster <mattiasmun@gmail.com>, 2019. # Anonymous <noreply@weblate.org>, 2020. # Joakim Lundberg <joakim@joakimlundberg.com>, 2020. -# Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020, 2021. +# Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020, 2021, 2022. # Jonas Robertsson <jonas.robertsson@posteo.net>, 2020, 2021. # André Andersson <andre.eric.andersson@gmail.com>, 2020. # Andreas Westrell <andreas.westrell@gmail.com>, 2020. @@ -22,16 +22,18 @@ # Shaggy <anton_christoffersson@hotmail.com>, 2020. # Marcus Toftedahl <marcus.toftedahl@his.se>, 2020. # Alex25820 <Alexander_sjogren@hotmail.se>, 2021. -# Leon <joel.lundborg@gmail.com>, 2021. +# Leon <joel.lundborg@gmail.com>, 2021, 2022. # Kent Jofur <kent.jofur@gmail.com>, 2021. # Alex25820 <alexs25820@gmail.com>, 2021. +# Björn Ã…kesson <bjorn.akesson@gmail.com>, 2022. +# Kenny Andersson <kenny@ordinary.se>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-12-20 18:53+0000\n" -"Last-Translator: Alex25820 <alexs25820@gmail.com>\n" +"PO-Revision-Date: 2022-07-23 03:57+0000\n" +"Last-Translator: Kenny Andersson <kenny@ordinary.se>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/" "godot/sv/>\n" "Language: sv\n" @@ -39,11 +41,12 @@ 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.10\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp +#, fuzzy msgid "Tablet Driver" -msgstr "" +msgstr "Drivrutin för surfplatta" #: core/bind/core_bind.cpp #, fuzzy @@ -51,18 +54,16 @@ msgid "Clipboard" msgstr "Klippbordet är tomt!" #: core/bind/core_bind.cpp -#, fuzzy msgid "Current Screen" -msgstr "Nuvarande Scen" +msgstr "Nuvarande Skärm" #: core/bind/core_bind.cpp msgid "Exit Code" msgstr "" #: core/bind/core_bind.cpp -#, fuzzy msgid "V-Sync Enabled" -msgstr "Aktivera" +msgstr "V-Synk Aktivt" #: core/bind/core_bind.cpp main/main.cpp msgid "V-Sync Via Compositor" @@ -73,9 +74,8 @@ msgid "Delta Smoothing" msgstr "" #: core/bind/core_bind.cpp -#, fuzzy msgid "Low Processor Usage Mode" -msgstr "Exportera Projekt" +msgstr "Läge för lÃ¥g processoranvändning" #: core/bind/core_bind.cpp msgid "Low Processor Usage Mode Sleep (µsec)" @@ -86,9 +86,8 @@ msgid "Keep Screen On" msgstr "" #: core/bind/core_bind.cpp -#, fuzzy msgid "Min Window Size" -msgstr "Storlek:" +msgstr "Minsta fönsterstorlek" #: core/bind/core_bind.cpp #, fuzzy @@ -108,11 +107,11 @@ msgstr "Nytt Fönster" #: core/bind/core_bind.cpp core/project_settings.cpp msgid "Borderless" -msgstr "" +msgstr "Kantlös" #: core/bind/core_bind.cpp msgid "Per Pixel Transparency Enabled" -msgstr "" +msgstr "Genomskinlighet per pixel aktiverad" #: core/bind/core_bind.cpp core/project_settings.cpp #, fuzzy @@ -121,16 +120,16 @@ msgstr "Växla Fullskärm" #: core/bind/core_bind.cpp msgid "Maximized" -msgstr "" +msgstr "Maximerad" #: core/bind/core_bind.cpp msgid "Minimized" -msgstr "" +msgstr "Minimerad" #: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp #: scene/gui/graph_node.cpp msgid "Resizable" -msgstr "" +msgstr "Anpassningsbar" #: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp #: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp @@ -150,36 +149,32 @@ msgstr "Dockposition" #: scene/resources/primitive_meshes.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/texture.cpp #: scene/resources/visual_shader.cpp servers/visual_server.cpp -#, fuzzy msgid "Size" -msgstr "Storlek:" +msgstr "Storlek" #: core/bind/core_bind.cpp msgid "Endian Swap" msgstr "" #: core/bind/core_bind.cpp -#, fuzzy msgid "Editor Hint" -msgstr "Redigera Tema" +msgstr "Redigeringsförslag" #: core/bind/core_bind.cpp msgid "Print Error Messages" -msgstr "" +msgstr "Skriv ut felmeddelanden" #: core/bind/core_bind.cpp -#, fuzzy msgid "Iterations Per Second" -msgstr "Interpolationsläge" +msgstr "Upprepningar per sekund" #: core/bind/core_bind.cpp msgid "Target FPS" -msgstr "" +msgstr "MÃ¥l FPS" #: core/bind/core_bind.cpp -#, fuzzy msgid "Time Scale" -msgstr "Skala" +msgstr "Tidsskala" #: core/bind/core_bind.cpp main/main.cpp #, fuzzy @@ -201,13 +196,12 @@ msgid "Error Line" msgstr "Fel vid sparande" #: core/bind/core_bind.cpp -#, fuzzy msgid "Result" -msgstr "Sök Hjälp" +msgstr "Resultat" #: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp msgid "Memory" -msgstr "" +msgstr "Minne" #: core/command_queue_mt.cpp core/message_queue.cpp #: core/register_core_types.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp @@ -218,7 +212,7 @@ msgstr "" #: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h #: servers/visual_server.cpp msgid "Limits" -msgstr "" +msgstr "Begränsningar" #: core/command_queue_mt.cpp #, fuzzy @@ -227,68 +221,63 @@ msgstr "Ctrl: Rotera" #: core/command_queue_mt.cpp msgid "Multithreading Queue Size (KB)" -msgstr "" +msgstr "FlertrÃ¥dsköstorlek (KB)" #: core/func_ref.cpp modules/visual_script/visual_script_builtin_funcs.cpp #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Function" -msgstr "Funktioner" +msgstr "Funktion" #: core/image.cpp core/packed_data_container.cpp scene/2d/polygon_2d.cpp #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp msgid "Data" -msgstr "" +msgstr "Data" #: core/io/file_access_network.cpp core/register_core_types.cpp #: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp #: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h #: scene/gui/file_dialog.cpp -#, fuzzy msgid "Network" -msgstr "Nätverksprofilerare" +msgstr "Nätverk" #: core/io/file_access_network.cpp -#, fuzzy msgid "Remote FS" -msgstr "Ta bort" +msgstr "Fjärr FS" #: core/io/file_access_network.cpp -#, fuzzy msgid "Page Size" -msgstr "Sida: " +msgstr "Sidstorlek" #: core/io/file_access_network.cpp msgid "Page Read Ahead" -msgstr "" +msgstr "Sida läs framÃ¥t" #: core/io/http_client.cpp msgid "Blocking Mode Enabled" -msgstr "" +msgstr "Blockeringsläge Aktiverat" #: core/io/http_client.cpp -#, fuzzy msgid "Connection" -msgstr "Anslut" +msgstr "Anslutning" #: core/io/http_client.cpp msgid "Read Chunk Size" -msgstr "" +msgstr "Läs segmentstorlek" #: core/io/marshalls.cpp msgid "Object ID" -msgstr "" +msgstr "Objekt ID" #: core/io/multiplayer_api.cpp core/io/packet_peer.cpp msgid "Allow Object Decoding" -msgstr "" +msgstr "TillÃ¥t objekt avkodning" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp msgid "Refuse New Network Connections" -msgstr "" +msgstr "Neka nya nätverksanslutningar" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp #, fuzzy @@ -312,36 +301,35 @@ msgstr "Transformera" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" -msgstr "" +msgstr "Maxstorlek för kodningsbufferten" #: core/io/packet_peer.cpp msgid "Input Buffer Max Size" -msgstr "" +msgstr "Maximal storlek pÃ¥ inmatningsbufferten" #: core/io/packet_peer.cpp msgid "Output Buffer Max Size" -msgstr "" +msgstr "Maxstorlek för utgÃ¥ngsbuffert" #: core/io/packet_peer.cpp msgid "Stream Peer" -msgstr "" +msgstr "Strömningsenhet" #: core/io/stream_peer.cpp msgid "Big Endian" -msgstr "" +msgstr "Big Endian" #: core/io/stream_peer.cpp msgid "Data Array" -msgstr "" +msgstr "Datamatris" #: core/io/stream_peer_ssl.cpp msgid "Blocking Handshake" -msgstr "" +msgstr "Blockering av handskakning" #: core/io/udp_server.cpp -#, fuzzy msgid "Max Pending Connections" -msgstr "Redigera Koppling:" +msgstr "Max väntande anslutningar" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -356,12 +344,11 @@ msgstr "Förväntade en sträng av längden 1 (ett tecken)." #: 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 "Inte nog med bytes för att avkoda, eller ogiltigt format." +msgstr "Otillräckligt antal bytes för att avkoda, eller ogiltigt format." #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" -msgstr "Ogiltig indata %i (ej överförd) i uttrycket" +msgstr "Ogiltig inmatning %d (ej överförd) i uttrycket" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -390,7 +377,7 @@ msgstr "I anrop till '%s':" #: core/math/random_number_generator.cpp #: modules/opensimplex/open_simplex_noise.cpp msgid "Seed" -msgstr "" +msgstr "Seed" #: core/math/random_number_generator.cpp #, fuzzy @@ -399,11 +386,11 @@ msgstr "Status" #: core/message_queue.cpp msgid "Message Queue" -msgstr "" +msgstr "Meddelandekö" #: core/message_queue.cpp msgid "Max Size (KB)" -msgstr "" +msgstr "Maxstorlek (KB)" #: core/os/input.cpp #, fuzzy @@ -412,7 +399,7 @@ msgstr "Växla Läge" #: core/os/input.cpp msgid "Use Accumulated Input" -msgstr "" +msgstr "Använd ackumulerad input" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -420,13 +407,12 @@ msgid "Device" msgstr "Enhet" #: core/os/input_event.cpp -#, fuzzy msgid "Alt" -msgstr "Alla" +msgstr "Alt" #: core/os/input_event.cpp msgid "Shift" -msgstr "" +msgstr "Shift" #: core/os/input_event.cpp #, fuzzy @@ -435,7 +421,7 @@ msgstr "Versionshantering" #: core/os/input_event.cpp msgid "Meta" -msgstr "" +msgstr "Meta" #: core/os/input_event.cpp #, fuzzy @@ -455,9 +441,8 @@ msgid "Pressed" msgstr "Ã…terställ Zoom" #: core/os/input_event.cpp -#, fuzzy msgid "Scancode" -msgstr "Skanna" +msgstr "Scancode" #: core/os/input_event.cpp msgid "Physical Scancode" @@ -465,7 +450,7 @@ msgstr "" #: core/os/input_event.cpp msgid "Unicode" -msgstr "" +msgstr "Unicode" #: core/os/input_event.cpp msgid "Echo" @@ -482,9 +467,8 @@ msgid "Global Position" msgstr "Konstant" #: core/os/input_event.cpp -#, fuzzy msgid "Factor" -msgstr "Vektor" +msgstr "Faktor" #: core/os/input_event.cpp #, fuzzy @@ -493,21 +477,23 @@ msgstr "Automatisk Indentering" #: core/os/input_event.cpp msgid "Doubleclick" -msgstr "" +msgstr "Dubbelklick" #: core/os/input_event.cpp msgid "Tilt" msgstr "" #: core/os/input_event.cpp -#, fuzzy msgid "Pressure" -msgstr "Ã…terställ Zoom" +msgstr "Tryck" + +#: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "Invertera penna" #: core/os/input_event.cpp -#, fuzzy msgid "Relative" -msgstr "GDNative" +msgstr "Relativ" #: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp @@ -523,9 +509,8 @@ msgid "Axis" msgstr "Axel" #: core/os/input_event.cpp -#, fuzzy msgid "Axis Value" -msgstr "Värde" +msgstr "Axelvärde" #: core/os/input_event.cpp modules/visual_script/visual_script_func_nodes.cpp #, fuzzy @@ -541,21 +526,19 @@ msgstr "Ã…tgärd" #: core/os/input_event.cpp scene/resources/environment.cpp #: scene/resources/material.cpp msgid "Strength" -msgstr "" +msgstr "Styrka" #: core/os/input_event.cpp msgid "Delta" -msgstr "" +msgstr "Delta" #: core/os/input_event.cpp -#, fuzzy msgid "Channel" -msgstr "Ändra" +msgstr "Kanal" #: core/os/input_event.cpp main/main.cpp -#, fuzzy msgid "Message" -msgstr "Synkronisera Skript-ändringar" +msgstr "Meddelande" #: core/os/input_event.cpp #, fuzzy @@ -566,11 +549,11 @@ msgstr "Växla" #: scene/2d/physics_body_2d.cpp scene/3d/cpu_particles.cpp #: scene/3d/physics_body.cpp scene/resources/particles_material.cpp msgid "Velocity" -msgstr "" +msgstr "Hastighet" #: core/os/input_event.cpp msgid "Instrument" -msgstr "" +msgstr "Instrument" #: core/os/input_event.cpp #, fuzzy @@ -584,13 +567,13 @@ msgstr "" #: core/project_settings.cpp editor/editor_node.cpp main/main.cpp #: platform/iphone/export/export.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp -#, fuzzy msgid "Application" -msgstr "Ã…tgärd" +msgstr "Applikation" #: core/project_settings.cpp main/main.cpp +#, fuzzy msgid "Config" -msgstr "" +msgstr "Konfigurera" #: core/project_settings.cpp #, fuzzy @@ -626,7 +609,7 @@ msgstr "Kör" #: core/project_settings.cpp editor/editor_node.cpp #: editor/run_settings_dialog.cpp main/main.cpp msgid "Main Scene" -msgstr "" +msgstr "Huvudscen" #: core/project_settings.cpp #, fuzzy @@ -640,15 +623,15 @@ msgstr "Avaktiverad" #: core/project_settings.cpp msgid "Use Hidden Project Data Directory" -msgstr "" +msgstr "Använda dold projektdatakatalog" #: core/project_settings.cpp msgid "Use Custom User Dir" -msgstr "" +msgstr "Använd anpassad användarkatalog" #: core/project_settings.cpp msgid "Custom User Dir Name" -msgstr "" +msgstr "Anpassad användarkatalognamn" #: core/project_settings.cpp main/main.cpp #: platform/javascript/export/export.cpp platform/osx/export/export.cpp @@ -661,7 +644,7 @@ msgstr "Ersätt Alla" #: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp #: scene/3d/label_3d.cpp scene/gui/text_edit.cpp scene/resources/texture.cpp msgid "Width" -msgstr "" +msgstr "Bredd" #: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp #: modules/gltf/gltf_node.cpp modules/opensimplex/noise_texture.cpp @@ -669,13 +652,12 @@ msgstr "" #: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp #: scene/resources/font.cpp scene/resources/navigation_mesh.cpp #: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp -#, fuzzy msgid "Height" -msgstr "Höger" +msgstr "Höjd" #: core/project_settings.cpp msgid "Always On Top" -msgstr "" +msgstr "Alltid överst" #: core/project_settings.cpp #, fuzzy @@ -702,11 +684,11 @@ msgstr "Ladda standard Buss-Layouten." #: editor/editor_settings.cpp editor/script_create_dialog.cpp #: scene/2d/camera_2d.cpp scene/3d/light.cpp scene/main/node.cpp msgid "Editor" -msgstr "" +msgstr "Redigerare" #: core/project_settings.cpp msgid "Main Run Args" -msgstr "" +msgstr "Huvudkörnings arg" #: core/project_settings.cpp #, fuzzy @@ -715,11 +697,12 @@ msgstr "Scen Filsökväg:" #: core/project_settings.cpp msgid "Search In File Extensions" -msgstr "" +msgstr "Sök i filändelser" #: core/project_settings.cpp +#, fuzzy msgid "Script Templates Search Path" -msgstr "" +msgstr "Sökväg för skriptmallar" #: core/project_settings.cpp #, fuzzy @@ -734,16 +717,16 @@ msgstr "Versionshantering" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp msgid "Input" -msgstr "" +msgstr "Input" #: core/project_settings.cpp +#, fuzzy msgid "UI Accept" -msgstr "" +msgstr "UI Acceptera" #: core/project_settings.cpp -#, fuzzy msgid "UI Select" -msgstr "Välj" +msgstr "Ui Välj" #: core/project_settings.cpp #, fuzzy @@ -775,9 +758,8 @@ msgid "UI Up" msgstr "" #: core/project_settings.cpp -#, fuzzy msgid "UI Down" -msgstr "Ladda ner" +msgstr "UI Ner" #: core/project_settings.cpp #, fuzzy @@ -786,11 +768,11 @@ msgstr "Sida: " #: core/project_settings.cpp msgid "UI Page Down" -msgstr "" +msgstr "UI sida ner" #: core/project_settings.cpp msgid "UI Home" -msgstr "" +msgstr "UI hem" #: core/project_settings.cpp msgid "UI End" @@ -927,7 +909,7 @@ msgstr "" #: core/register_core_types.cpp msgid "TCP" -msgstr "" +msgstr "TCP" #: core/register_core_types.cpp #, fuzzy @@ -940,11 +922,12 @@ msgstr "" #: core/register_core_types.cpp msgid "Max Buffer (Power of 2)" -msgstr "" +msgstr "Max buffer (2 potenser)" #: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp +#, fuzzy msgid "SSL" -msgstr "" +msgstr "SSL" #: core/register_core_types.cpp main/main.cpp #, fuzzy @@ -960,7 +943,7 @@ msgstr "Resurs" #: core/resource.cpp #, fuzzy msgid "Local To Scene" -msgstr "Stäng Scen" +msgstr "Lokalt till scenen" #: core/resource.cpp editor/dependency_editor.cpp #: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp @@ -979,12 +962,13 @@ msgid "Locale" msgstr "" #: core/translation.cpp +#, fuzzy msgid "Test" -msgstr "" +msgstr "Test" #: core/translation.cpp scene/resources/font.cpp msgid "Fallback" -msgstr "" +msgstr "Reserv" #: core/ustring.cpp scene/resources/segment_shape_2d.cpp msgid "B" @@ -1019,18 +1003,21 @@ msgstr "EiB" #: drivers/gles3/rasterizer_canvas_base_gles3.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp modules/gltf/gltf_state.cpp +#, fuzzy msgid "Buffers" -msgstr "" +msgstr "Buffertar" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp +#, fuzzy msgid "Canvas Polygon Buffer Size (KB)" -msgstr "" +msgstr "Buffertstorlek för canvaspolygon (KB)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp +#, fuzzy msgid "Canvas Polygon Index Buffer Size (KB)" -msgstr "" +msgstr "Buffertstorlek för Canvas Polygon Index (KB)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp @@ -1041,8 +1028,9 @@ msgstr "" #: servers/physics_2d/physics_2d_server_wrap_mt.h #: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp #: servers/visual_server.cpp +#, fuzzy msgid "2D" -msgstr "" +msgstr "2D" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp @@ -1053,42 +1041,47 @@ msgstr "Alternativ" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Use GPU Pixel Snap" -msgstr "" +msgstr "Använd GPU pixel vidhäftning" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp +#, fuzzy msgid "Immediate Buffer Size (KB)" -msgstr "" +msgstr "Omedelbar buffertstorlek (KB)" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp +#, fuzzy msgid "Lightmapping" -msgstr "" +msgstr "Ljusmappning" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp +#, fuzzy msgid "Use Bicubic Sampling" -msgstr "" +msgstr "Använd bikubisk sampling" #: drivers/gles3/rasterizer_scene_gles3.cpp +#, fuzzy msgid "Max Renderable Elements" -msgstr "" +msgstr "Max Ã¥tergivningsbara element" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Lights" -msgstr "" +msgstr "Max renderbara ljuskällor" #: drivers/gles3/rasterizer_scene_gles3.cpp +#, fuzzy msgid "Max Renderable Reflections" -msgstr "" +msgstr "Max renderingsbara reflektioner" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Lights Per Object" -msgstr "" +msgstr "Max antal ljuskällor per objekt" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Subsurface Scattering" -msgstr "" +msgstr "Subsurface Scattering" #: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp @@ -1112,16 +1105,19 @@ msgid "Weight Samples" msgstr "" #: drivers/gles3/rasterizer_scene_gles3.cpp +#, fuzzy msgid "Voxel Cone Tracing" -msgstr "" +msgstr "Voxel Kon SpÃ¥rning" #: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp +#, fuzzy msgid "High Quality" -msgstr "" +msgstr "Hög kvalitet" #: drivers/gles3/rasterizer_storage_gles3.cpp +#, fuzzy msgid "Blend Shape Max Buffer Size (KB)" -msgstr "" +msgstr "Mixform Max buffertstorlek (KB)" #. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror). #: editor/animation_bezier_editor.cpp @@ -1174,7 +1170,7 @@ msgstr "Anim Ta Bort Nycklar" #: editor/animation_track_editor.cpp msgid "Anim Change Keyframe Time" -msgstr "Anim Ändra Nyckelbildstid" +msgstr "Anim Ändra Tidsnyckelns Tid" #: editor/animation_track_editor.cpp msgid "Anim Change Transition" @@ -1232,7 +1228,7 @@ msgstr "Välj Färg" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp msgid "Args" -msgstr "" +msgstr "Argument" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp @@ -1243,23 +1239,25 @@ msgstr "Typ" #: editor/animation_track_editor.cpp msgid "In Handle" -msgstr "" +msgstr "Handtag in" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Out Handle" -msgstr "" +msgstr "Handtag ut" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp +#, fuzzy msgid "Stream" -msgstr "" +msgstr "Ström" #: editor/animation_track_editor.cpp #, fuzzy msgid "Start Offset" -msgstr "Icon Läge" +msgstr "Startförskjutning" #: editor/animation_track_editor.cpp #, fuzzy @@ -1278,7 +1276,7 @@ msgstr "Animation" #: editor/animation_track_editor.cpp msgid "Easing" -msgstr "" +msgstr "Lätta" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" @@ -1431,7 +1429,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Out-Handle:" -msgstr "" +msgstr "Handtag ut:" #: editor/animation_track_editor.cpp #, fuzzy @@ -1444,8 +1442,9 @@ msgid "Start (s):" msgstr "Starta" #: editor/animation_track_editor.cpp +#, fuzzy msgid "End (s):" -msgstr "" +msgstr "Slut (s):" #: editor/animation_track_editor.cpp #, fuzzy @@ -1505,7 +1504,7 @@ msgstr "Duplicera Nycklar" #: editor/animation_track_editor.cpp msgid "Add RESET Value(s)" -msgstr "" +msgstr "Lägg till RESET-värde(n)" #: editor/animation_track_editor.cpp msgid "Delete Key(s)" @@ -1587,7 +1586,7 @@ msgstr "" #. TRANSLATORS: This describes the target of new animation track, will be inserted into another string. #: editor/animation_track_editor.cpp msgid "property '%s'" -msgstr "egenskapen '%s'" +msgstr "egenskap '%s'" #: editor/animation_track_editor.cpp msgid "Anim Create & Insert" @@ -1820,9 +1819,8 @@ msgid "Go to Previous Step" msgstr "GÃ¥ till FöregÃ¥ende Steg" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Apply Reset" -msgstr "Ã…terställ Zoom" +msgstr "Verkställ Ã¥terställning" #: editor/animation_track_editor.cpp msgid "Optimize Animation" @@ -2205,14 +2203,15 @@ msgstr "Favoriter:" msgid "Recent:" msgstr "Senaste:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Sök:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Matchar:" @@ -2272,8 +2271,8 @@ msgstr "Sök Ersättningsresurs:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2282,17 +2281,17 @@ msgstr "Öppna" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Ägare av: %s (Totalt: %d)" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove the selected files from the project? (Cannot be undone.)\n" "Depending on your filesystem configuration, the files will either be moved " "to the system trash or deleted permanently." msgstr "" -"Ta bort valda filer frÃ¥n projektet? (Kan ej Ã¥terställas)\n" -"Du kan hitta de borttagna filerna i systemets papperskorg." +"Ta bort de valda filerna frÃ¥n projektet? (Kan ej Ã¥ngras.)\n" +"Beroende pÃ¥ hur ditt filsystem är konfigurerat sÃ¥ kommer filerna antingen " +"flyttas till systemets papperskorg eller tas bort permanent." #: editor/dependency_editor.cpp msgid "" @@ -2377,7 +2376,7 @@ msgstr "Tack frÃ¥n Godot-gemenskapen!" #: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp msgid "Click to copy." -msgstr "Klicka för att kopiera." +msgstr "Klicka för att kopiera" #: editor/editor_about.cpp msgid "Godot Engine contributors" @@ -2475,30 +2474,32 @@ msgid "Licenses" msgstr "Licenser" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Error opening asset file for \"%s\" (not in ZIP format)." -msgstr "Fel vid öppning av paketetfil, inte i zip-format." +msgstr "Fel vid öppning av tillgÃ¥ngsfilen för \"%s\" (inte i ZIP-format)." #: editor/editor_asset_installer.cpp msgid "%s (already exists)" msgstr "%s (existerar redan)" #: editor/editor_asset_installer.cpp +#, fuzzy msgid "Contents of asset \"%s\" - %d file(s) conflict with your project:" msgstr "" +"InnehÃ¥llet i resursen \"%s\" - %d fil(er) stÃ¥r i konflikt med ditt projekt:" #: editor/editor_asset_installer.cpp +#, fuzzy msgid "Contents of asset \"%s\" - No files conflict with your project:" msgstr "" +"InnehÃ¥llet i resursen \"%s\" - Inga filer stÃ¥r i konflikt med ditt projekt:" #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" msgstr "Dekomprimerar TillgÃ¥ngar" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "The following files failed extraction from asset \"%s\":" -msgstr "Följande filer misslyckades att packas upp frÃ¥n paketet:" +msgstr "Följande filer misslyckades att packas upp frÃ¥n paketet \"%s\":" #: editor/editor_asset_installer.cpp msgid "(and %s more files)" @@ -2506,7 +2507,7 @@ msgstr "(och %s fler filer)" #: editor/editor_asset_installer.cpp msgid "Asset \"%s\" installed successfully!" -msgstr "Paketet \"%s\" har installerats!" +msgstr "Installation av tillgÃ¥ngen \"%s\" lyckades!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2518,9 +2519,8 @@ msgid "Install" msgstr "Installera" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Asset Installer" -msgstr "Paketinstallerare" +msgstr "TillgÃ¥ngsinstallerare" #: editor/editor_audio_buses.cpp msgid "Speakers" @@ -2701,8 +2701,9 @@ msgid "Invalid name." msgstr "Ogiltigt namn." #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Cannot begin with a digit." -msgstr "" +msgstr "Kan inte börja med en siffra." #: editor/editor_autoload_settings.cpp msgid "Valid characters:" @@ -2767,7 +2768,7 @@ msgstr "%s är en ogiltig genväg. Filen existerar inte." #: editor/editor_autoload_settings.cpp msgid "%s is an invalid path. Not in resource path (res://)." -msgstr "" +msgstr "%s är en ogiltig genväg. Inte i resurs-genväg (res://)." #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2847,11 +2848,11 @@ msgstr "Välj" #: editor/editor_export.cpp msgid "Project export for platform:" -msgstr "" +msgstr "Projektexport för plattformen:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Kopiera Nod-Sökväg" #: editor/editor_export.cpp @@ -2934,8 +2935,8 @@ msgid "" "Target platform requires 'PVRTC' texture compression for GLES2. Enable " "'Import Pvrtc' in Project Settings." msgstr "" -"MÃ¥lplattformen kräver 'PVRTC'-texturkomprimering för GLES2. Aktivera 'Import " -"Pvrtc' i projektinställningarna." +"MÃ¥lplattformen kräver 'PVRTC' texturkomprimering för GLES2. Aktivera " +"'Importera Pvrtc' i Projektinställningarna." #: editor/editor_export.cpp msgid "" @@ -2967,7 +2968,7 @@ msgstr "Redigera Tema" #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #: platform/uwp/export/export.cpp msgid "Release" -msgstr "" +msgstr "Släpp" #: editor/editor_export.cpp #, fuzzy @@ -2976,11 +2977,12 @@ msgstr "Färg enhetlig." #: editor/editor_export.cpp msgid "64 Bits" -msgstr "" +msgstr "64 bitar" #: editor/editor_export.cpp +#, fuzzy msgid "Embed PCK" -msgstr "" +msgstr "Bädda in PCK" #: editor/editor_export.cpp platform/osx/export/export.cpp #, fuzzy @@ -3042,7 +3044,7 @@ msgstr "Hantera exportmallar..." #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp msgid "PCK Embedding" -msgstr "" +msgstr "PCK Inbäddning" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." @@ -3050,7 +3052,7 @@ msgstr "Den inbäddade PCK fÃ¥r inte vara större än 4 GiB pÃ¥ 32 bitars export #: editor/editor_export.cpp msgid "Convert Text Resources To Binary On Export" -msgstr "" +msgstr "Konvertera textresurser till binära vid export" #: editor/editor_feature_profile.cpp msgid "3D Editor" @@ -3079,9 +3081,8 @@ msgid "FileSystem Dock" msgstr "FilSystem" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Import Dock" -msgstr "Importera" +msgstr "Importera Brygga" #: editor/editor_feature_profile.cpp msgid "Allows to view and edit 3D scenes." @@ -3093,17 +3094,19 @@ msgstr "TillÃ¥ter att redigera skript via den integrerade skript-redigeraren." #: editor/editor_feature_profile.cpp msgid "Provides built-in access to the Asset Library." -msgstr "" +msgstr "Ger inbyggd tillgÃ¥ng till tillgÃ¥ngsbiblioteket." #: editor/editor_feature_profile.cpp +#, fuzzy msgid "Allows editing the node hierarchy in the Scene dock." -msgstr "" +msgstr "TillÃ¥ter redigering av nodhierarkin i scendockan." #: editor/editor_feature_profile.cpp msgid "" "Allows to work with signals and groups of the node selected in the Scene " "dock." msgstr "" +"TillÃ¥ter arbete med signaler och grupper av noden som valts i Scendockan." #: editor/editor_feature_profile.cpp msgid "Allows to browse the local file system via a dedicated dock." @@ -3141,19 +3144,16 @@ msgid "(Editor Disabled, Properties Disabled)" msgstr "(Editor inaktiverad, Egenskaper inaktiverad)" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "(Properties Disabled)" -msgstr "Egenskaper" +msgstr "(Egenskaper avstängda)" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "(Editor Disabled)" -msgstr "Redigera Variabel" +msgstr "(Redigeraren är avstängd)" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Class Options:" -msgstr "Beskrivning:" +msgstr "Klassalternativ:" #: editor/editor_feature_profile.cpp msgid "Enable Contextual Editor" @@ -3190,9 +3190,8 @@ msgid "Error saving profile to path: '%s'." msgstr "Fel vid laddning av mall '%s'." #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Reset to Default" -msgstr "Ladda Standard" +msgstr "Ã…terställ till Standard" #: editor/editor_feature_profile.cpp msgid "Current Profile:" @@ -3245,18 +3244,16 @@ msgid "Create or import a profile to edit available classes and properties." msgstr "" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "New profile name:" -msgstr "Nytt namn:" +msgstr "Nytt profilnamn:" #: editor/editor_feature_profile.cpp msgid "Godot Feature Profile" msgstr "Godot funktions profil" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Import Profile(s)" -msgstr "%d fler filer" +msgstr "Importera profil(er)" #: editor/editor_feature_profile.cpp #, fuzzy @@ -3290,9 +3287,8 @@ msgid "Copy Path" msgstr "Kopiera Sökväg" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "Open in File Manager" -msgstr "Visa I Filhanteraren" +msgstr "Öppna i filhanteraren" #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/project_manager.cpp @@ -5552,7 +5548,7 @@ msgstr "Miniatyr..." #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "Anslutningar" #: editor/editor_settings.cpp #, fuzzy @@ -5670,6 +5666,10 @@ msgid "Drag And Drop Selection" msgstr "Alla urval" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11297,7 +11297,7 @@ msgstr "Spela" #: editor/plugins/spatial_editor_plugin.cpp msgid "Orthogonal" -msgstr "" +msgstr "Ortogonal" #: editor/plugins/spatial_editor_plugin.cpp modules/gltf/gltf_camera.cpp msgid "Perspective" @@ -11464,7 +11464,7 @@ msgstr "Partiklar" #: editor/plugins/spatial_editor_plugin.cpp msgid "FPS: %d (%s ms)" -msgstr "" +msgstr "FPS: %d (%s ms)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View." @@ -12045,6 +12045,11 @@ msgid "New Animation" msgstr "Animation" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Filtrera noder" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20718,15 +20723,15 @@ msgstr "Det gick inte att hitta nyckellager, det gick inte att exportera." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "MÃ¥ste använda en giltigt filändelse." #: platform/windows/export/export.cpp #, fuzzy @@ -20750,15 +20755,15 @@ msgstr "Ogiltigt namn." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "MÃ¥ste använda en giltigt filändelse." #: platform/windows/export/export.cpp #, fuzzy @@ -21814,7 +21819,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "Roterar %s grader." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Konstant" @@ -23848,6 +23853,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transformera" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -24729,8 +24739,9 @@ msgid "Alpha" msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp +#, fuzzy msgid "Caret" -msgstr "" +msgstr "Markör" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" @@ -25388,9 +25399,8 @@ msgid "Draw 2D Outlines" msgstr "" #: scene/main/scene_tree.cpp servers/visual_server.cpp -#, fuzzy msgid "Reflections" -msgstr "Riktningar" +msgstr "Reflektioner" #: scene/main/scene_tree.cpp msgid "Atlas Size" @@ -28323,12 +28333,13 @@ msgid "UV Contract Amount" msgstr "" #: servers/visual_server.cpp +#, fuzzy msgid "Use Simple PVS" -msgstr "" +msgstr "Använd enkel PVS" #: servers/visual_server.cpp msgid "PVS Logging" -msgstr "" +msgstr "PVS loggning" #: servers/visual_server.cpp #, fuzzy @@ -28341,8 +28352,9 @@ msgid "Remove Danglers" msgstr "Ta Bort Mall" #: servers/visual_server.cpp +#, fuzzy msgid "Flip Imported Portals" -msgstr "" +msgstr "Vänd importerade portaler" #: servers/visual_server.cpp #, fuzzy @@ -28350,8 +28362,9 @@ msgid "Occlusion Culling" msgstr "Redigera Polygon" #: servers/visual_server.cpp +#, fuzzy msgid "Max Active Spheres" -msgstr "" +msgstr "Max aktiva sfärer" #: servers/visual_server.cpp #, fuzzy @@ -28364,13 +28377,15 @@ msgid "Shader Compilation Mode" msgstr "Interpolationsläge" #: servers/visual_server.cpp +#, fuzzy msgid "Max Simultaneous Compiles" -msgstr "" +msgstr "Max samtidiga kompileringar" #: servers/visual_server.cpp msgid "Log Active Async Compiles Count" msgstr "" #: servers/visual_server.cpp +#, fuzzy msgid "Shader Cache Size (MB)" -msgstr "" +msgstr "Shader Cache Storlek (MB)" diff --git a/editor/translations/te.po b/editor/translations/te.po index 9e49f9dcc5..af4c65f062 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -444,6 +444,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2070,14 +2074,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2133,8 +2138,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2693,8 +2698,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "సంఘం" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5267,6 +5273,10 @@ msgid "Drag And Drop Selection" msgstr "" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11228,6 +11238,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "గణనలà±" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -19310,14 +19325,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19338,14 +19352,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20306,7 +20319,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "à°¸à±à°¥à°¿à°°à°¾à°‚కాలà±" @@ -22146,6 +22159,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "గణనలà±" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index 1a6a4b71be..f1eb8b716f 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -501,6 +501,10 @@ msgid "Pressure" msgstr "พรีเซ็ต" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "จำà¸à¸±à¸”โดยใช้ตำà¹à¸«à¸™à¹ˆà¸‡à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™" @@ -2219,14 +2223,15 @@ msgstr "ที่ชื่นชà¸à¸š:" msgid "Recent:" msgstr "ล่าสุด:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "ค้นหา:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "พบ:" @@ -2287,8 +2292,8 @@ msgstr "ค้นหาทรัพยาà¸à¸£à¸¡à¸²à¹à¸—นที่:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2870,7 +2875,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "คัดลà¸à¸à¸•ำà¹à¸«à¸™à¹ˆà¸‡à¹‚หนด" #: editor/editor_export.cpp @@ -5649,6 +5654,10 @@ msgid "Drag And Drop Selection" msgstr "เติมที่เลืà¸à¸à¹ƒà¸™ GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11943,6 +11952,11 @@ msgid "New Animation" msgstr "à¹à¸à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™à¹ƒà¸«à¸¡à¹ˆ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "วิธีà¸à¸²à¸£à¸à¸£à¸à¸‡" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "ความเร็ว:" @@ -20696,15 +20710,15 @@ msgstr "เปิดเทมเพลตเพื่à¸à¸ªà¹ˆà¸‡à¸à¸à¸à¹„ม #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•้à¸à¸‡" #: platform/windows/export/export.cpp #, fuzzy @@ -20728,15 +20742,15 @@ msgstr "ชื่à¸à¸œà¸´à¸”พลาด" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•้à¸à¸‡" #: platform/windows/export/export.cpp #, fuzzy @@ -21830,7 +21844,7 @@ msgstr "à¸à¸²à¸£à¹€à¸„ลื่à¸à¸™à¸—ี่" msgid "Rotation Degrees" msgstr "หมุน %s à¸à¸‡à¸¨à¸²" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "คงที่" @@ -23918,6 +23932,11 @@ msgstr "" "เปลี่ยนขนาดขà¸à¸‡à¸‚à¸à¸šà¹€à¸‚ตà¸à¸²à¸£à¸Šà¸™à¸¥à¸¹à¸à¹à¸—น" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "เà¸à¹‡à¸š Global Transform" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/tl.po b/editor/translations/tl.po index d5a5d52332..fec7766383 100644 --- a/editor/translations/tl.po +++ b/editor/translations/tl.po @@ -476,6 +476,10 @@ msgid "Pressure" msgstr "Preset" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp #, fuzzy msgid "Relative" msgstr "GDNative" @@ -2171,14 +2175,15 @@ msgstr "Mga Paborito:" msgid "Recent:" msgstr "Kamakailan:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Maghanap:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Mga Tugma:" @@ -2238,8 +2243,8 @@ msgstr "Maghanap ng Pangpalit na Resource:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2809,8 +2814,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr "Kopyahin Ang Pinagpipilian" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5463,6 +5469,10 @@ msgid "Drag And Drop Selection" msgstr "Kopyahin Ang Pinagpipilian" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11569,6 +11579,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Salain ang mga method" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Bilis:" @@ -19966,14 +19981,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -19996,14 +20010,13 @@ msgstr "Di-wastong pangalan." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -21035,7 +21048,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Constant" @@ -23032,6 +23045,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Transisyon: " + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 1e4ab521bf..ab58a87c36 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -74,13 +74,17 @@ # Ramazan Aslan <legendraslan@gmail.com>, 2022. # paledega <paledega@yandex.ru>, 2022. # Yekez <yasintonge@gmail.com>, 2022. +# Deleted User <noreply+46833@weblate.org>, 2022. +# Emre <mr.inkaya@gmail.com>, 2022. +# Deleted User <noreply+46858@weblate.org>, 2022. +# Ümid Quliyev <lucifer25x@protonmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-03 00:44+0000\n" -"Last-Translator: Yekez <yasintonge@gmail.com>\n" +"PO-Revision-Date: 2022-08-05 01:04+0000\n" +"Last-Translator: Ümid Quliyev <lucifer25x@protonmail.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot/tr/>\n" "Language: tr\n" @@ -88,7 +92,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -333,15 +337,15 @@ msgstr "Transfer Modu" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" -msgstr "" +msgstr "Kodlama ArabelleÄŸi Maksimum Boyutu" #: core/io/packet_peer.cpp msgid "Input Buffer Max Size" -msgstr "" +msgstr "GiriÅŸ ArabelleÄŸi Maksimum Boyutu" #: core/io/packet_peer.cpp msgid "Output Buffer Max Size" -msgstr "" +msgstr "Çıkış ArabelleÄŸi Maksimum Boyutu" #: core/io/packet_peer.cpp msgid "Stream Peer" @@ -349,15 +353,15 @@ msgstr "" #: core/io/stream_peer.cpp msgid "Big Endian" -msgstr "" +msgstr "big-endian" #: core/io/stream_peer.cpp msgid "Data Array" -msgstr "" +msgstr "Veri Dizisi" #: core/io/stream_peer_ssl.cpp msgid "Blocking Handshake" -msgstr "" +msgstr "TokalaÅŸmayı blokla" #: core/io/udp_server.cpp msgid "Max Pending Connections" @@ -383,12 +387,10 @@ msgid "Invalid input %d (not passed) in expression" msgstr "İfadede geçersiz giriÅŸ %d" #: core/math/expression.cpp -#, fuzzy msgid "self can't be used because instance is null (not passed)" msgstr "self kullanılamaz çünkü örnek boÅŸ (geçilmedi)" #: core/math/expression.cpp -#, fuzzy msgid "Invalid operands to operator %s, %s and %s." msgstr "\"%s\" iÅŸlecinde geçersiz terimler, '%s' ve '%s'." @@ -411,7 +413,7 @@ msgstr "'%s' çaÄŸrıldığında:" #: core/math/random_number_generator.cpp #: modules/opensimplex/open_simplex_noise.cpp msgid "Seed" -msgstr "" +msgstr "Tohum" #: core/math/random_number_generator.cpp msgid "State" @@ -426,14 +428,12 @@ msgid "Max Size (KB)" msgstr "En Büyük Boyut (KB)" #: core/os/input.cpp -#, fuzzy msgid "Mouse Mode" -msgstr "Biçimi Taşı" +msgstr "Fare Modu" #: core/os/input.cpp -#, fuzzy msgid "Use Accumulated Input" -msgstr "GiriÅŸi Sil" +msgstr "BirikmiÅŸ Girdiyi Kullan" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -449,12 +449,10 @@ msgid "Shift" msgstr "Shift" #: core/os/input_event.cpp -#, fuzzy msgid "Control" -msgstr "Ctrl" +msgstr "Kontrol TuÅŸu" #: core/os/input_event.cpp -#, fuzzy msgid "Meta" msgstr "Meta" @@ -463,9 +461,8 @@ msgid "Command" msgstr "Komut" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (Fiziksel)" +msgstr "Fiziksel" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -474,7 +471,6 @@ msgid "Pressed" msgstr "Basılmış" #: core/os/input_event.cpp -#, fuzzy msgid "Scancode" msgstr "Tarama kodu" @@ -483,14 +479,12 @@ msgid "Physical Scancode" msgstr "Fiziksel TuÅŸ Kodu" #: core/os/input_event.cpp -#, fuzzy msgid "Unicode" -msgstr "Unicode" +msgstr "Evrensel Kod" #: core/os/input_event.cpp -#, fuzzy msgid "Echo" -msgstr "Eko" +msgstr "Yankı" #: core/os/input_event.cpp scene/gui/base_button.cpp msgid "Button Mask" @@ -501,9 +495,8 @@ msgid "Global Position" msgstr "Global Pozisyon" #: core/os/input_event.cpp -#, fuzzy msgid "Factor" -msgstr "Vektör" +msgstr "Etken" #: core/os/input_event.cpp msgid "Button Index" @@ -522,6 +515,11 @@ msgid "Pressure" msgstr "Baskı" #: core/os/input_event.cpp +#, fuzzy +msgid "Pen Inverted" +msgstr "Ters Kalem" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Göreceli" @@ -580,18 +578,16 @@ msgid "Velocity" msgstr "Hız" #: core/os/input_event.cpp -#, fuzzy msgid "Instrument" msgstr "Alet" #: core/os/input_event.cpp -#, fuzzy msgid "Controller Number" -msgstr "Satır Numarası:" +msgstr "Denetleyici Numarası" #: core/os/input_event.cpp msgid "Controller Value" -msgstr "" +msgstr "Denetleyici DeÄŸeri" #: core/project_settings.cpp editor/editor_node.cpp main/main.cpp #: platform/iphone/export/export.cpp platform/osx/export/export.cpp @@ -715,7 +711,7 @@ msgstr "Ana Sahne DeÄŸiÅŸtirgenleri:" #: core/project_settings.cpp #, fuzzy msgid "Scene Naming" -msgstr "Sahne Yolu:" +msgstr "Sahne Adlandırma" #: core/project_settings.cpp msgid "Search In File Extensions" @@ -728,12 +724,12 @@ msgstr "Script Dosyalarını Aramak İçin Dosya Yolu" #: core/project_settings.cpp #, fuzzy msgid "Version Control Autoload On Startup" -msgstr "BaÅŸlangıçta Otomatik Yükleme" +msgstr "BaÅŸlangıçta Otomatik Sürüm Kontrolü" #: core/project_settings.cpp #, fuzzy msgid "Version Control Plugin Name" -msgstr "Sürüm Kontrol" +msgstr "Sürüm Denetimi Eklenti Adı" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -917,7 +913,6 @@ msgid "Modules" msgstr "Modüller" #: core/register_core_types.cpp -#, fuzzy msgid "TCP" msgstr "TCP" @@ -926,8 +921,9 @@ msgid "Connect Timeout Seconds" msgstr "BaÄŸlanma Zaman Aşımı Süresi(Saniye)" #: core/register_core_types.cpp +#, fuzzy msgid "Packet Peer Stream" -msgstr "" +msgstr "Paket EÅŸ Akışı" #: core/register_core_types.cpp msgid "Max Buffer (Power of 2)" @@ -973,7 +969,7 @@ msgstr "Deneme" #: core/translation.cpp scene/resources/font.cpp msgid "Fallback" -msgstr "" +msgstr "Geri Dönüş" #: core/ustring.cpp scene/resources/segment_shape_2d.cpp msgid "B" @@ -1014,12 +1010,12 @@ msgstr "Arabellek" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Canvas Polygon Buffer Size (KB)" -msgstr "" +msgstr "Tuval Çokgen Arabellek Boyutu (KB)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp msgid "Canvas Polygon Index Buffer Size (KB)" -msgstr "" +msgstr "Tuval Çokgen Dizini Arabellek Boyutu (KB)" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp @@ -1035,36 +1031,33 @@ msgstr "2D" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Snapping" msgstr "Akıllı Hizalama" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Use GPU Pixel Snap" msgstr "Piksel Yapışması Kullan" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Immediate Buffer Size (KB)" -msgstr "" +msgstr "Anlık Arabellek Boyutu (KB)" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp -#, fuzzy msgid "Lightmapping" -msgstr "Işık-Haritalarını PiÅŸir" +msgstr "Işık Haritalama" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp +#, fuzzy msgid "Use Bicubic Sampling" -msgstr "" +msgstr "Bicubic Örneklemeyi Kullanın" #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Max Renderable Elements" -msgstr "Maks. Renderlanabilinecek Ögeler" +msgstr "Maksimum İşlenebilir Öğeler" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Max Renderable Lights" @@ -1101,11 +1094,12 @@ msgstr "Yüzeyi Takip Et" #: drivers/gles3/rasterizer_scene_gles3.cpp msgid "Weight Samples" -msgstr "" +msgstr "Ağırlık Örnekleri" #: drivers/gles3/rasterizer_scene_gles3.cpp +#, fuzzy msgid "Voxel Cone Tracing" -msgstr "" +msgstr "Işın İzleme" #: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp msgid "High Quality" @@ -1113,7 +1107,7 @@ msgstr "Yüksek Kalite" #: drivers/gles3/rasterizer_storage_gles3.cpp msgid "Blend Shape Max Buffer Size (KB)" -msgstr "" +msgstr "Karışım Åžekli Maksimum Arabellek Boyutu (KB)" #. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror). #: editor/animation_bezier_editor.cpp @@ -1187,9 +1181,8 @@ msgstr "Animasyon DeÄŸiÅŸikliÄŸi ÇaÄŸrısı" #: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Frame" -msgstr "Kare %" +msgstr "Kare" #: editor/animation_track_editor.cpp editor/editor_profiler.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp @@ -1244,8 +1237,9 @@ msgstr "Tutamacı Ayarla" #: editor/import/resource_importer_texture.cpp #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp +#, fuzzy msgid "Stream" -msgstr "" +msgstr "Aktarım" #: editor/animation_track_editor.cpp #, fuzzy @@ -1406,7 +1400,7 @@ msgstr "Tür:" #: editor/animation_track_editor.cpp #, fuzzy msgid "(Invalid, expected type: %s)" -msgstr "Geçersiz Dışa Aktarım Åžablonu:" +msgstr "(Geçersiz Dışa Aktarım Åžablonu: %s)" #: editor/animation_track_editor.cpp msgid "Easing:" @@ -1425,22 +1419,22 @@ msgstr "Tutamacı Ayarla" #: editor/animation_track_editor.cpp #, fuzzy msgid "Stream:" -msgstr "Radyo Ögesi" +msgstr "Aktarım:" #: editor/animation_track_editor.cpp #, fuzzy msgid "Start (s):" -msgstr "Yeniden BaÅŸlat (sn):" +msgstr "BaÅŸlangıç (lar):" #: editor/animation_track_editor.cpp #, fuzzy msgid "End (s):" -msgstr "Açılma (sn):" +msgstr "BitiÅŸ (ler):" #: editor/animation_track_editor.cpp #, fuzzy msgid "Animation Clip:" -msgstr "Animasyonlar:" +msgstr "Animasyon Klibi:" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -1531,7 +1525,7 @@ msgstr "Düzenleyici" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #, fuzzy msgid "Confirm Insert Track" -msgstr "Animasyon İz & Anahtar Ekle" +msgstr "Parça Eklemeyi Onayla" #. TRANSLATORS: %s will be replaced by a phrase describing the target of track. #: editor/animation_track_editor.cpp @@ -1658,7 +1652,7 @@ msgstr "Yöntem İz Anahtarı Ekle" #: editor/animation_track_editor.cpp #, fuzzy msgid "Method not found in object:" -msgstr "Metot, nesne içinde bulunamadı: " +msgstr "Metot, nesne içinde bulunamadı:" #: editor/animation_track_editor.cpp msgid "Anim Move Keys" @@ -2191,14 +2185,15 @@ msgstr "BeÄŸeniler:" msgid "Recent:" msgstr "Yakın zamanda:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Ara:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "EÅŸleÅŸmeler:" @@ -2258,8 +2253,8 @@ msgstr "Yerine Geçecek Kaynak Ara:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2267,8 +2262,9 @@ msgid "Open" msgstr "Aç" #: editor/dependency_editor.cpp +#, fuzzy msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "Sahipleri: %s (Toplam: %d)" #: editor/dependency_editor.cpp msgid "" @@ -2627,7 +2623,7 @@ msgstr "'%s' dosyası bulunamadı." #: editor/editor_audio_buses.cpp #, fuzzy msgid "Layout:" -msgstr "YerleÅŸim Düzeni" +msgstr "YerleÅŸim Düzeni:" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." @@ -2678,7 +2674,7 @@ msgstr "Yeni bir Bus YerleÅŸim Düzeni oluÅŸtur." #: editor/editor_audio_buses.cpp #, fuzzy msgid "Audio Bus Layout" -msgstr "Audio Bus YerleÅŸim Düzenini Aç" +msgstr "Ses Veri Yolu Düzeni" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -2830,23 +2826,24 @@ msgid "Choose" msgstr "Seç" #: editor/editor_export.cpp +#, fuzzy msgid "Project export for platform:" -msgstr "" +msgstr "Platform için proje dışa aktarımı:" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." -msgstr "Düğüm Yolunu Kopyala" +msgid "Completed with warnings." +msgstr "Hatalarla tamamlandı." #: editor/editor_export.cpp #, fuzzy msgid "Completed successfully." -msgstr "Paket BaÅŸarı ile Kuruldu!" +msgstr "BaÅŸarıyla tamamlandı." #: editor/editor_export.cpp #, fuzzy msgid "Failed." -msgstr "BaÅŸarısız:" +msgstr "BaÅŸarısız." #: editor/editor_export.cpp msgid "Storing File:" @@ -2863,27 +2860,27 @@ msgstr "Çıkınla" #: editor/editor_export.cpp #, fuzzy msgid "Save PCK" -msgstr "Farklı Kaydet" +msgstr "PCK'yi kaydet" #: editor/editor_export.cpp #, fuzzy msgid "Cannot create file \"%s\"." -msgstr "Klasör oluÅŸturulamadı." +msgstr "\"%s\" dosyası oluÅŸturulamıyor." #: editor/editor_export.cpp #, fuzzy msgid "Failed to export project files." -msgstr "Proje dosyaları dışa aktarılamadı" +msgstr "Proje dosyaları dışa aktarılamadı." #: editor/editor_export.cpp #, fuzzy msgid "Can't open file to read from path \"%s\"." -msgstr "Dosya yazmak için açılamıyor:" +msgstr "\"%s\" yolundan okunacak dosya açılamıyor." #: editor/editor_export.cpp #, fuzzy msgid "Save ZIP" -msgstr "Farklı Kaydet" +msgstr "ZIP dosyasını kaydet" #: editor/editor_export.cpp msgid "" @@ -2946,7 +2943,7 @@ msgstr "" #: platform/osx/export/export.cpp platform/uwp/export/export.cpp #, fuzzy msgid "Custom Template" -msgstr "Editör Teması" +msgstr "Özel Åžablon" #: editor/editor_export.cpp editor/project_export.cpp #: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp @@ -2958,36 +2955,42 @@ msgstr "Yayınlamak" #: editor/editor_export.cpp #, fuzzy msgid "Binary Format" -msgstr "Renk operatörü." +msgstr "Çift Biçim" #: editor/editor_export.cpp +#, fuzzy msgid "64 Bits" -msgstr "" +msgstr "64 Bit" #: editor/editor_export.cpp +#, fuzzy msgid "Embed PCK" -msgstr "" +msgstr "PCK'yı yerleÅŸtirin" #: editor/editor_export.cpp platform/osx/export/export.cpp #, fuzzy msgid "Texture Format" -msgstr "DokuBölgesi" +msgstr "Doku Biçimi" #: editor/editor_export.cpp +#, fuzzy msgid "BPTC" -msgstr "" +msgstr "BPTC" #: editor/editor_export.cpp platform/osx/export/export.cpp +#, fuzzy msgid "S3TC" -msgstr "" +msgstr "S3TC" #: editor/editor_export.cpp platform/osx/export/export.cpp +#, fuzzy msgid "ETC" -msgstr "" +msgstr "ETC" #: editor/editor_export.cpp platform/osx/export/export.cpp +#, fuzzy msgid "ETC2" -msgstr "" +msgstr "ETC2" #: editor/editor_export.cpp #, fuzzy @@ -3009,7 +3012,7 @@ msgstr "Özel yayınlama ÅŸablonu bulunamadı." #: editor/editor_export.cpp #, fuzzy msgid "Prepare Template" -msgstr "Åžablonlarını Yönet" +msgstr "Åžablon Hazırla" #: editor/editor_export.cpp platform/osx/export/export.cpp #, fuzzy @@ -3019,12 +3022,12 @@ msgstr "Belirtilen Dışa aktarım yolu mevcut deÄŸil:" #: editor/editor_export.cpp platform/javascript/export/export.cpp #, fuzzy msgid "Template file not found: \"%s\"." -msgstr "Åžablon dosyası bulunamadı:" +msgstr "Åžablon dosyası bulunamadı: \"%s\"." #: editor/editor_export.cpp #, fuzzy msgid "Failed to copy export template." -msgstr "Geçersiz Dışa Aktarım Åžablonu:" +msgstr "Dışa aktarma ÅŸablonu kopyalanamadı." #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp @@ -3037,8 +3040,9 @@ msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." msgstr "32-bit dışa aktarımlarda gömülü PCK 4GiB'tan büyük olamaz." #: editor/editor_export.cpp +#, fuzzy msgid "Convert Text Resources To Binary On Export" -msgstr "" +msgstr "Dışa Aktarmada Metin Kaynaklarını İkili Dosyaya Dönüştür" #: editor/editor_feature_profile.cpp msgid "3D Editor" @@ -3249,7 +3253,7 @@ msgstr "Dışa Aktarım Åžablonlarını Yönet" #: editor/editor_feature_profile.cpp #, fuzzy msgid "Default Feature Profile" -msgstr "Godot Özellik Profili" +msgstr "Varsayılan Özellik Profili" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -3323,12 +3327,12 @@ msgstr "Bir Dosya Kaydet" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp #, fuzzy msgid "Access" -msgstr "BaÅŸarılı!" +msgstr "EriÅŸim" #: editor/editor_file_dialog.cpp editor/editor_settings.cpp #, fuzzy msgid "Display Mode" -msgstr "Oynatma Modu:" +msgstr "Ekran Modu" #: editor/editor_file_dialog.cpp #: editor/import/resource_importer_layered_texture.cpp @@ -3343,32 +3347,33 @@ msgstr "Oynatma Modu:" #: servers/audio/effects/audio_effect_distortion.cpp #, fuzzy msgid "Mode" -msgstr "Kaydırma Biçimi" +msgstr "Mod" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp #, fuzzy msgid "Current Dir" -msgstr "Geçerli:" +msgstr "Geçerli Dizin" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp #, fuzzy msgid "Current File" -msgstr "Åžu Anki Profil:" +msgstr "Geçerli Dosya" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp #, fuzzy msgid "Current Path" -msgstr "Geçerli:" +msgstr "Geçerli Yol" #: editor/editor_file_dialog.cpp editor/editor_settings.cpp #: scene/gui/file_dialog.cpp #, fuzzy msgid "Show Hidden Files" -msgstr "Gizli Dosyalari Aç / Kapat" +msgstr "Gizli Dosyaları Göster" #: editor/editor_file_dialog.cpp +#, fuzzy msgid "Disable Overwrite Warning" -msgstr "" +msgstr "Üzerine Yazma Uyarısını Devre Dışı Bırak" #: editor/editor_file_dialog.cpp msgid "Go Back" @@ -3470,8 +3475,9 @@ msgid "(Re)Importing Assets" msgstr "Varlıklar Yeniden-İçe Aktarılıyor" #: editor/editor_file_system.cpp +#, fuzzy msgid "Reimport Missing Imported Files" -msgstr "" +msgstr "İçe Aktarılan Eksik Dosyaları Yeniden İçe Aktar" #: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp #: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp @@ -3503,7 +3509,7 @@ msgstr "Özellikler" #: editor/editor_help.cpp #, fuzzy msgid "overrides %s:" -msgstr "% üzerine yazılmışlar:" +msgstr "%s'yi geçersiz kılar:" #: editor/editor_help.cpp msgid "default:" @@ -3575,7 +3581,7 @@ msgstr "" #: modules/gdscript/gdscript_editor.cpp #, fuzzy msgid "Text Editor" -msgstr "Düzenleyiciyi Aç" +msgstr "Metin Düzenleyici" #: editor/editor_help.cpp editor/editor_node.cpp editor/editor_settings.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -3583,8 +3589,9 @@ msgid "Help" msgstr "Yardım" #: editor/editor_help.cpp +#, fuzzy msgid "Sort Functions Alphabetically" -msgstr "" +msgstr "Fonksiyonları Alfabetik Olarak Sırala" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp @@ -3666,34 +3673,34 @@ msgstr "Özellik:" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp #, fuzzy msgid "Label" -msgstr "DeÄŸer" +msgstr "Etiket" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp #: scene/resources/default_theme/default_theme.cpp #, fuzzy msgid "Read Only" -msgstr "Sadece Metotlar" +msgstr "Sadece Okunur" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp #, fuzzy msgid "Checkable" -msgstr "Öğeyi Denetle" +msgstr "Kontrol edilebilir" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp #, fuzzy msgid "Checked" -msgstr "Denetlenen Öğe" +msgstr "Kontrol edildi" #: editor/editor_inspector.cpp #, fuzzy msgid "Draw Red" -msgstr "Çizim ÇaÄŸrıları:" +msgstr "Kırmızı Çiz" #: editor/editor_inspector.cpp #, fuzzy msgid "Keying" -msgstr "Oynat" +msgstr "Anahtarlama" #: editor/editor_inspector.cpp msgid "Pin value" @@ -4058,12 +4065,12 @@ msgstr "BetiÄŸi Hızlı Aç..." #: editor/editor_node.cpp #, fuzzy msgid "Save & Reload" -msgstr "Kaydet ve BaÅŸtan BaÅŸlat" +msgstr "Kaydet ve Yeniden Yükle" #: editor/editor_node.cpp #, fuzzy msgid "Save changes to '%s' before reloading?" -msgstr "Kapatmadan önce deÄŸiÅŸklikler buraya '%s' kaydedilsin mi?" +msgstr "Çıkmadan önce deÄŸiÅŸiklikler '%s' ‘ye kaydedilsin mi?" #: editor/editor_node.cpp msgid "Save & Close" @@ -4184,7 +4191,7 @@ msgstr "Proje Yöneticisi Açılsın Mı?" #: editor/editor_node.cpp #, fuzzy msgid "Save changes to the following scene(s) before reloading?" -msgstr "Çıkmadan önce deÄŸiÅŸiklikler aÅŸağıdaki sahne(ler)e kaydedilsin mi?" +msgstr "Çıkmadan önce deÄŸiÅŸiklikler sahne(ler)e kaydedilsin mi?" #: editor/editor_node.cpp msgid "Save & Quit" @@ -4368,54 +4375,53 @@ msgid "%d more files" msgstr "%d daha fazla dosyalar" #: editor/editor_node.cpp +#, fuzzy msgid "" "Unable to write to file '%s', file in use, locked or lacking permissions." msgstr "" +"'%s' dosyasına yazılamıyor, dosya kullanımda, kilitli veya izinler eksik." #: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp #: servers/arvr/arvr_interface.cpp -#, fuzzy msgid "Interface" -msgstr "Kullanıcı Arayüzü" +msgstr "Arayüz" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Scene Tabs" -msgstr "Sahne Sekmesine Geç" +msgstr "Sahne Sekmeleri" #: editor/editor_node.cpp -#, fuzzy msgid "Always Show Close Button" -msgstr "Daima Izgarayı Göster" +msgstr "Daima Kapatma Düğmesini Göster" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Resize If Many Tabs" -msgstr "" +msgstr "Çok Sayıda Sekme Varsa Yeniden Boyutlandır" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Minimum Width" -msgstr "" +msgstr "Minimum GeniÅŸlik" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Output" msgstr "Çıktı" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Always Clear Output On Play" -msgstr "Çıktıyı Temizle" +msgstr "Oynatıldığında Çıktıyı Daima Temizle" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Open Output On Play" -msgstr "" +msgstr "Oynatıldığında Çıktıyı Daima Aç" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Close Output On Stop" -msgstr "" +msgstr "DurdurulduÄŸunda Çıktıyı Daima Kapat" #: editor/editor_node.cpp +#, fuzzy msgid "Save On Focus Loss" -msgstr "" +msgstr "Odak Kaybından Tasarruf Edin" #: editor/editor_node.cpp editor/editor_settings.cpp #, fuzzy @@ -4452,8 +4458,9 @@ msgid "Restore Scenes On Load" msgstr "Sahne Düğümünü Al" #: editor/editor_node.cpp editor/editor_settings.cpp +#, fuzzy msgid "Show Thumbnail On Hover" -msgstr "" +msgstr "Fareyle üzerine gelindiÄŸinde  küçük resmi göster" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Inspector" @@ -4479,11 +4486,11 @@ msgstr "" #: editor/editor_node.cpp msgid "Horizontal Vector2 Editing" -msgstr "" +msgstr "Yatay Vector2 Düzenleme" #: editor/editor_node.cpp msgid "Horizontal Vector Types Editing" -msgstr "" +msgstr "Yatay Vector tipleri düzenleme" #: editor/editor_node.cpp #, fuzzy @@ -4496,8 +4503,9 @@ msgid "Resources To Open In New Inspector" msgstr "Gözetmen Bölümünde Aç" #: editor/editor_node.cpp +#, fuzzy msgid "Default Color Picker Mode" -msgstr "" +msgstr "Varsayılan renk seçme modu" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Version Control" @@ -5231,9 +5239,8 @@ msgid "Size:" msgstr "Boyut:" #: editor/editor_properties_array_dict.cpp -#, fuzzy msgid "Page:" -msgstr "Sayfa: " +msgstr "Sayfa:" #: editor/editor_properties_array_dict.cpp #: editor/plugins/theme_editor_plugin.cpp @@ -5374,19 +5381,19 @@ msgstr "Hepsini Görüntüle" #: editor/editor_settings.cpp msgid "Custom Display Scale" -msgstr "" +msgstr "Özel Ekran ÖlçeÄŸi" #: editor/editor_settings.cpp msgid "Main Font Size" -msgstr "" +msgstr "Ana font ölçüsü" #: editor/editor_settings.cpp msgid "Code Font Size" -msgstr "" +msgstr "Kod font'u ölçüsü" #: editor/editor_settings.cpp msgid "Font Antialiased" -msgstr "" +msgstr "Kenarı yumuÅŸatılmış font" #: editor/editor_settings.cpp msgid "Font Hinting" @@ -5399,7 +5406,7 @@ msgstr "Ana Sahne" #: editor/editor_settings.cpp msgid "Main Font Bold" -msgstr "" +msgstr "Ana font kalınlığı" #: editor/editor_settings.cpp #, fuzzy @@ -5407,8 +5414,9 @@ msgid "Code Font" msgstr "Düğüm Noktası Ekle" #: editor/editor_settings.cpp +#, fuzzy msgid "Dim Editor On Dialog Popup" -msgstr "" +msgstr "İletiÅŸim penceresinde Dim Editörü" #: editor/editor_settings.cpp main/main.cpp msgid "Low Processor Mode Sleep (µsec)" @@ -5425,11 +5433,12 @@ msgstr "Dikkat Dağıtmayan Kip" #: editor/editor_settings.cpp msgid "Automatically Open Screenshots" -msgstr "" +msgstr "Otomatik olarak ekran görüntülerini aç" #: editor/editor_settings.cpp +#, fuzzy msgid "Max Array Dictionary Items Per Page" -msgstr "" +msgstr "Her sayfada maks dizi sözlüğü öğesi" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp @@ -5443,7 +5452,7 @@ msgstr "Ön ayar" #: editor/editor_settings.cpp msgid "Icon And Font Color" -msgstr "" +msgstr "Simge ve Font rengi" #: editor/editor_settings.cpp #, fuzzy @@ -5457,7 +5466,7 @@ msgstr "Renk Seç" #: editor/editor_settings.cpp scene/resources/environment.cpp msgid "Contrast" -msgstr "" +msgstr "Kontrast" #: editor/editor_settings.cpp msgid "Relationship Line Opacity" @@ -5533,7 +5542,7 @@ msgstr "Küçük Resim..." #: editor/editor_settings.cpp msgid "Docks" -msgstr "" +msgstr "Eklentiler" #: editor/editor_settings.cpp #, fuzzy @@ -5555,8 +5564,9 @@ msgid "Property Editor" msgstr "Grup Düzenleyici" #: editor/editor_settings.cpp +#, fuzzy msgid "Auto Refresh Interval" -msgstr "" +msgstr "Otomatik yenileme intervalı" #: editor/editor_settings.cpp #, fuzzy @@ -5571,7 +5581,7 @@ msgstr "Editör Teması" #: editor/editor_settings.cpp scene/3d/label_3d.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Line Spacing" -msgstr "" +msgstr "Satır aralığı" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp #: modules/gdscript/editor/gdscript_highlighter.cpp @@ -5590,7 +5600,7 @@ msgstr "" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight Current Line" -msgstr "" +msgstr "Geçerli satırı vurgula" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Highlight Type Safe Lines" @@ -5629,11 +5639,11 @@ msgstr "Gezinim" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Smooth Scrolling" -msgstr "" +msgstr "Pürüzsüz kaydırma" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "V Scroll Speed" -msgstr "" +msgstr "V kaydırma hızı" #: editor/editor_settings.cpp #, fuzzy @@ -5642,7 +5652,7 @@ msgstr "BaÅŸlatımı Göster" #: editor/editor_settings.cpp msgid "Minimap Width" -msgstr "" +msgstr "Küçük Harita GeniÅŸliÄŸi" #: editor/editor_settings.cpp msgid "Mouse Extra Buttons Navigate History" @@ -5654,8 +5664,13 @@ msgid "Drag And Drop Selection" msgstr "GridMap Seçimi" #: editor/editor_settings.cpp +#, fuzzy +msgid "Stay In Script Editor On Node Selected" +msgstr "SeçilmiÅŸ Düğümde Script Editöründe Kal" + +#: editor/editor_settings.cpp msgid "Appearance" -msgstr "" +msgstr "Dış görünüş" #: editor/editor_settings.cpp scene/gui/text_edit.cpp #, fuzzy @@ -5681,12 +5696,14 @@ msgid "Show Info Gutter" msgstr "" #: editor/editor_settings.cpp +#, fuzzy msgid "Code Folding" -msgstr "" +msgstr "Kod katlama" #: editor/editor_settings.cpp +#, fuzzy msgid "Word Wrap" -msgstr "" +msgstr "Kelime Paketle" #: editor/editor_settings.cpp msgid "Show Line Length Guidelines" @@ -5707,7 +5724,7 @@ msgstr "Kod Düzenleyici" #: editor/editor_settings.cpp msgid "Show Members Overview" -msgstr "" +msgstr "Üyelerin Genel Bakışını Göster" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -5724,16 +5741,19 @@ msgid "Autosave Interval Secs" msgstr "" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp +#, fuzzy msgid "Restore Scripts On Load" -msgstr "" +msgstr "Script'leri Yüklemede Eski Haline Getir" #: editor/editor_settings.cpp +#, fuzzy msgid "Auto Reload And Parse Scripts On Save" -msgstr "" +msgstr "Kaydederken Script'leri Otomatik Tekrar yükle ve Ayrıştır" #: editor/editor_settings.cpp +#, fuzzy msgid "Auto Reload Scripts On External Change" -msgstr "" +msgstr "Dış DeÄŸiÅŸiklikte Otomatik Olarak Script'i Geri Yükle" #: editor/editor_settings.cpp #, fuzzy @@ -5746,11 +5766,11 @@ msgstr "" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Cursor" -msgstr "" +msgstr "İmleç" #: editor/editor_settings.cpp msgid "Scroll Past End Of File" -msgstr "" +msgstr "Dosyanın Sonunu Kaydır" #: editor/editor_settings.cpp msgid "Block Caret" @@ -5786,7 +5806,7 @@ msgstr "" #: editor/editor_settings.cpp msgid "Code Complete Delay" -msgstr "" +msgstr "Kod Tamamlama Gecikme Süresi" #: editor/editor_settings.cpp msgid "Put Callhint Tooltip Below Current Line" @@ -5843,12 +5863,14 @@ msgid "Preview Size" msgstr "Önizleme" #: editor/editor_settings.cpp +#, fuzzy msgid "Primary Grid Color" -msgstr "" +msgstr "Birincil Izgara Rengi" #: editor/editor_settings.cpp +#, fuzzy msgid "Secondary Grid Color" -msgstr "" +msgstr "İkincil Izgara Rengi" #: editor/editor_settings.cpp #, fuzzy @@ -5885,7 +5907,7 @@ msgstr "Nokta" #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Shape" -msgstr "" +msgstr "Åžekil" #: editor/editor_settings.cpp #, fuzzy @@ -5997,7 +6019,7 @@ msgstr "Gezinim Kipi" #: editor/editor_settings.cpp msgid "Orbit Sensitivity" -msgstr "" +msgstr "Yörünge Hassasiyeti" #: editor/editor_settings.cpp msgid "Orbit Inertia" @@ -6200,7 +6222,7 @@ msgstr "Önden Görünüm" #: modules/gdscript/language_server/gdscript_language_server.cpp #, fuzzy msgid "Remote Host" -msgstr "Uzak " +msgstr "Uzak Ana Bilgisayar" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp @@ -7195,7 +7217,7 @@ msgstr "İfade" #: editor/import/resource_importer_obj.cpp #, fuzzy msgid "Optimize Mesh Flags" -msgstr "Boyut: " +msgstr "Boyut:" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" @@ -7399,7 +7421,7 @@ msgstr "Işık-haritaları Üretiliyor" #: editor/import/resource_importer_scene.cpp #, fuzzy msgid "Generating for Mesh:" -msgstr "Örüntü için Üretiliyor: " +msgstr "Örüntü için Üretiliyor:" #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." @@ -7499,7 +7521,7 @@ msgstr "Rastgele Ölçek:" #: editor/import/resource_importer_texture.cpp #, fuzzy msgid "Size Limit" -msgstr "Boyut: " +msgstr "Boyut Limiti" #: editor/import/resource_importer_texture.cpp msgid "Detect 3D" @@ -8422,7 +8444,7 @@ msgstr "" #: editor/plugins/animation_state_machine_editor.cpp #, fuzzy msgid "Transition:" -msgstr "GeçiÅŸ: " +msgstr "GeçiÅŸ:" #: editor/plugins/animation_state_machine_editor.cpp msgid "Play Mode:" @@ -10191,7 +10213,7 @@ msgstr "Oylum" #: editor/plugins/particles_editor_plugin.cpp #, fuzzy msgid "Emission Source:" -msgstr "Emisyon Kaynağı: " +msgstr "Emisyon Kaynağı:" #: editor/plugins/particles_editor_plugin.cpp msgid "A processor material of type 'ParticlesMaterial' is required." @@ -11289,15 +11311,13 @@ msgstr "Çevir" #. TRANSLATORS: Refers to changing the scale of a node in the 3D editor. #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Scaling:" -msgstr "Ölçekleniyor: " +msgstr "Ölçekleniyor:" #. TRANSLATORS: Refers to changing the position of a node in the 3D editor. #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Translating:" -msgstr "Çeviriliyor: " +msgstr "Çevriliyor:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." @@ -11839,19 +11859,17 @@ msgid "Sprite" msgstr "HayaliÇizimlik" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Simplification:" -msgstr "SadeleÅŸtirme: " +msgstr "SadeleÅŸtirme:" #: editor/plugins/sprite_editor_plugin.cpp #, fuzzy msgid "Shrink (Pixels):" -msgstr "Sıkıştır (Pikselleri): " +msgstr "Sıkıştır (Pikselleri):" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Grow (Pixels):" -msgstr "Büyüt (Pikselleri): " +msgstr "Büyüt (Piksel):" #: editor/plugins/sprite_editor_plugin.cpp msgid "Update Preview" @@ -11914,6 +11932,11 @@ msgid "New Animation" msgstr "Yeni Animasyon" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Metotları filtrele" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Hız:" @@ -13304,7 +13327,6 @@ msgid "Select SSH private key path" msgstr "SSH özel anahtar yolu seç" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "SSH Passphrase" msgstr "SSH Parolası" @@ -16013,7 +16035,7 @@ msgstr "Düğüm BetiÄŸi İliÅŸtir" #: editor/script_editor_debugger.cpp #, fuzzy msgid "Remote %s:" -msgstr "Uzak " +msgstr "Uzak %s:" #: editor/script_editor_debugger.cpp msgid "Bytes:" @@ -17073,9 +17095,8 @@ msgid "Disabled GDNative Singleton" msgstr "GDNative İskeleti PasifleÅŸtirildi" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Libraries:" -msgstr "Kütüphaneler: " +msgstr "Kütüphaneler:" #: modules/gdnative/nativescript/nativescript.cpp #, fuzzy @@ -17979,7 +18000,7 @@ msgstr "" #: modules/visual_script/visual_script.cpp #, fuzzy msgid "Node returned an invalid sequence output:" -msgstr "Düğüm geçersiz bir dizi çıktısı döndürdü: " +msgstr "Düğüm geçersiz bir dizi çıktısı döndürdü:" #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" @@ -18341,8 +18362,9 @@ msgid "if (cond) is:" msgstr "" #: modules/visual_script/visual_script_flow_control.cpp +#, fuzzy msgid "While" -msgstr "While" +msgstr "Sürece" #: modules/visual_script/visual_script_flow_control.cpp msgid "while (cond):" @@ -20650,15 +20672,15 @@ msgstr "Anahtar deposu bulunamadı, dışa aktarılamadı." #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Geçersiz uzantı." #: platform/windows/export/export.cpp #, fuzzy @@ -20682,15 +20704,15 @@ msgstr "Geçersiz ad." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Geçersiz uzantı." #: platform/windows/export/export.cpp #, fuzzy @@ -21799,7 +21821,7 @@ msgstr "Seyahat" msgid "Rotation Degrees" msgstr "%s Düzey Dönüyor." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Genel Sabit" @@ -22067,7 +22089,7 @@ msgstr "Kenar BoÅŸluk Belirle" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #, fuzzy msgid "Sync To Physics" -msgstr " (Fiziksel)" +msgstr "FiziÄŸe Senkronize Et" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #, fuzzy @@ -23571,7 +23593,7 @@ msgstr "Bir RoomGroup, bir Portal'ın çocuÄŸu veya torunu olmamalıdır." #: scene/3d/portal.cpp #, fuzzy msgid "Portal Active" -msgstr " [portallar aktif]" +msgstr "Portal Aktif" #: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp msgid "Two Way" @@ -23938,6 +23960,11 @@ msgstr "" "Bunun yerine alt düğümlerde çarpışma ÅŸekillerindeki boyutu deÄŸiÅŸtirin." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Bütünsel Dönüşümü Tut" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" @@ -24857,7 +24884,7 @@ msgstr "" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Caret" -msgstr "" +msgstr "Karet" #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Blink" @@ -25779,14 +25806,12 @@ msgid "3D Render" msgstr "OluÅŸturucu:" #: scene/register_scene_types.cpp -#, fuzzy msgid "2D Physics" -msgstr " (Fiziksel)" +msgstr "2B Fizik" #: scene/register_scene_types.cpp -#, fuzzy msgid "3D Physics" -msgstr " (Fiziksel)" +msgstr "3B Fizik" #: scene/register_scene_types.cpp #, fuzzy diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 4d22a47dea..d87aa168d7 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -29,7 +29,7 @@ msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-07-03 00:44+0000\n" +"PO-Revision-Date: 2022-07-26 01:55+0000\n" "Last-Translator: Artem <artem@molotov.work>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -39,7 +39,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -467,6 +467,11 @@ msgid "Pressure" msgstr "ТиÑк" #: core/os/input_event.cpp +#, fuzzy +msgid "Pen Inverted" +msgstr "Інвертувати" + +#: core/os/input_event.cpp msgid "Relative" msgstr "ВідноÑний" @@ -2111,14 +2116,15 @@ msgstr "Вибране:" msgid "Recent:" msgstr "Ðещодавні:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Пошук:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Збіги:" @@ -2178,8 +2184,8 @@ msgstr "Знайти замінний реÑурÑ:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2751,7 +2757,8 @@ msgid "Project export for platform:" msgstr "ЕкÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð¸:" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "Завершено з помилками." #: editor/editor_export.cpp @@ -5495,6 +5502,10 @@ msgid "Drag And Drop Selection" msgstr "Вибір GridMap" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "ВиглÑд" @@ -11607,6 +11618,11 @@ msgid "New Animation" msgstr "Ðова анімаціÑ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Фільтрувати методи" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "ШвидкіÑть:" @@ -20108,18 +20124,18 @@ msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ Ñховище ключів. Ðемож #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "Щоб мати змогу змінювати піктограму або дані щодо програми, має бути " "налаштовано інÑтрумент rcedit у параметрах редактора (ЕкÑпорт > Windows > " "Rcedit)." #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Ðекоректний виконуваний файл." #: platform/windows/export/export.cpp #, fuzzy @@ -20144,18 +20160,18 @@ msgstr "Ðекоректна назва." #: platform/windows/export/export.cpp #, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "Щоб мати змогу змінювати піктограму або дані щодо програми, має бути " "налаштовано інÑтрумент rcedit у параметрах редактора (ЕкÑпорт > Windows > " "Rcedit)." #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Ðекоректний виконуваний файл." #: platform/windows/export/export.cpp #, fuzzy @@ -21149,7 +21165,7 @@ msgstr "Подорож" msgid "Rotation Degrees" msgstr "ГрудуÑи обертаннÑ" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "Загальна Ñтала" @@ -23109,6 +23125,11 @@ msgstr "" "ЗаміÑть цієї зміни, вам варто змінити розміри дочірніх форм зіткненнÑ." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Зберегти загальне перетвореннÑ" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "МатрицÑ" @@ -25878,11 +25899,11 @@ msgstr "Розмір крапки" #: scene/resources/material.cpp msgid "Billboard Mode" -msgstr "Режим афіші" +msgstr "Режим розголоÑника" #: scene/resources/material.cpp msgid "Billboard Keep Scale" -msgstr "Зберегти маÑштаб афіші" +msgstr "Зберегти маÑштаб розголоÑника" #: scene/resources/material.cpp msgid "Grow" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index e1bae41d6b..a428250cc7 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -465,6 +465,10 @@ msgid "Pressure" msgstr "" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2128,14 +2132,15 @@ msgstr "" msgid "Recent:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "" @@ -2191,8 +2196,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2759,8 +2764,9 @@ msgid "Project export for platform:" msgstr "" #: editor/editor_export.cpp -msgid "Completed with errors." -msgstr "" +#, fuzzy +msgid "Completed with warnings." +msgstr ".تمام کا انتخاب" #: editor/editor_export.cpp msgid "Completed successfully." @@ -5417,6 +5423,10 @@ msgid "Drag And Drop Selection" msgstr ".تمام کا انتخاب" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -11595,6 +11605,11 @@ msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "سب سکریپشن بنائیں" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20048,14 +20063,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +msgid "rcedit failed to modify executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -20077,14 +20091,13 @@ msgstr "" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +msgid "Signtool failed to sign executable: %s." msgstr "" #: platform/windows/export/export.cpp @@ -21088,7 +21101,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "مستقل" @@ -23012,6 +23025,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "سب سکریپشن بنائیں" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index c8eae36ad6..0a6885872f 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -470,6 +470,10 @@ msgid "Pressure" msgstr "Ãp lá»±c" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "Tương đối" @@ -2145,14 +2149,15 @@ msgstr "Ưa thÃch:" msgid "Recent:" msgstr "Gần đây:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "Tìm kiếm:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "Phù hợp:" @@ -2212,8 +2217,8 @@ msgstr "Tìm kiếm tà i nguyên thay thế:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2792,7 +2797,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "Sao chép đưá»ng dẫn nút" #: editor/editor_export.cpp @@ -5502,6 +5507,10 @@ msgid "Drag And Drop Selection" msgstr "Chá»n tất cả" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "Ngoại hình" @@ -11784,6 +11793,11 @@ msgid "New Animation" msgstr "Hoạt hình má»›i" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "Lá»c phương thức" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "Tốc độ:" @@ -20560,15 +20574,15 @@ msgstr "Không thể mở bản mẫu để xuất:" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "Tên Ä‘uôi không hợp lệ." #: platform/windows/export/export.cpp #, fuzzy @@ -20592,15 +20606,15 @@ msgstr "Tên không hợp lệ." #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "Tên Ä‘uôi không hợp lệ." #: platform/windows/export/export.cpp #, fuzzy @@ -21691,7 +21705,7 @@ msgstr "Di chuyển" msgid "Rotation Degrees" msgstr "Xoay %s độ." -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "Hằng số" @@ -23778,6 +23792,11 @@ msgstr "" "Hãy sá»a kÃch cỡ khối va chạm cá»§a nút con ý." #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "Xóa biến đổi" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 976fe38138..f25a372128 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -89,7 +89,7 @@ msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2022-06-30 16:42+0000\n" +"PO-Revision-Date: 2022-07-29 01:36+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" @@ -98,7 +98,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.13.1-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -467,9 +467,8 @@ msgid "Command" msgstr "Command" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (物ç†ï¼‰" +msgstr "物ç†" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp @@ -522,6 +521,10 @@ msgid "Pressure" msgstr "压力" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "笔触翻转" + +#: core/os/input_event.cpp msgid "Relative" msgstr "相对" @@ -2153,14 +2156,15 @@ msgstr "æ”¶è—:" msgid "Recent:" msgstr "最近使用:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "æœç´¢ï¼š" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "匹é…项:" @@ -2220,8 +2224,8 @@ msgstr "查找替æ¢èµ„æºï¼š" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2787,7 +2791,8 @@ msgid "Project export for platform:" msgstr "针对平å°å¯¼å‡ºé¡¹ç›®ï¼š" #: editor/editor_export.cpp -msgid "Completed with errors." +#, fuzzy +msgid "Completed with warnings." msgstr "已完æˆï¼Œå˜åœ¨é”™è¯¯ã€‚" #: editor/editor_export.cpp @@ -5436,9 +5441,12 @@ msgid "Mouse Extra Buttons Navigate History" msgstr "ä½¿ç”¨ä¸“é—¨é¼ æ ‡æŒ‰é”®æŸ¥çœ‹åŽ†å²" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "GridMap 选择" +msgstr "拖放选ä¸å†…容" + +#: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "选ä¸èŠ‚ç‚¹æ—¶ä¿æŒè„šæœ¬ç¼–è¾‘å™¨" #: editor/editor_settings.cpp msgid "Appearance" @@ -5672,7 +5680,7 @@ msgstr "ç½‘æ ¼ç»†åˆ†çº§åˆ«ä¸‹é™" #: editor/editor_settings.cpp msgid "Grid Division Level Bias" -msgstr "ç½‘æ ¼ç»†åˆ†çº§åˆ«å倚" +msgstr "ç½‘æ ¼ç»†åˆ†çº§åˆ«åç½®" #: editor/editor_settings.cpp msgid "Grid XZ Plane" @@ -10697,7 +10705,7 @@ msgid "" "This shader has been modified on on disk.\n" "What action should be taken?" msgstr "" -"æ¤ç€è‰²å™¨å·²åœ¨ç£ç›˜ä¸Šä¿®æ”¹ã€‚\n" +"这个ç€è‰²å™¨å·²åœ¨ç£ç›˜ä¸Šä¿®æ”¹ã€‚\n" "应该采å–什么行动?" #: editor/plugins/shader_editor_plugin.cpp scene/resources/material.cpp @@ -11463,6 +11471,10 @@ msgid "New Animation" msgstr "新建动画" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "ç›é€‰åŠ¨ç”»" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "速度:" @@ -14180,7 +14192,7 @@ msgid "" "Please edit the project and set the main scene in the Project Settings under " "the \"Application\" category." msgstr "" -"æ— æ³•è¿è¡Œé¡¹ç›®ï¼šæœªå®šä¹‰ä¸»åœºæ™¯ã€‚ \n" +"æ— æ³•è¿è¡Œé¡¹ç›®ï¼šæœªå®šä¹‰ä¸»åœºæ™¯ã€‚\n" "请编辑项目并在 “项目设置†的 “Application†类别下设置主场景。" #: editor/project_manager.cpp @@ -18075,9 +18087,8 @@ msgid "The package must have at least one '.' separator." msgstr "包必须至少有一个 “.†分隔符。" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Custom Build" -msgstr "使用自定义构建" +msgstr "自定义构建" #: platform/android/export/export_plugin.cpp msgid "Use Custom Build" @@ -18354,51 +18365,52 @@ msgstr "å¿…é¡»å¯ç”¨ “使用自定义构建†æ‰èƒ½ä½¿ç”¨æ’件。" msgid "" "\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" " "or \"OpenXR\"." -msgstr "" -"“Hand Trackingâ€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOculus Mobile VrApiâ€æˆ–“OpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚" +msgstr "“手势跟踪â€åªæœ‰åœ¨å½““XR 模å¼â€æ˜¯â€œOculus Mobile VrApiâ€æˆ–“OpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export_plugin.cpp msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"." -msgstr "“Passthroughâ€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚" +msgstr "“穿é€â€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export_plugin.cpp msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled." -msgstr "“Export AABâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚" +msgstr "“Export AABâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export_plugin.cpp msgid "" "\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled." -msgstr "修改“Min SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚" +msgstr "ä¿®æ”¹â€œæœ€å° SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export_plugin.cpp msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid." -msgstr "" +msgstr "â€œæœ€å° SDKâ€åº”å½“ä¸ºæœ‰æ•ˆçš„æ•´æ•°ï¼Œä½†èŽ·å¾—äº†æ— æ•ˆçš„â€œ%sâ€ã€‚" #: platform/android/export/export_plugin.cpp msgid "" "\"Min SDK\" cannot be lower than %d, which is the version needed by the " "Godot library." -msgstr "" +msgstr "â€œæœ€å° SDKâ€ä¸èƒ½ä½ŽäºŽ %d,这是 Godot 库所需è¦çš„版本。" #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled." -msgstr "修改“Target SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚" +msgstr "ä¿®æ”¹â€œç›®æ ‡ SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid." -msgstr "" +msgstr "â€œç›®æ ‡ SDKâ€åº”å½“ä¸ºæœ‰æ•ˆçš„æ•´æ•°ï¼Œä½†èŽ·å¾—äº†æ— æ•ˆçš„â€œ%sâ€ã€‚" #: platform/android/export/export_plugin.cpp msgid "" "\"Target SDK\" %d is higher than the default version %d. This may work, but " "wasn't tested and may be unstable." msgstr "" +"â€œç›®æ ‡ SDKâ€%d 比默认版本 %d è¦é«˜ã€‚è¿™æ ·åšä¹Ÿè®¸å¯è¡Œï¼Œä½†å¹¶æ²¡æœ‰ç»è¿‡æµ‹è¯•,å¯èƒ½ä¸ç¨³" +"定。" #: platform/android/export/export_plugin.cpp msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version." -msgstr "“Target SDKâ€ç‰ˆæœ¬å¿…须大于ç‰äºŽâ€œMin SDKâ€ç‰ˆæœ¬ã€‚" +msgstr "â€œç›®æ ‡ SDKâ€ç‰ˆæœ¬å¿…须大于ç‰äºŽâ€œæœ€å° SDKâ€ç‰ˆæœ¬ã€‚" #: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp #: platform/windows/export/export.cpp @@ -19669,17 +19681,18 @@ msgid "Could not find wine executable at \"%s\"." msgstr "æ— æ³•åœ¨â€œ%sâ€æ‰¾åˆ° wine 坿‰§è¡Œæ–‡ä»¶ã€‚" #: platform/windows/export/export.cpp +#, fuzzy msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" "æ— æ³•å¯åЍ rcedit 坿‰§è¡Œæ–‡ä»¶ï¼Œè¯·åœ¨ç¼–辑器设置ä¸é…ç½® rcedit 路径(导出 > Windows " "> Rcedit)。" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" +#, fuzzy +msgid "rcedit failed to modify executable: %s." msgstr "" "rcedit ä¿®æ”¹å¯æ‰§è¡Œæ–‡ä»¶å¤±è´¥ï¼š\n" "%s" @@ -19701,17 +19714,18 @@ msgid "Invalid timestamp server." msgstr "时间戳æœåŠ¡å™¨æ— æ•ˆã€‚" #: platform/windows/export/export.cpp +#, fuzzy msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" "æ— æ³•å¯åЍ signtool 坿‰§è¡Œæ–‡ä»¶ï¼Œè¯·åœ¨ç¼–辑器设置ä¸é…ç½® signtool 路径(导出 > " "Windows > Signtool)。" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" +#, fuzzy +msgid "Signtool failed to sign executable: %s." msgstr "" "Signtool ç¾å坿‰§è¡Œæ–‡ä»¶å¤±è´¥ï¼š\n" "%s" @@ -19725,8 +19739,8 @@ msgid "" "The rcedit tool must be configured in the Editor Settings (Export > Windows " "> Rcedit) to change the icon or app information data." msgstr "" -"必须在编辑器设置ä¸é…ç½® rcedit 工具(Export > Windows > Rcedit)æ‰èƒ½ä¿®æ”¹å›¾æ ‡æˆ–" -"åº”ç”¨ä¿¡æ¯æ•°æ®ã€‚" +"必须在编辑器设置ä¸é…ç½® rcedit 工具(导出 > Windows > Rcedit)æ‰èƒ½ä¿®æ”¹å›¾æ ‡æˆ–应" +"ç”¨ä¿¡æ¯æ•°æ®ã€‚" #: platform/windows/export/export.cpp msgid "Invalid icon path:" @@ -20429,7 +20443,7 @@ msgstr "节点 B" #: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp #: scene/resources/environment.cpp msgid "Bias" -msgstr "å倚" +msgstr "åç½®" #: scene/2d/joints_2d.cpp msgid "Disable Collision" @@ -20606,9 +20620,8 @@ msgstr "" "移除。请用“Navigation2DServer.map_get_path()â€æ›¿ä»£ã€‚" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Pathfinding" -msgstr "绑定" +msgstr "寻路" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Path Desired Distance" @@ -20623,9 +20636,8 @@ msgid "Path Max Distance" msgstr "路径最大è·ç¦»" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Avoidance" -msgstr "高级" +msgstr "é¿éšœ" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Avoidance Enabled" @@ -20686,7 +20698,7 @@ msgstr "移动消耗" msgid "Rotation Degrees" msgstr "旋转角度" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp msgid "Global Rotation" msgstr "全局旋转" @@ -21590,7 +21602,7 @@ msgstr "动æ€èŒƒå›´" #: scene/3d/gi_probe.cpp scene/3d/light.cpp msgid "Normal Bias" -msgstr "法线å倚" +msgstr "法线åç½®" #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp #: scene/resources/primitive_meshes.cpp @@ -21701,7 +21713,7 @@ msgstr "æ··åˆæ‹†åˆ†" #: scene/3d/light.cpp msgid "Bias Split Scale" -msgstr "å倚拆分缩放" +msgstr "å置拆分缩放" #: scene/3d/light.cpp msgid "Depth Range" @@ -21935,7 +21947,7 @@ msgstr "角度下é™" #: scene/3d/physics_body.cpp msgid "Angular Limit Bias" -msgstr "角度é™åˆ¶å倚" +msgstr "角度é™åˆ¶åç½®" #: scene/3d/physics_body.cpp msgid "Angular Limit Softness" @@ -22561,6 +22573,10 @@ msgstr "" "建议修改å节点的碰撞体形状尺寸。" #: scene/3d/spatial.cpp +msgid "Global Translation" +msgstr "全局平移" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "矩阵" @@ -23651,9 +23667,8 @@ msgid "Fold Gutter" msgstr "æŠ˜å æ " #: scene/gui/text_edit.cpp -#, fuzzy msgid "Drag And Drop Selection Enabled" -msgstr "å¯ç”¨é€‰æ‹©" +msgstr "å¯ç”¨æ‹–放选ä¸å†…容" #: scene/gui/text_edit.cpp msgid "Hiding Enabled" @@ -24024,6 +24039,9 @@ msgid "" "Effects.\n" "HDR will be disabled for this Viewport." msgstr "" +"这个 Viewport å¯ç”¨äº† HDR,但其 Usage 为 2D 或 2D No-Sampling。\n" +"HDR 仅在 Usage 为 3D 或 3D No-Effects çš„ Viewport 䏿”¯æŒã€‚\n" +"这个 Viewport å°†ç¦ç”¨ HDR。" #: scene/main/viewport.cpp msgid "ARVR" @@ -25662,7 +25680,7 @@ msgstr "A" #: scene/resources/shape_2d.cpp msgid "Custom Solver Bias" -msgstr "自定义求解器å倚" +msgstr "自定义求解器åç½®" #: scene/resources/skin.cpp msgid "Bind Count" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 201811d543..79760d0de7 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -479,6 +479,10 @@ msgid "Pressure" msgstr "é‡è¨ç¸®æ”¾æ¯”例" #: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "" + +#: core/os/input_event.cpp msgid "Relative" msgstr "" @@ -2224,14 +2228,15 @@ msgstr "最愛:" msgid "Recent:" msgstr "最近:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "æœå°‹ï¼š" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "å»åˆï¼š" @@ -2287,8 +2292,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2886,7 +2891,7 @@ msgstr "" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." +msgid "Completed with warnings." msgstr "複製路徑" #: editor/editor_export.cpp @@ -5673,6 +5678,10 @@ msgid "Drag And Drop Selection" msgstr "刪除é¸ä¸æª”案" #: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "" + +#: editor/editor_settings.cpp msgid "Appearance" msgstr "" @@ -12112,6 +12121,11 @@ msgid "New Animation" msgstr "新的動畫å稱:" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "Filter animations" +msgstr "篩é¸:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "" @@ -20853,15 +20867,15 @@ msgstr "無法新增資料夾" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "無效副檔å" #: platform/windows/export/export.cpp #, fuzzy @@ -20885,15 +20899,15 @@ msgstr "無效å稱。" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "無效副檔å" #: platform/windows/export/export.cpp #, fuzzy @@ -21926,7 +21940,7 @@ msgstr "" msgid "Rotation Degrees" msgstr "" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "常數" @@ -23919,6 +23933,11 @@ msgid "" msgstr "" #: scene/3d/spatial.cpp +#, fuzzy +msgid "Global Translation" +msgstr "ç¿»è¯" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 9021c16fc8..8ad86d4b2a 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -23,7 +23,7 @@ # binotaliu <binota@protonmail.ch>, 2020. # Allen H. <w84miracle@gmail.com>, 2020. # BinotaLIU <binota@protonmail.ch>, 2020. -# BinotaLIU <me@binota.org>, 2020, 2021. +# BinotaLIU <me@binota.org>, 2020, 2021, 2022. # MintSoda <lionlxh@qq.com>, 2020. # meowmeowmeowcat <meowmeowcat1211@gmail.com>, 2021. # anthonychen <anton1554970211@126.com>, 2021. @@ -33,13 +33,16 @@ # Haoyu Qiu <timothyqiu32@gmail.com>, 2022. # Otis Kao <momoslim@gmail.com>, 2022. # YuChiang Chang <chiang.c.tw@gmail.com>, 2022. +# è˜è˜ <rrt467778@gmail.com>, 2022. +# marktwtn <marktwtn@gmail.com>, 2022. +# Shi-Xun Hong <jimmy3421@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-05-30 16:17+0000\n" -"Last-Translator: YuChiang Chang <chiang.c.tw@gmail.com>\n" +"PO-Revision-Date: 2022-07-31 18:34+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" @@ -47,7 +50,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.13-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: core/bind/core_bind.cpp main/main.cpp msgid "Tablet Driver" @@ -70,27 +73,22 @@ msgid "V-Sync Enabled" msgstr "å•Ÿç”¨åž‚ç›´åŒæ¥" #: core/bind/core_bind.cpp main/main.cpp -#, fuzzy msgid "V-Sync Via Compositor" msgstr "é€éŽåˆæˆå™¨åž‚ç›´åŒæ¥" #: core/bind/core_bind.cpp main/main.cpp -#, fuzzy msgid "Delta Smoothing" -msgstr "變é‡å¹³æ»‘" +msgstr "å·®é‡å¹³æ»‘" #: core/bind/core_bind.cpp -#, fuzzy msgid "Low Processor Usage Mode" msgstr "低處ç†å™¨ä½¿ç”¨çŽ‡æ¨¡å¼" #: core/bind/core_bind.cpp -#, fuzzy msgid "Low Processor Usage Mode Sleep (µsec)" msgstr "低處ç†å™¨ä½¿ç”¨çŽ‡æ¨¡å¼ç¡çœ (微秒)" #: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp -#, fuzzy msgid "Keep Screen On" msgstr "ä¿æŒèž¢å¹•開啟" @@ -157,9 +155,8 @@ msgid "Size" msgstr "大å°" #: core/bind/core_bind.cpp -#, fuzzy msgid "Endian Swap" -msgstr "切æ›ç«¯åº" +msgstr "切æ›å—節åº" #: core/bind/core_bind.cpp msgid "Editor Hint" @@ -178,9 +175,8 @@ msgid "Target FPS" msgstr "標準FPS" #: core/bind/core_bind.cpp -#, fuzzy msgid "Time Scale" -msgstr "TimeScale 節點" +msgstr "時間縮放" #: core/bind/core_bind.cpp main/main.cpp msgid "Physics Jitter Fix" @@ -199,9 +195,8 @@ msgid "Error Line" msgstr "發生錯誤之行數" #: core/bind/core_bind.cpp -#, fuzzy msgid "Result" -msgstr "æœå°‹çµæžœ" +msgstr "çµæžœ" #: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp msgid "Memory" @@ -230,7 +225,6 @@ msgstr "多執行緒佇列大å°(KB)" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Function" msgstr "函å¼" @@ -260,17 +254,14 @@ msgid "Page Read Ahead" msgstr "é 先讀å–é æ•¸" #: core/io/http_client.cpp -#, fuzzy msgid "Blocking Mode Enabled" -msgstr "啟用阻礙模å¼" +msgstr "啟用阻塞模å¼" #: core/io/http_client.cpp -#, fuzzy msgid "Connection" msgstr "連接" #: core/io/http_client.cpp -#, fuzzy msgid "Read Chunk Size" msgstr "讀å–å€å¡Šå¤§å°" @@ -287,12 +278,10 @@ msgid "Refuse New Network Connections" msgstr "拒絕新網路連接" #: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp -#, fuzzy msgid "Network Peer" -msgstr "å°ç‰ç¶²è·¯ä½¿ç”¨è€…" +msgstr "å°ç‰ç¶²è·¯" #: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp -#, fuzzy msgid "Root Node" msgstr "æ ¹ç¯€é»ž" @@ -301,9 +290,8 @@ msgid "Refuse New Connections" msgstr "拒絕新網路連接" #: core/io/networked_multiplayer_peer.cpp -#, fuzzy msgid "Transfer Mode" -msgstr "轉æ›é¡žåž‹" +msgstr "傳輸模å¼" #: core/io/packet_peer.cpp msgid "Encode Buffer Max Size" @@ -353,9 +341,8 @@ msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "ä½å…ƒçµ„長度ä¸è¶³ä»¥é€²è¡Œè§£ç¢¼æˆ–æˆ–æ ¼å¼ç„¡æ•ˆã€‚" #: core/math/expression.cpp -#, fuzzy msgid "Invalid input %d (not passed) in expression" -msgstr "é‹ç®—å¼ä¸çš„輸入 %i 無效 (未傳éžï¼‰" +msgstr "é‹ç®—å¼çš„輸入%d 無效(未傳éžï¼‰" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -387,7 +374,6 @@ msgid "Seed" msgstr "種å" #: core/math/random_number_generator.cpp -#, fuzzy msgid "State" msgstr "狀態" @@ -400,14 +386,12 @@ msgid "Max Size (KB)" msgstr "最大大å°ï¼ˆKB)" #: core/os/input.cpp -#, fuzzy msgid "Mouse Mode" -msgstr "移動模å¼" +msgstr "æ»‘é¼ æ¨¡å¼" #: core/os/input.cpp -#, fuzzy msgid "Use Accumulated Input" -msgstr "刪除輸入" +msgstr "使用累ç©è¼¸å…¥" #: core/os/input_event.cpp editor/project_settings_editor.cpp #: servers/audio_server.cpp @@ -435,14 +419,12 @@ msgid "Command" msgstr "Command" #: core/os/input_event.cpp -#, fuzzy msgid "Physical" -msgstr " (物ç†ï¼‰" +msgstr "物ç†" #: core/os/input_event.cpp scene/2d/touch_screen_button.cpp #: scene/gui/base_button.cpp scene/gui/texture_button.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Pressed" msgstr "按下" @@ -451,21 +433,18 @@ msgid "Scancode" msgstr "éµç›¤æŽƒæç¢¼" #: core/os/input_event.cpp -#, fuzzy msgid "Physical Scancode" -msgstr "實體éµç›¤æŽƒæç¢¼" +msgstr "ç‰©ç†æŽƒæç¢¼" #: core/os/input_event.cpp msgid "Unicode" msgstr "Unicode" #: core/os/input_event.cpp -#, fuzzy msgid "Echo" -msgstr "Echo" +msgstr "回è²" #: core/os/input_event.cpp scene/gui/base_button.cpp -#, fuzzy msgid "Button Mask" msgstr "按éµé®ç½©" @@ -474,7 +453,6 @@ msgid "Global Position" msgstr "全域ä½ç½®" #: core/os/input_event.cpp -#, fuzzy msgid "Factor" msgstr "å› ç´ " @@ -491,12 +469,14 @@ msgid "Tilt" msgstr "傾斜" #: core/os/input_event.cpp -#, fuzzy msgid "Pressure" -msgstr "按壓" +msgstr "壓力" + +#: core/os/input_event.cpp +msgid "Pen Inverted" +msgstr "å轉ç†è§¸" #: core/os/input_event.cpp -#, fuzzy msgid "Relative" msgstr "相å°" @@ -532,12 +512,10 @@ msgid "Strength" msgstr "強度" #: core/os/input_event.cpp -#, fuzzy msgid "Delta" -msgstr "變é‡" +msgstr "å·®é‡" #: core/os/input_event.cpp -#, fuzzy msgid "Channel" msgstr "é »é“" @@ -613,14 +591,12 @@ msgid "Main Scene" msgstr "ä¸»å ´æ™¯" #: core/project_settings.cpp -#, fuzzy msgid "Disable stdout" -msgstr "ç¦ç”¨è‡ªå‹•圖塊" +msgstr "åœç”¨æ¨™æº–輸出" #: core/project_settings.cpp -#, fuzzy msgid "Disable stderr" -msgstr "å·²åœç”¨çš„é …ç›®" +msgstr "åœç”¨æ¨™æº–錯誤輸出" #: core/project_settings.cpp msgid "Use Hidden Project Data Directory" @@ -637,15 +613,14 @@ msgstr "自訂使用者目錄å稱" #: core/project_settings.cpp main/main.cpp #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #: platform/uwp/os_uwp.cpp -#, fuzzy msgid "Display" -msgstr "全部顯示" +msgstr "顯示" #: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp #: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp #: scene/3d/label_3d.cpp scene/gui/text_edit.cpp scene/resources/texture.cpp msgid "Width" -msgstr "" +msgstr "寬" #: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp #: modules/gltf/gltf_node.cpp modules/opensimplex/noise_texture.cpp @@ -653,23 +628,20 @@ msgstr "" #: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp #: scene/resources/font.cpp scene/resources/navigation_mesh.cpp #: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp -#, fuzzy msgid "Height" -msgstr "燈光" +msgstr "高度" #: core/project_settings.cpp msgid "Always On Top" -msgstr "" +msgstr "ç½®é ‚" #: core/project_settings.cpp -#, fuzzy msgid "Test Width" -msgstr "左延展" +msgstr "測試寬度" #: core/project_settings.cpp -#, fuzzy msgid "Test Height" -msgstr "測試" +msgstr "測試高度" #: core/project_settings.cpp editor/animation_track_editor.cpp #: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp @@ -688,33 +660,28 @@ msgid "Editor" msgstr "編輯器" #: core/project_settings.cpp -#, fuzzy msgid "Main Run Args" msgstr "主執行引數" #: core/project_settings.cpp -#, fuzzy msgid "Scene Naming" -msgstr "å ´æ™¯è·¯å¾‘ï¼š" +msgstr "å ´æ™¯å‘½å" #: core/project_settings.cpp -#, fuzzy msgid "Search In File Extensions" -msgstr "ä»¥å‰¯æª”åæœå°‹" +msgstr "ä»¥æª”æ¡ˆå‰¯æª”åæœå°‹" #: core/project_settings.cpp msgid "Script Templates Search Path" msgstr "è…³æœ¬æ¨£æ¿æœå°‹è·¯å¾‘" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Autoload On Startup" -msgstr "啟動時自動載入" +msgstr "啟動時自動載入版本控制" #: core/project_settings.cpp -#, fuzzy msgid "Version Control Plugin Name" -msgstr "版本控制" +msgstr "版本控制外掛å稱" #: core/project_settings.cpp scene/2d/collision_object_2d.cpp #: scene/3d/collision_object.cpp scene/gui/control.cpp @@ -722,9 +689,8 @@ msgid "Input" msgstr "輸入" #: core/project_settings.cpp -#, fuzzy msgid "UI Accept" -msgstr "UI確定" +msgstr "確定 (UI)" #: core/project_settings.cpp msgid "UI Select" @@ -735,43 +701,36 @@ msgid "UI Cancel" msgstr "UIå–æ¶ˆ" #: core/project_settings.cpp -#, fuzzy msgid "UI Focus Next" -msgstr "èšç„¦è·¯å¾‘" +msgstr "èšç„¦ä¸‹ä¸€å€‹ (UI)" #: core/project_settings.cpp -#, fuzzy msgid "UI Focus Prev" -msgstr "èšç„¦è·¯å¾‘" +msgstr "èšç„¦ä¸Šä¸€å€‹ (UI)" #: core/project_settings.cpp -#, fuzzy msgid "UI Left" -msgstr "左上" +msgstr "å·¦ (UI)" #: core/project_settings.cpp -#, fuzzy msgid "UI Right" -msgstr "å³ä¸Š" +msgstr "å³ (UI)" #: core/project_settings.cpp msgid "UI Up" msgstr "UI上" #: core/project_settings.cpp -#, fuzzy msgid "UI Down" -msgstr "UI下" +msgstr "下 (UI)" #: core/project_settings.cpp -#, fuzzy msgid "UI Page Up" -msgstr "UIé é¢å‘上滾動" +msgstr "é é¢ä¸Šæ»¾ (UI)" #: core/project_settings.cpp -#, fuzzy msgid "UI Page Down" -msgstr "UIé é¢å‘下滾動" +msgstr "é é¢ä¸‹æ»¾ (UI)" #: core/project_settings.cpp msgid "UI Home" @@ -803,7 +762,6 @@ msgid "3D" msgstr "3D" #: core/project_settings.cpp -#, fuzzy msgid "Smooth Trimesh Collision" msgstr "å¹³æ»‘ä¸‰è§’ç¶²æ ¼ç¢°æ’ž" @@ -832,12 +790,10 @@ msgstr "å“質" #: core/project_settings.cpp scene/gui/file_dialog.cpp #: scene/main/scene_tree.cpp scene/resources/navigation_mesh.cpp #: servers/visual_server.cpp -#, fuzzy msgid "Filters" msgstr "篩é¸å™¨" #: core/project_settings.cpp scene/main/viewport.cpp -#, fuzzy msgid "Sharpen Intensity" msgstr "銳化強度" @@ -864,9 +820,8 @@ msgid "Profiler" msgstr "分æžå·¥å…·" #: core/project_settings.cpp -#, fuzzy msgid "Max Functions" -msgstr "最大值函å¼" +msgstr "æœ€å¤§å‡½å¼æ•¸" #: core/project_settings.cpp scene/3d/vehicle_body.cpp msgid "Compression" @@ -881,18 +836,16 @@ msgid "Zstd" msgstr "Zstd" #: core/project_settings.cpp -#, fuzzy msgid "Long Distance Matching" -msgstr "é•·è·é…å°" +msgstr "é•·è·é›¢åŒ¹é…" #: core/project_settings.cpp msgid "Compression Level" msgstr "壓縮ç‰ç´š" #: core/project_settings.cpp -#, fuzzy msgid "Window Log Size" -msgstr "視窗日誌大å°" +msgstr "è¦–çª—å°æ•¸å¤§å°" #: core/project_settings.cpp msgid "Zlib" @@ -915,14 +868,12 @@ msgid "TCP" msgstr "TCP" #: core/register_core_types.cpp -#, fuzzy msgid "Connect Timeout Seconds" -msgstr "連接逾時秒數" +msgstr "連線逾時秒數" #: core/register_core_types.cpp -#, fuzzy msgid "Packet Peer Stream" -msgstr "å°åŒ…å°ç‰ä¸²æµ" +msgstr "å°åŒ…å°ç‰æµ" #: core/register_core_types.cpp msgid "Max Buffer (Power of 2)" @@ -933,7 +884,6 @@ msgid "SSL" msgstr "SSL" #: core/register_core_types.cpp main/main.cpp -#, fuzzy msgid "Certificates" msgstr "憑è‰" @@ -944,9 +894,8 @@ msgid "Resource" msgstr "資æº" #: core/resource.cpp -#, fuzzy msgid "Local To Scene" -msgstr "é—œé–‰å ´æ™¯" +msgstr "åƒ…é™æœ¬å ´æ™¯" #: core/resource.cpp editor/dependency_editor.cpp #: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp @@ -964,14 +913,12 @@ msgid "Locale" msgstr "地å€" #: core/translation.cpp -#, fuzzy msgid "Test" msgstr "測試" #: core/translation.cpp scene/resources/font.cpp -#, fuzzy msgid "Fallback" -msgstr "éžè£œ" +msgstr "後備語言" #: core/ustring.cpp scene/resources/segment_shape_2d.cpp msgid "B" @@ -1033,27 +980,23 @@ msgstr "2D" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Snapping" msgstr "å¸é™„" #: drivers/gles2/rasterizer_canvas_base_gles2.cpp #: drivers/gles3/rasterizer_canvas_base_gles3.cpp -#, fuzzy msgid "Use GPU Pixel Snap" -msgstr "使用GPUåƒç´ å¸é™„" +msgstr "使用 GPU åƒç´ å¸é™„" #: drivers/gles2/rasterizer_scene_gles2.cpp #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Immediate Buffer Size (KB)" msgstr "峿™‚ç·©è¡å€å¤§å°ï¼ˆKB)" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp -#, fuzzy msgid "Lightmapping" -msgstr "烘焙光照圖" +msgstr "光照貼圖" #: drivers/gles2/rasterizer_storage_gles2.cpp #: drivers/gles3/rasterizer_storage_gles3.cpp @@ -1102,9 +1045,8 @@ msgid "Weight Samples" msgstr "æ¬Šé‡æŽ¡æ¨£" #: drivers/gles3/rasterizer_scene_gles3.cpp -#, fuzzy msgid "Voxel Cone Tracing" -msgstr "é«”ç´ æ¤Žé«”ææ‘¹" +msgstr "é«”ç´ éŒè¿½è¸ª" #: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp msgid "High Quality" @@ -1186,9 +1128,8 @@ msgstr "更改動畫呼å«" #: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp #: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Frame" -msgstr "å½±æ ¼ %" +msgstr "å½±æ ¼" #: editor/animation_track_editor.cpp editor/editor_profiler.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp @@ -1199,16 +1140,14 @@ msgstr "時間" #: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp #: platform/osx/export/export.cpp -#, fuzzy msgid "Location" -msgstr "本地化" +msgstr "ä½ç½®" #: editor/animation_track_editor.cpp modules/gltf/gltf_node.cpp #: scene/2d/polygon_2d.cpp scene/2d/remote_transform_2d.cpp #: scene/3d/remote_transform.cpp scene/3d/spatial.cpp scene/gui/control.cpp -#, fuzzy msgid "Rotation" -msgstr "旋轉æ¥é•·ï¼š" +msgstr "旋轉" #: editor/animation_track_editor.cpp editor/script_editor_debugger.cpp #: modules/visual_script/visual_script_nodes.cpp scene/gui/range.cpp @@ -1216,14 +1155,13 @@ msgid "Value" msgstr "數值" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Arg Count" -msgstr "數é‡ï¼š" +msgstr "引數數é‡" #: editor/animation_track_editor.cpp main/main.cpp #: modules/mono/mono_gd/gd_mono.cpp msgid "Args" -msgstr "" +msgstr "åƒæ•¸" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp @@ -1233,31 +1171,27 @@ msgid "Type" msgstr "型別" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In Handle" -msgstr "è¨å®šè™•ç†ç¨‹å¼" +msgstr "進入控點" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out Handle" -msgstr "è¨å®šè™•ç†ç¨‹å¼" +msgstr "離開控點" #: editor/animation_track_editor.cpp #: editor/import/resource_importer_texture.cpp #: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp #: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp msgid "Stream" -msgstr "" +msgstr "æµ" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "起點åç§»" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End Offset" -msgstr "å移:" +msgstr "終點åç§»" #: editor/animation_track_editor.cpp editor/editor_settings.cpp #: editor/import/resource_importer_scene.cpp @@ -1270,7 +1204,6 @@ msgid "Animation" msgstr "å‹•ç•«" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing" msgstr "緩入緩出" @@ -1381,19 +1314,16 @@ msgid "Remove this track." msgstr "移除該動畫軌。" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Time (s):" -msgstr "時間(秒) : " +msgstr "時間(秒):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Position:" -msgstr "ä½ç½®" +msgstr "ä½ç½®ï¼š" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Rotation:" -msgstr "旋轉æ¥é•·ï¼š" +msgstr "旋轉:" #: editor/animation_track_editor.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp @@ -1410,44 +1340,36 @@ msgid "Type:" msgstr "型別:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "(Invalid, expected type: %s)" -msgstr "無效的輸出樣æ¿ï¼š" +msgstr "ï¼ˆç„¡æ•ˆï¼Œé æœŸåž‹åˆ¥ï¼š%s)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Easing:" -msgstr "緩入緩出" +msgstr "緩入緩出:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "In-Handle:" -msgstr "è¨å®šè™•ç†ç¨‹å¼" +msgstr "進入控點:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Out-Handle:" -msgstr "è¨å®šè™•ç†ç¨‹å¼" +msgstr "離開控點:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Stream:" -msgstr "串æµä½¿ç”¨è€…" +msgstr "æµï¼š" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Start (s):" -msgstr "釿–°é–‹å§‹ï¼ˆç§’):" +msgstr "開始(秒):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "End (s):" -msgstr "淡入(秒):" +msgstr "çµæŸï¼ˆç§’):" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Clip:" -msgstr "動畫:" +msgstr "動畫片段:" #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -1501,9 +1423,8 @@ msgid "Duplicate Key(s)" msgstr "é‡è¤‡é—œéµç•«æ ¼" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add RESET Value(s)" -msgstr "新增 %d å€‹å½±æ ¼" +msgstr "新增 RESET 值" #: editor/animation_track_editor.cpp msgid "Delete Key(s)" @@ -1532,14 +1453,12 @@ msgstr "刪除動畫軌" #: editor/plugins/tile_map_editor_plugin.cpp editor/scene_tree_dock.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Editors" msgstr "編輯器" #: editor/animation_track_editor.cpp editor/editor_settings.cpp -#, fuzzy msgid "Confirm Insert Track" -msgstr "新增動畫軌é“與關éµç•«æ ¼" +msgstr "ç¢ºèªæ’入軌é“" #. TRANSLATORS: %s will be replaced by a phrase describing the target of track. #: editor/animation_track_editor.cpp @@ -1663,9 +1582,8 @@ msgid "Add Method Track Key" msgstr "新增方法軌é“é—œéµç•«æ ¼" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Method not found in object:" -msgstr "åœ¨ç‰©ä»¶ä¸æ‰¾ä¸åˆ°æ–¹æ³•: " +msgstr "åœ¨ç‰©ä»¶ä¸æ‰¾ä¸åˆ°è©²æ–¹æ³•:" #: editor/animation_track_editor.cpp msgid "Anim Move Keys" @@ -1706,9 +1624,8 @@ msgid "" msgstr "該é¸é …ä¸é©ç”¨è²èŒ²æ›²ç·šç·¨è¼¯ï¼Œå› 曲線僅有單一軌é“。" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Add RESET Keys" -msgstr "動畫縮放關éµå½±æ ¼" +msgstr "新增動畫 RESET éµ" #: editor/animation_track_editor.cpp msgid "" @@ -1722,7 +1639,7 @@ msgid "" "Alternatively, use an import preset that imports animations to separate " "files." msgstr "" -"è©²å‹•ç•«å±¬æ–¼å¤–éƒ¨åŒ¯å…¥ä¹‹å ´æ™¯ï¼Œå¥—ç”¨æ–¼åŒ¯å…¥è»Œé“çš„ä¿®æ”¹å°‡ä¸æœƒè¢«ä¿å˜ã€‚\n" +"è©²å‹•ç•«å±¬æ–¼å¤–éƒ¨åŒ¯å…¥ä¹‹å ´æ™¯ï¼Œå¥—ç”¨æ–¼åŒ¯å…¥è»Œé“çš„ä¿®æ”¹å°‡ä¸æœƒè¢«å„²å˜ã€‚\n" "\n" "è‹¥è¦é–‹å•Ÿã€ŒåŠ å…¥å®¢åˆ¶è»Œã€çš„åŠŸèƒ½ï¼Œè«‹åœ¨å ´æ™¯åœ¨åŒ¯å…¥è¨å®šä¸å°‡ [Animation] -> " "[Storage] è¨å®šç‚º\n" @@ -2191,14 +2108,15 @@ msgstr "我的最愛:" msgid "Recent:" msgstr "最近å˜å–:" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp +#: editor/rename_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" msgstr "æœå°‹ï¼š" -#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/create_dialog.cpp editor/editor_quick_open.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" msgstr "ç¬¦åˆæ¢ä»¶ï¼š" @@ -2258,8 +2176,8 @@ msgstr "æœå°‹ä¸¦å–代資æºï¼š" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp -#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#: editor/property_selector.cpp editor/quick_open.cpp +#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp +#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp @@ -2268,7 +2186,7 @@ msgstr "開啟" #: editor/dependency_editor.cpp msgid "Owners of: %s (Total: %d)" -msgstr "" +msgstr "%s 的所有者(總計:%d)" #: editor/dependency_editor.cpp msgid "" @@ -2377,7 +2295,6 @@ msgstr "主è¦é–‹ç™¼è€…" #. TRANSLATORS: This refers to a job title. #: editor/editor_about.cpp -#, fuzzy msgctxt "Job Title" msgid "Project Manager" msgstr "專案管ç†å“¡" @@ -2619,9 +2536,8 @@ msgid "There is no '%s' file." msgstr "檔案「%sã€ä¸å˜åœ¨ã€‚" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Layout:" -msgstr "ç•«é¢é…ç½®" +msgstr "佈局:" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." @@ -2655,7 +2571,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" @@ -2670,9 +2586,8 @@ msgid "Create a new Bus Layout." msgstr "å»ºç«‹æ–°åŒ¯æµæŽ’é…置。" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Audio Bus Layout" -msgstr "é–‹å•ŸéŸ³è¨ŠåŒ¯æµæŽ’é…ç½®" +msgstr "éŸ³è¨ŠåŒ¯æµæŽ’ä½ˆå±€" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -2790,7 +2705,7 @@ msgstr "[空]" #: editor/plugins/text_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "[unsaved]" -msgstr "[未ä¿å˜]" +msgstr "[未儲å˜]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first." @@ -2825,22 +2740,20 @@ msgstr "鏿“‡" #: editor/editor_export.cpp msgid "Project export for platform:" -msgstr "" +msgstr "專案匯出平å°ï¼š" #: editor/editor_export.cpp #, fuzzy -msgid "Completed with errors." -msgstr "複製節點路徑" +msgid "Completed with warnings." +msgstr "已完æˆï¼Œå˜åœ¨éŒ¯èª¤ã€‚" #: editor/editor_export.cpp -#, fuzzy msgid "Completed successfully." -msgstr "å¥—ä»¶å®‰è£æˆåŠŸï¼" +msgstr "å¥—ä»¶å®‰è£æˆåŠŸã€‚" #: editor/editor_export.cpp -#, fuzzy msgid "Failed." -msgstr "失敗:" +msgstr "失敗。" #: editor/editor_export.cpp msgid "Storing File:" @@ -2855,29 +2768,24 @@ msgid "Packing" msgstr "æ£åœ¨æ‰“包" #: editor/editor_export.cpp -#, fuzzy msgid "Save PCK" -msgstr "å¦å˜æ–°æª”" +msgstr "å„²å˜ PCK" #: editor/editor_export.cpp -#, fuzzy msgid "Cannot create file \"%s\"." -msgstr "無法新增資料夾。" +msgstr "無法建立「%sã€æª”案。" #: editor/editor_export.cpp -#, fuzzy msgid "Failed to export project files." -msgstr "無法匯出專案檔案" +msgstr "無法匯出專案檔。" #: editor/editor_export.cpp -#, fuzzy msgid "Can't open file to read from path \"%s\"." -msgstr "無法開啟欲寫入的檔案:" +msgstr "ç„¡æ³•æ‰“é–‹ä½æ–¼ã€Œ%sã€çš„æª”案用於讀å–。" #: editor/editor_export.cpp -#, fuzzy msgid "Save ZIP" -msgstr "å¦å˜æ–°æª”" +msgstr "å„²å˜ ZIP" #: editor/editor_export.cpp msgid "" @@ -2902,7 +2810,7 @@ msgid "" "Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" -"目標平å°ä¸Šçš„ GLES2 å›žé€€é©…å‹•å™¨åŠŸèƒ½å¿…é ˆä½¿ç”¨ã€ŒETCã€ç´‹ç†å£“縮。\n" +"目標平å°ä¸Šçš„ GLES2 å¾Œå‚™é©…å‹•å™¨åŠŸèƒ½å¿…é ˆä½¿ç”¨ã€ŒETCã€ç´‹ç†å£“縮。\n" "請在專案è¨å®šä¸å•Ÿç”¨ã€ŒImport Etcã€æˆ–是ç¦ç”¨ã€ŒDriver Fallback Enabledã€ã€‚" #: editor/editor_export.cpp @@ -2928,15 +2836,14 @@ msgid "" "Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" -"目標平å°ä¸Šçš„ GLES2 å›žé€€é©…å‹•å™¨åŠŸèƒ½å¿…é ˆä½¿ç”¨ã€ŒPVRTCã€ç´‹ç†å£“縮。\n" +"目標平å°ä¸Šçš„ GLES2 å¾Œå‚™é©…å‹•å™¨åŠŸèƒ½å¿…é ˆä½¿ç”¨ã€ŒPVRTCã€ç´‹ç†å£“縮。\n" "請在專案è¨å®šä¸å•Ÿç”¨ã€ŒImport Pvrtcã€æˆ–是ç¦ç”¨ã€ŒDriver Fallback Enabledã€ã€‚" #: editor/editor_export.cpp platform/android/export/export_plugin.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom Template" -msgstr "編輯器主題" +msgstr "自訂模æ¿" #: editor/editor_export.cpp editor/project_export.cpp #: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp @@ -2946,9 +2853,8 @@ msgid "Release" msgstr "發行" #: editor/editor_export.cpp -#, fuzzy msgid "Binary Format" -msgstr "色彩é‹ç®—å。" +msgstr "äºŒé€²ä½æ ¼å¼" #: editor/editor_export.cpp msgid "64 Bits" @@ -2959,9 +2865,8 @@ msgid "Embed PCK" msgstr "內嵌PCK" #: editor/editor_export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Texture Format" -msgstr "ç´‹ç†è²¼åœ–å€åŸŸ" +msgstr "ç´‹ç†è²¼åœ–æ ¼å¼" #: editor/editor_export.cpp msgid "BPTC" @@ -2980,9 +2885,8 @@ msgid "ETC2" msgstr "ETC2" #: editor/editor_export.cpp -#, fuzzy msgid "No BPTC Fallbacks" -msgstr "ç„¡BPTC回è½" +msgstr "ç„¡ BPTC 後備" #: editor/editor_export.cpp platform/android/export/export_plugin.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -2997,30 +2901,25 @@ msgid "Custom release template not found." msgstr "找ä¸åˆ°è‡ªå®šç¾©ç™¼è¡Œæ¨£æ¿ã€‚" #: editor/editor_export.cpp -#, fuzzy msgid "Prepare Template" -msgstr "ç®¡ç†æ¨£æ¿" +msgstr "ç®¡ç†æ¨¡æ¿" #: editor/editor_export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "The given export path doesn't exist." -msgstr "給定的匯出路徑ä¸å˜åœ¨ï¼š" +msgstr "給定的匯出路徑ä¸å˜åœ¨ã€‚" #: editor/editor_export.cpp platform/javascript/export/export.cpp -#, fuzzy msgid "Template file not found: \"%s\"." -msgstr "找ä¸åˆ°æ¨£æ¿æª”案:" +msgstr "找ä¸åˆ°æ¨¡æ¿æª”案:「%sã€ã€‚" #: editor/editor_export.cpp -#, fuzzy msgid "Failed to copy export template." -msgstr "無效的輸出樣æ¿ï¼š" +msgstr "複製匯出模æ¿å¤±æ•—。" #: editor/editor_export.cpp platform/windows/export/export.cpp #: platform/x11/export/export.cpp -#, fuzzy msgid "PCK Embedding" -msgstr "å¡«å……" +msgstr "PCK 內嵌" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." @@ -3228,9 +3127,8 @@ msgid "Manage Editor Feature Profiles" msgstr "管ç†ç·¨è¼¯å™¨åŠŸèƒ½è¨å®šæª”" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Default Feature Profile" -msgstr "Godot 功能è¨å®šæª”" +msgstr "é è¨åŠŸèƒ½è¨å®šæª”" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -3295,21 +3193,19 @@ msgstr "開啟檔案或資料夾" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/file_dialog.cpp msgid "Save" -msgstr "ä¿å˜" +msgstr "儲å˜" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Save a File" -msgstr "ä¿å˜æª”案" +msgstr "å„²å˜æª”案" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Access" -msgstr "æˆåŠŸï¼" +msgstr "å˜å–" #: editor/editor_file_dialog.cpp editor/editor_settings.cpp -#, fuzzy msgid "Display Mode" -msgstr "æ’æ”¾æ¨¡å¼ï¼š" +msgstr "顯示模å¼" #: editor/editor_file_dialog.cpp #: editor/import/resource_importer_layered_texture.cpp @@ -3322,30 +3218,25 @@ msgstr "æ’æ”¾æ¨¡å¼ï¼š" #: scene/resources/environment.cpp scene/resources/material.cpp #: scene/resources/visual_shader.cpp #: servers/audio/effects/audio_effect_distortion.cpp -#, fuzzy msgid "Mode" -msgstr "平移模å¼" +msgstr "模å¼" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Current Dir" -msgstr "ç›®å‰ï¼š" +msgstr "ç›®å‰ç›®éŒ„" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Current File" -msgstr "ç›®å‰è¨å®šæª”:" +msgstr "所在檔案" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Current Path" -msgstr "ç›®å‰ï¼š" +msgstr "所在目錄" #: editor/editor_file_dialog.cpp editor/editor_settings.cpp #: scene/gui/file_dialog.cpp -#, fuzzy msgid "Show Hidden Files" -msgstr "顯示ï¼å–æ¶ˆé¡¯ç¤ºéš±è—æª”案" +msgstr "顯示隱è—的檔案" #: editor/editor_file_dialog.cpp msgid "Disable Overwrite Warning" @@ -3480,9 +3371,8 @@ msgid "Properties" msgstr "屬性" #: editor/editor_help.cpp -#, fuzzy msgid "overrides %s:" -msgstr "複寫:" +msgstr "覆蓋 %s:" #: editor/editor_help.cpp msgid "default:" @@ -3640,46 +3530,39 @@ msgid "Property:" msgstr "屬性:" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp -#, fuzzy msgid "Label" -msgstr "數值" +msgstr "標籤" #: editor/editor_inspector.cpp editor/editor_spin_slider.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Read Only" -msgstr "僅顯示方法" +msgstr "åªè®€" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp -#, fuzzy msgid "Checkable" -msgstr "æª¢æŸ¥é …ç›®" +msgstr "å¯å‹¾é¸" #: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Checked" -msgstr "å·²æª¢æŸ¥çš„é …ç›®" +msgstr "已勾é¸" #: editor/editor_inspector.cpp -#, fuzzy msgid "Draw Red" -msgstr "繪製呼å«ï¼š" +msgstr "繪製紅色" #: editor/editor_inspector.cpp -#, fuzzy msgid "Keying" -msgstr "執行" +msgstr "輸入" #: editor/editor_inspector.cpp -#, fuzzy msgid "Pin value" -msgstr "(數值)" +msgstr "固定值" #: editor/editor_inspector.cpp msgid "" "Pinning a value forces it to be saved even if it's equal to the default." -msgstr "釘é¸çš„æ•¸å€¼å°‡è¢«è¿«ä¿å˜ï¼Œå³ä½¿å…¶å€¼èˆ‡é è¨å€¼ç›¸åŒã€‚" +msgstr "釘é¸çš„æ•¸å€¼å°‡è¢«è¿«å„²å˜ï¼Œå³ä½¿å…¶å€¼èˆ‡é è¨å€¼ç›¸åŒã€‚" #: editor/editor_inspector.cpp msgid "Pin value [Disabled because '%s' is editor-only]" @@ -3707,19 +3590,16 @@ msgid "Unpinned %s" msgstr "已解除釘é¸%s" #: editor/editor_inspector.cpp -#, fuzzy msgid "Copy Property" msgstr "複製屬性" #: editor/editor_inspector.cpp -#, fuzzy msgid "Paste Property" msgstr "貼上屬性" #: editor/editor_inspector.cpp -#, fuzzy msgid "Copy Property Path" -msgstr "複製腳本路徑" +msgstr "複製屬性路徑" #: editor/editor_log.cpp msgid "Output:" @@ -3809,7 +3689,7 @@ msgstr "ç·¨è¼¯å™¨è¦–çª—é‡æ–°ç¹ªè£½æ™‚旋轉。" #: editor/editor_node.cpp msgid "Imported resources can't be saved." -msgstr "匯入的資æºç„¡æ³•ä¿å˜ã€‚" +msgstr "匯入的資æºç„¡æ³•儲å˜ã€‚" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp @@ -3825,7 +3705,7 @@ msgstr "ä¿å˜è³‡æºæ™‚發生錯誤ï¼" msgid "" "This resource can't be saved because it does not belong to the edited scene. " "Make it unique first." -msgstr "由於該資æºä¸å±¬æ–¼å·²ç·¨è¼¯çš„å ´æ™¯ï¼Œç„¡æ³•ä¿å˜è©²è³‡æºã€‚請先使其ç¨ç«‹åŒ–。" +msgstr "由於該資æºä¸å±¬æ–¼å·²ç·¨è¼¯çš„å ´æ™¯ï¼Œç„¡æ³•å„²å˜è©²è³‡æºã€‚請先使其ç¨ç«‹åŒ–。" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -3884,22 +3764,22 @@ 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" +"è©²å ´æ™¯æœ‰å¾ªç’°æ€§å¯¦é«”åŒ–å•題,無法儲å˜ã€‚\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 msgid "Could not save one or more scenes!" -msgstr "無法ä¿å˜ä¸€æˆ–å¤šå€‹å ´æ™¯ï¼" +msgstr "無法儲å˜ä¸€æˆ–å¤šå€‹å ´æ™¯ï¼" #: editor/editor_node.cpp msgid "Save All Scenes" -msgstr "ä¿å˜æ‰€æœ‰å ´æ™¯" +msgstr "å„²å˜æ‰€æœ‰å ´æ™¯" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" @@ -3926,7 +3806,7 @@ msgid "" "An error occurred while trying to save the editor layout.\n" "Make sure the editor's user data path is writable." msgstr "" -"ä¿å˜ç·¨è¼¯å™¨ç•«é¢é…置時發生錯誤。\n" +"儲å˜ç·¨è¼¯å™¨ç•«é¢é…置時發生錯誤。\n" "請確èªç·¨è¼¯å™¨çš„使用者資料路徑是å¦å¯å¯«å…¥ã€‚" #: editor/editor_node.cpp @@ -3995,7 +3875,7 @@ msgstr "æœªå®šç¾©æ¬²åŸ·è¡Œä¹‹å ´æ™¯ã€‚" #: editor/editor_node.cpp msgid "Save scene before running..." -msgstr "執行å‰å…ˆä¿å˜å ´æ™¯..." +msgstr "執行å‰å…ˆå„²å˜å ´æ™¯..." #: editor/editor_node.cpp msgid "Could not start subprocess!" @@ -4022,38 +3902,36 @@ msgid "Quick Open Script..." msgstr "快速開啟腳本…" #: editor/editor_node.cpp -#, fuzzy msgid "Save & Reload" -msgstr "ä¿å˜ä¸¦é‡æ–°å•Ÿå‹•" +msgstr "儲å˜ä¸¦é‡æ–°è¼‰å…¥" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to '%s' before reloading?" -msgstr "é—œé–‰å‰æ˜¯å¦ä¿å˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ" +msgstr "是å¦åœ¨é‡æ–°è¼‰å…¥å‰å„²å˜å°ã€Œ%sã€çš„變更?" #: editor/editor_node.cpp msgid "Save & Close" -msgstr "ä¿å˜ä¸¦é—œé–‰" +msgstr "儲å˜ä¸¦é—œé–‰" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" -msgstr "é—œé–‰å‰æ˜¯å¦ä¿å˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ" +msgstr "é—œé–‰å‰æ˜¯å¦å„²å˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ" #: editor/editor_node.cpp msgid "%s no longer exists! Please specify a new save location." -msgstr "%sä¸å˜åœ¨ï¼è«‹æŒ‡å®šæ–°çš„ä¿å˜ä½ç½®ã€‚" +msgstr "%sä¸å˜åœ¨ï¼è«‹æŒ‡å®šæ–°çš„儲å˜ä½ç½®ã€‚" #: editor/editor_node.cpp msgid "" "The current scene has no root node, but %d modified external resource(s) " "were saved anyway." -msgstr "ç›®å‰çš„å ´æ™¯ç„¡æ ¹ç¯€é»žï¼Œä½†%d個被更改的外部資æºå·²è¢«ä¿å˜ã€‚" +msgstr "ç›®å‰çš„å ´æ™¯ç„¡æ ¹ç¯€é»žï¼Œä½†%d個被更改的外部資æºå·²è¢«å„²å˜ã€‚" #: editor/editor_node.cpp msgid "" "A root node is required to save the scene. You can add a root node using the " "Scene tree dock." -msgstr "å¿…é ˆæœ‰æ ¹ç¯€é»žæ‰å¯ä¿å˜å ´æ™¯ã€‚您å¯ä½¿ç”¨å ´æ™¯åœä½‡åˆ—ä»¥åŠ å…¥ä¸€å€‹æ ¹ç¯€é»žã€‚" +msgstr "å¿…é ˆæœ‰æ ¹ç¯€é»žæ‰å¯å„²å˜å ´æ™¯ã€‚您å¯ä½¿ç”¨å ´æ™¯åœä½‡åˆ—ä»¥åŠ å…¥ä¸€å€‹æ ¹ç¯€é»žã€‚" #: editor/editor_node.cpp msgid "Save Scene As..." @@ -4081,7 +3959,7 @@ msgstr "è«‹å…ˆé¸æ“‡ç¯€é»žä»¥åŸ·è¡Œè©²æ“作。" #: editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "尚未ä¿å˜ç›®å‰å ´æ™¯ã€‚ä»ç„¶è¦é–‹å•Ÿå—Žï¼Ÿ" +msgstr "尚未儲å˜ç›®å‰å ´æ™¯ã€‚ä»ç„¶è¦é–‹å•Ÿå—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Can't undo while mouse buttons are pressed." @@ -4109,18 +3987,18 @@ msgstr "å–æ¶ˆå¾©åŽŸï¼š%s" #: editor/editor_node.cpp msgid "Can't reload a scene that was never saved." -msgstr "ç„¡æ³•é‡æ–°è¼‰å…¥å¾žæœªä¿å˜éŽçš„å ´æ™¯ã€‚" +msgstr "ç„¡æ³•é‡æ–°è¼‰å…¥å¾žæœªå„²å˜éŽçš„å ´æ™¯ã€‚" #: editor/editor_node.cpp 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" +"ç›®å‰å ´æ™¯æœ‰æœªå„²å˜çš„æ”¹å‹•。\n" "ä»è¦é‡æ–°è¼‰å…¥å ´æ™¯å—Žï¼Ÿæ¤æ“作將無法復原。" #: editor/editor_node.cpp @@ -4144,21 +4022,20 @@ msgid "Open Project Manager?" msgstr "è¦é–‹å•Ÿå°ˆæ¡ˆç®¡ç†å“¡å—Žï¼Ÿ" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to the following scene(s) before reloading?" -msgstr "退出å‰è¦å…ˆä¿å˜ä¸‹åˆ—å ´æ™¯å—Žï¼Ÿ" +msgstr "釿–°è¼‰å…¥å‰è¦å„²å˜ä¸‹åˆ—å ´æ™¯çš„è®Šæ›´å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Save & Quit" -msgstr "ä¿å˜ä¸¦é€€å‡º" +msgstr "儲å˜ä¸¦é€€å‡º" #: editor/editor_node.cpp msgid "Save changes to the following scene(s) before quitting?" -msgstr "退出å‰è¦å…ˆä¿å˜ä¸‹åˆ—å ´æ™¯å—Žï¼Ÿ" +msgstr "退出å‰è¦å…ˆå„²å˜ä¸‹åˆ—å ´æ™¯å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Save changes to the following scene(s) before opening Project Manager?" -msgstr "開啟專案管ç†å“¡å‰è¦å…ˆä¿å˜ä»¥ä¸‹å ´æ™¯å—Žï¼Ÿ" +msgstr "開啟專案管ç†å“¡å‰è¦å…ˆå„²å˜ä»¥ä¸‹å ´æ™¯å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "" @@ -4222,7 +4099,7 @@ msgid "" "open the scene, then save it inside the project path." msgstr "" "è¼‰å…¥å ´æ™¯æ™‚ç™¼ç”ŸéŒ¯èª¤ï¼Œå ´æ™¯å¿…é ˆç½®æ–¼å°ˆæ¡ˆè·¯å¾‘å…§ã€‚è«‹ä½¿ç”¨ [匯入] ä¾†é–‹å•Ÿè©²å ´æ™¯ï¼Œä¸¦å°‡" -"å…¶ä¿å˜æ–¼å°ˆæ¡ˆè·¯å¾‘內。" +"å…¶å„²å˜æ–¼å°ˆæ¡ˆè·¯å¾‘內。" #: editor/editor_node.cpp msgid "Scene '%s' has broken dependencies:" @@ -4324,19 +4201,16 @@ msgstr "無法寫入檔案'%s',該檔案æ£è¢«ä½¿ç”¨ã€éŽ–å®šæˆ–å› æ¬Šé™ä¸è¶ #: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp #: servers/arvr/arvr_interface.cpp -#, fuzzy msgid "Interface" -msgstr "使用者界é¢" +msgstr "界é¢" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Scene Tabs" -msgstr "切æ›å ´æ™¯åˆ†é " +msgstr "å ´æ™¯åˆ†é " #: editor/editor_node.cpp -#, fuzzy msgid "Always Show Close Button" -msgstr "æ°¸é é¡¯ç¤ºç¶²æ ¼" +msgstr "æ°¸é 顯示關閉按鈕" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Resize If Many Tabs" @@ -4351,14 +4225,12 @@ msgid "Output" msgstr "輸出" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Always Clear Output On Play" -msgstr "清除輸出" +msgstr "åŸ·è¡Œæ™‚æ°¸é æ¸…除輸出" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Always Open Output On Play" -msgstr "æ’æ”¾æ™‚æ°¸é 開啟輸出" +msgstr "執行時永é 開啟輸出" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Always Close Output On Stop" @@ -4366,41 +4238,35 @@ msgstr "åœæ¢æ™‚æ°¸é 關閉輸出" #: editor/editor_node.cpp msgid "Save On Focus Loss" -msgstr "失去焦點時ä¿å˜" +msgstr "失去焦點時儲å˜" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Save Each Scene On Quit" -msgstr "ä¿å˜åˆ†æ”¯ç‚ºå ´æ™¯" +msgstr "退出時儲å˜å„å ´æ™¯" #: editor/editor_node.cpp editor/editor_settings.cpp -#, fuzzy msgid "Quit Confirmation" -msgstr "檢視資訊" +msgstr "退出確èª" #: editor/editor_node.cpp -#, fuzzy msgid "Show Update Spinner" -msgstr "éš±è—æ›´æ–°æ—‹è½‰åœ–" +msgstr "顯示更新旋轉圖" #: editor/editor_node.cpp msgid "Update Continuously" msgstr "æŒçºŒæ›´æ–°" #: editor/editor_node.cpp -#, fuzzy msgid "Update Vital Only" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "僅更新 Vital" #: editor/editor_node.cpp -#, fuzzy msgid "Localize Settings" -msgstr "本地化" +msgstr "在地化è¨å®š" #: editor/editor_node.cpp -#, fuzzy msgid "Restore Scenes On Load" -msgstr "TimeSeek 節點" +msgstr "載入時æ¢å¾©å ´æ™¯" #: editor/editor_node.cpp editor/editor_settings.cpp msgid "Show Thumbnail On Hover" @@ -4411,23 +4277,20 @@ msgid "Inspector" msgstr "å±¬æ€§é¢æ¿" #: editor/editor_node.cpp -#, fuzzy msgid "Default Property Name Style" -msgstr "專案路徑:" +msgstr "é è¨å±¬æ€§å稱樣å¼" #: editor/editor_node.cpp msgid "Default Float Step" msgstr "é è¨æµ®é»žæ•¸é–“éš”" #: editor/editor_node.cpp scene/gui/tree.cpp -#, fuzzy msgid "Disable Folding" -msgstr "å·²åœç”¨çš„æŒ‰éˆ•" +msgstr "åœç”¨æŠ˜ç–Š" #: editor/editor_node.cpp -#, fuzzy msgid "Auto Unfold Foreign Scenes" -msgstr "自動展開å°å¤–å ´æ™¯" +msgstr "è‡ªå‹•å±•é–‹å ´æ™¯" #: editor/editor_node.cpp msgid "Horizontal Vector2 Editing" @@ -4438,14 +4301,12 @@ msgid "Horizontal Vector Types Editing" msgstr "æ°´å¹³Vector類別編輯" #: editor/editor_node.cpp -#, fuzzy msgid "Open Resources In Current Inspector" -msgstr "åœ¨å±¬æ€§é¢æ¿ä¸é–‹å•Ÿ" +msgstr "在目å‰çš„å±¬æ€§é¢æ¿æ‰“開資æº" #: editor/editor_node.cpp -#, fuzzy msgid "Resources To Open In New Inspector" -msgstr "åœ¨å±¬æ€§é¢æ¿ä¸é–‹å•Ÿ" +msgstr "åœ¨æ–°çš„å±¬æ€§é¢æ¿é–‹å•Ÿè³‡æº" #: editor/editor_node.cpp msgid "Default Color Picker Mode" @@ -4456,9 +4317,8 @@ msgid "Version Control" msgstr "版本控制" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Username" -msgstr "釿–°å‘½å" +msgstr "使用者å稱" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "SSH Public Key Path" @@ -4530,7 +4390,7 @@ msgstr "æœ€è¿‘é–‹å•Ÿçš„å ´æ™¯" #: editor/editor_node.cpp msgid "Save Scene" -msgstr "ä¿å˜å ´æ™¯" +msgstr "儲å˜å ´æ™¯" #: editor/editor_node.cpp msgid "Convert To..." @@ -4584,9 +4444,8 @@ msgid "Install Android Build Template..." msgstr "å®‰è£ Android 建置樣æ¿..." #: editor/editor_node.cpp -#, fuzzy msgid "Open User Data Folder" -msgstr "開啟編輯器資料目錄" +msgstr "打開使用者資料資料夾" #: editor/editor_node.cpp editor/editor_settings.cpp #: editor/plugins/tile_set_editor_plugin.cpp @@ -4662,12 +4521,10 @@ msgid "" msgstr "開啟該é¸é …å¾Œï¼Œå°Žèˆªç¶²æ ¼èˆ‡å¤šé‚Šå½¢å°‡åœ¨å°ˆæ¡ˆåŸ·è¡Œæ™‚å¯è¦‹ã€‚" #: editor/editor_node.cpp -#, fuzzy msgid "Force Shader Fallbacks" -msgstr "強制著色器回è½" +msgstr "強制著色器後備" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, shaders will be used in their fallback form " "(either visible via an ubershader or hidden) during all the run time.\n" @@ -4676,10 +4533,10 @@ msgid "" "Asynchronous shader compilation must be enabled in the project settings for " "this option to make a difference." msgstr "" -"當該é¸é …啟用時,著色器將以回è½çš„形弿–¼åŸ·è¡Œæ™‚作用(é€éŽUbershader顯示或隱" +"啟用該é¸é …時,著色器在é‹è¡Œæ™‚會使用其後備形å¼ï¼ˆé€éŽ ubershader 顯示或隱" "è—)。\n" -"å¯ç”¨æ–¼é©—è‰å›žè½çš„外觀和效能,其在æ£å¸¸çš„æƒ…å½¢ä¸‹åªæœƒçŸæš«åœ°é¡¯ç¤ºã€‚\n" -"需啟用專案è¨å®šä¸çš„éžåŒæ¥è‘—色器編è¯ä»¥ä½¿è©²é¸é …ç™¼æ®æ•ˆæžœã€‚" +"å¯ç”¨æ–¼é©—è‰å¾Œå‚™å¤–觀和效能,æ£å¸¸æƒ…æ³ä¸‹åªæœƒçŸæš«é¡¯ç¤ºã€‚\n" +"å¿…é ˆåœ¨å°ˆæ¡ˆè¨å®šä¸å•Ÿç”¨éžåŒæ¥è‘—色器編è¯ï¼Œè©²é¸é …æ‰æœƒæœ‰æ•ˆæžœã€‚" #: editor/editor_node.cpp msgid "Synchronize Scene Changes" @@ -4706,7 +4563,7 @@ msgid "" "When used remotely on a device, this is more efficient when the network " "filesystem option is enabled." msgstr "" -"開啟該é¸é …後,ä¿å˜è…³æœ¬æ™‚會於執行ä¸çš„éŠæˆ²å…§é‡æ–°è¼‰å…¥è…³æœ¬ã€‚\n" +"開啟該é¸é …後,儲å˜è…³æœ¬æ™‚會於執行ä¸çš„éŠæˆ²å…§é‡æ–°è¼‰å…¥è…³æœ¬ã€‚\n" "若在é 端è£ç½®ä¸Šä½¿ç”¨ï¼Œå¯ä½¿ç”¨ç¶²è·¯æª”案系統 NFS 以ç²å¾—最佳效能。" #: editor/editor_node.cpp @@ -4824,17 +4681,15 @@ msgstr "更改視訊驅動程å¼éœ€è¦é‡æ–°å•Ÿå‹•編輯器。" #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp msgid "Save & Restart" -msgstr "ä¿å˜ä¸¦é‡æ–°å•Ÿå‹•" +msgstr "儲å˜ä¸¦é‡æ–°å•Ÿå‹•" #: editor/editor_node.cpp -#, fuzzy msgid "Update All Changes" -msgstr "更改時更新" +msgstr "更新所有變更" #: editor/editor_node.cpp -#, fuzzy msgid "Update Vital Changes" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "æ›´æ–° Vital æ›´å‹•" #: editor/editor_node.cpp msgid "Hide Update Spinner" @@ -4852,7 +4707,7 @@ msgstr "å±•é–‹åº•éƒ¨é¢æ¿" #: editor/editor_node.cpp msgid "Don't Save" -msgstr "ä¸ä¿å˜" +msgstr "ä¸å„²å˜" #: editor/editor_node.cpp msgid "Android build template is missing, please install relevant templates." @@ -4938,7 +4793,7 @@ msgstr "釿–°è¼‰å…¥" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp msgid "Resave" -msgstr "釿–°ä¿å˜" +msgstr "釿–°å„²å˜" #: editor/editor_node.cpp msgid "New Inherited" @@ -5090,14 +4945,12 @@ msgid "Debugger" msgstr "除錯工具" #: editor/editor_profiler.cpp -#, fuzzy msgid "Profiler Frame History Size" -msgstr "效能分æžå·¥å…·å¹€æ•¸æ·å²æ—¥èªŒå¤§å°" +msgstr "分æžå·¥å…·å½±æ ¼æ·å²å¤§å°" #: editor/editor_profiler.cpp -#, fuzzy msgid "Profiler Frame Max Functions" -msgstr "釿–°å‘½å函å¼" +msgstr "分æžå·¥å…·å½±æ ¼æœ€å¤§å‡½å¼æ•¸" #: editor/editor_properties.cpp msgid "Edit Text:" @@ -5136,7 +4989,7 @@ msgid "" "Can't create a ViewportTexture on resources saved as a file.\n" "Resource needs to belong to a scene." msgstr "" -"無法為欲ä¿å˜æˆæª”案之資æºå»ºç«‹ ViewportTexture。\n" +"ç„¡æ³•ç‚ºæ¬²å„²å˜æˆæª”案之資æºå»ºç«‹ ViewportTexture。\n" "資æºå¿…é ˆå±¬æ–¼ä¸€å€‹å ´æ™¯ã€‚" #: editor/editor_properties.cpp @@ -5164,9 +5017,8 @@ msgid "Size:" msgstr "大å°ï¼š" #: editor/editor_properties_array_dict.cpp -#, fuzzy msgid "Page:" -msgstr "é : " +msgstr "é :" #: editor/editor_properties_array_dict.cpp #: editor/plugins/theme_editor_plugin.cpp @@ -5226,20 +5078,17 @@ msgstr "新增 %s" #: modules/visual_script/visual_script_func_nodes.cpp #: modules/visual_script/visual_script_nodes.cpp #: modules/visual_script/visual_script_yield_nodes.cpp -#, fuzzy msgid "Base Type" -msgstr "更改基礎型別" +msgstr "基礎型別" #: editor/editor_resource_picker.cpp -#, fuzzy msgid "Edited Resource" -msgstr "新增資æº" +msgstr "已經編輯資" #: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp #: scene/gui/slider.cpp scene/gui/spin_box.cpp -#, fuzzy msgid "Editable" -msgstr "å¯ç·¨è¼¯çš„é …ç›®" +msgstr "å¯ç·¨è¼¯" #: editor/editor_resource_picker.cpp editor/property_editor.cpp msgid "New Script" @@ -5250,9 +5099,8 @@ msgid "Extend Script" msgstr "擴充腳本" #: editor/editor_resource_picker.cpp -#, fuzzy msgid "Script Owner" -msgstr "腳本å稱:" +msgstr "腳本所有者" #: editor/editor_run_native.cpp msgid "" @@ -5264,9 +5112,8 @@ msgstr "" "請在 [匯出] é¸å–®ä¸æ–°å¢žä¸€å€‹å¯åŸ·è¡Œçš„é è¨è¨å®šï¼Œæˆ–å°‡ç¾æœ‰çš„é è¨è¨å®šè¨ç‚ºå¯åŸ·è¡Œã€‚" #: editor/editor_run_native.cpp -#, fuzzy msgid "Project Run" -msgstr "專案" +msgstr "執行專案" #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." @@ -5293,21 +5140,18 @@ msgid "Did you forget the '_run' method?" msgstr "æ˜¯å¦æœªæ–°å¢žã€Œ_runã€æ–¹æ³•?" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor Language" -msgstr "編輯器é…ç½®" +msgstr "編輯器語言" #: editor/editor_settings.cpp -#, fuzzy msgid "Display Scale" -msgstr "全部顯示" +msgstr "顯示縮放" #: editor/editor_settings.cpp msgid "Custom Display Scale" msgstr "自訂顯示縮放" #: editor/editor_settings.cpp -#, fuzzy msgid "Main Font Size" msgstr "主è¦å—體大å°" @@ -5324,46 +5168,40 @@ msgid "Font Hinting" msgstr "å—體微調" #: editor/editor_settings.cpp -#, fuzzy msgid "Main Font" -msgstr "ä¸»å ´æ™¯" +msgstr "主è¦å—é«”" #: editor/editor_settings.cpp msgid "Main Font Bold" msgstr "主è¦å—體粗體" #: editor/editor_settings.cpp -#, fuzzy msgid "Code Font" -msgstr "æ–°å¢žç¯€é»žé ‚é»ž" +msgstr "程å¼ç¢¼å—é«”" #: editor/editor_settings.cpp msgid "Dim Editor On Dialog Popup" msgstr "å°è©±æ¡†å½ˆå‡ºæ™‚使編輯器變暗" #: editor/editor_settings.cpp main/main.cpp -#, fuzzy msgid "Low Processor Mode Sleep (µsec)" -msgstr "低處ç†å™¨ä½¿ç”¨æ¨¡å¼ç¡çœ (微秒)" +msgstr "低處ç†å™¨ç¡çœ 模å¼ï¼ˆå¾®ç§’)" #: editor/editor_settings.cpp -#, fuzzy msgid "Unfocused Low Processor Mode Sleep (µsec)" -msgstr "éžèšç„¦ä½Žè™•ç†å™¨ä½¿ç”¨æ¨¡å¼ç¡çœ (微秒)" +msgstr "未èšç„¦ä½Žè™•ç†å™¨ç¡çœ 模å¼ï¼ˆå¾®ç§’)" #: editor/editor_settings.cpp -#, fuzzy msgid "Separate Distraction Mode" -msgstr "專注模å¼" +msgstr "ç¨ç«‹å°ˆæ³¨æ¨¡å¼" #: editor/editor_settings.cpp msgid "Automatically Open Screenshots" msgstr "自動開啟截圖" #: editor/editor_settings.cpp -#, fuzzy msgid "Max Array Dictionary Items Per Page" -msgstr "æ¯é 最大陣列å—å…¸é …ç›®æ•¸" +msgstr "æ¯é 最大陣列å—å…¸ç‰©å“æ•¸" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp @@ -5380,131 +5218,108 @@ msgid "Icon And Font Color" msgstr "圖標åŠå—é«”é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Color" -msgstr "é¡è‰²" +msgstr "基礎é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Accent Color" -msgstr "鏿“‡é¡è‰²" +msgstr "強調é¡è‰²" #: editor/editor_settings.cpp scene/resources/environment.cpp msgid "Contrast" msgstr "å°æ¯”" #: editor/editor_settings.cpp -#, fuzzy msgid "Relationship Line Opacity" msgstr "關係線ä¸é€æ˜Žåº¦" #: editor/editor_settings.cpp -#, fuzzy msgid "Highlight Tabs" -msgstr "æ£åœ¨ä¿å˜å…‰ç…§åœ–" +msgstr "çªé¡¯é¸é …å¡" #: editor/editor_settings.cpp -#, fuzzy msgid "Border Size" -msgstr "邊界åƒç´ " +msgstr "邊框大å°" #: editor/editor_settings.cpp msgid "Use Graph Node Headers" msgstr "使用圖形節點標題" #: editor/editor_settings.cpp -#, fuzzy msgid "Additional Spacing" -msgstr "é‡è¤‡å‹•ç•«" +msgstr "é¡å¤–é–“è·" #: editor/editor_settings.cpp -#, fuzzy msgid "Custom Theme" -msgstr "編輯器主題" +msgstr "自訂主題" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Script Button" -msgstr "滾輪å‘峿Œ‰éµ" +msgstr "顯示腳本按鈕" #: editor/editor_settings.cpp -#, fuzzy msgid "Directories" msgstr "æ–¹å‘" #: editor/editor_settings.cpp -#, fuzzy msgid "Autoscan Project Path" -msgstr "專案路徑:" +msgstr "自動掃æå°ˆæ¡ˆè·¯å¾‘" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Project Path" -msgstr "專案路徑:" +msgstr "é è¨å°ˆæ¡ˆè·¯å¾‘" #: editor/editor_settings.cpp -#, fuzzy msgid "On Save" -msgstr "ä¿å˜" +msgstr "å„²å˜æ™‚" #: editor/editor_settings.cpp -#, fuzzy msgid "Compress Binary Resources" -msgstr "複製資æº" +msgstr "壓縮二進ä½è³‡æº" #: editor/editor_settings.cpp msgid "Safe Save On Backup Then Rename" -msgstr "備份時安全ä¿å˜å¾Œé‡æ–°å‘½å" +msgstr "備份時安全儲å˜å¾Œé‡æ–°å‘½å" #: editor/editor_settings.cpp -#, fuzzy msgid "File Dialog" -msgstr "XForm å°è©±æ¡†" +msgstr "檔案å°è©±æ¡†" #: editor/editor_settings.cpp -#, fuzzy msgid "Thumbnail Size" -msgstr "縮圖…" +msgstr "縮圖大å°" #: editor/editor_settings.cpp -#, fuzzy msgid "Docks" -msgstr "功能介é¢" +msgstr "颿¿" #: editor/editor_settings.cpp -#, fuzzy msgid "Scene Tree" -msgstr "æ£åœ¨ç·¨è¼¯å ´æ™¯æ¨¹" +msgstr "å ´æ™¯æ¨¹" #: editor/editor_settings.cpp -#, fuzzy msgid "Start Create Dialog Fully Expanded" -msgstr "開始新建完全展開å°è©±" +msgstr "é è¨å®Œå…¨å±•開建立å°è©±æ¡†" #: editor/editor_settings.cpp -#, fuzzy msgid "Always Show Folders" -msgstr "æ°¸é é¡¯ç¤ºç¶²æ ¼" +msgstr "æ°¸é 顯示資料夾" #: editor/editor_settings.cpp -#, fuzzy msgid "Property Editor" -msgstr "群組編輯器" +msgstr "屬性編輯器" #: editor/editor_settings.cpp -#, fuzzy msgid "Auto Refresh Interval" -msgstr "自動刷新間隔" +msgstr "è‡ªå‹•æ›´æ–°é »çŽ‡" #: editor/editor_settings.cpp -#, fuzzy msgid "Subresource Hue Tint" -msgstr "å資æº" +msgstr "å資æºå½©è‰²é¡¯ç¤º" #: editor/editor_settings.cpp -#, fuzzy msgid "Color Theme" -msgstr "編輯器主題" +msgstr "é¡è‰²ä¸»é¡Œ" #: editor/editor_settings.cpp scene/3d/label_3d.cpp #: scene/resources/default_theme/default_theme.cpp @@ -5513,52 +5328,44 @@ msgstr "行間è·" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp #: modules/gdscript/editor/gdscript_highlighter.cpp -#, fuzzy msgid "Highlighting" -msgstr "呿€§å…‰ç…§" +msgstr "çªå‡ºé¡¯ç¤º" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Syntax Highlighting" -msgstr "高亮顯示語法" +msgstr "語法çªå‡ºé¡¯ç¤º" #: editor/editor_settings.cpp scene/gui/text_edit.cpp msgid "Highlight All Occurrences" msgstr "凸顯所有符åˆé …ç›®" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Highlight Current Line" -msgstr "凸顯目å‰è¡Œ" +msgstr "çªé¡¯ç›®å‰è¡Œ" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Highlight Type Safe Lines" msgstr "凸顯型別安全的行" #: editor/editor_settings.cpp -#, fuzzy msgid "Indent" -msgstr "å‘左縮排" +msgstr "縮排" #: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp msgid "Auto Indent" msgstr "自動縮排" #: editor/editor_settings.cpp -#, fuzzy msgid "Convert Indent On Save" -msgstr "轉æ›ç¸®æŽ’為空白" +msgstr "å„²å˜æ™‚轉æ›ç¸®æŽ’" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Draw Tabs" -msgstr "繪製呼å«ï¼š" +msgstr "繪製分é " #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Draw Spaces" -msgstr "繪製呼å«ï¼š" +msgstr "ç¹ªè£½ç©ºæ ¼" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp @@ -5576,98 +5383,88 @@ msgid "V Scroll Speed" msgstr "垂直滾動速度" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Minimap" -msgstr "顯示原點" +msgstr "é¡¯ç¤ºè¿·ä½ åœ°åœ–" #: editor/editor_settings.cpp msgid "Minimap Width" msgstr "è¿·ä½ åœ°åœ–å¯¬åº¦" #: editor/editor_settings.cpp -#, fuzzy msgid "Mouse Extra Buttons Navigate History" -msgstr "æ»‘é¼ é¡å¤–æŒ‰éµæ“作æ·å²ç´€éŒ„" +msgstr "使用é¡å¤–æ»‘é¼ æŒ‰éµæŸ¥çœ‹æ·å²" #: editor/editor_settings.cpp -#, fuzzy msgid "Drag And Drop Selection" -msgstr "鏿“‡ç¶²æ ¼åœ°åœ–" +msgstr "æ‹–ç§»é¸æ“‡çš„æª”案" + +#: editor/editor_settings.cpp +msgid "Stay In Script Editor On Node Selected" +msgstr "鏿“‡ç¯€é»žæ™‚ä¿ç•™åœ¨è…³æœ¬ç·¨è¼¯å™¨ä¸" #: editor/editor_settings.cpp msgid "Appearance" msgstr "外觀" #: editor/editor_settings.cpp scene/gui/text_edit.cpp -#, fuzzy msgid "Show Line Numbers" -msgstr "行號:" +msgstr "顯示行號" #: editor/editor_settings.cpp -#, fuzzy msgid "Line Numbers Zero Padded" -msgstr "行號:" +msgstr "行號æ¸é›¶" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Bookmark Gutter" -msgstr "顯示書籤欄ä½" +msgstr "顯示書籤欄" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Breakpoint Gutter" -msgstr "è·³éŽä¸æ–·é»ž" +msgstr "é¡¯ç¤ºä¸æ–·é»žæ¬„" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Info Gutter" -msgstr "顯示資訊欄ä½" +msgstr "顯示資訊欄" #: editor/editor_settings.cpp msgid "Code Folding" msgstr "程å¼ç¢¼æŠ˜ç–Š" #: editor/editor_settings.cpp -#, fuzzy msgid "Word Wrap" -msgstr "æ›è¡Œ" +msgstr "自動æ›è¡Œ" #: editor/editor_settings.cpp msgid "Show Line Length Guidelines" msgstr "顯示行長度åƒè€ƒç·š" #: editor/editor_settings.cpp -#, fuzzy msgid "Line Length Guideline Soft Column" -msgstr "行長度åƒè€ƒç·šè»Ÿåˆ—" +msgstr "行長度åƒè€ƒç·šè»Ÿåˆ—數" #: editor/editor_settings.cpp -#, fuzzy msgid "Line Length Guideline Hard Column" -msgstr "行長度åƒè€ƒç·šç¡¬åˆ—" +msgstr "行長度åƒè€ƒç·šç¡¬åˆ—數" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script List" -msgstr "腳本編輯器" +msgstr "腳本列表" #: editor/editor_settings.cpp msgid "Show Members Overview" msgstr "顯示æˆå“¡æ¦‚è¦" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Files" msgstr "檔案" #: editor/editor_settings.cpp -#, fuzzy msgid "Trim Trailing Whitespace On Save" -msgstr "移除後方空白å—å…ƒ" +msgstr "ä¿å˜æ™‚移除後方空白å—å…ƒ" #: editor/editor_settings.cpp msgid "Autosave Interval Secs" -msgstr "自動ä¿å˜é–“隔秒數" +msgstr "自動儲å˜é–“隔秒數" #: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp msgid "Restore Scripts On Load" @@ -5675,11 +5472,11 @@ msgstr "載入時æ¢å¾©è…³æœ¬" #: editor/editor_settings.cpp msgid "Auto Reload And Parse Scripts On Save" -msgstr "" +msgstr "å„²å˜æ™‚è‡ªå‹•é‡æ–°è¼‰å…¥èˆ‡è§£æžè…³æœ¬" #: editor/editor_settings.cpp msgid "Auto Reload Scripts On External Change" -msgstr "" +msgstr "å¾žå¤–éƒ¨æ›´æ”¹æ™‚è‡ªå‹•é‡æ–°è¼‰å…¥è…³æœ¬" #: editor/editor_settings.cpp msgid "Create Signal Callbacks" @@ -5694,14 +5491,12 @@ msgid "Cursor" msgstr "游標" #: editor/editor_settings.cpp -#, fuzzy msgid "Scroll Past End Of File" -msgstr "æ»¾å‹•è¶…éŽæª”案çµå°¾" +msgstr "æ»¾å‹•è¶…éŽæª”案末尾" #: editor/editor_settings.cpp -#, fuzzy msgid "Block Caret" -msgstr "方形æ’入符" +msgstr "方形 Caret" #: editor/editor_settings.cpp msgid "Caret Blink" @@ -5712,14 +5507,12 @@ msgid "Caret Blink Speed" msgstr "æ’入符閃çˆé€Ÿåº¦" #: editor/editor_settings.cpp -#, fuzzy msgid "Right Click Moves Caret" -msgstr "å³éµé»žæ“Šä»¥æ–°å¢žæŽ§åˆ¶é»ž" +msgstr "按一下å³éµä¾†ç§»å‹•éŠæ¨™" #: editor/editor_settings.cpp modules/gdscript/gdscript.cpp #: modules/gdscript/gdscript_editor.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion" msgstr "自動完æˆ" @@ -5728,103 +5521,91 @@ msgid "Idle Parse Delay" msgstr "閒置解æžå»¶é²" #: editor/editor_settings.cpp -#, fuzzy msgid "Auto Brace Complete" msgstr "自動補齊括號" #: editor/editor_settings.cpp -#, fuzzy msgid "Code Complete Delay" -msgstr "程å¼ç¢¼å®Œæˆå»¶é²" +msgstr "程å¼ç¢¼è‡ªå‹•完æˆå»¶é²" #: editor/editor_settings.cpp msgid "Put Callhint Tooltip Below Current Line" -msgstr "" +msgstr "å°‡å‘¼å«æç¤ºå·¥å…·æç¤ºæ¡†ç½®æ–¼ç•¶å‰è¡Œä¹‹ä¸‹" #: editor/editor_settings.cpp msgid "Callhint Tooltip Offset" -msgstr "" +msgstr "å‘¼å«æç¤ºå·¥å…·æç¤ºæ¡†åç§»é‡" #: editor/editor_settings.cpp -#, fuzzy msgid "Complete File Paths" -msgstr "複製節點路徑" +msgstr "補全檔案路徑" #: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp -#, fuzzy msgid "Add Type Hints" -msgstr "新增類別" +msgstr "新增類別æç¤º" #: editor/editor_settings.cpp msgid "Use Single Quotes" msgstr "使用單引號" #: editor/editor_settings.cpp -#, fuzzy msgid "Show Help Index" -msgstr "顯示輔助資訊" +msgstr "顯示輔助索引" #: editor/editor_settings.cpp msgid "Help Font Size" -msgstr "" +msgstr "幫助å—體大å°" #: editor/editor_settings.cpp msgid "Help Source Font Size" -msgstr "" +msgstr "幫助æºå—體大å°" #: editor/editor_settings.cpp msgid "Help Title Font Size" -msgstr "" +msgstr "幫助標題å—體大å°" #: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp msgid "Grid Map" msgstr "ç¶²æ ¼åœ°åœ–" #: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Pick Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "拾å–è·é›¢" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Preview Size" -msgstr "é 覽" +msgstr "é 覽大å°" #: editor/editor_settings.cpp msgid "Primary Grid Color" -msgstr "" +msgstr "主è¦ç¶²æ ¼é¡è‰²" #: editor/editor_settings.cpp msgid "Secondary Grid Color" -msgstr "" +msgstr "次è¦ç¶²æ ¼é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Selection Box Color" -msgstr "僅æœå°‹æ‰€é¸å€åŸŸ" +msgstr "所é¸å€åŸŸé¡è‰²" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "3D Gizmos" -msgstr "Gizmo" +msgstr "3D æŽ§åˆ¶é …" #: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Gizmo Colors" -msgstr "發射色彩" +msgstr "æŽ§åˆ¶é …é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Instanced" -msgstr "實體" +msgstr "已實體化" #: editor/editor_settings.cpp modules/gltf/gltf_node.cpp #: scene/3d/physics_body.cpp -#, fuzzy msgid "Joint" -msgstr "點" +msgstr "交點" #: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp #: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp @@ -5833,347 +5614,301 @@ msgstr "點" #: scene/resources/particles_material.cpp servers/physics_2d_server.cpp #: servers/physics_server.cpp msgid "Shape" -msgstr "" +msgstr "形狀" #: editor/editor_settings.cpp -#, fuzzy msgid "Primary Grid Steps" -msgstr "ç¶²æ ¼å¤§å°ï¼š" +msgstr "ä¸»ç¶²æ ¼æ¥é•·" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid Size" -msgstr "ç¶²æ ¼å¤§å°ï¼š" +msgstr "ç¶²æ ¼å¤§å°" #: editor/editor_settings.cpp msgid "Grid Division Level Max" -msgstr "" +msgstr "ç¶²æ ¼åŠƒåˆ†ç´šåˆ¥æœ€å¤§å€¼" #: editor/editor_settings.cpp msgid "Grid Division Level Min" -msgstr "" +msgstr "ç¶²æ ¼åŠƒåˆ†ç´šåˆ¥æœ€å°å€¼" #: editor/editor_settings.cpp msgid "Grid Division Level Bias" -msgstr "" +msgstr "ç¶²æ ¼åŠƒåˆ†ç´šåˆ¥å差值" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XZ Plane" -msgstr "ç¶²æ ¼åœ°åœ–ç¹ªåœ–" +msgstr "ç¶²æ ¼XZå¹³é¢" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid XY Plane" -msgstr "ç¶²æ ¼åœ°åœ–ç¹ªåœ–" +msgstr "ç¶²æ ¼XYå¹³é¢" #: editor/editor_settings.cpp -#, fuzzy msgid "Grid YZ Plane" -msgstr "ç¶²æ ¼åœ°åœ–ç¹ªåœ–" +msgstr "ç¶²æ ¼YZå¹³é¢" #: editor/editor_settings.cpp -#, fuzzy msgid "Default FOV" -msgstr "é è¨" +msgstr "é è¨FOV" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Near" -msgstr "é è¨ä¸»é¡Œ" +msgstr "é è¨Z近處" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Z Far" -msgstr "é è¨" +msgstr "é è¨Zé 處" #: editor/editor_settings.cpp msgid "Lightmap Baking Number Of CPU Threads" -msgstr "" +msgstr "光照圖烘焙ä¸å¤®è™•ç†å™¨ç·šç¨‹æ•¸" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Scheme" -msgstr "導航模å¼" +msgstr "導引模å¼" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert Y Axis" -msgstr "編輯 Y 軸" +msgstr "翻轉 Y 軸" #: editor/editor_settings.cpp -#, fuzzy msgid "Invert X Axis" -msgstr "編輯 X 軸" +msgstr "翻轉 X 軸" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Style" -msgstr "縮å°" +msgstr "縮放樣å¼" #: editor/editor_settings.cpp msgid "Emulate Numpad" -msgstr "" +msgstr "模擬數å—éµç›¤" #: editor/editor_settings.cpp msgid "Emulate 3 Button Mouse" -msgstr "" +msgstr "æ¨¡æ“¬ä¸‰éµæ»‘é¼ " #: editor/editor_settings.cpp -#, fuzzy msgid "Orbit Modifier" -msgstr "按最早修改時間排åº" +msgstr "軌é“修改器" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Modifier" -msgstr "平移模å¼" +msgstr "平移修改器" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Modifier" -msgstr "已修改" +msgstr "縮放修改器" #: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Warped Mouse Panning" -msgstr "" +msgstr "å½Žæ›²æ»‘é¼ å¹³ç§»" #: editor/editor_settings.cpp -#, fuzzy msgid "Navigation Feel" -msgstr "導航模å¼" +msgstr "å°Žèˆªé¢¨æ ¼" #: editor/editor_settings.cpp msgid "Orbit Sensitivity" -msgstr "" +msgstr "軌é“éˆæ•度" #: editor/editor_settings.cpp msgid "Orbit Inertia" -msgstr "" +msgstr "è»Œé“æ…£æ€§" #: editor/editor_settings.cpp -#, fuzzy msgid "Translation Inertia" -msgstr "ç¿»è¯" +msgstr "平移慣性" #: editor/editor_settings.cpp -#, fuzzy msgid "Zoom Inertia" -msgstr "放大" +msgstr "變焦慣性" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook" -msgstr "自由視圖 上" +msgstr "自由觀看" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Navigation Scheme" -msgstr "å»ºç«‹å°Žèˆªç¶²æ ¼" +msgstr "自由觀看ç€è¦½æ¨¡å¼" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Sensitivity" -msgstr "自由視圖 å·¦" +msgstr "è‡ªç”±è§€çœ‹éˆæ•度" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Inertia" -msgstr "自由視圖 å·¦" +msgstr "自由觀看慣性" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Base Speed" -msgstr "åŠ é€Ÿè‡ªç”±è¦–åœ–é€Ÿåº¦" +msgstr "自由觀看基本速度" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Activation Modifier" -msgstr "放慢自由視圖速度" +msgstr "自由觀看啟動修飾符" #: editor/editor_settings.cpp -#, fuzzy msgid "Freelook Speed Zoom Link" -msgstr "åŠ é€Ÿè‡ªç”±è¦–åœ–é€Ÿåº¦" +msgstr "自由觀看速度縮放連çµ" #: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Grid Color" -msgstr "鏿“‡é¡è‰²" +msgstr "ç¶²æ ¼é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Guides Color" -msgstr "鏿“‡é¡è‰²" +msgstr "åƒè€ƒç·šé¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Smart Snapping Line Color" -msgstr "智慧型å¸é™„" +msgstr "æ™ºæ…§æ•æ‰ç·šé¡è‰²" #: editor/editor_settings.cpp msgid "Bone Width" -msgstr "" +msgstr "骨骼寬度" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 1" -msgstr "釿–°å‘½åé¡è‰²é …ç›®" +msgstr "骨骼é¡è‰²1" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Color 2" -msgstr "釿–°å‘½åé¡è‰²é …ç›®" +msgstr "骨骼é¡è‰²2" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Selected Color" -msgstr "è¨å®šæ‰€é¸ä¹‹è¨å®šæª”:" +msgstr "所é¸ä¹‹éª¨éª¼é¡è‰²" #: editor/editor_settings.cpp msgid "Bone IK Color" -msgstr "" +msgstr "骨骼IKé¡è‰²" #: editor/editor_settings.cpp msgid "Bone Outline Color" -msgstr "" +msgstr "骨骼輪廓é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Bone Outline Size" -msgstr "輪廓尺寸:" +msgstr "骨骼輪廓大å°" #: editor/editor_settings.cpp msgid "Viewport Border Color" -msgstr "" +msgstr "檢視å€é‚Šæ¡†é¡è‰²" #: editor/editor_settings.cpp msgid "Constrain Editor View" -msgstr "" +msgstr "é™åˆ¶ç·¨è¼¯å™¨è¦–圖" #: editor/editor_settings.cpp msgid "Simple Panning" -msgstr "" +msgstr "簡易平移" #: editor/editor_settings.cpp msgid "Scroll To Pan" -msgstr "" +msgstr "滾動以平移" #: editor/editor_settings.cpp -#, fuzzy msgid "Pan Speed" -msgstr "速度:" +msgstr "平移速度" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Poly Editor" -msgstr "Polygon2D UV 編輯器" +msgstr "多邊形編輯器" #: editor/editor_settings.cpp msgid "Point Grab Radius" -msgstr "" +msgstr "點抓å–åŠå¾‘" #: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Show Previous Outline" -msgstr "上一個平é¢" +msgstr "顯示上一個大綱" #: editor/editor_settings.cpp editor/scene_tree_dock.cpp -#, fuzzy msgid "Autorename Animation Tracks" -msgstr "釿–°å‘½åå‹•ç•«" +msgstr "è‡ªå‹•é‡æ–°å‘½å動畫軌é“" #: editor/editor_settings.cpp msgid "Default Create Bezier Tracks" -msgstr "" +msgstr "é è¨å»ºç«‹è²èŒ²è»Œé“" #: editor/editor_settings.cpp -#, fuzzy msgid "Default Create Reset Tracks" -msgstr "貼上關éµç•«æ ¼" +msgstr "é è¨å»ºç«‹é‡ç½®è»Œé“" #: editor/editor_settings.cpp msgid "Onion Layers Past Color" -msgstr "" +msgstr "洋蔥層先å‰é¡è‰²" #: editor/editor_settings.cpp msgid "Onion Layers Future Color" -msgstr "" +msgstr "洋蔥層未來é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Visual Editors" -msgstr "群組編輯器" +msgstr "視覺化編輯器" #: editor/editor_settings.cpp msgid "Minimap Opacity" -msgstr "" +msgstr "è¿·ä½ åœ°åœ–ä¸é€æ˜Žåº¦" #: editor/editor_settings.cpp msgid "Window Placement" -msgstr "" +msgstr "視窗擺放" #: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp #: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp #: scene/gui/control.cpp -#, fuzzy msgid "Rect" -msgstr "全矩形" +msgstr "矩形" #: editor/editor_settings.cpp -#, fuzzy msgid "Rect Custom Position" -msgstr "è¨å®šæ›²ç·šå¤–控制點ä½ç½®" +msgstr "矩形自定義ä½ç½®" #: editor/editor_settings.cpp platform/android/export/export_plugin.cpp msgid "Screen" -msgstr "" +msgstr "螢幕" #: editor/editor_settings.cpp -#, fuzzy msgid "Auto Save" -msgstr "自動剪è£" +msgstr "自動ä¿å˜" #: editor/editor_settings.cpp -#, fuzzy msgid "Save Before Running" -msgstr "執行å‰å…ˆä¿å˜å ´æ™¯..." +msgstr "執行å‰å„²å˜" #: editor/editor_settings.cpp -#, fuzzy msgid "Font Size" -msgstr "å‰è¦–圖" +msgstr "å—體大å°" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Remote Host" -msgstr "é 端 " +msgstr "é 端主機" #: editor/editor_settings.cpp #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Remote Port" -msgstr "移除控制點" +msgstr "é 端阜" #: editor/editor_settings.cpp -#, fuzzy msgid "Editor SSL Certificates" -msgstr "編輯器è¨å®š" +msgstr "編輯SSLèªè‰" #: editor/editor_settings.cpp msgid "HTTP Proxy" -msgstr "" +msgstr "HTTP 代ç†ç¨‹å¼" #: editor/editor_settings.cpp msgid "Host" -msgstr "" +msgstr "主機" #: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Port" -msgstr "" +msgstr "é€£æŽ¥åŸ " #. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects. #: editor/editor_settings.cpp @@ -6182,185 +5917,162 @@ msgstr "專案管ç†å“¡" #. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects. #: editor/editor_settings.cpp -#, fuzzy msgid "Sorting Order" -msgstr "釿–°å‘½å資料夾:" +msgstr "æŽ’åºæ–¹å¼" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Symbol Color" -msgstr "" +msgstr "符號é¡è‰²" #: editor/editor_settings.cpp msgid "Keyword Color" -msgstr "" +msgstr "é—œéµå—é¡è‰²" #: editor/editor_settings.cpp msgid "Control Flow Keyword Color" -msgstr "" +msgstr "控制æµé—œéµå—é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Base Type Color" -msgstr "更改基礎型別" +msgstr "基礎型別é¡è‰²" #: editor/editor_settings.cpp msgid "Engine Type Color" -msgstr "" +msgstr "引擎類別é¡è‰²" #: editor/editor_settings.cpp msgid "User Type Color" -msgstr "" +msgstr "使用者類別é¡è‰²" #: editor/editor_settings.cpp msgid "Comment Color" -msgstr "" +msgstr "註解é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "String Color" -msgstr "å„²å˜æª”案:" +msgstr "å—串é¡è‰²" #: editor/editor_settings.cpp platform/javascript/export/export.cpp #: platform/uwp/export/export.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Background Color" -msgstr "無效的背景é¡è‰²ã€‚" +msgstr "背景é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Background Color" -msgstr "無效的背景é¡è‰²ã€‚" +msgstr "自動補全背景é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Completion Selected Color" -msgstr "匯入所é¸" +msgstr "自動補全所é¸é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Existing Color" -msgstr "" +msgstr "è‡ªå‹•è£œå…¨ç¾æœ‰é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Scroll Color" -msgstr "" +msgstr "自動補全æ²è»¸é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Completion Font Color" -msgstr "" +msgstr "自動補全å—åž‹é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Text Color" -msgstr "下一個地æ¿" +msgstr "æ–‡å—é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Line Number Color" -msgstr "行號:" +msgstr "行號é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Safe Line Number Color" -msgstr "行號:" +msgstr "安全行號é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Caret Color" -msgstr "" +msgstr "跳脫å—å…ƒé¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Caret Background Color" -msgstr "無效的背景é¡è‰²ã€‚" +msgstr "跳脫å—元背景é¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Text Selected Color" -msgstr "刪除所é¸" +msgstr "æ‰€é¸æ–‡å—é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Selection Color" -msgstr "僅æœå°‹æ‰€é¸å€åŸŸ" +msgstr "所é¸é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Brace Mismatch Color" -msgstr "" +msgstr "大括號ä¸å°ç¨±é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Current Line Color" -msgstr "ç›®å‰å ´æ™¯" +msgstr "ç›®å‰è¡Œé¡è‰²" #: editor/editor_settings.cpp msgid "Line Length Guideline Color" -msgstr "" +msgstr "線長導引é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Word Highlighted Color" -msgstr "高亮顯示語法" +msgstr "å–®å—醒目顯示é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Number Color" -msgstr "" +msgstr "數å—é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Function Color" -msgstr "函å¼" +msgstr "函å¼é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Member Variable Color" -msgstr "釿–°å‘½å變數" +msgstr "æˆå“¡è®Šæ•¸é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Mark Color" -msgstr "鏿“‡é¡è‰²" +msgstr "標記é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Bookmark Color" -msgstr "書籤" +msgstr "書籤é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Breakpoint Color" -msgstr "䏿–·é»ž" +msgstr "䏿–·é»žé¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Executing Line Color" -msgstr "" +msgstr "執行列é¡è‰²" #: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp msgid "Code Folding Color" -msgstr "" +msgstr "程å¼ç¢¼æ‘ºç–Šé¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Color" -msgstr "æœå°‹çµæžœ" +msgstr "æœå°‹çµæžœé¡è‰²" #: editor/editor_settings.cpp -#, fuzzy msgid "Search Result Border Color" -msgstr "æœå°‹çµæžœ" +msgstr "æœå°‹çµæžœé‚Šç•Œé¡è‰²" #: editor/editor_spin_slider.cpp msgid "Hold %s to round to integers. Hold Shift for more precise changes." msgstr "æŒ‰ä½ %s 以喿•´æ•¸ã€‚æŒ‰ä½ Shift 以進行更精確的更動。" #: editor/editor_spin_slider.cpp scene/gui/button.cpp -#, fuzzy msgid "Flat" -msgstr "å¹³é¢0" +msgstr "å¹³é¢" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hide Slider" -msgstr "碰撞模å¼" +msgstr "éš±è—æ‹–曳æ¢" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -6380,9 +6092,8 @@ msgstr "自節點ä¸åŒ¯å…¥ï¼š" #. TRANSLATORS: %s refers to the name of a version control system (e.g. "Git"). #: editor/editor_vcs_interface.cpp -#, fuzzy msgid "%s Error" -msgstr "錯誤" +msgstr "%s 錯誤" #: editor/export_template_manager.cpp msgid "Open the folder containing these templates." @@ -6646,13 +6357,13 @@ msgstr "" #: editor/fileserver/editor_file_server.cpp msgid "File Server" -msgstr "" +msgstr "檔案伺æœå™¨" #: editor/fileserver/editor_file_server.cpp #: editor/plugins/version_control_editor_plugin.cpp #: platform/uwp/export/export.cpp platform/windows/export/export.cpp msgid "Password" -msgstr "" +msgstr "密碼" #: editor/filesystem_dock.cpp msgid "Favorites" @@ -6710,6 +6421,9 @@ msgid "" "After renaming to an unknown extension, the file won't be shown in the " "editor anymore." msgstr "" +"編輯器無法辨è˜è©²æª”案副檔å。\n" +"å¦‚æžœä½ ä»è¦é‡æ–°å‘½å,請使用系統的檔案管ç†å“¡ã€‚\n" +"釿–°å‘½å為未知副檔åå¾Œï¼Œè©²æª”æ¡ˆä¸æœƒåœ¨ç·¨è¼¯å™¨ä¸é¡¯ç¤ºã€‚" #: editor/filesystem_dock.cpp msgid "" @@ -6929,14 +6643,12 @@ msgid "Replace..." msgstr "å–代..." #: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Replace in Files" -msgstr "å–代全部" +msgstr "在檔案ä¸å–代" #: editor/find_in_files.cpp -#, fuzzy msgid "Replace All (NO UNDO)" -msgstr "å–代全部" +msgstr "å–代全部(ä¸å¯å¾©åŽŸï¼‰" #: editor/find_in_files.cpp msgid "Searching..." @@ -7009,43 +6721,40 @@ msgstr "管ç†ç¾¤çµ„" #: editor/import/editor_import_collada.cpp msgid "Collada" -msgstr "" +msgstr "Collada" #: editor/import/editor_import_collada.cpp msgid "Use Ambient" -msgstr "" +msgstr "使用環境通é“" #: editor/import/resource_importer_bitmask.cpp -#, fuzzy msgid "Create From" -msgstr "建立資料夾" +msgstr "建立自" #: editor/import/resource_importer_bitmask.cpp #: servers/audio/effects/audio_effect_compressor.cpp msgid "Threshold" -msgstr "" +msgstr "臨界值" #: editor/import/resource_importer_csv_translation.cpp #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_scene.cpp #: editor/import/resource_importer_texture.cpp #: editor/import/resource_importer_wav.cpp scene/3d/gi_probe.cpp -#, fuzzy msgid "Compress" -msgstr "元件" +msgstr "壓縮" #: editor/import/resource_importer_csv_translation.cpp msgid "Delimiter" -msgstr "" +msgstr "分隔符號" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "ColorCorrect" -msgstr "é¡è‰²å‡½å¼ã€‚" +msgstr "é¡è‰²æ ¡æ£" #: editor/import/resource_importer_layered_texture.cpp msgid "No BPTC If RGB" -msgstr "" +msgstr "å‡è¨æ˜¯RGBä¸ä½¿ç”¨BPTC" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp @@ -7053,83 +6762,73 @@ msgstr "" #: scene/resources/material.cpp scene/resources/particles_material.cpp #: scene/resources/texture.cpp scene/resources/visual_shader.cpp msgid "Flags" -msgstr "" +msgstr "旗標" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp #: scene/resources/texture.cpp msgid "Repeat" -msgstr "" +msgstr "é‡è¦†" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp #: scene/gui/control.cpp -#, fuzzy msgid "Filter" -msgstr "篩é¸ï¼š" +msgstr "篩é¸" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Mipmaps" -msgstr "訊號" +msgstr "Mipmap" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "Anisotropic" -msgstr "" +msgstr "ç•°å‘æ€§" #: editor/import/resource_importer_layered_texture.cpp #: editor/import/resource_importer_texture.cpp msgid "sRGB" -msgstr "" +msgstr "sRGB" #: editor/import/resource_importer_layered_texture.cpp -#, fuzzy msgid "Slices" -msgstr "自動剪è£" +msgstr "切片" #: editor/import/resource_importer_layered_texture.cpp #: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp #: scene/gui/nine_patch_rect.cpp scene/gui/scroll_container.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Horizontal" -msgstr "水平:" +msgstr "æ°´å¹³" #: editor/import/resource_importer_layered_texture.cpp #: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp #: scene/gui/nine_patch_rect.cpp scene/gui/scroll_container.cpp #: scene/resources/style_box.cpp -#, fuzzy msgid "Vertical" -msgstr "垂直:" +msgstr "垂直" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Generate Tangents" -msgstr "產生點" +msgstr "產生切線" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Scale Mesh" -msgstr "縮放模å¼" +msgstr "ç¸®æ”¾ç¶²æ ¼" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Offset Mesh" -msgstr "å移:" +msgstr "Mesh åç§»" #: editor/import/resource_importer_obj.cpp #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Octahedral Compression" -msgstr "è¨å®šè¡¨ç¤ºå¼" +msgstr "å…«é¢é«”壓縮" #: editor/import/resource_importer_obj.cpp -#, fuzzy msgid "Optimize Mesh Flags" -msgstr "大å°ï¼š " +msgstr "優化 Mesh 標誌" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" @@ -7173,101 +6872,84 @@ msgstr "åŒ¯å…¥ç‚ºå¤šå€‹å ´æ™¯ + ç´ æ" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Nodes" msgstr "節點" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Type" -msgstr "æˆå“¡åž‹åˆ¥" +msgstr "æ ¹åž‹åˆ¥" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Name" -msgstr "é 端 " +msgstr "æ ¹å稱" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Root Scale" -msgstr "縮放" +msgstr "æ ¹ç¸®æ”¾" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Custom Script" -msgstr "剪下節點" +msgstr "自訂腳本" #: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp -#, fuzzy msgid "Storage" -msgstr "å„²å˜æª”案:" +msgstr "儲å˜" #: editor/import/resource_importer_scene.cpp msgid "Use Legacy Names" -msgstr "" +msgstr "使用既有å稱" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp -#, fuzzy msgid "Materials" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "æè³ª" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep On Reimport" -msgstr "釿–°åŒ¯å…¥" +msgstr "ä¿æŒæˆ–釿–°åŒ¯å…¥" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp -#, fuzzy msgid "Meshes" msgstr "ç¶²æ ¼" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Ensure Tangents" -msgstr "修改曲線切線" +msgstr "確ä¿åˆ‡ç·š" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Light Baking" -msgstr "烘焙光照圖" +msgstr "光照烘焙" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Lightmap Texel Size" -msgstr "烘焙光照圖" +msgstr "光照圖紋ç†å…ƒç´ 大å°" #: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp msgid "Skins" -msgstr "" +msgstr "Skin" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Use Named Skins" -msgstr "使用縮放å¸é™„" +msgstr "使用命å Skin" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "External Files" -msgstr "開啟檔案" +msgstr "é¡å¤–檔案" #: editor/import/resource_importer_scene.cpp msgid "Store In Subdir" -msgstr "" +msgstr "å„²å˜æ–¼å目錄" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Filter Script" msgstr "篩é¸è…³æœ¬" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Keep Custom Tracks" -msgstr "變æ›" +msgstr "ä¿ç•™è‡ªå®šè»Œé“" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Optimizer" -msgstr "最佳化" +msgstr "最佳化器" #: editor/import/resource_importer_scene.cpp #: editor/plugins/item_list_editor_plugin.cpp main/main.cpp @@ -7281,41 +6963,34 @@ msgstr "最佳化" #: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp #: scene/gui/rich_text_label.cpp scene/resources/curve.cpp #: scene/resources/environment.cpp scene/resources/material.cpp -#, fuzzy msgid "Enabled" -msgstr "啟用" +msgstr "已啟用" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Linear Error" -msgstr "最大線性誤差:" +msgstr "最大線性誤差" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Angular Error" -msgstr "最大角度誤差:" +msgstr "最大角度誤差" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Max Angle" -msgstr "數值" +msgstr "最大角度" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Remove Unused Tracks" -msgstr "刪除動畫軌" +msgstr "移除未使用的動畫軌" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Clips" msgstr "動畫片段" #: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp #: scene/3d/particles.cpp scene/resources/environment.cpp -#, fuzzy msgid "Amount" -msgstr "數é‡ï¼š" +msgstr "數é‡" #: editor/import/resource_importer_scene.cpp #: editor/plugins/mesh_library_editor_plugin.cpp @@ -7331,9 +7006,8 @@ msgid "Generating Lightmaps" msgstr "æ£åœ¨ç”¢ç”Ÿå…‰ç…§åœ–" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Generating for Mesh:" -msgstr "æ£åœ¨ç”¢ç”Ÿç¶²æ ¼ï¼š " +msgstr "ç”Ÿæˆ Mesh ä¸ï¼š" #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." @@ -7364,159 +7038,144 @@ msgid "" "%s: Texture detected as used as a normal map in 3D. Enabling red-green " "texture compression to reduce memory usage (blue channel is discarded)." msgstr "" +"%s: 嵿¸¬åˆ°ä½¿ç”¨åœ¨3D上的法線貼圖。啟用紅-ç¶ æè³ªå£“縮來減少記憶體用é‡(è—色通é“å·²" +"è¢«æ¨æ£„)。" #: editor/import/resource_importer_texture.cpp msgid "" "%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap " "generation and VRAM texture compression." -msgstr "" +msgstr "%s: 嵿¸¬åˆ°ä½¿ç”¨åœ¨3D上的æè³ªã€‚啟用濾é¡ã€é‡è¦†ã€Mipmap產生和VRAMæè³ªå£“縮。" #: editor/import/resource_importer_texture.cpp msgid "2D, Detect 3D" -msgstr "" +msgstr "2Dï¼Œåµæ¸¬3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "2D Pixel" -msgstr "實體åƒç´ " +msgstr "2Dåƒç´ " #: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp msgid "Lossy Quality" -msgstr "" +msgstr "低å“質" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "HDR Mode" -msgstr "鏿“‡æ¨¡å¼" +msgstr "HDR模å¼" #: editor/import/resource_importer_texture.cpp msgid "BPTC LDR" -msgstr "" +msgstr "BPTC LDR" #: editor/import/resource_importer_texture.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp #: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp msgid "Normal Map" -msgstr "" +msgstr "法線貼圖" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Process" -msgstr "後處ç†" +msgstr "處ç†" #: editor/import/resource_importer_texture.cpp msgid "Fix Alpha Border" -msgstr "" +msgstr "ä¿®æ£Alpha邊界" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Premult Alpha" -msgstr "編輯多邊形" +msgstr "é 乘 Alpha" #: editor/import/resource_importer_texture.cpp msgid "Hdr As Srgb" -msgstr "" +msgstr "Hdr作為SRGB" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Invert Color" -msgstr "é ‚é»ž" +msgstr "翻轉é¡è‰²" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Normal Map Invert Y" -msgstr "隨機縮放:" +msgstr "法線貼圖å轉 Y" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "Size Limit" -msgstr "大å°ï¼š " +msgstr "大å°é™åˆ¶" #: editor/import/resource_importer_texture.cpp msgid "Detect 3D" -msgstr "" +msgstr "嵿¸¬3D" #: editor/import/resource_importer_texture.cpp -#, fuzzy msgid "SVG" -msgstr "HSV" +msgstr "SVG" #: editor/import/resource_importer_texture.cpp msgid "" "Warning, no suitable PC VRAM compression enabled in Project Settings. This " "texture will not display correctly on PC." msgstr "" +"注æ„,專案è¨å®šå…§å•Ÿç”¨äº†éžé©åˆçš„PC VRAMå£“ç¸®ã€‚æ¤æè³ªå°‡ç„¡æ³•åœ¨PC上æ£ç¢ºé¡¯ç¤ºã€‚" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Atlas File" -msgstr "輪廓尺寸:" +msgstr "åˆé›†æª”案" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Import Mode" -msgstr "匯出模å¼ï¼š" +msgstr "匯入模å¼" #: editor/import/resource_importer_texture_atlas.cpp -#, fuzzy msgid "Crop To Region" -msgstr "鏿“‡åœ–塊å€åŸŸ" +msgstr "è£å‰ªè‡³å€åŸŸ" #: editor/import/resource_importer_texture_atlas.cpp msgid "Trim Alpha Border From Region" -msgstr "" +msgstr "從å€åŸŸç°¡åŒ–Alpha邊界" #: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Force" -msgstr "來æºç¶²æ ¼ï¼š" +msgstr "強制" #: editor/import/resource_importer_wav.cpp msgid "8 Bit" -msgstr "" +msgstr "8ä½å…ƒçµ„" #: editor/import/resource_importer_wav.cpp main/main.cpp #: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp msgid "Mono" -msgstr "" +msgstr "Mono" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate" -msgstr "Mix 節點" +msgstr "æœ€å¤§é »çŽ‡" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Max Rate Hz" -msgstr "Mix 節點" +msgstr "æœ€å¤§é »çŽ‡Hz" #: editor/import/resource_importer_wav.cpp msgid "Trim" -msgstr "" +msgstr "簡化" #: editor/import/resource_importer_wav.cpp -#, fuzzy msgid "Normalize" -msgstr "æ ¼å¼" +msgstr "æ£è¦åŒ–" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Mode" -msgstr "移動模å¼" +msgstr "é‡è¦†æ¨¡å¼" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop Begin" -msgstr "移動模å¼" +msgstr "é–‹å§‹é‡è¦†" #: editor/import/resource_importer_wav.cpp #: scene/resources/audio_stream_sample.cpp -#, fuzzy msgid "Loop End" -msgstr "移動模å¼" +msgstr "çµæŸé‡è¦†" #: editor/import_defaults_editor.cpp msgid "Select Importer" @@ -7567,7 +7226,7 @@ msgstr "匯入為:" #: editor/import_dock.cpp msgid "Save Scenes, Re-Import, and Restart" -msgstr "ä¿å˜å ´æ™¯ã€é‡æ–°åŒ¯å…¥ã€ä¸¦é‡æ–°å•Ÿå‹•" +msgstr "儲å˜å ´æ™¯ã€é‡æ–°åŒ¯å…¥ã€ä¸¦é‡æ–°å•Ÿå‹•" #: editor/import_dock.cpp msgid "Changing the type of an imported file requires editor restart." @@ -7582,34 +7241,31 @@ msgstr "è¦å‘Šï¼šæœ‰ç´ æä½¿ç”¨è©²è³‡æºï¼Œå°‡ç„¡æ³•æ£ç¢ºåŠ è¼‰ã€‚" msgid "" "Select a resource file in the filesystem or in the inspector to adjust " "import settings." -msgstr "" +msgstr "從檔案系統ä¸é¸æ“‡è³‡æºæª”ï¼Œæˆ–æ˜¯åœ¨é¢æ¿ä¸Šèª¿æ•´åŒ¯å…¥è¨å®šã€‚" #: editor/inspector_dock.cpp msgid "Failed to load resource." msgstr "åŠ è¼‰è³‡æºå¤±æ•—。" #: editor/inspector_dock.cpp -#, fuzzy msgid "Property Name Style" -msgstr "專案å稱:" +msgstr "屬性å稱樣å¼" #: editor/inspector_dock.cpp scene/gui/color_picker.cpp msgid "Raw" msgstr "原始" #: editor/inspector_dock.cpp -#, fuzzy msgid "Capitalized" msgstr "首嗿¯å¤§å¯«" #: editor/inspector_dock.cpp -#, fuzzy msgid "Localized" -msgstr "地å€" +msgstr "已本地化" #: editor/inspector_dock.cpp msgid "Localization not available for current language." -msgstr "" +msgstr "ç›®å‰çš„èªžè¨€ä¸æ”¯æ´æœ¬åœ°åŒ–。" #: editor/inspector_dock.cpp msgid "Copy Properties" @@ -7633,7 +7289,7 @@ msgstr "從ç£ç¢Ÿä¸è¼‰å…¥ç¾æœ‰çš„資æºä¸¦ç·¨è¼¯ã€‚" #: editor/inspector_dock.cpp msgid "Save the currently edited resource." -msgstr "ä¿å˜ç›®å‰ç·¨è¼¯çš„資æºã€‚" +msgstr "儲å˜ç›®å‰ç·¨è¼¯çš„資æºã€‚" #: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp @@ -8146,9 +7802,8 @@ msgid "New" msgstr "新增" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Paste As Reference" -msgstr "%s 類別åƒç…§" +msgstr "複製為åƒç…§" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -8337,9 +7992,8 @@ msgid "Set the end animation. This is useful for sub-transitions." msgstr "è¨å®šçµå°¾å‹•畫。é©ç”¨æ–¼åè½‰å ´ã€‚" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition:" -msgstr "è½‰å ´ï¼š " +msgstr "è½‰å ´æ•ˆæžœï¼š" #: editor/plugins/animation_state_machine_editor.cpp msgid "Play Mode:" @@ -8476,7 +8130,7 @@ msgstr "篩é¸..." #: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp msgid "Use Threads" -msgstr "" +msgstr "使用執行緒" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Contents:" @@ -8524,7 +8178,7 @@ msgstr "è¦æ±‚失敗,回傳代碼:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Cannot save response to:" -msgstr "無法ä¿å˜å›žè¦†è‡³ï¼š" +msgstr "無法儲å˜å›žè¦†è‡³ï¼š" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Write error." @@ -8603,9 +8257,8 @@ msgid "Download Error" msgstr "下載錯誤" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Available URLs" -msgstr "å¯ç”¨è¨å®šæª”:" +msgstr "å¯ç”¨ URL" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" @@ -8640,28 +8293,24 @@ msgid "Loading..." msgstr "æ£åœ¨è¼‰å…¥..." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "First" -msgstr "首é " +msgstr "第一個" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Previous" -msgstr "上一é " +msgstr "上一個" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Next" -msgstr "下一é " +msgstr "下一個" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgctxt "Pagination" msgid "Last" -msgstr "最後" +msgstr "最後一個" #: editor/plugins/asset_library_editor_plugin.cpp msgid "All" @@ -8709,7 +8358,7 @@ msgstr "測試" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed to get repository configuration." -msgstr "" +msgstr "無法å–得倉儲è¨å®šã€‚" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" @@ -8724,8 +8373,8 @@ msgid "" "Can't determine a save path for lightmap images.\n" "Save your scene and try again." msgstr "" -"無法判斷光照圖的ä¿å˜è·¯å¾‘。\n" -"è«‹ä¿å˜å ´æ™¯ä¸¦é‡è©¦ã€‚" +"無法判斷光照圖的儲å˜è·¯å¾‘。\n" +"請儲å˜å ´æ™¯ä¸¦é‡è©¦ã€‚" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -8760,7 +8409,7 @@ msgstr "烘焙光照圖" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "LightMap Bake" -msgstr "" +msgstr "光照貼圖烘培" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Select lightmap bake file:" @@ -9069,9 +8718,8 @@ msgid "Alt+Drag: Move selected node." msgstr "Alt+拖移:移動所é¸çš„節點。" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Alt+Drag: Scale selected node." -msgstr "Alt+拖移:移動所é¸çš„節點。" +msgstr "Alt+拖曳:縮放所é¸çš„節點。" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "V: Set selected node's pivot position." @@ -9103,7 +8751,7 @@ msgstr "縮放模å¼" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Shift: Scale proportionally." -msgstr "" +msgstr "Shift:按比例縮放。" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -9202,9 +8850,8 @@ msgstr "在其ä½ç½®ä¸ŠéŽ–å®šæ‰€é¸ç‰©ä»¶ï¼ˆç„¡æ³•移動)。" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Lock Selected Node(s)" -msgstr "鎖定所é¸" +msgstr "鎖定所é¸çš„節點" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -9213,9 +8860,8 @@ msgstr "解鎖所é¸ç‰©ä»¶ï¼ˆå¯ç§»å‹•)。" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Unlock Selected Node(s)" -msgstr "å–æ¶ˆéŽ–å®šæ‰€é¸" +msgstr "å–æ¶ˆéŽ–å®šæ‰€é¸çš„節點" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -9224,9 +8870,8 @@ msgstr "確ä¿ç‰©ä»¶çš„åç´šé …ç›®ç„¡æ³•è¢«é¸æ“‡ã€‚" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Group Selected Node(s)" -msgstr "為所é¸çš„é …ç›®å»ºç«‹ç¾¤çµ„" +msgstr "為所é¸çš„節點建立群組" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -9235,9 +8880,8 @@ msgstr "æ¢å¾©è®“物件的åç´šé …ç›®å¯é¸æ“‡ã€‚" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Ungroup Selected Node(s)" -msgstr "移除所é¸é …目的群組" +msgstr "å–æ¶ˆæ‰€é¸ç¯€é»žçš„群組" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Skeleton Options" @@ -9262,23 +8906,20 @@ msgid "View" msgstr "檢視" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show" -msgstr "é¡¯ç¤ºç¶²æ ¼" +msgstr "顯示" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show When Snapping" -msgstr "智慧型å¸é™„" +msgstr "ç•¶å¸é™„時顯示" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Hide" -msgstr "" +msgstr "éš±è—" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid" -msgstr "åˆ‡æ›æ¨¡å¼" +msgstr "切æ›ç¶²æ ¼" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -9556,7 +9197,7 @@ msgstr "å¹³é¢0" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat 1" -msgstr "" +msgstr "å¹³é¢ 1" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease In" @@ -9628,16 +9269,15 @@ msgstr "漸層編輯" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap GradientTexture2D Fill Points" -msgstr "" +msgstr "äº¤æ› GradientTexture2D 的填充點" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp msgid "Swap Gradient Fill Points" -msgstr "" +msgstr "äº¤æ› Gradient 填充點" #: editor/plugins/gradient_texture_2d_editor_plugin.cpp -#, fuzzy msgid "Toggle Grid Snap" -msgstr "åˆ‡æ›æ¨¡å¼" +msgstr "切æ›ç¶²æ ¼å¸é™„" #: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp #: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp @@ -9656,13 +9296,12 @@ msgstr "圖示" #: editor/plugins/item_list_editor_plugin.cpp msgid "ID" -msgstr "" +msgstr "ID" #: editor/plugins/item_list_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separator" -msgstr "分隔:" +msgstr "分隔線" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" @@ -9891,9 +9530,8 @@ msgstr "" "%s" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "MeshLibrary" -msgstr "ç¶²æ ¼åº«" +msgstr "ç¶²æ ¼è³‡æºåº«" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Add Item" @@ -9916,14 +9554,12 @@ msgid "Update from Scene" msgstr "è‡ªå ´æ™¯æ›´æ–°" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply without Transforms" -msgstr "套用MeshInstance變æ›" +msgstr "ä¸åŒ…å«è®Šæ›çš„套用" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Apply with Transforms" -msgstr "套用MeshInstance變æ›" +msgstr "包å«è®Šæ›çš„套用" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." @@ -10089,9 +9725,8 @@ msgid "Volume" msgstr "é«”ç©" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Emission Source:" -msgstr "發射æºï¼š " +msgstr "發射æºï¼š" #: editor/plugins/particles_editor_plugin.cpp msgid "A processor material of type 'ParticlesMaterial' is required." @@ -10443,7 +10078,7 @@ msgstr "åŒæ¥éª¨éª¼åˆ°å¤šé‚Šå½¢" #: editor/plugins/ray_cast_2d_editor_plugin.cpp msgid "Set cast_to" -msgstr "" +msgstr "è¨å®š cast_to" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" @@ -10522,7 +10157,7 @@ msgstr "清除最近的檔案" #: editor/plugins/script_editor_plugin.cpp msgid "Close and save changes?" -msgstr "關閉並ä¿å˜ä¿®æ”¹å—Žï¼Ÿ" +msgstr "關閉並儲å˜ä¿®æ”¹å—Žï¼Ÿ" #: editor/plugins/script_editor_plugin.cpp msgid "Error writing TextFile:" @@ -10595,7 +10230,7 @@ msgstr "ä¿å˜éŒ¯èª¤" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As..." -msgstr "ä¿å˜ä¸»é¡Œç‚º..." +msgstr "儲å˜ä¸»é¡Œç‚º..." #: editor/plugins/script_editor_plugin.cpp msgid "%s Class Reference" @@ -10662,7 +10297,7 @@ msgstr "釿–°æ‰“開關閉的腳本" #: editor/plugins/script_editor_plugin.cpp msgid "Save All" -msgstr "全部ä¿å˜" +msgstr "全部儲å˜" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" @@ -10690,7 +10325,7 @@ msgstr "釿–°è¼‰å…¥ä¸»é¡Œ" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" -msgstr "ä¿å˜ä¸»é¡Œ" +msgstr "儲å˜ä¸»é¡Œ" #: editor/plugins/script_editor_plugin.cpp msgid "Close All" @@ -10772,58 +10407,51 @@ msgstr "æœå°‹çµæžœ" #: editor/plugins/script_editor_plugin.cpp msgid "Open Dominant Script On Scene Change" -msgstr "" +msgstr "å ´æ™¯æ›´æ”¹æ™‚é–‹å•Ÿä¸»è…³æœ¬" #: editor/plugins/script_editor_plugin.cpp msgid "External" -msgstr "" +msgstr "é¡å¤–çš„" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Use External Editor" -msgstr "使用外部編輯器進行除錯" +msgstr "使用外部編輯器" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Exec Path" -msgstr "匯出路徑" +msgstr "執行路徑" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Script Temperature Enabled" -msgstr "鏿“‡æ¨£æ¿æª”案" +msgstr "啟用腳本樣å¼" #: editor/plugins/script_editor_plugin.cpp msgid "Highlight Current Script" -msgstr "" +msgstr "強調顯示目å‰çš„腳本" #: editor/plugins/script_editor_plugin.cpp msgid "Script Temperature History Size" -msgstr "" +msgstr "腳本溫度æ·å²å¤§å°" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Current Script Background Color" -msgstr "無效的背景é¡è‰²ã€‚" +msgstr "ç›®å‰è…³æœ¬èƒŒæ™¯é¡è‰²" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Group Help Pages" -msgstr "為所é¸çš„é …ç›®å»ºç«‹ç¾¤çµ„" +msgstr "幫助é 分組" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Sort Scripts By" -msgstr "建立腳本" +msgstr "排åºè…³æœ¬æ ¹æ“š" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "List Script Names As" -msgstr "腳本å稱:" +msgstr "將腳本å稱列為" #: editor/plugins/script_editor_plugin.cpp msgid "Exec Flags" -msgstr "" +msgstr "執行旗標" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Scripts" @@ -10976,9 +10604,8 @@ msgid "Find in Files..." msgstr "åœ¨æª”æ¡ˆä¸æœå°‹..." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Replace in Files..." -msgstr "å–代..." +msgstr "在檔案ä¸å–代..." #: editor/plugins/script_text_editor.cpp msgid "Contextual Help" @@ -11182,15 +10809,13 @@ msgstr "移動" #. TRANSLATORS: Refers to changing the scale of a node in the 3D editor. #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Scaling:" -msgstr "縮放: " +msgstr "縮放:" #. TRANSLATORS: Refers to changing the position of a node in the 3D editor. #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Translating:" -msgstr "移動: " +msgstr "移動:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." @@ -11238,7 +10863,7 @@ msgstr "é ‚é»žï¼š" #: editor/plugins/spatial_editor_plugin.cpp msgid "FPS: %d (%s ms)" -msgstr "" +msgstr "FPS: %d (%s 毫秒)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View." @@ -11338,49 +10963,48 @@ msgstr "效果é 覽" #: editor/plugins/spatial_editor_plugin.cpp msgid "(Not in GLES2)" -msgstr "" +msgstr "(ä¸åœ¨GLES2ä¸)" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "" "Debug draw modes are only available when using the GLES3 renderer, not GLES2." -msgstr "使用 GLES2 算繪引擎時無法使用。" +msgstr "除錯繪製模å¼åƒ…å¯åœ¨ GLES3 算繪引擎下使用,無法在 GLES2 下使用。" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" -msgstr "自由視圖 å·¦" +msgstr "自由觀看 å·¦" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Right" -msgstr "自由視圖 å³" +msgstr "自由觀看 å³" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Forward" -msgstr "自由視圖 å‰" +msgstr "自由觀看 å‰" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Backwards" -msgstr "自由視圖 後" +msgstr "自由觀看 後" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "自由視圖 上" +msgstr "自由觀看 上" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" -msgstr "自由視圖 下" +msgstr "自由觀看 下" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Speed Modifier" -msgstr "åŠ é€Ÿè‡ªç”±è¦–åœ–é€Ÿåº¦" +msgstr "自由觀看速度調整" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Slow Modifier" -msgstr "放慢自由視圖速度" +msgstr "自由觀看減速調整" #: editor/plugins/spatial_editor_plugin.cpp msgid "Toggle Camera Preview" -msgstr "切æ›ç›¸æ©Ÿé 覽開關" +msgstr "開啟ï¼é—œé–‰ç›¸æ©Ÿé 覽" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Rotation Locked" @@ -11389,7 +11013,7 @@ msgstr "視圖旋轉已鎖定" #: editor/plugins/spatial_editor_plugin.cpp msgid "" "To zoom further, change the camera's clipping planes (View -> Settings...)" -msgstr "è‹¥è¦å†ç¹¼çºŒæ”¾å¤§ï¼Œè«‹è‡³ 檢視 -> è¨å®š... 修改æ”影機的剪è£å¹³é¢" +msgstr "è‹¥è¦å†ç¹¼çºŒæ”¾å¤§ï¼Œè«‹è‡³ [檢視] -> [è¨å®š...] 修改æ”影機的剪è£å¹³é¢" #: editor/plugins/spatial_editor_plugin.cpp msgid "" @@ -11507,16 +11131,15 @@ msgstr "開啟ï¼é—œé–‰è‡ªç”±è¦–圖" #: editor/plugins/spatial_editor_plugin.cpp msgid "Decrease Field of View" -msgstr "" +msgstr "減少å¯è¦–範åœ" #: editor/plugins/spatial_editor_plugin.cpp msgid "Increase Field of View" -msgstr "" +msgstr "å¢žåŠ å¯è¦–範åœ" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Reset Field of View to Default" -msgstr "é‡è¨ç‚ºé è¨å€¼" +msgstr "é‡è¨ç‚ºé è¨è¦–野" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Object to Floor" @@ -11637,16 +11260,15 @@ msgstr "後置" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Size" -msgstr "" +msgstr "æ“ç¸±å™¨æŽ§åˆ¶é …å¤§å°" #: editor/plugins/spatial_editor_plugin.cpp msgid "Manipulator Gizmo Opacity" -msgstr "" +msgstr "æ“ç¸±å™¨æŽ§åˆ¶é …ä¸é€æ˜Žåº¦" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Show Viewport Rotation Gizmo" -msgstr "鎖定視角旋轉" +msgstr "顯示檢視å€çš„æ—‹è½‰æŽ§åˆ¶å™¨" #: editor/plugins/spatial_editor_plugin.cpp msgid "Unnamed Gizmo" @@ -11697,9 +11319,8 @@ msgid "Invalid geometry, can't replace by mesh." msgstr "ç„¡æ•ˆçš„å¹¾ä½•åœ–å½¢ï¼Œç„¡æ³•ä»¥ç¶²æ ¼å–代。" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Convert to MeshInstance2D" -msgstr "轉æ›ç‚º Mesh2D" +msgstr "轉æ›ç‚º MeshInstance2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't create polygon." @@ -11730,19 +11351,16 @@ msgid "Sprite" msgstr "拼åˆåœ–" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Simplification:" -msgstr "簡化: " +msgstr "簡化:" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Shrink (Pixels):" -msgstr "收縮(åƒç´ ): " +msgstr "收縮(åƒç´ ):" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Grow (Pixels):" -msgstr "擴展(åƒç´ ): " +msgstr "擴展(åƒç´ ):" #: editor/plugins/sprite_editor_plugin.cpp msgid "Update Preview" @@ -11805,6 +11423,10 @@ msgid "New Animation" msgstr "新增動畫" #: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Filter animations" +msgstr "篩é¸å‹•ç•«" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" msgstr "速度:" @@ -12099,9 +11721,8 @@ msgstr "" "確定è¦é—œé–‰å—Žï¼Ÿ" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Type" -msgstr "移除圖塊" +msgstr "移除型別" #: editor/plugins/theme_editor_plugin.cpp msgid "" @@ -12144,14 +11765,12 @@ msgstr "" "æ‰‹å‹•åŠ å…¥æ›´å¤šé …ç›®æ–¼å…¶ä¸æˆ–從å¦ä¸€å€‹ä¸»é¡ŒåŒ¯å…¥ã€‚" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Add Theme Type" -msgstr "æ–°å¢žé …ç›®é¡žåž‹" +msgstr "新增主題型別" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove Theme Type" -msgstr "ç§»é™¤é …ç›®" +msgstr "移除主題型別" #: editor/plugins/theme_editor_plugin.cpp msgid "Add Color Item" @@ -12266,9 +11885,8 @@ msgid "Select Another Theme Resource:" msgstr "鏿“‡å…¶ä»–主題資æºï¼š" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Theme Resource" -msgstr "釿–°å‘½å資æº" +msgstr "主題資æº" #: editor/plugins/theme_editor_plugin.cpp msgid "Another Theme" @@ -12280,22 +11898,19 @@ msgstr "新增類別" #: editor/plugins/theme_editor_plugin.cpp msgid "Filter the list of types or create a new custom type:" -msgstr "" +msgstr "篩é¸åž‹åˆ¥åˆ—表,或是建立新的自定型別:" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Available Node-based types:" -msgstr "å¯ç”¨è¨å®šæª”:" +msgstr "å¯ç”¨ä¹‹åŸºæ–¼ç¯€é»žçš„型別:" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Type name is empty!" -msgstr "檔案å稱為空。" +msgstr "型別å稱為空ï¼" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Are you sure you want to create an empty type?" -msgstr "ç¢ºå®šè¦æ‰“開多個專案嗎?" +msgstr "確定è¦å»ºç«‹ç©ºåž‹åˆ¥å—Žï¼Ÿ" #: editor/plugins/theme_editor_plugin.cpp msgid "Confirm Item Rename" @@ -12325,14 +11940,12 @@ msgid "Add Item Type" msgstr "æ–°å¢žé …ç›®é¡žåž‹" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Variation Base Type" -msgstr "è¨å®šè®Šæ•¸åž‹åˆ¥" +msgstr "è¨å®šè®ŠåŒ–基礎型別" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Set Base Type" -msgstr "更改基礎型別" +msgstr "è¨å®šåŸºç¤Žåž‹åˆ¥" #: editor/plugins/theme_editor_plugin.cpp msgid "Show Default" @@ -12352,13 +11965,13 @@ msgstr "複寫所有é è¨é¡žåˆ¥é …目。" #: editor/plugins/theme_editor_plugin.cpp msgid "Select the variation base type from a list of available types." -msgstr "" +msgstr "從å¯ç”¨çš„型別列表ä¸é¸æ“‡åŸºç¤Žåž‹åˆ¥çš„變化。" #: editor/plugins/theme_editor_plugin.cpp msgid "" "A type associated with a built-in class cannot be marked as a variation of " "another type." -msgstr "" +msgstr "與內建型別相關è¯çš„型別無法被標記為å¦ä¸€å€‹åž‹åˆ¥çš„變化。" #: editor/plugins/theme_editor_plugin.cpp msgid "Theme:" @@ -12593,55 +12206,46 @@ msgid "Clear Transform" msgstr "清除變æ›" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Tile Map" -msgstr "繪製圖塊地圖" +msgstr "圖塊地圖" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Palette Min Width" -msgstr "" +msgstr "調色盤最å°å¯¬åº¦" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Palette Item H Separation" -msgstr "帶å稱的分隔線" +msgstr "èª¿è‰²ç›¤é …ç›®çš„æ°´å¹³åˆ†éš”ç·š" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Names" -msgstr "顯示所有地å€" +msgstr "顯示圖塊å稱" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Show Tile Ids" -msgstr "顯示尺è¦" +msgstr "顯示圖塊 ID" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Sort Tiles By Name" -msgstr "檔案排åº" +msgstr "以å稱排åºåœ–塊" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Bucket Fill Preview" -msgstr "油漆桶填滿" +msgstr "油漆桶填充é 覽" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Editor Side" -msgstr "編輯器" +msgstr "ç·¨è¼¯å™¨å´æ¬„" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Display Grid" -msgstr "顯示éŽåº¦ç¹ªåœ–" +msgstr "顯示柵欄" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Axis Color" -msgstr "鏿“‡é¡è‰²" +msgstr "座標軸é¡è‰²" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Add Texture(s) to TileSet." @@ -12974,7 +12578,6 @@ msgid "This property can't be changed." msgstr "該屬性無法修改。" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Snap Options" msgstr "å¸é™„é¸é …" @@ -12987,9 +12590,8 @@ msgstr "å¸é™„é¸é …" #: scene/gui/graph_node.cpp scene/gui/rich_text_effect.cpp #: scene/main/canvas_layer.cpp scene/resources/material.cpp #: scene/resources/particles_material.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Offset" -msgstr "å移:" +msgstr "åç§»" #: editor/plugins/tile_set_editor_plugin.cpp editor/rename_dialog.cpp #: scene/gui/range.cpp scene/resources/animation.cpp @@ -13000,14 +12602,12 @@ msgstr "æ¥é•·" #: editor/plugins/tile_set_editor_plugin.cpp #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Separation" -msgstr "分隔:" +msgstr "é–“è·" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Tile" -msgstr "鏿“‡" +msgstr "所é¸åœ–塊" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp #: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp @@ -13016,158 +12616,132 @@ msgstr "鏿“‡" #: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp #: scene/resources/material.cpp scene/resources/sky.cpp #: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Texture" -msgstr "純文å—" +msgstr "ç´‹ç†è²¼åœ–" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tex Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "ç´‹ç†åç§»" #: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp #: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp #: scene/3d/mesh_instance.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Material" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "æè³ª" #: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp #: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Modulate" -msgstr "å¡«å……" +msgstr "調變" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Mode" -msgstr "åˆ‡æ›æ¨¡å¼" +msgstr "圖塊模å¼" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Autotile Bitmask Mode" -msgstr "優先模å¼" +msgstr "自動圖塊的ä½å…ƒé®ç½©æ¨¡å¼" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Size" -msgstr "輪廓尺寸:" +msgstr "å圖塊大å°" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Subtile Spacing" -msgstr "行間è·" +msgstr "自圖塊間è·" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Occluder Offset" -msgstr "建立é®å…‰å¤šé‚Šå½¢" +msgstr "é®å…‰åç§»" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation Offset" -msgstr "導航模å¼" +msgstr "導航åç§»" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Offset" -msgstr "å移:" +msgstr "形狀åç§»" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Shape Transform" -msgstr "變æ›" +msgstr "形狀變æ›" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision" -msgstr "碰撞" +msgstr "所é¸ç¢°æ’ž" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way" -msgstr "僅æœå°‹æ‰€é¸å€åŸŸ" +msgstr "所é¸ç¢°æ’žå–®å‘" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Collision One Way Margin" -msgstr "碰撞模å¼" +msgstr "所é¸ç¢°æ’žå–®å‘外邊è·" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Navigation" -msgstr "顯示導航" +msgstr "所é¸å°Žèˆª" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Selected Occlusion" -msgstr "鏿“‡" +msgstr "所é¸é®æ“‹" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tileset Script" -msgstr "篩é¸è…³æœ¬" +msgstr "圖塊集腳本" #: editor/plugins/tile_set_editor_plugin.cpp msgid "TileSet" msgstr "圖塊集" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "No VCS plugins are available." -msgstr "ç„¡å¯ç”¨çš„版本控制 (VCS) 擴充功能。" +msgstr "ç„¡å¯ç”¨çš„版本控制 (VCS) 外掛。" #: editor/plugins/version_control_editor_plugin.cpp msgid "" "Remote settings are empty. VCS features that use the network may not work." -msgstr "" +msgstr "é 端è¨å®šæ˜¯ç©ºçš„。使用網路的VCS功能æç„¡æ³•é‹ä½œã€‚" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "No commit message was provided." -msgstr "未æä¾›å稱。" +msgstr "未æä¾›èªå¯ (Commit) 訊æ¯ã€‚" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit" msgstr "æäº¤" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Staged Changes" -msgstr "著色器變更:" +msgstr "æš«å˜è®Šæ›´" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Unstaged Changes" -msgstr "著色器變更:" +msgstr "未暫å˜è®Šæ›´" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Commit:" -msgstr "æäº¤" +msgstr "æäº¤ï¼š" #: editor/plugins/version_control_editor_plugin.cpp msgid "Date:" -msgstr "" +msgstr "日期:" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Subtitle:" -msgstr "忍¹" +msgstr "副標題:" #: editor/plugins/version_control_editor_plugin.cpp msgid "Do you want to remove the %s branch?" -msgstr "" +msgstr "ä½ ç¢ºå®šè¦ç§»é™¤ %s 分支?" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Do you want to remove the %s remote?" -msgstr "ç¢ºå®šè¦æ‰“開多個專案嗎?" +msgstr "確定è¦ç§»é™¤é 端「%sã€ï¼Ÿ" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Apply" -msgstr "套用é‡è¨" +msgstr "套用" #: editor/plugins/version_control_editor_plugin.cpp msgid "Version Control System" @@ -13178,123 +12752,108 @@ msgid "Initialize" msgstr "åˆå§‹åŒ–" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remote Login" -msgstr "移除控制點" +msgstr "é 端登入" #: editor/plugins/version_control_editor_plugin.cpp msgid "Select SSH public key path" -msgstr "" +msgstr "鏿“‡SSH公鑰的路徑" #: editor/plugins/version_control_editor_plugin.cpp msgid "Select SSH private key path" -msgstr "" +msgstr "鏿“‡SSHç§é‘°çš„路徑" #: editor/plugins/version_control_editor_plugin.cpp msgid "SSH Passphrase" -msgstr "" +msgstr "SSH 通關片段" #: editor/plugins/version_control_editor_plugin.cpp msgid "Detect new changes" msgstr "嵿¸¬æ–°æ”¹å‹•" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Discard all changes" -msgstr "關閉並ä¿å˜ä¿®æ”¹å—Žï¼Ÿ" +msgstr "æ¨æ£„所有變更" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Stage all changes" -msgstr "æ£åœ¨å„²å˜è®Šæ›´..." +msgstr "é å˜æ‰€æœ‰è®Šæ›´" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Unstage all changes" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "æ’¤éŠ·æš«å˜æ‰€æœ‰è®Šæ›´" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Commit Message" -msgstr "æäº¤æ”¹å‹•" +msgstr "èªå¯ (Commit) 訊æ¯" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit Changes" msgstr "æäº¤æ”¹å‹•" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Commit List" -msgstr "æäº¤" +msgstr "èªå¯åˆ—表" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit list size" -msgstr "" +msgstr "èªå¯åˆ—表大å°" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Branches" -msgstr "ç¬¦åˆæ¢ä»¶ï¼š" +msgstr "分支" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Create New Branch" -msgstr "建立新專案" +msgstr "建立分支" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remove Branch" -msgstr "刪除動畫軌" +msgstr "移除分支" #: editor/plugins/version_control_editor_plugin.cpp msgid "Branch Name" -msgstr "" +msgstr "分支å稱" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remotes" msgstr "é 端" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Create New Remote" -msgstr "建立新專案" +msgstr "建立é 端" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remove Remote" -msgstr "ç§»é™¤é …ç›®" +msgstr "移除é 端" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remote Name" -msgstr "é 端 " +msgstr "é 端å稱" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Remote URL" -msgstr "é 端 " +msgstr "é 端網å€" #: editor/plugins/version_control_editor_plugin.cpp msgid "Fetch" -msgstr "" +msgstr "æˆªå– (Fetch)" #: editor/plugins/version_control_editor_plugin.cpp msgid "Pull" -msgstr "" +msgstr "æå– (Pull)" #: editor/plugins/version_control_editor_plugin.cpp msgid "Push" -msgstr "" +msgstr "æŽ¨é€ (Push)" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Force Push" -msgstr "來æºç¶²æ ¼ï¼š" +msgstr "強制推é€" #: editor/plugins/version_control_editor_plugin.cpp msgid "Modified" -msgstr "已修改" +msgstr "修改" #: editor/plugins/version_control_editor_plugin.cpp msgid "Renamed" @@ -13302,30 +12861,27 @@ msgstr "釿–°å‘½å" #: editor/plugins/version_control_editor_plugin.cpp msgid "Deleted" -msgstr "已刪除" +msgstr "刪除" #: editor/plugins/version_control_editor_plugin.cpp msgid "Typechange" -msgstr "æ ¼å¼æ›´æ”¹" +msgstr "更改型別" #: editor/plugins/version_control_editor_plugin.cpp msgid "Unmerged" -msgstr "" +msgstr "未åˆä½µ" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "View:" -msgstr "檢視" +msgstr "檢視:" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Split" -msgstr "拆分路徑" +msgstr "分割" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Unified" -msgstr "已修改" +msgstr "åˆä½µ" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(GLES3 only)" @@ -14182,11 +13738,11 @@ msgstr "å¯åŸ·è¡Œ" #: editor/project_export.cpp msgid "Export the project for all the presets defined." -msgstr "" +msgstr "使用æ¯å€‹å·²å®šç¾©çš„é è¨è¨å®šä¾†åŒ¯å‡ºè©²å°ˆæ¡ˆã€‚" #: editor/project_export.cpp msgid "All presets must have an export path defined for Export All to work." -msgstr "" +msgstr "所有é è¨è¨å®šéƒ½å¿…é ˆå®šç¾©å¥½åŒ¯å‡ºè·¯å¾‘ï¼Œæ‰å¯ä½¿ç”¨ [匯出全部] 功能。" #: editor/project_export.cpp msgid "Delete preset '%s'?" @@ -14297,53 +13853,48 @@ msgid "" "Note: Encryption key needs to be stored in the binary,\n" "you need to build the export templates from source." msgstr "" +"注æ„ï¼šåŠ å¯†é‡‘é‘°å¿…é ˆä»¥äºŒé€²ä½å½¢å¼ä¿å˜ï¼Œ\n" +"å¿…é ˆå¾žåŽŸå§‹ç¢¼ä¾†ç·¨è¯åŒ¯å‡ºæ¨£æ¿ã€‚" #: editor/project_export.cpp -#, fuzzy msgid "More Info..." -msgstr "移動至..." +msgstr "更多資訊..." #: editor/project_export.cpp -#, fuzzy msgid "Export PCK/Zip..." -msgstr "匯出 PCK/ZIP" +msgstr "匯出 PCK/ZIP..." #: editor/project_export.cpp -#, fuzzy msgid "Export Project..." -msgstr "匯出專案" +msgstr "匯出專案..." #: editor/project_export.cpp msgid "Export All" msgstr "全部匯出" #: editor/project_export.cpp -#, fuzzy msgid "Choose an export mode:" -msgstr "è«‹é¸æ“‡ä¸€å€‹ç©ºè³‡æ–™å¤¾ã€‚" +msgstr "鏿“‡åŒ¯å‡ºæ¨¡å¼ï¼š" #: editor/project_export.cpp -#, fuzzy msgid "Export All..." -msgstr "全部匯出" +msgstr "全部匯出..." #: editor/project_export.cpp editor/project_manager.cpp msgid "ZIP File" msgstr "ZIP 檔案" #: editor/project_export.cpp -#, fuzzy msgid "Godot Project Pack" -msgstr "Godot éŠæˆ²åŒ…" +msgstr "Godot 專案包" #: editor/project_export.cpp msgid "Export templates for this platform are missing:" msgstr "缺少匯出該平å°ç”¨çš„æ¨£æ¿ï¼š" #: editor/project_export.cpp -#, fuzzy msgid "Project Export" -msgstr "專案發起人" +msgstr "專案匯出" #: editor/project_export.cpp msgid "Manage Export Templates" @@ -14630,8 +14181,8 @@ msgid "" "Language changed.\n" "The interface will update after restarting the editor or project manager." msgstr "" -"語言已更改。\n" -"界é¢å°‡æœƒåœ¨é‡æ–°å•Ÿå‹•編輯器或專案管ç†å“¡å¾Œæ›´æ–°ã€‚" +"語言已變更。\n" +"釿–°å•Ÿå‹•編輯器或專案管ç†å“¡å¾Œå°‡æœƒå¥—ç”¨ç•Œé¢æ›´æ–°ã€‚" #: editor/project_manager.cpp msgid "" @@ -14643,7 +14194,6 @@ msgstr "" #. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp -#, fuzzy msgctxt "Application" msgid "Project Manager" msgstr "專案管ç†å“¡" @@ -14908,7 +14458,7 @@ msgstr "ä¿å˜è¨å®šæ™‚發生錯誤。" #: editor/project_settings_editor.cpp msgid "Settings saved OK." -msgstr "è¨å®šä¿å˜æˆåŠŸã€‚" +msgstr "è¨å®šå„²å˜æˆåŠŸã€‚" #: editor/project_settings_editor.cpp msgid "Moved Input Action Event" @@ -14992,7 +14542,7 @@ msgstr "索引:" #: editor/project_settings_editor.cpp msgid "Localization" -msgstr "本地化" +msgstr "在地化" #: editor/project_settings_editor.cpp msgid "Translations" @@ -15367,7 +14917,7 @@ msgid "" "FileSystem dock context menu\n" "or create an inherited scene using Scene > New Inherited Scene... instead." msgstr "" -"無法ä¿å˜ä½œç‚ºå¯¦é«”åŒ–å ´æ™¯çš„æ ¹ç¯€é»žåˆ†æ”¯ã€‚\n" +"無法儲å˜ä½œç‚ºå¯¦é«”åŒ–å ´æ™¯çš„æ ¹ç¯€é»žåˆ†æ”¯ã€‚\n" "請使用檔案系統åœä½‡åˆ—çš„å³éµé¸å–®ä¾†è¤‡è£½å®ƒï¼Œä»¥æ‹·è²ç›®å‰å ´æ™¯åŠ ä»¥ç·¨è¼¯ã€‚\n" "æˆ–æ˜¯ä½¿ç”¨å ´æ™¯ > æ–°å¢žç¹¼æ‰¿å ´æ™¯...ä»¥å»ºç«‹ä¸€å€‹ç¹¼æ‰¿å ´æ™¯ã€‚" @@ -15377,7 +14927,7 @@ msgid "" "To create a variation of a scene, you can make an inherited scene based on " "the instanced scene using Scene > New Inherited Scene... instead." msgstr "" -"無法ä¿å˜å·²å¯¦é«”åŒ–å ´æ™¯çš„åˆ†æ”¯ã€‚\n" +"無法儲å˜å·²å¯¦é«”åŒ–å ´æ™¯çš„åˆ†æ”¯ã€‚\n" "è‹¥è¦å»ºç«‹å ´æ™¯è®Šé«”,您å¯ä½¿ç”¨å ´æ™¯ > æ–°å¢žç¹¼æ‰¿å ´æ™¯...æ ¹æ“šå¯¦é«”åŒ–çš„å ´æ™¯å»ºç«‹ä¸€å€‹ç¹¼æ‰¿" "å ´æ™¯ã€‚" @@ -15387,6 +14937,9 @@ msgid "" "To save this branch into its own scene, open the original scene, right click " "on this branch, and select \"Save Branch as Scene\"." msgstr "" +"無法ä¿å˜åˆ†æ”¯ï¼Œè©²åˆ†æ”¯æ˜¯å·²å¯¦é«”åŒ–å ´æ™¯çš„åé …ç›®ã€‚\n" +"è‹¥è¦å°‡è©²åˆ†æ”¯ä¿å˜é€²ç¨ç«‹çš„å ´æ™¯ä¸ï¼Œè«‹é–‹å•ŸåŽŸå§‹å ´æ™¯ï¼Œä¸¦åœ¨è©²åˆ†æ”¯ä¸Šé»žæ“Šå³éµï¼Œç„¶å¾Œé¸" +"擇 [將分支ä¿å˜ç‚ºå ´æ™¯]。" #: editor/scene_tree_dock.cpp msgid "" @@ -15394,6 +14947,9 @@ msgid "" "To save this branch into its own scene, open the original scene, right click " "on this branch, and select \"Save Branch as Scene\"." msgstr "" +"無法ä¿å˜åˆ†æ”¯ï¼Œè©²åˆ†æ”¯æ˜¯ç¹¼æ‰¿å ´æ™¯çš„一部分。\n" +"è‹¥è¦å°‡è©²åˆ†æ”¯ä¿å˜ç‚ºç¨ç«‹çš„å ´æ™¯ï¼Œè«‹é–‹å•ŸåŽŸå§‹å ´æ™¯ï¼Œä¸¦åœ¨è©²åˆ†æ”¯ä¸Šé»žæ“Šå³éµï¼Œç„¶å¾Œé¸æ“‡ " +"[將分支ä¿å˜ç‚ºå ´æ™¯]。" #: editor/scene_tree_dock.cpp msgid "Save New Scene As..." @@ -15419,17 +14975,15 @@ msgstr "轉為本地" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp msgid "Another node already uses this unique name in the scene." -msgstr "" +msgstr "å¦ä¸€å€‹ç¯€é»žå·²åœ¨è©²å ´æ™¯ä¸ä½¿ç”¨äº†é€™å€‹ä¸å¯é‡è¤‡çš„å稱。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Enable Scene Unique Name" -msgstr "節點å稱:" +msgstr "å•Ÿç”¨å ´æ™¯ç¨ç«‹å稱" #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -#, fuzzy msgid "Disable Scene Unique Name" -msgstr "節點å稱:" +msgstr "åœç”¨å ´æ™¯ç¨ç«‹å稱" #: editor/scene_tree_dock.cpp msgid "New Scene Root" @@ -15487,7 +15041,7 @@ msgstr "更改節點的型別" msgid "" "Couldn't save new scene. Likely dependencies (instances) couldn't be " "satisfied." -msgstr "無法ä¿å˜æ–°å ´æ™¯ã€‚å¯èƒ½æ˜¯ç”±æ–¼ç„¡æ³•滿足其ä¾è³´æ€§ï¼ˆå¯¦é«”)。" +msgstr "ç„¡æ³•å„²å˜æ–°å ´æ™¯ã€‚å¯èƒ½æ˜¯ç”±æ–¼ç„¡æ³•滿足其ä¾è³´æ€§ï¼ˆå¯¦é«”)。" #: editor/scene_tree_dock.cpp msgid "Error saving scene." @@ -15495,7 +15049,7 @@ msgstr "ä¿å˜å ´æ™¯æ™‚發生錯誤。" #: editor/scene_tree_dock.cpp msgid "Error duplicating scene to save it." -msgstr "è¤‡è£½å ´æ™¯ä»¥é€²è¡Œä¿å˜æ™‚發生錯誤。" +msgstr "è¤‡è£½å ´æ™¯ä»¥é€²è¡Œå„²å˜æ™‚發生錯誤。" #: editor/scene_tree_dock.cpp msgid "Sub-Resources" @@ -15503,7 +15057,7 @@ msgstr "å資æº" #: editor/scene_tree_dock.cpp msgid "Access as Scene Unique Name" -msgstr "" +msgstr "以ä¸é‡è¤‡çš„å ´æ™¯å稱來å˜å–" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" @@ -15552,7 +15106,7 @@ msgstr "åˆä½µè‡ªå ´æ™¯" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Save Branch as Scene" -msgstr "ä¿å˜åˆ†æ”¯ç‚ºå ´æ™¯" +msgstr "儲å˜åˆ†æ”¯ç‚ºå ´æ™¯" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Copy Node Path" @@ -15598,18 +15152,16 @@ msgid "Clear Inheritance? (No Undo!)" msgstr "ç¢ºå®šè¦æ¸…除繼承嗎?(無法復原ï¼ï¼‰" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Show Scene Tree Root Selection" -msgstr "ç½®ä¸æ‰€é¸" +msgstr "é¡¯ç¤ºå ´æ™¯æ¨¹çš„æ ¹é¸æ“‡" #: editor/scene_tree_dock.cpp msgid "Derive Script Globals By Name" -msgstr "" +msgstr "ä¾ç…§å稱來推斷腳本的全域變數" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Use Favorites Root Selection" -msgstr "完整顯示所é¸" +msgstr "ä½¿ç”¨æˆ‘çš„æœ€æ„›æ ¹é¸æ“‡" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" @@ -15637,6 +15189,8 @@ msgid "" "with the '%s' prefix in a node path.\n" "Click to disable this." msgstr "" +"該節點å¯åœ¨æ¤å ´æ™¯ä¸çš„任何地方通éŽåœ¨ç¯€é»žè·¯å¾‘剿–¹åŠ ä¸Šã€Œ%sã€å‰ç½®è©žä¾†å˜å–。\n" +"點擊以ç¦ç”¨ã€‚" #: editor/scene_tree_editor.cpp msgid "" @@ -15843,9 +15397,8 @@ msgid "Attach Node Script" msgstr "é™„åŠ ç¯€é»žè…³æœ¬" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote %s:" -msgstr "é 端 " +msgstr "é 端 %s:" #: editor/script_editor_debugger.cpp msgid "Bytes:" @@ -15920,21 +15473,20 @@ msgid "Stack Frames" msgstr "å †ç–Šæ¡†" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Filter stack variables" -msgstr "篩é¸åœ–塊" +msgstr "篩é¸å †ç–Šè®Šæ•¸" #: editor/script_editor_debugger.cpp msgid "Auto Switch To Remote Scene Tree" -msgstr "" +msgstr "自動切æ›è‡³é ç«¯å ´æ™¯æ¨¹" #: editor/script_editor_debugger.cpp msgid "Remote Scene Tree Refresh Interval" -msgstr "" +msgstr "é ç«¯å ´æ™¯æ¨¹é‡æ–°æ•´ç†é–“éš”" #: editor/script_editor_debugger.cpp msgid "Remote Inspect Refresh Interval" -msgstr "" +msgstr "é ç«¯æª¢æŸ¥é‡æ–°æ•´ç†é–“éš”" #: editor/script_editor_debugger.cpp msgid "Network Profiler" @@ -16032,7 +15584,7 @@ msgstr "更改光照åŠå¾‘" #: editor/spatial_editor_gizmos.cpp msgid "Stream Player 3D" -msgstr "" +msgstr "StreamPlayer3D" #: editor/spatial_editor_gizmos.cpp msgid "Change AudioStreamPlayer3D Emission Angle" @@ -16042,7 +15594,7 @@ msgstr "更改 AudioStreamPlayer3D 發射角" #: platform/osx/export/export.cpp #: scene/resources/default_theme/default_theme.cpp msgid "Camera" -msgstr "" +msgstr "相機" #: editor/spatial_editor_gizmos.cpp msgid "Change Camera FOV" @@ -16054,7 +15606,7 @@ msgstr "更改相機尺寸" #: editor/spatial_editor_gizmos.cpp msgid "Visibility Notifier" -msgstr "" +msgstr "VisibilityNotifier" #: editor/spatial_editor_gizmos.cpp msgid "Change Notifier AABB" @@ -16065,23 +15617,20 @@ msgid "Change Particles AABB" msgstr "更改粒å AABB" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Reflection Probe" -msgstr "鏿“‡å±¬æ€§" +msgstr "å射探查" #: editor/spatial_editor_gizmos.cpp msgid "Change Probe Extents" msgstr "更改探查範åœ" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "GI Probe" -msgstr "烘焙 GI 探查" +msgstr "GI 探查" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Baked Indirect Light" -msgstr "éžå‘性光照" +msgstr "烘焙間接光照" #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp msgid "Change Sphere Shape Radius" @@ -16112,14 +15661,12 @@ msgid "Change Ray Shape Length" msgstr "更改射線形長度" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge" -msgstr "導航模å¼" +msgstr "導航邊界" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Navigation Edge Disabled" -msgstr "導航模å¼" +msgstr "å·²ç¦ç”¨å°Žèˆªé‚Šç•Œ" #: editor/spatial_editor_gizmos.cpp #, fuzzy @@ -16297,9 +15844,8 @@ msgid "Driver" msgstr "" #: main/main.cpp -#, fuzzy msgid "Driver Name" -msgstr "腳本å稱:" +msgstr "é©…å‹•å稱" #: main/main.cpp msgid "Fallback To GLES2" @@ -16384,9 +15930,8 @@ msgid "Physics FPS" msgstr "物ç†å½±æ ¼ %" #: main/main.cpp -#, fuzzy msgid "Force FPS" -msgstr "來æºç¶²æ ¼ï¼š" +msgstr "強制 FPS" #: main/main.cpp msgid "Enable Pause Aware Picking" @@ -16500,9 +16045,8 @@ msgid "Fullsize" msgstr "" #: main/main.cpp scene/resources/dynamic_font.cpp -#, fuzzy msgid "Use Filter" -msgstr "篩é¸ï¼š" +msgstr "使用篩é¸å™¨" #: main/main.cpp scene/resources/style_box.cpp #, fuzzy @@ -16549,9 +16093,8 @@ msgid "Custom Image Hotspot" msgstr "" #: main/main.cpp -#, fuzzy msgid "Tooltip Position Offset" -msgstr "旋轉åç§»é‡ï¼š" +msgstr "工具æç¤ºä½ç½®åç§»" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp #, fuzzy @@ -16564,9 +16107,8 @@ msgid "Wait For Debugger" msgstr "除錯工具" #: main/main.cpp modules/mono/mono_gd/gd_mono.cpp -#, fuzzy msgid "Wait Timeout" -msgstr "逾時。" +msgstr "ç‰å¾…逾時" #: main/main.cpp msgid "Runtime" @@ -16680,14 +16222,12 @@ msgstr "轉æ›å¤§å°å¯«" #: scene/resources/cylinder_shape.cpp scene/resources/environment.cpp #: scene/resources/navigation_mesh.cpp scene/resources/primitive_meshes.cpp #: scene/resources/sphere_shape.cpp -#, fuzzy msgid "Radius" -msgstr "åŠå¾‘:" +msgstr "åŠå¾‘" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Radial Segments" -msgstr "ä¸»å ´æ™¯å¼•æ•¸ï¼š" +msgstr "徑呿®µæ•¸" #: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp #, fuzzy @@ -16756,9 +16296,8 @@ msgid "Path Simplify Angle" msgstr "" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Rotation" -msgstr "隨機旋轉:" +msgstr "路徑旋轉" #: modules/csg/csg_shape.cpp #, fuzzy @@ -16771,14 +16310,12 @@ msgid "Path Continuous U" msgstr "連續" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path U Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "路徑 U è·é›¢" #: modules/csg/csg_shape.cpp -#, fuzzy msgid "Path Joined" -msgstr "隨機旋轉:" +msgstr "路徑接åˆ" #: modules/enet/networked_multiplayer_enet.cpp #, fuzzy @@ -16826,9 +16363,8 @@ msgid "Use FBX" msgstr "" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Config File" -msgstr "å„²å˜æª”案:" +msgstr "組態檔案" #: modules/gdnative/gdnative.cpp #, fuzzy @@ -16842,9 +16378,8 @@ msgid "Singleton" msgstr "骨架" #: modules/gdnative/gdnative.cpp -#, fuzzy msgid "Symbol Prefix" -msgstr "å‰ç½®ï¼š" +msgstr "符號å‰ç¶´" #: modules/gdnative/gdnative.cpp #, fuzzy @@ -16902,19 +16437,16 @@ msgid "Disabled GDNative Singleton" msgstr "ç¦ç”¨ GDNative 單例" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Libraries:" -msgstr "函å¼åº«ï¼š " +msgstr "函å¼åº«ï¼š" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Class Name" -msgstr "類別å稱:" +msgstr "類別å稱" #: modules/gdnative/nativescript/nativescript.cpp -#, fuzzy msgid "Script Class" -msgstr "腳本å稱:" +msgstr "腳本類別" #: modules/gdnative/nativescript/nativescript.cpp #, fuzzy @@ -16993,9 +16525,8 @@ msgid "Object can't provide a length." msgstr "物件無法æä¾›é•·åº¦ã€‚" #: modules/gdscript/language_server/gdscript_language_server.cpp -#, fuzzy msgid "Language Server" -msgstr "語言:" +msgstr "語言伺æœå™¨" #: modules/gdscript/language_server/gdscript_language_server.cpp #, fuzzy @@ -17024,9 +16555,8 @@ msgid "Buffer View" msgstr "後視圖" #: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp -#, fuzzy msgid "Byte Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "å—節åç§»" #: modules/gltf/gltf_accessor.cpp #, fuzzy @@ -17039,9 +16569,8 @@ msgid "Normalized" msgstr "æ ¼å¼" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Count" -msgstr "數é‡ï¼š" +msgstr "數é‡" #: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp #, fuzzy @@ -17067,9 +16596,8 @@ msgid "Sparse Indices Byte Offset" msgstr "" #: modules/gltf/gltf_accessor.cpp -#, fuzzy msgid "Sparse Indices Component Type" -msgstr "æ£åœ¨è§£æžå¤šé‚Šå½¢..." +msgstr "稀ç–é ‚é»žå…ƒä»¶åž‹åˆ¥" #: modules/gltf/gltf_accessor.cpp msgid "Sparse Values Buffer View" @@ -17099,9 +16627,8 @@ msgid "Indices" msgstr "所有è£ç½®" #: modules/gltf/gltf_camera.cpp -#, fuzzy msgid "FOV Size" -msgstr "大å°ï¼š" +msgstr "FOV 大å°" #: modules/gltf/gltf_camera.cpp msgid "Zfar" @@ -17148,9 +16675,8 @@ msgid "Blend Weights" msgstr "烘焙光照圖" #: modules/gltf/gltf_mesh.cpp -#, fuzzy msgid "Instance Materials" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "實體æè³ª" #: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp #, fuzzy @@ -17238,9 +16764,8 @@ msgid "Gloss Factor" msgstr "" #: modules/gltf/gltf_spec_gloss.cpp -#, fuzzy msgid "Specular Factor" -msgstr "ç´”é‡é‹ç®—å。" +msgstr "é¡é¢å射係數" #: modules/gltf/gltf_spec_gloss.cpp msgid "Spec Gloss Img" @@ -17279,9 +16804,8 @@ msgid "Accessors" msgstr "" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Scene Name" -msgstr "å ´æ™¯è·¯å¾‘ï¼š" +msgstr "å ´æ™¯å稱" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17308,9 +16832,8 @@ msgid "Lights" msgstr "燈光" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Unique Animation Names" -msgstr "新增動畫å稱:" +msgstr "ç¨ç«‹å‹•ç•«å稱" #: modules/gltf/gltf_state.cpp #, fuzzy @@ -17323,9 +16846,8 @@ msgid "Skeleton To Node" msgstr "鏿“‡ä¸€å€‹ç¯€é»ž" #: modules/gltf/gltf_state.cpp -#, fuzzy msgid "Animations" -msgstr "動畫:" +msgstr "å‹•ç•«" #: modules/gltf/gltf_texture.cpp #, fuzzy @@ -17570,9 +17092,8 @@ msgstr "" #: modules/minimp3/resource_importer_mp3.cpp #: modules/stb_vorbis/audio_stream_ogg_vorbis.cpp #: modules/stb_vorbis/resource_importer_ogg_vorbis.cpp -#, fuzzy msgid "Loop Offset" -msgstr "å移:" +msgstr "循環åç§»" #: modules/mobile_vr/mobile_vr_interface.cpp msgid "Eye Height" @@ -17691,9 +17212,8 @@ msgid "Seamless" msgstr "" #: modules/opensimplex/noise_texture.cpp -#, fuzzy msgid "As Normal Map" -msgstr "隨機縮放:" +msgstr "作為法線貼圖" #: modules/opensimplex/noise_texture.cpp msgid "Bump Strength" @@ -17704,9 +17224,8 @@ msgid "Noise" msgstr "" #: modules/opensimplex/noise_texture.cpp -#, fuzzy msgid "Noise Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "噪è²åç§»" #: modules/opensimplex/open_simplex_noise.cpp msgid "Octaves" @@ -17735,9 +17254,8 @@ msgid "Names" msgstr "å稱" #: modules/regex/regex.cpp -#, fuzzy msgid "Strings" -msgstr "è¨å®šï¼š" +msgstr "å—串" #: modules/upnp/upnp.cpp msgid "Discover Multicast If" @@ -17798,18 +17316,16 @@ msgid "" msgstr "回傳值需被指定為é‹ç®—è¨˜æ†¶é«”ç¯€é»žçš„ç¬¬ä¸€å€‹å…ƒç´ ï¼è«‹ä¿®æ£è©²ç¯€é»žã€‚" #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Node returned an invalid sequence output:" -msgstr "節點回傳了一個無效的連續輸出: " +msgstr "節點回傳了一個無效的åºåˆ—輸出:" #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" msgstr "發ç¾äº†é€£çºŒä½å…ƒ (Sequance Bit) 但並éžåœ¨å †ç–Šä¸çš„ç¯€é»žï¼Œè«‹å›žå ±è©²éŒ¯èª¤ï¼" #: modules/visual_script/visual_script.cpp -#, fuzzy msgid "Stack overflow with stack depth:" -msgstr "å †ç–Šæ·±åº¦çš„å †ç–Šæº¢å‡ºï¼š " +msgstr "å †ç–Šæ·±åº¦çš„å †ç–Šæº¢å‡ºï¼š" #: modules/visual_script/visual_script.cpp #, fuzzy @@ -18176,18 +17692,16 @@ msgid "for (elem) in (input):" msgstr "" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Input type not iterable:" -msgstr "輸入型別éžå¯è¿ä»£åž‹åˆ¥ï¼š " +msgstr "輸入型別éžå¯è¿ä»£åž‹åˆ¥ï¼š" #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid" msgstr "è¿ä»£å™¨å·²ä¸å¯ç”¨" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Iterator became invalid:" -msgstr "è¿ä»£å™¨å·²ä¸å¯ç”¨ï¼š " +msgstr "è¿ä»£å™¨ç„¡æ•ˆï¼š" #: modules/visual_script/visual_script_flow_control.cpp msgid "Sequence" @@ -18204,18 +17718,16 @@ msgid "Steps" msgstr "æ¥é•·" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Switch" -msgstr "仰角:" +msgstr "切æ›" #: modules/visual_script/visual_script_flow_control.cpp msgid "'input' is:" msgstr "" #: modules/visual_script/visual_script_flow_control.cpp -#, fuzzy msgid "Type Cast" -msgstr "類別:" +msgstr "型別轉æ›" #: modules/visual_script/visual_script_flow_control.cpp msgid "Is %s?" @@ -18261,9 +17773,8 @@ msgid "Use Default Args" msgstr "é‡è¨ç‚ºé è¨" #: modules/visual_script/visual_script_func_nodes.cpp -#, fuzzy msgid "Validate" -msgstr "å¯ä½¿ç”¨çš„å—元:" +msgstr "é©—è‰" #: modules/visual_script/visual_script_func_nodes.cpp #, fuzzy @@ -18355,19 +17866,16 @@ msgstr "調整陣列大å°" #: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Operator" -msgstr "ç–ŠåŠ é‹ç®—å。" +msgstr "é‹ç®—å" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Invalid argument of type:" -msgstr ": 無效的引數型別: " +msgstr "無效的引數型別:" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "Invalid arguments:" -msgstr ": 無效的引數: " +msgstr "無效的引數:" #: modules/visual_script/visual_script_nodes.cpp msgid "a if cond, else b" @@ -18379,14 +17887,12 @@ msgid "Var Name" msgstr "å稱" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "VariableGet not found in script:" -msgstr "è…³æœ¬ä¸æœªæ‰¾åˆ° VariableGet(å–得變數): " +msgstr "è…³æœ¬ä¸æœªæ‰¾åˆ° VariableGet(å–得變數):" #: modules/visual_script/visual_script_nodes.cpp -#, fuzzy msgid "VariableSet not found in script:" -msgstr "è…³æœ¬ä¸æœªæ‰¾åˆ° VariableSet(è¨å®šè®Šæ•¸ï¼‰ï¼š " +msgstr "è…³æœ¬ä¸æœªæ‰¾åˆ° VariableSet(è¨å®šè®Šæ•¸ï¼‰ï¼š" #: modules/visual_script/visual_script_nodes.cpp #, fuzzy @@ -18501,7 +18007,7 @@ msgstr "產生" #: modules/visual_script/visual_script_yield_nodes.cpp msgid "Wait" -msgstr "" +msgstr "ç‰å¾…" #: modules/visual_script/visual_script_yield_nodes.cpp #, fuzzy @@ -18606,9 +18112,8 @@ msgid "CA Chain" msgstr "清除 IK éˆ" #: modules/websocket/websocket_server.cpp -#, fuzzy msgid "Handshake Timeout" -msgstr "逾時。" +msgstr "Handshake 逾時" #: modules/webxr/webxr_interface.cpp #, fuzzy @@ -18616,14 +18121,12 @@ msgid "Session Mode" msgstr "å€åŸŸæ¨¡å¼" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Required Features" -msgstr "主è¦åŠŸèƒ½ï¼š" +msgstr "å¿…è¦ç‰¹æ€§" #: modules/webxr/webxr_interface.cpp -#, fuzzy msgid "Optional Features" -msgstr "主è¦åŠŸèƒ½ï¼š" +msgstr "å¯é¸ç‰¹æ€§" #: modules/webxr/webxr_interface.cpp msgid "Requested Reference Space Types" @@ -18728,9 +18231,8 @@ msgid "Export Format" msgstr "匯出路徑" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Min SDK" -msgstr "輪廓尺寸:" +msgstr "æœ€å° SDK" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18785,9 +18287,8 @@ msgid "Package" msgstr "æ£åœ¨æ‰“包" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Unique Name" -msgstr "節點å稱:" +msgstr "ç¨ç«‹å稱" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18795,9 +18296,8 @@ msgid "Signed" msgstr "訊號" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Classify As Game" -msgstr "類別å稱:" +msgstr "åˆ†é¡žç‚ºéŠæˆ²" #: platform/android/export/export_plugin.cpp msgid "Retain Data On Uninstall" @@ -18809,9 +18309,8 @@ msgid "Exclude From Recents" msgstr "刪除節點" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Graphics" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "圖形" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -18881,9 +18380,8 @@ msgid "Command Line" msgstr "社群" #: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Extra Args" -msgstr "é¡å¤–呼å«å¼•數:" +msgstr "é¡å¤–引數" #: platform/android/export/export_plugin.cpp #, fuzzy @@ -19080,14 +18578,12 @@ msgid "Code Signing" msgstr "訊號" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "'apksigner' could not be found. Please check that the command is available " "in the Android SDK build-tools directory. The resulting %s is unsigned." msgstr "" -"找ä¸åˆ°ã€Œapksigner'ã€ã€‚\n" -"è«‹ç¢ºèªæ¤å‘½ä»¤å¯ç”¨æ–¼Android SDK build-tools的目錄。\n" -"%s 未簽署。" +"找ä¸åˆ°ã€Œapksignerã€ã€‚請檢查 Android SDK çš„ build-tools è³‡æ–™å¤¾ä¸æ˜¯å¦æœ‰æ¤æŒ‡ä»¤ã€‚" +"「%sã€æœªç°½ç½²ã€‚" #: platform/android/export/export_plugin.cpp msgid "Signing debug %s..." @@ -19102,9 +18598,8 @@ msgid "Could not find keystore, unable to export." msgstr "找ä¸åˆ°é‡‘鑰儲å˜å€ï¼Œç„¡æ³•匯出。" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not start apksigner executable." -msgstr "無法啟動å處ç†ç¨‹åºï¼" +msgstr "無法啟動 apksigner å¯åŸ·è¡Œæª”案。" #: platform/android/export/export_plugin.cpp msgid "'apksigner' returned with error #%d" @@ -19135,9 +18630,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension." msgstr "無效的檔案å稱ï¼Android APK å¿…é ˆè¦æœ‰ *.apk 副檔å。" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Unsupported export format!" -msgstr "䏿”¯æ´çš„åŒ¯å‡ºæ ¼å¼ï¼\n" +msgstr "䏿”¯æ´çš„åŒ¯å‡ºæ ¼å¼ï¼" #: platform/android/export/export_plugin.cpp msgid "" @@ -19147,26 +18641,21 @@ msgstr "" "嘗試自自定建置樣æ¿é€²è¡Œå»ºç½®ï¼Œä½†ç„¡ç‰ˆæœ¬è³‡è¨Šå¯ç”¨ã€‚請自「專案ã€é¸å–®ä¸é‡æ–°å®‰è£ã€‚" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Android build version mismatch: Template installed: %s, Godot version: %s. " "Please reinstall Android build template from 'Project' menu." msgstr "" -"Android 建置版本ä¸ç¬¦åˆï¼š\n" -" 已安è£çš„æ¨£æ¿ï¼š%s\n" -" Godot 版本:%s\n" -"請自「專案ã€ç›®éŒ„ä¸é‡æ–°å®‰è£ Android 建置樣æ¿ã€‚" +"Android 建構版本ä¸åŒ¹é…ï¼šå·²å®‰è£æ¨¡æ¿ï¼š %s,Godot 版本:%s。請從專案é¸å–®é‡æ–°å®‰" +"è£ Android 構建模æ¿ã€‚" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Unable to overwrite res://android/build/res/*.xml files with project name." -msgstr "無法以專案å稱覆蓋檔案res://android/build/res/*.xml" +msgstr "無法以專案å稱覆蓋 res://android/build/res/*.xml 檔案。" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files to gradle project." -msgstr "無法匯出專案檔至Gradle專案。\n" +msgstr "無法匯出專案檔至 Gradle 專案。" #: platform/android/export/export_plugin.cpp msgid "Could not write expansion package file!" @@ -19177,13 +18666,12 @@ msgid "Building Android Project (gradle)" msgstr "建置 Android 專案(Gradle)" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Building of Android project failed, check output for the error. " "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"建置 Android 專案失敗,請檢查輸出以確èªéŒ¯èª¤ã€‚\n" -"也å¯ä»¥ç€è¦½ docs.godotengine.org 以ç€è¦½ Android 建置說明文件。" +"建置 Android 專案失敗,請檢查輸出以確èªéŒ¯èª¤ã€‚也å¯ä»¥ç€è¦½ docs.godotengine.org " +"檢視 Android 建置說明文件。" #: platform/android/export/export_plugin.cpp msgid "Moving output" @@ -19196,39 +18684,33 @@ msgid "" msgstr "無法複製並更å匯出的檔案,請於 Gradle 專案資料夾內確èªè¼¸å‡ºã€‚" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Package not found: \"%s\"." -msgstr "未找到套件:「%sã€" +msgstr "未找到套件:「%sã€ã€‚" #: platform/android/export/export_plugin.cpp msgid "Creating APK..." msgstr "æ£åœ¨å»ºç«‹APK……" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not find template APK to export: \"%s\"." -msgstr "" -"找ä¸åˆ°æ¨£æ¿APK以匯出:\n" -"%s" +msgstr "找ä¸åˆ° APK 模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "" "Missing libraries in the export template for the selected architectures: %s. " "Please build a template with all required libraries, or uncheck the missing " "architectures in the export preset." msgstr "" -"éºå¤±æ‰€é¸å–架構(%s)的匯出樣æ¿å‡½å¼åº«ã€‚\n" -"請使用所有必è¦çš„函å¼åº«å»ºæ§‹æ¨£æ¿ï¼Œæˆ–在匯出é è¨è¨å®šä¸å–消勾é¸éºå¤±çš„æž¶æ§‹ã€‚" +"éºå¤±æ‰€é¸æž¶æ§‹ï¼ˆ%s)的匯出模æ¿å‡½å¼åº«ã€‚請使用所有必è¦çš„函å¼åº«å»ºæ§‹æ¨¡æ¿ï¼Œæˆ–在匯出" +"é è¨è¨å®šä¸å–消勾é¸éºå¤±çš„æž¶æ§‹ã€‚" #: platform/android/export/export_plugin.cpp msgid "Adding files..." msgstr "æ£åœ¨åŠ å…¥æª”æ¡ˆ %s……" #: platform/android/export/export_plugin.cpp -#, fuzzy msgid "Could not export project files." -msgstr "無法匯出專案檔案" +msgstr "無法匯出專案檔。" #: platform/android/export/export_plugin.cpp msgid "Aligning APK..." @@ -19324,9 +18806,8 @@ msgid "Code Sign Identity Release" msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Export Method Release" -msgstr "匯出模å¼ï¼š" +msgstr "發行匯出模å¼" #: platform/iphone/export/export.cpp msgid "Targeted Device Family" @@ -19337,9 +18818,8 @@ msgid "Info" msgstr "" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp -#, fuzzy msgid "Identifier" -msgstr "無效的è˜åˆ¥ç¬¦ï¼š" +msgstr "標è˜ç¬¦" #: platform/iphone/export/export.cpp platform/osx/export/export.cpp #, fuzzy @@ -19363,14 +18843,12 @@ msgid "Capabilities" msgstr "貼上屬性" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Access Wi-Fi" -msgstr "æˆåŠŸï¼" +msgstr "å˜å– Wi-Fi" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Push Notifications" -msgstr "隨機旋轉:" +msgstr "推é€é€šçŸ¥" #: platform/iphone/export/export.cpp #, fuzzy @@ -19502,19 +18980,16 @@ msgid "Run exported HTML in the system's default browser." msgstr "在系統的é è¨ç€è¦½å™¨ä¸åŸ·è¡Œå·²åŒ¯å‡ºçš„ HTML。" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not open template for export: \"%s\"." -msgstr "無法開啟樣æ¿ä»¥è¼¸å‡ºï¼š" +msgstr "無法開啟模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Invalid export template: \"%s\"." -msgstr "無效的輸出樣æ¿ï¼š" +msgstr "無效的匯出模æ¿ï¼šã€Œ%sã€ã€‚" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not write file: \"%s\"." -msgstr "無法寫入檔案:" +msgstr "無法寫入檔案:「%sã€ã€‚" #: platform/javascript/export/export.cpp platform/osx/export/export.cpp #, fuzzy @@ -19522,18 +18997,16 @@ msgid "Icon Creation" msgstr "è¨å®šå¤–邊è·" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read file: \"%s\"." -msgstr "ç„¡æ³•è®€å–æª”案:" +msgstr "ç„¡æ³•è®€å–æª”案:「%sã€ã€‚" #: platform/javascript/export/export.cpp msgid "PWA" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Variant" -msgstr "分隔:" +msgstr "變體" #: platform/javascript/export/export.cpp #, fuzzy @@ -19605,19 +19078,16 @@ msgid "Icon 512 X 512" msgstr "" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read HTML shell: \"%s\"." -msgstr "無法讀å–HTML殼層:" +msgstr "ç„¡æ³•è®€å– HTML 殼層:「%sã€ã€‚" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not create HTTP server directory: %s." -msgstr "無法建立HTTP伺æœå™¨ç›®éŒ„:" +msgstr "無法建立 HTTP 伺æœå™¨ç›®éŒ„:%s。" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Error starting HTTP server: %d." -msgstr "啟動HTTP伺æœå™¨æ™‚發生錯誤:" +msgstr "啟動 HTTP 伺æœå™¨æ™‚發生錯誤:%d。" #: platform/javascript/export/export.cpp msgid "Web" @@ -19721,9 +19191,8 @@ msgid "Unknown object type." msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "App Category" -msgstr "分類:" +msgstr "App 分類" #: platform/osx/export/export.cpp msgid "High Res" @@ -19899,9 +19368,8 @@ msgid "Custom Options" msgstr "åŒ¯æµæŽ’é¸é …" #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization" -msgstr "本地化" +msgstr "å…¬è‰" #: platform/osx/export/export.cpp msgid "Apple ID Name" @@ -19916,19 +19384,16 @@ msgid "Apple Team ID" msgstr "" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open icon file \"%s\"." -msgstr "無法匯出專案檔案" +msgstr "無法開啟符號檔 「%sã€ã€‚" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start xcrun executable." -msgstr "無法啟動å處ç†ç¨‹åºï¼" +msgstr "無法啟動 xcrun å¯åŸ·è¡Œæª”案。" #: platform/osx/export/export.cpp -#, fuzzy msgid "Notarization failed." -msgstr "本地化" +msgstr "å…¬è‰å¤±æ•—。" #: platform/osx/export/export.cpp msgid "Notarization request UUID: \"%s\"" @@ -19981,9 +19446,8 @@ msgid "No identity found." msgstr "未發ç¾ä»»ä½•圖示。" #: platform/osx/export/export.cpp -#, fuzzy msgid "Cannot sign file %s." -msgstr "無法ä¿å˜æª”案:%s" +msgstr "無法簽署檔案 %s。" #: platform/osx/export/export.cpp msgid "Relative symlinks are not supported, exported \"%s\" might be broken!" @@ -19995,9 +19459,8 @@ msgid "DMG Creation" msgstr "æ–¹å‘" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not start hdiutil executable." -msgstr "無法啟動å處ç†ç¨‹åºï¼" +msgstr "無法啟動 hdiutil å¯åŸ·è¡Œæª”案。" #: platform/osx/export/export.cpp msgid "`hdiutil create` failed - file exists." @@ -20013,16 +19476,12 @@ msgid "Creating app bundle" msgstr "æ£åœ¨å»ºç«‹ç¸®åœ–" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not find template app to export: \"%s\"." -msgstr "" -"找ä¸åˆ°æ¨£æ¿APK以匯出:\n" -"%s" +msgstr "找ä¸åˆ° app 模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚" #: platform/osx/export/export.cpp -#, fuzzy msgid "Invalid export format." -msgstr "無效的輸出樣æ¿ï¼š" +msgstr "ç„¡æ•ˆçš„åŒ¯å‡ºæ ¼å¼ã€‚" #: platform/osx/export/export.cpp msgid "" @@ -20078,9 +19537,8 @@ msgid "ZIP Creation" msgstr "專案" #: platform/osx/export/export.cpp -#, fuzzy msgid "Could not open file to read from path \"%s\"." -msgstr "無法匯出專案檔至Gradle專案。\n" +msgstr "ç„¡æ³•æ‰“é–‹ä½æ–¼ã€Œ%sã€çš„æª”案進行讀å–。" #: platform/osx/export/export.cpp msgid "Invalid bundle identifier:" @@ -20207,23 +19665,20 @@ msgid "Display Name" msgstr "全部顯示" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Short Name" -msgstr "腳本å稱:" +msgstr "çŸå稱" #: platform/uwp/export/export.cpp msgid "Publisher" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Publisher Display Name" -msgstr "無效的套件發佈者顯示å稱。" +msgstr "發布者顯示å稱" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Product GUID" -msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。" +msgstr "ç”¢å“ GUID" #: platform/uwp/export/export.cpp #, fuzzy @@ -20236,9 +19691,8 @@ msgid "Signing" msgstr "訊號" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Certificate" -msgstr "é ‚é»žï¼š" +msgstr "憑è‰" #: platform/uwp/export/export.cpp #, fuzzy @@ -20306,9 +19760,8 @@ msgid "Wide 310 X 150 Logo" msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Splash Screen" -msgstr "繪製呼å«ï¼š" +msgstr "啟動畫é¢" #: platform/uwp/export/export.cpp #, fuzzy @@ -20398,9 +19851,8 @@ msgid "Debug Algorithm" msgstr "除錯工具" #: platform/windows/export/export.cpp -#, fuzzy msgid "Failed to rename temporary file \"%s\"." -msgstr "無法移除臨時檔案:" +msgstr "ç„¡æ³•é‡æ–°å‘½åæ¨¡æ¿æª”案 「%sã€ã€‚" #: platform/windows/export/export.cpp msgid "Identity Type" @@ -20426,19 +19878,16 @@ msgid "File Version" msgstr "版本" #: platform/windows/export/export.cpp -#, fuzzy msgid "Product Version" -msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。" +msgstr "產å“版本" #: platform/windows/export/export.cpp -#, fuzzy msgid "Company Name" -msgstr "節點å稱:" +msgstr "å…¬å¸å稱" #: platform/windows/export/export.cpp -#, fuzzy msgid "Product Name" -msgstr "專案å稱:" +msgstr "產å“å稱" #: platform/windows/export/export.cpp #, fuzzy @@ -20450,9 +19899,8 @@ msgid "Trademarks" msgstr "" #: platform/windows/export/export.cpp -#, fuzzy msgid "Resources Modification" -msgstr "隨機旋轉:" +msgstr "資æºä¿®æ”¹" #: platform/windows/export/export.cpp #, fuzzy @@ -20466,15 +19914,15 @@ msgstr "找ä¸åˆ°é‡‘鑰儲å˜å€ï¼Œç„¡æ³•匯出。" #: platform/windows/export/export.cpp msgid "" -"Could not start rcedit executable, configure rcedit path in the Editor " -"Settings (Export > Windows > Rcedit)." +"Could not start rcedit executable. Configure rcedit path in the Editor " +"Settings (Export > Windows > Rcedit), or disable \"Application > Modify " +"Resources\" in the export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"rcedit failed to modify executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "rcedit failed to modify executable: %s." +msgstr "無效的副檔å。" #: platform/windows/export/export.cpp #, fuzzy @@ -20487,9 +19935,8 @@ msgid "Could not find osslsigncode executable at \"%s\"." msgstr "找ä¸åˆ°é‡‘鑰儲å˜å€ï¼Œç„¡æ³•匯出。" #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid identity type." -msgstr "無效的è˜åˆ¥ç¬¦ï¼š" +msgstr "身份類型無效。" #: platform/windows/export/export.cpp #, fuzzy @@ -20498,20 +19945,19 @@ msgstr "無效的å稱。" #: platform/windows/export/export.cpp msgid "" -"Could not start signtool executable, configure signtool path in the Editor " -"Settings (Export > Windows > Signtool)." +"Could not start signtool executable. Configure signtool path in the Editor " +"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the " +"export preset." msgstr "" #: platform/windows/export/export.cpp -msgid "" -"Signtool failed to sign executable:\n" -"%s" -msgstr "" +#, fuzzy +msgid "Signtool failed to sign executable: %s." +msgstr "無效的副檔å。" #: platform/windows/export/export.cpp -#, fuzzy msgid "Failed to remove temporary file \"%s\"." -msgstr "無法移除臨時檔案:" +msgstr "ç„¡æ³•ç§»é™¤æ¨¡æ¿æª”案 「%sã€ã€‚" #: platform/windows/export/export.cpp msgid "" @@ -20520,19 +19966,16 @@ msgid "" msgstr "" #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid icon path:" -msgstr "無效的路徑。" +msgstr "無效符號路徑:" #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid file version:" -msgstr "無效的副檔å。" +msgstr "無效的檔案版本:" #: platform/windows/export/export.cpp -#, fuzzy msgid "Invalid product version:" -msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。" +msgstr "無效的產å“版本:" #: platform/windows/export/export.cpp msgid "Windows executables cannot be >= 4 GiB." @@ -20701,9 +20144,8 @@ msgstr "" #: scene/3d/light.cpp scene/3d/reflection_probe.cpp #: scene/3d/visibility_notifier.cpp scene/3d/visual_instance.cpp #: scene/resources/material.cpp -#, fuzzy msgid "Max Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "最大è·é›¢" #: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp #, fuzzy @@ -20731,15 +20173,13 @@ msgid "Anchor Mode" msgstr "圖示模å¼" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Rotating" -msgstr "旋轉æ¥é•·ï¼š" +msgstr "旋轉" #: scene/2d/camera_2d.cpp scene/2d/listener_2d.cpp scene/3d/camera.cpp #: scene/3d/listener.cpp scene/animation/animation_blend_tree.cpp -#, fuzzy msgid "Current" -msgstr "ç›®å‰ï¼š" +msgstr "ç›®å‰" #: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp #, fuzzy @@ -20821,14 +20261,12 @@ msgid "Drag Margin" msgstr "è¨å®šå¤–邊è·" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Screen" -msgstr "繪製呼å«ï¼š" +msgstr "繪製螢幕" #: scene/2d/camera_2d.cpp -#, fuzzy msgid "Draw Limits" -msgstr "繪製呼å«ï¼š" +msgstr "繪製é™åˆ¶" #: scene/2d/camera_2d.cpp #, fuzzy @@ -21005,9 +20443,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Emitting" -msgstr "è¨å®šï¼š" +msgstr "發射" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp @@ -21033,9 +20470,8 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp #: scene/3d/cpu_particles.cpp scene/3d/particles.cpp -#, fuzzy msgid "Randomness" -msgstr "éš¨æ©Ÿé‡æ–°é–‹å§‹ï¼ˆç§’):" +msgstr "隨機性" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21077,9 +20513,8 @@ msgstr "發射é®ç½©" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Sphere Radius" -msgstr "發射æºï¼š " +msgstr "çƒé«”åŠå¾‘" #: scene/2d/cpu_particles_2d.cpp #, fuzzy @@ -21147,9 +20582,8 @@ msgstr "線性" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Accel" -msgstr "æˆåŠŸï¼" +msgstr "åŠ é€Ÿåº¦" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21208,9 +20642,8 @@ msgid "Angle Curve" msgstr "關閉曲線" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp -#, fuzzy msgid "Scale Amount" -msgstr "數é‡ï¼š" +msgstr "縮放é‡" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp msgid "Scale Amount Random" @@ -21234,27 +20667,23 @@ msgstr "" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Hue Variation" -msgstr "分隔:" +msgstr "色相變化" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Variation" -msgstr "分隔:" +msgstr "變化" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Variation Random" -msgstr "分隔:" +msgstr "隨機變化" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Variation Curve" -msgstr "分隔:" +msgstr "變化曲線" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21270,9 +20699,8 @@ msgstr "拆分控制點" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp -#, fuzzy msgid "Offset Random" -msgstr "å移:" +msgstr "隨機åç§»" #: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp #: scene/resources/particles_material.cpp @@ -21465,14 +20893,12 @@ msgid "Begin Cap Mode" msgstr "å€åŸŸæ¨¡å¼" #: scene/2d/line_2d.cpp -#, fuzzy msgid "End Cap Mode" -msgstr "å¸é™„模å¼ï¼š" +msgstr "尾端模å¼" #: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp -#, fuzzy msgid "Border" -msgstr "釿–°å‘½å資料夾:" +msgstr "邊框" #: scene/2d/line_2d.cpp msgid "Sharp Limit" @@ -21499,9 +20925,8 @@ msgid "Cell Size" msgstr "" #: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp -#, fuzzy msgid "Edge Connection Margin" -msgstr "編輯連接內容:" +msgstr "邊界連接邊è·" #: scene/2d/navigation_2d.cpp msgid "" @@ -21516,18 +20941,16 @@ msgid "Pathfinding" msgstr "ç¶å®š" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Path Desired Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "路徑所需è·é›¢" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp msgid "Target Desired Distance" msgstr "" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Path Max Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "路徑最大è·é›¢" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp #, fuzzy @@ -21553,9 +20976,8 @@ msgid "Time Horizon" msgstr "水平翻轉" #: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp -#, fuzzy msgid "Max Speed" -msgstr "速度:" +msgstr "最大速度" #: scene/2d/navigation_agent_2d.cpp msgid "" @@ -21597,24 +21019,21 @@ msgstr "行程" #: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp #: scene/main/canvas_layer.cpp -#, fuzzy msgid "Rotation Degrees" -msgstr "旋轉 %s 度。" +msgstr "旋轉角度" -#: scene/2d/node_2d.cpp +#: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy msgid "Global Rotation" msgstr "常數" #: scene/2d/node_2d.cpp -#, fuzzy msgid "Global Rotation Degrees" -msgstr "旋轉 %s 度。" +msgstr "全域旋轉角度" #: scene/2d/node_2d.cpp -#, fuzzy msgid "Global Scale" -msgstr "隨機縮放:" +msgstr "全域縮放" #: scene/2d/node_2d.cpp scene/3d/spatial.cpp #, fuzzy @@ -21632,9 +21051,8 @@ msgid "Scroll" msgstr "" #: scene/2d/parallax_background.cpp -#, fuzzy msgid "Base Offset" -msgstr "å移:" +msgstr "基礎åç§»" #: scene/2d/parallax_background.cpp #, fuzzy @@ -21724,19 +21142,16 @@ msgid "PathFollow2D only works when set as a child of a Path2D node." msgstr "PathFollow2D 僅在其為 Path2D çš„å節點時有效。" #: scene/2d/path_2d.cpp scene/3d/path.cpp -#, fuzzy msgid "Unit Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "å–®ä½åç§»" #: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp -#, fuzzy msgid "H Offset" -msgstr "å移:" +msgstr "H åç§»" #: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp -#, fuzzy msgid "V Offset" -msgstr "å移:" +msgstr "V åç§»" #: scene/2d/path_2d.cpp scene/3d/path.cpp msgid "Cubic Interp" @@ -21797,9 +21212,8 @@ msgid "Mass" msgstr "" #: scene/2d/physics_body_2d.cpp -#, fuzzy msgid "Inertia" -msgstr "垂直:" +msgstr "慣性" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #, fuzzy @@ -21836,9 +21250,8 @@ msgid "Sleeping" msgstr "智慧型å¸é™„" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Can Sleep" -msgstr "速度:" +msgstr "å¯ä»¥ç¡çœ " #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp msgid "Damp" @@ -21862,9 +21275,8 @@ msgid "Safe Margin" msgstr "è¨å®šå¤–邊è·" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Sync To Physics" -msgstr " (物ç†ï¼‰" +msgstr "與物ç†åŒæ¥" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #, fuzzy @@ -21884,9 +21296,8 @@ msgid "Normal" msgstr "æ ¼å¼" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Remainder" -msgstr "算繪引擎:" +msgstr "餘é‡" #: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp #, fuzzy @@ -22076,9 +21487,8 @@ msgid "Compatibility Mode" msgstr "優先模å¼" #: scene/2d/tile_map.cpp -#, fuzzy msgid "Centered Textures" -msgstr "主è¦åŠŸèƒ½ï¼š" +msgstr "ç´‹ç†å±…ä¸" #: scene/2d/tile_map.cpp msgid "Cell Clip UV" @@ -22197,9 +21607,8 @@ msgid "ARVROrigin requires an ARVRCamera child node." msgstr "ARVROrigin å¿…é ˆæœ‰ä¸€å€‹ ARVRCamera å節點。" #: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp -#, fuzzy msgid "World Scale" -msgstr "隨機縮放:" +msgstr "世界縮放" #: scene/3d/audio_stream_player_3d.cpp #, fuzzy @@ -22228,9 +21637,8 @@ msgid "Emission Angle" msgstr "發射色彩" #: scene/3d/audio_stream_player_3d.cpp -#, fuzzy msgid "Degrees" -msgstr "旋轉 %s 度。" +msgstr "角度" #: scene/3d/audio_stream_player_3d.cpp #, fuzzy @@ -22312,9 +21720,8 @@ msgid "Bounce Indirect Energy" msgstr "" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Use Denoiser" -msgstr "篩é¸ï¼š" +msgstr "使用é™å™ªå™¨" #: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp msgid "Use HDR" @@ -22341,9 +21748,8 @@ msgid "Generate" msgstr "一般" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Max Size" -msgstr "大å°ï¼š" +msgstr "最大大å°" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -22351,9 +21757,8 @@ msgid "Custom Sky" msgstr "剪下節點" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Custom Sky Rotation Degrees" -msgstr "旋轉 %s 度。" +msgstr "自定義天空旋轉角度" #: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp #, fuzzy @@ -22385,9 +21790,8 @@ msgid "Light Data" msgstr "åŒ…å«æ•¸æ“š" #: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp -#, fuzzy msgid "Bone Name" -msgstr "節點å稱:" +msgstr "骨骼å稱" #: scene/3d/camera.cpp msgid "Keep Aspect" @@ -22412,9 +21816,8 @@ msgid "FOV" msgstr "" #: scene/3d/camera.cpp -#, fuzzy msgid "Frustum Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "視éŒåç§»" #: scene/3d/camera.cpp #, fuzzy @@ -22666,9 +22069,8 @@ msgid "Font" msgstr "å—é«”" #: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp -#, fuzzy msgid "Horizontal Alignment" -msgstr "水平:" +msgstr "æ°´å¹³å°é½Š" #: scene/3d/label_3d.cpp #, fuzzy @@ -22732,9 +22134,8 @@ msgid "Split 3" msgstr "拆分路徑" #: scene/3d/light.cpp -#, fuzzy msgid "Blend Splits" -msgstr "æ··åˆæ™‚間:" +msgstr "æ··åˆæ‹†åˆ†" #: scene/3d/light.cpp #, fuzzy @@ -22778,9 +22179,8 @@ msgid "Software Skinning" msgstr "" #: scene/3d/mesh_instance.cpp -#, fuzzy msgid "Transform Normals" -msgstr "已䏿¢è®Šæ›ã€‚" +msgstr "è®Šæ›æ³•ç·š" #: scene/3d/navigation.cpp msgid "" @@ -22869,14 +22269,12 @@ msgid "Visibility AABB" msgstr "切æ›å¯è¦‹ï¼éš±è—" #: scene/3d/particles.cpp -#, fuzzy msgid "Draw Passes" -msgstr "繪製呼å«ï¼š" +msgstr "繪製階段" #: scene/3d/particles.cpp -#, fuzzy msgid "Passes" -msgstr "繪製呼å«ï¼š" +msgstr "階段" #: scene/3d/path.cpp msgid "PathFollow only works when set as a child of a Path node." @@ -22972,9 +22370,8 @@ msgstr "" #: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Relaxation" -msgstr "分隔:" +msgstr "鬆弛" #: scene/3d/physics_body.cpp #, fuzzy @@ -22987,9 +22384,8 @@ msgid "Angular Limit Upper" msgstr "線性" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Angular Limit Lower" -msgstr "最大角度誤差:" +msgstr "角度下é™" #: scene/3d/physics_body.cpp #, fuzzy @@ -23120,9 +22516,8 @@ msgid "Angular Equilibrium Point" msgstr "" #: scene/3d/physics_body.cpp -#, fuzzy msgid "Body Offset" -msgstr "å移:" +msgstr "形體åç§»" #: scene/3d/physics_joint.cpp msgid "Node A and Node B must be PhysicsBodies" @@ -23154,9 +22549,8 @@ msgid "Exclude Nodes" msgstr "刪除節點" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Params" -msgstr "å·²æ›´æ”¹åƒæ•¸ï¼š" +msgstr "引數" #: scene/3d/physics_joint.cpp msgid "Angular Limit" @@ -23182,9 +22576,8 @@ msgid "Target Velocity" msgstr "å‘å³ç’°è¦–" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Max Impulse" -msgstr "速度:" +msgstr "最大è¡é‡" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23192,14 +22585,12 @@ msgid "Linear Limit" msgstr "線性" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Upper Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "è·é›¢ä¸Šé™" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Lower Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "è·é›¢ä¸‹é™" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23232,9 +22623,8 @@ msgid "Angular Motion" msgstr "å‹•ç•«" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Angular Ortho" -msgstr "最大角度誤差:" +msgstr "角度æ£äº¤" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23247,9 +22637,8 @@ msgid "Linear Motor X" msgstr "åˆå§‹åŒ–" #: scene/3d/physics_joint.cpp -#, fuzzy msgid "Force Limit" -msgstr "繪製呼å«ï¼š" +msgstr "力度é™åˆ¶" #: scene/3d/physics_joint.cpp #, fuzzy @@ -23347,9 +22736,8 @@ msgid "Two Way" msgstr "" #: scene/3d/portal.cpp -#, fuzzy msgid "Linked Room" -msgstr "峿™‚ç·¨è¼¯æ ¹ç¯€é»žï¼š" +msgstr "連接房間" #: scene/3d/portal.cpp #, fuzzy @@ -23366,9 +22754,8 @@ msgid "Dispatch Mode" msgstr "" #: scene/3d/proximity_group.cpp -#, fuzzy msgid "Grid Radius" -msgstr "åŠå¾‘:" +msgstr "ç¶²æ ¼åŠå¾‘" #: scene/3d/ray_cast.cpp #, fuzzy @@ -23385,9 +22772,8 @@ msgid "Update Mode" msgstr "旋轉模å¼" #: scene/3d/reflection_probe.cpp -#, fuzzy msgid "Origin Offset" -msgstr "ç¶²æ ¼åç§»é‡ï¼š" +msgstr "原點åç§»" #: scene/3d/reflection_probe.cpp #, fuzzy @@ -23649,14 +23035,12 @@ msgid "Parent Collision Ignore" msgstr "建立碰撞多邊形" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Simulation Precision" -msgstr "無效的動畫樹。" +msgstr "模擬精度" #: scene/3d/soft_body.cpp -#, fuzzy msgid "Total Mass" -msgstr "總計:" +msgstr "總質é‡" #: scene/3d/soft_body.cpp msgid "Linear Stiffness" @@ -23700,13 +23084,16 @@ msgstr "" "請改為修改其å節點的碰撞形狀之大å°ã€‚" #: scene/3d/spatial.cpp +msgid "Global Translation" +msgstr "全域變æ›" + +#: scene/3d/spatial.cpp msgid "Matrix" msgstr "" #: scene/3d/spatial.cpp -#, fuzzy msgid "Gizmo" -msgstr "Gizmo" +msgstr "控制器" #: scene/3d/spatial_velocity_tracker.cpp #, fuzzy @@ -23765,18 +23152,16 @@ msgid "VehicleBody Motion" msgstr "" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Use As Traction" -msgstr "分隔:" +msgstr "用作牽引" #: scene/3d/vehicle_body.cpp msgid "Use As Steering" msgstr "" #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "Wheel" -msgstr "滾輪å‘上。" +msgstr "車輪" #: scene/3d/vehicle_body.cpp msgid "Roll Influence" @@ -23812,9 +23197,8 @@ msgid "Material Override" msgstr "複寫" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Material Overlay" -msgstr "æè³ªè®Šæ›´ï¼š" +msgstr "æè³ªè¦†è“‹å±¤" #: scene/3d/visual_instance.cpp #, fuzzy @@ -23822,9 +23206,8 @@ msgid "Cast Shadow" msgstr "建立著色器節點" #: scene/3d/visual_instance.cpp -#, fuzzy msgid "Extra Cull Margin" -msgstr "é¡å¤–呼å«å¼•數:" +msgstr "é¡å¤–剔除邊è·" #: scene/3d/visual_instance.cpp #, fuzzy @@ -23846,9 +23229,8 @@ msgstr "" #: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp #: scene/resources/material.cpp -#, fuzzy msgid "Min Distance" -msgstr "鏿“‡è·é›¢ï¼š" +msgstr "最å°è·é›¢" #: scene/3d/visual_instance.cpp msgid "Min Hysteresis" @@ -24349,18 +23731,16 @@ msgid "Mouse" msgstr "" #: scene/gui/control.cpp -#, fuzzy msgid "Default Cursor Shape" -msgstr "載入é è¨åŒ¯æµæŽ’é…置。" +msgstr "é è¨æ¸¸æ¨™å½¢ç‹€" #: scene/gui/control.cpp msgid "Pass On Modal Close Click" msgstr "" #: scene/gui/control.cpp -#, fuzzy msgid "Size Flags" -msgstr "大å°ï¼š " +msgstr "å¤§å° Flag:" #: scene/gui/control.cpp #, fuzzy @@ -24726,9 +24106,8 @@ msgid "Max Value" msgstr "數值" #: scene/gui/range.cpp -#, fuzzy msgid "Page" -msgstr "é : " +msgstr "é " #: scene/gui/range.cpp #, fuzzy @@ -24916,9 +24295,8 @@ msgid "All Tabs In Front" msgstr "" #: scene/gui/tab_container.cpp scene/gui/tabs.cpp -#, fuzzy msgid "Drag To Rearrange Enabled" -msgstr "æ‹–æ”¾ä»¥é‡æ–°æŽ’列。" +msgstr "å•Ÿç”¨æ‹–ç§»é‡æ–°æŽ’列" #: scene/gui/tab_container.cpp msgid "Use Hidden Tabs For Min Size" @@ -25055,9 +24433,8 @@ msgid "Initial Angle" msgstr "åˆå§‹åŒ–" #: scene/gui/texture_progress.cpp -#, fuzzy msgid "Fill Degrees" -msgstr "旋轉 %s 度。" +msgstr "填充角度" #: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp #, fuzzy @@ -25164,9 +24541,8 @@ msgid "Max Redirects" msgstr "" #: scene/main/http_request.cpp -#, fuzzy msgid "Timeout" -msgstr "逾時。" +msgstr "逾時" #: scene/main/node.cpp msgid "" @@ -25294,9 +24670,8 @@ msgid "Draw 2D Outlines" msgstr "建立輪廓" #: scene/main/scene_tree.cpp servers/visual_server.cpp -#, fuzzy msgid "Reflections" -msgstr "æ–¹å‘" +msgstr "åå°„" #: scene/main/scene_tree.cpp #, fuzzy @@ -25933,9 +25308,8 @@ msgid "Labeled Separator Right" msgstr "帶å稱的分隔線" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Separator" -msgstr "色彩é‹ç®—å。" +msgstr "分隔線å—é«”" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -25943,9 +25317,8 @@ msgid "Font Color Accel" msgstr "釿–°å‘½åé¡è‰²é …ç›®" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Font Color Separator" -msgstr "色彩é‹ç®—å。" +msgstr "分隔線å—é«”é¡è‰²" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26233,9 +25606,8 @@ msgid "Label Width" msgstr "左延展" #: scene/resources/default_theme/default_theme.cpp -#, fuzzy msgid "Screen Picker" -msgstr "濾色é‹ç®—å。" +msgstr "å±å¹•å–色器" #: scene/resources/default_theme/default_theme.cpp #, fuzzy @@ -26450,9 +25822,8 @@ msgid "Sky Rotation" msgstr "旋轉æ¥é•·ï¼š" #: scene/resources/environment.cpp -#, fuzzy msgid "Sky Rotation Degrees" -msgstr "旋轉 %s 度。" +msgstr "天空旋轉角度" #: scene/resources/environment.cpp msgid "Canvas Max Layer" @@ -26632,9 +26003,8 @@ msgid "Distance" msgstr "鏿“‡è·é›¢ï¼š" #: scene/resources/environment.cpp -#, fuzzy msgid "Transition" -msgstr "è½‰å ´ï¼š " +msgstr "è½‰å ´æ•ˆæžœ" #: scene/resources/environment.cpp msgid "DOF Near Blur" @@ -26717,9 +26087,8 @@ msgid "Saturation" msgstr "分隔:" #: scene/resources/environment.cpp -#, fuzzy msgid "Color Correction" -msgstr "é¡è‰²å‡½å¼ã€‚" +msgstr "é¡è‰²æ ¡æ£" #: scene/resources/font.cpp #, fuzzy @@ -26801,9 +26170,8 @@ msgid "Disable Ambient Light" msgstr "å‘å³ç¸®æŽ’" #: scene/resources/material.cpp -#, fuzzy msgid "Ensure Correct Normals" -msgstr "已䏿¢è®Šæ›ã€‚" +msgstr "ç¢ºä¿æ£ç¢ºæ³•ç·š" #: scene/resources/material.cpp msgid "Albedo Tex MSDF" @@ -26970,9 +26338,8 @@ msgid "Subsurf Scatter" msgstr "" #: scene/resources/material.cpp -#, fuzzy msgid "Transmission" -msgstr "è½‰å ´ï¼š " +msgstr "è½‰å ´" #: scene/resources/material.cpp #, fuzzy @@ -27040,14 +26407,12 @@ msgid "NavMesh Transform" msgstr "清除變æ›" #: scene/resources/multimesh.cpp -#, fuzzy msgid "Color Format" -msgstr "色彩é‹ç®—å。" +msgstr "é¡è‰²æ ¼å¼" #: scene/resources/multimesh.cpp -#, fuzzy msgid "Transform Format" -msgstr "已䏿¢è®Šæ›ã€‚" +msgstr "è®Šæ›æ ¼å¼" #: scene/resources/multimesh.cpp msgid "Custom Data Format" @@ -27063,9 +26428,8 @@ msgid "Visible Instance Count" msgstr "" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Sampling" -msgstr "縮放: " +msgstr "縮放:" #: scene/resources/navigation_mesh.cpp #, fuzzy @@ -27073,9 +26437,8 @@ msgid "Partition Type" msgstr "è¨å®šè®Šæ•¸åž‹åˆ¥" #: scene/resources/navigation_mesh.cpp -#, fuzzy msgid "Parsed Geometry Type" -msgstr "æ£åœ¨è§£æžå¤šé‚Šå½¢..." +msgstr "è§£æžå¹¾ä½•體類型" #: scene/resources/navigation_mesh.cpp msgid "Source Geometry Mode" @@ -27209,14 +26572,12 @@ msgid "Point Texture" msgstr "發射點:" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Normal Texture" -msgstr "發射æºï¼š " +msgstr "法線紋ç†è²¼åœ–" #: scene/resources/particles_material.cpp -#, fuzzy msgid "Color Texture" -msgstr "編輯器主題" +msgstr "é¡è‰²ç´‹ç†è²¼åœ–" #: scene/resources/particles_material.cpp #, fuzzy @@ -27415,9 +26776,8 @@ msgid "Base Texture" msgstr "移除紋ç†" #: scene/resources/texture.cpp -#, fuzzy msgid "Image Size" -msgstr "é : " +msgstr "圖片大å°" #: scene/resources/texture.cpp #, fuzzy @@ -27829,9 +27189,8 @@ msgid "Pan Pullout" msgstr "" #: servers/audio/effects/audio_effect_stereo_enhance.cpp -#, fuzzy msgid "Time Pullout (ms)" -msgstr "逾時。" +msgstr "撤離時間(毫秒)" #: servers/audio/effects/audio_effect_stereo_enhance.cpp msgid "Surround" @@ -27886,119 +27245,105 @@ msgstr "é€è¦–" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Sleep Threshold Linear" -msgstr "" +msgstr "線性ç¡çœ 速度閾值" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Sleep Threshold Angular" -msgstr "" +msgstr "ç¡çœ 角速度閾值" #: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp msgid "Time Before Sleep" -msgstr "" +msgstr "ç¡çœ 剿™‚é–“" #: servers/physics_2d/physics_2d_server_sw.cpp -#, fuzzy msgid "BP Hash Table Size" -msgstr "大å°ï¼š" +msgstr "BP 雜湊表大å°" #: servers/physics_2d/physics_2d_server_sw.cpp msgid "Large Object Surface Threshold In Cells" -msgstr "" +msgstr "大物件表é¢å–®ä½æ ¼é–¾å€¼" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Inverse Mass" -msgstr "" +msgstr "逆質é‡" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Inverse Inertia" -msgstr "自由視圖 å·¦" +msgstr "逆慣性" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Total Angular Damp" -msgstr "" +msgstr "總角速度減幅" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Total Linear Damp" -msgstr "線性" +msgstr "總線性速度減幅" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Total Gravity" -msgstr "é è¨é 覽" +msgstr "總é‡åŠ›" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Linear Velocity" -msgstr "åˆå§‹åŒ–" +msgstr "線性速度" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Exclude" -msgstr "" +msgstr "排除" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Shape RID" -msgstr "" +msgstr "形狀RID" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collide With Bodies" -msgstr "碰撞模å¼" +msgstr "形體間碰撞" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Collide With Areas" -msgstr "" +msgstr "å€åŸŸé–“碰撞" #: servers/physics_2d_server.cpp servers/physics_server.cpp msgid "Motion Remainder" -msgstr "" +msgstr "é‹å‹•剩餘é‡" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Point" -msgstr "碰撞模å¼" +msgstr "碰撞點" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Normal" -msgstr "碰撞模å¼" +msgstr "碰撞法線" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Depth" -msgstr "碰撞模å¼" +msgstr "碰撞深度" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Safe Fraction" -msgstr "碰撞模å¼" +msgstr "碰撞安全比值" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Collision Unsafe Fraction" -msgstr "碰撞模å¼" +msgstr "碰撞éžå®‰å…¨æ¯”值" #: servers/physics_2d_server.cpp servers/physics_server.cpp -#, fuzzy msgid "Physics Engine" -msgstr "物ç†å½±æ ¼ %" +msgstr "物ç†å¼•擎" #: servers/physics_server.cpp -#, fuzzy msgid "Center Of Mass" -msgstr "ä¸å·¦" +msgstr "質é‡ä¸å¿ƒ" #: servers/physics_server.cpp msgid "Principal Inertia Axes" -msgstr "" +msgstr "主慣性軸" #: servers/visual/shader_language.cpp msgid "Varying may not be assigned in the '%s' function." -msgstr "Varying 變數ä¸å¯åœ¨å‡½å¼ã€Œ%sã€ä¸è¢«æŒ‡æ´¾ã€‚" +msgstr "Varying變數ä¸å¯åœ¨ã€Œ%sã€å‡½å¼ä¸è¢«æŒ‡æ´¾ã€‚" #: servers/visual/shader_language.cpp -#, fuzzy msgid "" "Varyings which were assigned in 'vertex' function may not be reassigned in " "'fragment' or 'light'." @@ -28007,7 +27352,6 @@ msgstr "" "指派。" #: servers/visual/shader_language.cpp -#, fuzzy msgid "" "Varyings which were assigned in 'fragment' function may not be reassigned in " "'vertex' or 'light'." @@ -28028,39 +27372,32 @@ msgid "Constants cannot be modified." msgstr "ä¸å¯ä¿®æ”¹å¸¸æ•¸ã€‚" #: servers/visual/visual_server_scene.cpp -#, fuzzy msgid "Spatial Partitioning" -msgstr "æ£åœ¨åˆ†å‰²..." +msgstr "空間分割" #: servers/visual_server.cpp -#, fuzzy msgid "Render Loop Enabled" -msgstr "篩é¸è¨Šè™Ÿ" +msgstr "啟用算繪迴圈" #: servers/visual_server.cpp -#, fuzzy msgid "VRAM Compression" -msgstr "è¨å®šè¡¨ç¤ºå¼" +msgstr "VRAM壓縮" #: servers/visual_server.cpp -#, fuzzy msgid "Import BPTC" -msgstr "匯入" +msgstr "匯入BPTC" #: servers/visual_server.cpp -#, fuzzy msgid "Import S3TC" -msgstr "匯入" +msgstr "匯入S3TC" #: servers/visual_server.cpp -#, fuzzy msgid "Import ETC" -msgstr "匯入" +msgstr "匯入ETC" #: servers/visual_server.cpp -#, fuzzy msgid "Import ETC2" -msgstr "匯入" +msgstr "匯入ETC2" #: servers/visual_server.cpp #, fuzzy @@ -28072,9 +27409,8 @@ msgid "Lossless Compression" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Force PNG" -msgstr "來æºç¶²æ ¼ï¼š" +msgstr "強制 PNG" #: servers/visual_server.cpp msgid "WebP Compression Level" @@ -28118,7 +27454,7 @@ msgstr "篩é¸ç¯€é»ž" #: servers/visual_server.cpp #, fuzzy msgid "Texture Array Reflections" -msgstr "ç½®ä¸æ‰€é¸" +msgstr "ç´‹ç†è²¼åœ–陣列åå°„" #: servers/visual_server.cpp msgid "High Quality GGX" @@ -28175,20 +27511,24 @@ msgid "Use Nearest Mipmap Filter" msgstr "" #: servers/visual_server.cpp +#, fuzzy msgid "Skinning" -msgstr "" +msgstr "外觀變更" #: servers/visual_server.cpp +#, fuzzy msgid "Software Skinning Fallback" -msgstr "" +msgstr "軟體外觀變更後備" #: servers/visual_server.cpp +#, fuzzy msgid "Force Software Skinning" -msgstr "" +msgstr "強制軟體外觀變更" #: servers/visual_server.cpp +#, fuzzy msgid "Use Software Skinning" -msgstr "" +msgstr "使用軟體外觀變更" #: servers/visual_server.cpp #, fuzzy @@ -28218,9 +27558,8 @@ msgid "Legacy Stream" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Batching" -msgstr "æ£åœ¨æœå°‹..." +msgstr "分批" #: servers/visual_server.cpp msgid "Use Batching" @@ -28250,7 +27589,7 @@ msgstr "" #: servers/visual_server.cpp #, fuzzy msgid "Max Join Items" -msgstr "管ç†é …目……" +msgstr "æœ€å¤§åŠ å…¥é …ç›®æ•¸" #: servers/visual_server.cpp msgid "Batch Buffer Size" @@ -28306,7 +27645,7 @@ msgstr "使用縮放å¸é™„" #: servers/visual_server.cpp msgid "PVS Logging" -msgstr "" +msgstr "PVS 日誌" #: servers/visual_server.cpp #, fuzzy @@ -28338,9 +27677,8 @@ msgid "Max Active Polygons" msgstr "移動多邊形" #: servers/visual_server.cpp -#, fuzzy msgid "Shader Compilation Mode" -msgstr "æ’值模å¼" +msgstr "è‘—è‰²å™¨ç·¨è¯æ¨¡å¼" #: servers/visual_server.cpp msgid "Max Simultaneous Compiles" @@ -28351,6 +27689,5 @@ msgid "Log Active Async Compiles Count" msgstr "" #: servers/visual_server.cpp -#, fuzzy msgid "Shader Cache Size (MB)" -msgstr "更改相機尺寸" +msgstr "著色器快å–å¤§å° ï¼ˆMB)" diff --git a/gles3_builders.py b/gles3_builders.py index 6b2d315603..a9fabd93ce 100644 --- a/gles3_builders.py +++ b/gles3_builders.py @@ -436,7 +436,7 @@ def build_gles3_header(filename, include, class_suffix, output_attribs): ) fd.write( - """_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix,RID p_version,ShaderVariant p_variant""" + """_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Projection& p_matrix,RID p_version,ShaderVariant p_variant""" + defvariant + """,uint64_t p_specialization=""" + str(defspec) diff --git a/main/main.cpp b/main/main.cpp index 2bb67f17f1..965fcc66c6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -31,6 +31,7 @@ #include "main.h" #include "core/config/project_settings.h" +#include "core/core_globals.h" #include "core/core_string_names.h" #include "core/crypto/crypto.h" #include "core/debugger/engine_debugger.h" @@ -148,7 +149,7 @@ static bool cmdline_tool = false; static String locale; static bool show_help = false; static bool auto_quit = false; -static OS::ProcessID allow_focus_steal_pid = 0; +static OS::ProcessID editor_pid = 0; #ifdef TOOLS_ENABLED static bool auto_build_solutions = false; static String debug_server_uri; @@ -181,7 +182,6 @@ static bool debug_navigation = false; static int frame_delay = 0; static bool disable_render_loop = false; static int fixed_fps = -1; -static String write_movie_path; static MovieWriter *movie_writer = nullptr; static bool disable_vsync = false; static bool print_fps = false; @@ -286,6 +286,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print("\n"); OS::get_singleton()->print("Run options:\n"); + OS::get_singleton()->print(" -- Separator for user-provided arguments. Following arguments are not used by the engine, but can be read from `OS.get_cmdline_user_args()`.\n"); #ifdef TOOLS_ENABLED OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n"); OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); @@ -344,6 +345,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n"); OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); + OS::get_singleton()->print(" --xr-mode <mode> Select XR mode (default/off/on).\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Debug options:\n"); @@ -410,6 +412,8 @@ Error Main::test_setup() { String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); + register_core_settings(); //here globals are present + translation_server = memnew(TranslationServer); tsman = memnew(TextServerManager); @@ -427,6 +431,7 @@ Error Main::test_setup() { /** INITIALIZE SERVERS **/ register_server_types(); + XRServer::set_xr_mode(XRServer::XRMODE_OFF); // Skip in tests. initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); @@ -621,6 +626,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph /* argument parsing and main creation */ List<String> args; List<String> main_args; + List<String> user_args; + bool adding_user_args = false; List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args(); // Add command line arguments. @@ -685,7 +692,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph I = args.front(); while (I) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED // Ignore the process serial number argument passed by macOS Gatekeeper. // Otherwise, Godot would try to open a non-existent project on the first start and abort. if (I->get().begins_with("-psn_")) { @@ -693,9 +700,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph continue; } #endif + List<String>::Element *N = I->next(); - if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help + if (adding_user_args) { + user_args.push_back(I->get()); + } else if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help show_help = true; exit_code = ERR_HELP; // Hack to force an early exit in `main()` with a success code. @@ -1044,10 +1054,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (I->next()) { String p = I->next()->get(); - if (OS::get_singleton()->set_cwd(p) == OK) { - //nothing - } else { - project_path = I->next()->get(); //use project_path instead + if (OS::get_singleton()->set_cwd(p) != OK) { + OS::get_singleton()->print("Invalid project path specified: \"%s\", aborting.\n", p.utf8().get_data()); + goto error; } N = I->next()->next(); } else { @@ -1141,9 +1150,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Missing remote debug host address, aborting.\n"); goto error; } - } else if (I->get() == "--allow_focus_steal_pid") { // not exposed to user + } else if (I->get() == "--editor-pid") { // not exposed to user if (I->next()) { - allow_focus_steal_pid = I->next()->get().to_int(); + editor_pid = I->next()->get().to_int(); N = I->next()->next(); } else { OS::get_singleton()->print("Missing editor PID argument, aborting.\n"); @@ -1161,7 +1170,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "--write-movie") { if (I->next()) { - write_movie_path = I->next()->get(); + Engine::get_singleton()->set_write_movie_path(I->next()->get()); N = I->next()->next(); if (fixed_fps == -1) { fixed_fps = 60; @@ -1181,6 +1190,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->disable_crash_handler(); } else if (I->get() == "--skip-breakpoints") { skip_breakpoints = true; + } else if (I->get() == "--xr-mode") { + if (I->next()) { + String xr_mode = I->next()->get().to_lower(); + N = I->next()->next(); + if (xr_mode == "default") { + XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT); + } else if (xr_mode == "off") { + XRServer::set_xr_mode(XRServer::XRMODE_OFF); + } else if (xr_mode == "on") { + XRServer::set_xr_mode(XRServer::XRMODE_ON); + } else { + OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data()); + goto error; + } + } else { + OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n"); + goto error; + } + } else if (I->get() == "--") { + adding_user_args = true; } else { main_args.push_back(I->get()); } @@ -1273,7 +1302,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph PROPERTY_HINT_RANGE, "0, 200, 1, or_greater")); - EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints); + EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints, []() { + if (editor_pid) { + DisplayServer::get_singleton()->enable_for_stealing_focus(editor_pid); + } + }); #ifdef TOOLS_ENABLED if (editor) { @@ -1344,16 +1377,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph quiet_stdout = true; } if (bool(ProjectSettings::get_singleton()->get("application/run/disable_stderr"))) { - _print_error_enabled = false; + CoreGlobals::print_error_enabled = false; }; if (quiet_stdout) { - _print_line_enabled = false; + CoreGlobals::print_line_enabled = false; } Logger::set_flush_stdout_on_print(ProjectSettings::get_singleton()->get("application/run/flush_stdout_on_print")); - OS::get_singleton()->set_cmdline(execpath, main_args); + OS::get_singleton()->set_cmdline(execpath, main_args, user_args); // possibly be worth changing the default from vulkan to something lower spec, // for the project manager, depending on how smooth the fallback is. @@ -1431,7 +1464,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } - GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); + GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF("internationalization/locale/include_text_server_data", false); OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true); @@ -1448,7 +1481,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->_allow_layered = false; } - OS::get_singleton()->_keep_screen_on = GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true); if (rtm == -1) { rtm = GLOBAL_DEF("rendering/driver/threads/thread_model", OS::RENDER_THREAD_SAFE); } @@ -1507,7 +1539,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph audio_driver_idx = 0; } - if (write_movie_path != String()) { + if (Engine::get_singleton()->get_write_movie_path() != String()) { // Always use dummy driver for audio driver (which is last), also in no threaded mode. audio_driver_idx = AudioDriverManager::get_driver_count() - 1; AudioDriverDummy::get_dummy_singleton()->set_use_threads(false); @@ -1604,7 +1636,7 @@ error: display_driver = ""; audio_driver = ""; tablet_driver = ""; - write_movie_path = ""; + Engine::get_singleton()->set_write_movie_path(String()); project_path = ""; args.clear(); @@ -1646,6 +1678,7 @@ error: unregister_core_types(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); if (message_queue) { memdelete(message_queue); @@ -1779,11 +1812,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) { rendering_server->set_print_gpu_profile(true); } - if (write_movie_path != String()) { - movie_writer = MovieWriter::find_writer_for_file(write_movie_path); + if (Engine::get_singleton()->get_write_movie_path() != String()) { + movie_writer = MovieWriter::find_writer_for_file(Engine::get_singleton()->get_write_movie_path()); if (movie_writer == nullptr) { - ERR_PRINT("Can't find movie writer for file type, aborting: " + write_movie_path); - write_movie_path = String(); + ERR_PRINT("Can't find movie writer for file type, aborting: " + Engine::get_singleton()->get_write_movie_path()); + Engine::get_singleton()->set_write_movie_path(String()); } } @@ -1838,10 +1871,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) { DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true); } - if (allow_focus_steal_pid) { - DisplayServer::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid); - } - MAIN_PRINT("Main: Load Boot Image"); Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)); @@ -1965,7 +1994,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: Load TextServer"); /* Enum text drivers */ - GLOBAL_DEF("internationalization/rendering/text_driver", ""); + GLOBAL_DEF_RST("internationalization/rendering/text_driver", ""); String text_driver_options; for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { if (i > 0) { @@ -2078,7 +2107,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { // able to load resources, load the global shader variables. // If running on editor, don't load the textures because the editor // may want to import them first. Editor will reload those later. - rendering_server->global_variables_load_settings(!editor); + rendering_server->global_shader_uniforms_load_settings(!editor); } _start_success = true; @@ -2410,6 +2439,8 @@ bool Main::start() { } if (debug_navigation) { sml->set_debug_navigation_hint(true); + NavigationServer3D::get_singleton()->set_active(true); + NavigationServer3D::get_singleton_mut()->set_debug_enabled(true); } #endif @@ -2575,7 +2606,7 @@ bool Main::start() { PropertyInfo(Variant::FLOAT, "display/window/stretch/scale", PROPERTY_HINT_RANGE, - "1.0,8.0,0.1")); + "0.5,8.0,0.01")); sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true); @@ -2669,7 +2700,7 @@ bool Main::start() { ERR_FAIL_COND_V_MSG(!scene, false, "Failed loading scene: " + local_game_path); sml->add_current_scene(scene); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED String mac_iconpath = GLOBAL_DEF("application/config/macos_native_icon", "Variant()"); if (!mac_iconpath.is_empty()) { DisplayServer::get_singleton()->set_native_icon(mac_iconpath); @@ -2723,7 +2754,7 @@ bool Main::start() { OS::get_singleton()->set_main_loop(main_loop); if (movie_writer) { - movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, write_movie_path); + movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, Engine::get_singleton()->get_write_movie_path()); } if (minimum_time_msec) { @@ -2979,6 +3010,7 @@ void Main::cleanup(bool p_force) { OS::get_singleton()->delete_main_loop(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); OS::get_singleton()->_execpath = ""; OS::get_singleton()->_local_clipboard = ""; @@ -2991,7 +3023,7 @@ void Main::cleanup(bool p_force) { RenderingServer::get_singleton()->sync(); //clear global shader variables before scene and other graphics stuff are deinitialized. - rendering_server->global_variables_clear(); + rendering_server->global_shader_uniforms_clear(); if (xr_server) { // Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer diff --git a/main/performance.cpp b/main/performance.cpp index 25659b999f..0de525134e 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -283,7 +283,7 @@ Variant Performance::MonitorCall::call(bool &r_error, String &r_error_message) { int argc = _arguments.size(); Variant return_value; Callable::CallError error; - _callable.call(args, argc, return_value, error); + _callable.callp(args, argc, return_value, error); r_error = (error.error != Callable::CallError::CALL_OK); if (r_error) { r_error_message = Variant::get_callable_error_text(_callable, args, argc, error); diff --git a/methods.py b/methods.py index b4a55cab79..82c19f09e3 100644 --- a/methods.py +++ b/methods.py @@ -1,5 +1,6 @@ import os import re +import sys import glob import subprocess from collections import OrderedDict @@ -125,9 +126,21 @@ def update_version(module_version_string=""): if os.path.isfile(os.path.join(gitfolder, "HEAD")): head = open(os.path.join(gitfolder, "HEAD"), "r", encoding="utf8").readline().strip() if head.startswith("ref: "): - head = os.path.join(gitfolder, head[5:]) + ref = head[5:] + head = os.path.join(gitfolder, ref) + packedrefs = os.path.join(gitfolder, "packed-refs") if os.path.isfile(head): githash = open(head, "r").readline().strip() + elif os.path.isfile(packedrefs): + # Git may pack refs into a single file. This code searches .git/packed-refs file for the current ref's hash. + # https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-pack-refs.html + for line in open(packedrefs, "r").read().splitlines(): + if line.startswith("#"): + continue + (line_hash, line_ref) = line.split(" ") + if ref == line_ref: + githash = line_hash + break else: githash = head @@ -324,7 +337,20 @@ def disable_module(self): self.disabled_modules.append(self.current_module) -def module_check_dependencies(self, module, dependencies, silent=False): +def module_add_dependencies(self, module, dependencies, optional=False): + """ + Adds dependencies for a given module. + Meant to be used in module `can_build` methods. + """ + if module not in self.module_dependencies: + self.module_dependencies[module] = [[], []] + if optional: + self.module_dependencies[module][1].extend(dependencies) + else: + self.module_dependencies[module][0].extend(dependencies) + + +def module_check_dependencies(self, module): """ Checks if module dependencies are enabled for a given module, and prints a warning if they aren't. @@ -332,23 +358,41 @@ def module_check_dependencies(self, module, dependencies, silent=False): Returns a boolean (True if dependencies are satisfied). """ missing_deps = [] - for dep in dependencies: + required_deps = self.module_dependencies[module][0] if module in self.module_dependencies else [] + for dep in required_deps: opt = "module_{}_enabled".format(dep) if not opt in self or not self[opt]: missing_deps.append(dep) if missing_deps != []: - if not silent: - print( - "Disabling '{}' module as the following dependencies are not satisfied: {}".format( - module, ", ".join(missing_deps) - ) + print( + "Disabling '{}' module as the following dependencies are not satisfied: {}".format( + module, ", ".join(missing_deps) ) + ) return False else: return True +def sort_module_list(env): + out = OrderedDict() + deps = {k: v[0] + list(filter(lambda x: x in env.module_list, v[1])) for k, v in env.module_dependencies.items()} + + frontier = list(env.module_list.keys()) + explored = [] + while len(frontier): + cur = frontier.pop() + deps_list = deps[cur] if cur in deps else [] + if len(deps_list) and any([d not in explored for d in deps_list]): + # Will explore later, after its dependencies + frontier.insert(0, cur) + continue + explored.append(cur) + for k in explored: + env.module_list.move_to_end(k) + + def use_windows_spawn_fix(self, platform=None): if os.name != "nt": @@ -595,8 +639,18 @@ def find_visual_c_batch_file(env): find_batch_file, ) + # Syntax changed in SCons 4.4.0. + from SCons import __version__ as scons_raw_version + + scons_ver = env._get_major_minor_revision(scons_raw_version) + version = get_default_version(env) - (host_platform, target_platform, _) = get_host_target(env) + + if scons_ver >= (4, 4, 0): + (host_platform, target_platform, _) = get_host_target(env, version) + else: + (host_platform, target_platform, _) = get_host_target(env) + return find_batch_file(env, version, host_platform, target_platform)[0] @@ -833,15 +887,15 @@ def Run(env, function, short_message, subprocess=True): def detect_darwin_sdk_path(platform, env): sdk_name = "" - if platform == "osx": + if platform == "macos": sdk_name = "macosx" var_name = "MACOS_SDK_PATH" - elif platform == "iphone": + elif platform == "ios": sdk_name = "iphoneos" - var_name = "IPHONESDK" - elif platform == "iphonesimulator": + var_name = "IOS_SDK_PATH" + elif platform == "iossimulator": sdk_name = "iphonesimulator" - var_name = "IPHONESDK" + var_name = "IOS_SDK_PATH" else: raise Exception("Invalid platform argument passed to detect_darwin_sdk_path") diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/Info.plist b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/Info.plist index 846533594f..846533594f 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/Info.plist +++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/Info.plist diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64/empty b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/empty index bd3e894333..bd3e894333 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64/empty +++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/empty diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64_x86_64-simulator/empty b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/empty index bd3e894333..bd3e894333 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64_x86_64-simulator/empty +++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/empty diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/Info.plist b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/Info.plist index 846533594f..846533594f 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/Info.plist +++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/Info.plist diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64/empty b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64/empty index bd3e894333..bd3e894333 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64/empty +++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64/empty diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64_x86_64-simulator/empty b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/empty index bd3e894333..bd3e894333 100644 --- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64_x86_64-simulator/empty +++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/empty diff --git a/misc/dist/osx/editor.entitlements b/misc/dist/macos/editor.entitlements index d0137910a3..d0137910a3 100644 --- a/misc/dist/osx/editor.entitlements +++ b/misc/dist/macos/editor.entitlements diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/macos_template.app/Contents/Info.plist index 542146cdb8..542146cdb8 100644 --- a/misc/dist/osx_template.app/Contents/Info.plist +++ b/misc/dist/macos_template.app/Contents/Info.plist diff --git a/misc/dist/osx_template.app/Contents/PkgInfo b/misc/dist/macos_template.app/Contents/PkgInfo index 6f749b0f37..6f749b0f37 100644 --- a/misc/dist/osx_template.app/Contents/PkgInfo +++ b/misc/dist/macos_template.app/Contents/PkgInfo diff --git a/misc/dist/osx_template.app/Contents/Resources/icon.icns b/misc/dist/macos_template.app/Contents/Resources/icon.icns Binary files differindex be9254630c..be9254630c 100644 --- a/misc/dist/osx_template.app/Contents/Resources/icon.icns +++ b/misc/dist/macos_template.app/Contents/Resources/icon.icns diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/macos_tools.app/Contents/Info.plist index 886df87cc6..886df87cc6 100644 --- a/misc/dist/osx_tools.app/Contents/Info.plist +++ b/misc/dist/macos_tools.app/Contents/Info.plist diff --git a/misc/dist/osx_tools.app/Contents/PkgInfo b/misc/dist/macos_tools.app/Contents/PkgInfo index 6f749b0f37..6f749b0f37 100644 --- a/misc/dist/osx_tools.app/Contents/PkgInfo +++ b/misc/dist/macos_tools.app/Contents/PkgInfo diff --git a/misc/dist/osx_tools.app/Contents/Resources/GDScript.icns b/misc/dist/macos_tools.app/Contents/Resources/GDScript.icns Binary files differindex b08e8df339..b08e8df339 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/GDScript.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/GDScript.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/Godot.icns b/misc/dist/macos_tools.app/Contents/Resources/Godot.icns Binary files differindex 61697976c6..61697976c6 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/Godot.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/Godot.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/Project.icns b/misc/dist/macos_tools.app/Contents/Resources/Project.icns Binary files differindex 10e31528e4..10e31528e4 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/Project.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/Project.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/Resource.icns b/misc/dist/macos_tools.app/Contents/Resources/Resource.icns Binary files differindex 9648cb616e..9648cb616e 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/Resource.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/Resource.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/Scene.icns b/misc/dist/macos_tools.app/Contents/Resources/Scene.icns Binary files differindex c8c3dee07e..c8c3dee07e 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/Scene.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/Scene.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/Shader.icns b/misc/dist/macos_tools.app/Contents/Resources/Shader.icns Binary files differindex a76e648a1a..a76e648a1a 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/Shader.icns +++ b/misc/dist/macos_tools.app/Contents/Resources/Shader.icns diff --git a/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/af.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/af.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/az.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/az.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/br.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/br.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/da.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/da.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/de.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/de.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/el.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/el.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/en.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/en.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/en.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/en.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/es.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/es.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/et.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/et.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/he.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/he.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/id.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/id.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/is.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/is.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/it.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/it.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/km.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/km.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/or.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/or.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/si.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/si.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/te.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/te.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/th.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/th.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings index e69de29bb2..e69de29bb2 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings +++ b/misc/dist/macos_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings diff --git a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json deleted file mode 100644 index c4f8f71d0e..0000000000 --- a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "file_format_version" : "1.0.0", - "ICD": { - "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version" : "1.1.0" - } -} diff --git a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json deleted file mode 100644 index c4f8f71d0e..0000000000 --- a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "file_format_version" : "1.0.0", - "ICD": { - "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version" : "1.1.0" - } -} diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh index c767d3f8a0..731b3ee005 100755 --- a/misc/scripts/file_format.sh +++ b/misc/scripts/file_format.sh @@ -37,6 +37,8 @@ while IFS= read -rd '' f; do continue elif [[ "$f" == *"-so_wrap."* ]]; then continue + elif [[ "$f" == *".test.txt" ]]; then + continue fi # Ensure that files are UTF-8 formatted. recode UTF-8 "$f" 2> /dev/null diff --git a/misc/scripts/header_guards.sh b/misc/scripts/header_guards.sh new file mode 100755 index 0000000000..9a830f3ad2 --- /dev/null +++ b/misc/scripts/header_guards.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +if [ ! -f "version.py" ]; then + echo "Warning: This script is intended to be run from the root of the Godot repository." + echo "Some of the paths checks may not work as intended from a different folder." +fi + +for file in $(find -name "thirdparty" -prune -o -name "*.h" -print); do + # Skip *.gen.h and *-so_wrap.h, they're generated. + if [[ "$file" == *".gen.h" || "$file" == *"-so_wrap.h" ]]; then continue; fi + # Has important define before normal header guards. + if [[ "$file" == *"thread.h" || "$file" == *"platform_config.h" ]]; then continue; fi + + bname=$(basename $file .h) + + # Add custom prefix or suffix for generic filenames with a well-defined namespace. + + prefix= + if [[ "$file" == "./modules/"*"/register_types.h" ]]; then + module=$(echo $file | sed "s@.*modules/\([^/]*\).*@\1@") + prefix="${module^^}_" + fi + if [[ "$file" == "./platform/"*"/api/api.h" || "$file" == "./platform/"*"/export/"* ]]; then + platform=$(echo $file | sed "s@.*platform/\([^/]*\).*@\1@") + prefix="${platform^^}_" + fi + if [[ "$file" == "./modules/mono/utils/"* && "$bname" != *"mono"* ]]; then prefix="MONO_"; fi + if [[ "$file" == "./servers/rendering/storage/utilities.h" ]]; then prefix="RENDERER_"; fi + + suffix= + if [[ "$file" == *"dummy"* && "$bname" != *"dummy"* ]]; then suffix="_DUMMY"; fi + if [[ "$file" == *"gles3"* && "$bname" != *"gles3"* ]]; then suffix="_GLES3"; fi + if [[ "$file" == *"renderer_rd"* && "$bname" != *"rd"* ]]; then suffix="_RD"; fi + if [[ "$file" == *"ustring.h" ]]; then suffix="_GODOT"; fi + + # ^^ is bash builtin for UPPERCASE. + guard="${prefix}${bname^^}${suffix}_H" + + # Replaces guards to use computed name. + # We also add some \n to make sure there's a proper separation. + sed -i $file -e "0,/ifndef/s/#ifndef.*/\n#ifndef $guard/" + sed -i $file -e "0,/define/s/#define.*/#define $guard\n/" + sed -i $file -e "$ s/#endif.*/\n#endif \/\/ $guard/" + # Removes redundant \n added before, if they weren't needed. + sed -i $file -e "/^$/N;/^\n$/D" +done + +diff=$(git diff --color) + +# If no diff has been generated all is OK, clean up, and exit. +if [ -z "$diff" ] ; then + printf "Files in this commit comply with the header guards formatting rules.\n" + exit 0 +fi + +# A diff has been created, notify the user, clean up, and exit. +printf "\n*** The following differences were found between the code " +printf "and the header guards formatting rules:\n\n" +echo "$diff" +printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n" +exit 1 diff --git a/misc/scripts/install_vulkan_sdk_macos.sh b/misc/scripts/install_vulkan_sdk_macos.sh index e03a907749..d78659fa9f 100755 --- a/misc/scripts/install_vulkan_sdk_macos.sh +++ b/misc/scripts/install_vulkan_sdk_macos.sh @@ -1,13 +1,14 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh set -euo pipefail IFS=$'\n\t' # Download and install the Vulkan SDK. -curl -LO "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg" -hdiutil attach vulkan-sdk.dmg -mountpoint /Volumes/vulkan-sdk +curl -L "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg" -o /tmp/vulkan-sdk.dmg +hdiutil attach /tmp/vulkan-sdk.dmg -mountpoint /Volumes/vulkan-sdk /Volumes/vulkan-sdk/InstallVulkan.app/Contents/MacOS/InstallVulkan \ --accept-licenses --default-answer --confirm-command install hdiutil detach /Volumes/vulkan-sdk +rm -f /tmp/vulkan-sdk.dmg echo 'Vulkan SDK installed successfully! You can now build Godot by running "scons".' diff --git a/modules/bmp/SCsub b/modules/bmp/SCsub index 4f3405ff28..9d317887c3 100644 --- a/modules/bmp/SCsub +++ b/modules/bmp/SCsub @@ -5,5 +5,5 @@ Import("env_modules") env_bmp = env_modules.Clone() -# Godot's own source files +# Godot source files env_bmp.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/camera/SCsub b/modules/camera/SCsub index de97724d09..9a6147d433 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -9,6 +9,6 @@ if env["platform"] == "windows": env_camera.add_source_files(env.modules_sources, "register_types.cpp") env_camera.add_source_files(env.modules_sources, "camera_win.cpp") -elif env["platform"] == "osx": +elif env["platform"] == "macos": env_camera.add_source_files(env.modules_sources, "register_types.cpp") - env_camera.add_source_files(env.modules_sources, "camera_osx.mm") + env_camera.add_source_files(env.modules_sources, "camera_macos.mm") diff --git a/modules/camera/camera_osx.h b/modules/camera/camera_macos.h index b0db844599..903eda51bf 100644 --- a/modules/camera/camera_osx.h +++ b/modules/camera/camera_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_osx.h */ +/* camera_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERAOSX_H -#define CAMERAOSX_H +#ifndef CAMERA_MACOS_H +#define CAMERA_MACOS_H ///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!! // If you fix something here, make sure you fix it there as well! #include "servers/camera_server.h" -class CameraOSX : public CameraServer { +class CameraMacOS : public CameraServer { public: - CameraOSX(); + CameraMacOS(); void update_feeds(); }; -#endif /* CAMERAOSX_H */ +#endif // CAMERA_MACOS_H diff --git a/modules/camera/camera_osx.mm b/modules/camera/camera_macos.mm index d199c31b2f..0b9696a3e9 100644 --- a/modules/camera/camera_osx.mm +++ b/modules/camera/camera_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_osx.mm */ +/* camera_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,7 +31,7 @@ ///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!! // If you fix something here, make sure you fix it there as well! -#include "camera_osx.h" +#include "camera_macos.h" #include "servers/camera/camera_feed.h" #import <AVFoundation/AVFoundation.h> @@ -191,9 +191,9 @@ @end ////////////////////////////////////////////////////////////////////////// -// CameraFeedOSX - Subclass for camera feeds in OSX +// CameraFeedMacOS - Subclass for camera feeds in macOS -class CameraFeedOSX : public CameraFeed { +class CameraFeedMacOS : public CameraFeed { private: AVCaptureDevice *device; MyCaptureSession *capture_session; @@ -201,7 +201,7 @@ private: public: AVCaptureDevice *get_device() const; - CameraFeedOSX(); + CameraFeedMacOS(); void set_device(AVCaptureDevice *p_device); @@ -209,16 +209,16 @@ public: void deactivate_feed(); }; -AVCaptureDevice *CameraFeedOSX::get_device() const { +AVCaptureDevice *CameraFeedMacOS::get_device() const { return device; }; -CameraFeedOSX::CameraFeedOSX() { +CameraFeedMacOS::CameraFeedMacOS() { device = nullptr; capture_session = nullptr; }; -void CameraFeedOSX::set_device(AVCaptureDevice *p_device) { +void CameraFeedMacOS::set_device(AVCaptureDevice *p_device) { device = p_device; // get some info @@ -232,7 +232,7 @@ void CameraFeedOSX::set_device(AVCaptureDevice *p_device) { }; }; -bool CameraFeedOSX::activate_feed() { +bool CameraFeedMacOS::activate_feed() { if (capture_session) { // Already recording! } else { @@ -258,7 +258,7 @@ bool CameraFeedOSX::activate_feed() { return true; }; -void CameraFeedOSX::deactivate_feed() { +void CameraFeedMacOS::deactivate_feed() { // end camera capture if we have one if (capture_session) { [capture_session cleanup]; @@ -271,7 +271,7 @@ void CameraFeedOSX::deactivate_feed() { // when devices are connected/disconnected @interface MyDeviceNotifications : NSObject { - CameraOSX *camera_server; + CameraMacOS *camera_server; } @end @@ -282,7 +282,7 @@ void CameraFeedOSX::deactivate_feed() { camera_server->update_feeds(); } -- (id)initForServer:(CameraOSX *)p_server { +- (id)initForServer:(CameraMacOS *)p_server { if (self = [super init]) { camera_server = p_server; @@ -303,9 +303,9 @@ void CameraFeedOSX::deactivate_feed() { MyDeviceNotifications *device_notifications = nil; ////////////////////////////////////////////////////////////////////////// -// CameraOSX - Subclass for our camera server on OSX +// CameraMacOS - Subclass for our camera server on macOS -void CameraOSX::update_feeds() { +void CameraMacOS::update_feeds() { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeExternalUnknown, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; NSArray *devices = session.devices; @@ -315,7 +315,7 @@ void CameraOSX::update_feeds() { // remove devices that are gone.. for (int i = feeds.size() - 1; i >= 0; i--) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; + Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i]; if (![devices containsObject:feed->get_device()]) { // remove it from our array, this will also destroy it ;) @@ -326,14 +326,14 @@ void CameraOSX::update_feeds() { for (AVCaptureDevice *device in devices) { bool found = false; for (int i = 0; i < feeds.size() && !found; i++) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; + Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i]; if (feed->get_device() == device) { found = true; }; }; if (!found) { - Ref<CameraFeedOSX> newfeed; + Ref<CameraFeedMacOS> newfeed; newfeed.instantiate(); newfeed->set_device(device); @@ -346,7 +346,7 @@ void CameraOSX::update_feeds() { }; }; -CameraOSX::CameraOSX() { +CameraMacOS::CameraMacOS() { // Find available cameras we have at this time update_feeds(); diff --git a/modules/camera/camera_win.h b/modules/camera/camera_win.h index 9563326acb..ebfc117190 100644 --- a/modules/camera/camera_win.h +++ b/modules/camera/camera_win.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERAWIN_H -#define CAMERAWIN_H +#ifndef CAMERA_WIN_H +#define CAMERA_WIN_H #include "servers/camera/camera_feed.h" #include "servers/camera_server.h" @@ -43,4 +43,4 @@ public: ~CameraWindows() {} }; -#endif /* CAMERAWIN_H */ +#endif // CAMERA_WIN_H diff --git a/modules/camera/config.py b/modules/camera/config.py index 8a22751aa7..d2b2542dd9 100644 --- a/modules/camera/config.py +++ b/modules/camera/config.py @@ -1,5 +1,5 @@ def can_build(env, platform): - return platform == "osx" or platform == "windows" + return platform == "macos" or platform == "windows" def configure(env): diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp index 98a4b5ca1a..40e2224d6b 100644 --- a/modules/camera/register_types.cpp +++ b/modules/camera/register_types.cpp @@ -33,8 +33,8 @@ #if defined(WINDOWS_ENABLED) #include "camera_win.h" #endif -#if defined(OSX_ENABLED) -#include "camera_osx.h" +#if defined(MACOS_ENABLED) +#include "camera_macos.h" #endif void initialize_camera_module(ModuleInitializationLevel p_level) { @@ -45,8 +45,8 @@ void initialize_camera_module(ModuleInitializationLevel p_level) { #if defined(WINDOWS_ENABLED) CameraServer::make_default<CameraWindows>(); #endif -#if defined(OSX_ENABLED) - CameraServer::make_default<CameraOSX>(); +#if defined(MACOS_ENABLED) + CameraServer::make_default<CameraMacOS>(); #endif } diff --git a/modules/csg/SCsub b/modules/csg/SCsub index c7307ddefd..55f859db11 100644 --- a/modules/csg/SCsub +++ b/modules/csg/SCsub @@ -3,10 +3,9 @@ Import("env") Import("env_modules") -# Godot's own source files env_csg = env_modules.Clone() -# Godot's own source files +# Godot source files env_csg.add_source_files(env.modules_sources, "*.cpp") if env["tools"]: env_csg.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 93533e1690..6b05c146e6 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -729,7 +729,7 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() { } } -void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vector2 p_uvs[], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { +void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[3], const Vector2 p_uvs[3], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { int indices[3]; for (int i = 0; i < 3; i++) { VertexKey vk; diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 0f09eb2020..56be4e65f0 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1858,7 +1858,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } Transform3D facing = Transform3D().looking_at(direction, current_up); - current_xform = base_xform.translated(current_point) * facing; + current_xform = base_xform.translated_local(current_point) * facing; } // Create the mesh. @@ -1897,7 +1897,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { switch (mode) { case MODE_DEPTH: { - current_xform.translate(Vector3(0, 0, -depth)); + current_xform.translate_local(Vector3(0, 0, -depth)); } break; case MODE_SPIN: { current_xform.rotate(Vector3(0, 1, 0), spin_step); @@ -1945,7 +1945,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } Transform3D facing = Transform3D().looking_at(direction, current_up); - current_xform = base_xform.translated(current_point) * facing; + current_xform = base_xform.translated_local(current_point) * facing; } break; } diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index a7cfcaa262..3322ff0a1b 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -129,14 +129,6 @@ static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const } } -static void _digest_job_queue(void *p_job_queue) { - CVTTCompressionJobQueue *job_queue = static_cast<CVTTCompressionJobQueue *>(p_job_queue); - - for (uint32_t next_task = job_queue->current_task.increment(); next_task <= job_queue->num_tasks; next_task = job_queue->current_task.increment()) { - _digest_row_task(job_queue->job_params, job_queue->job_tasks[next_task - 1]); - } -} - void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChannels p_channels) { if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) { return; //do not compress, already compressed @@ -202,7 +194,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann job_queue.job_params.bytes_per_pixel = is_hdr ? 6 : 4; cvtt::Kernels::ConfigureBC7EncodingPlanFromQuality(job_queue.job_params.bc7_plan, 5); - int num_job_threads = 0; // Amdahl's law (Wikipedia) // If a program needs 20 hours to complete using a single thread, but a one-hour portion of the program cannot be parallelized, // therefore only the remaining 19 hours (p = 0.95) of execution time can be parallelized, then regardless of how many threads are devoted @@ -229,11 +220,7 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann row_task.in_mm_bytes = in_bytes; row_task.out_mm_bytes = out_bytes; - if (num_job_threads > 0) { - tasks.push_back(row_task); - } else { - _digest_row_task(job_queue.job_params, row_task); - } + _digest_row_task(job_queue.job_params, row_task); out_bytes += 16 * (bw / 4); } @@ -243,29 +230,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann h = MAX(h / 2, 1); } - if (num_job_threads > 0) { - Vector<Thread *> threads; - threads.resize(num_job_threads); - - Thread **threads_wb = threads.ptrw(); - - const CVTTCompressionRowTask *tasks_rb = tasks.ptr(); - - job_queue.job_tasks = &tasks_rb[0]; - job_queue.current_task.set(0); - job_queue.num_tasks = static_cast<uint32_t>(tasks.size()); - - for (int i = 0; i < num_job_threads; i++) { - threads_wb[i] = memnew(Thread); - threads_wb[i]->start(_digest_job_queue, &job_queue); - } - _digest_job_queue(&job_queue); - - for (int i = 0; i < num_job_threads; i++) { - threads_wb[i]->wait_to_finish(); - memdelete(threads_wb[i]); - } - } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); } diff --git a/modules/denoise/config.py b/modules/denoise/config.py index 3aa840acb0..521115dae5 100644 --- a/modules/denoise/config.py +++ b/modules/denoise/config.py @@ -4,7 +4,7 @@ def can_build(env, platform): # It's also only relevant for tools build and desktop platforms, # as doing lightmap generation and denoising on Android or HTML5 # would be a bit far-fetched. - desktop_platforms = ["linuxbsd", "osx", "windows"] + desktop_platforms = ["linuxbsd", "macos", "windows"] supported_arch = env["bits"] == "64" if env["arch"] == "arm64": supported_arch = False diff --git a/modules/enet/enet_multiplayer_peer.cpp b/modules/enet/enet_multiplayer_peer.cpp index cd94cc9425..dfdd08c9f4 100644 --- a/modules/enet/enet_multiplayer_peer.cpp +++ b/modules/enet/enet_multiplayer_peer.cpp @@ -441,15 +441,15 @@ Error ENetMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size channel = SYSCH_MAX + transfer_channel - 1; } else { switch (get_transfer_mode()) { - case Multiplayer::TRANSFER_MODE_UNRELIABLE: { + case TRANSFER_MODE_UNRELIABLE: { packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT; channel = SYSCH_UNRELIABLE; } break; - case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED: { + case TRANSFER_MODE_UNRELIABLE_ORDERED: { packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT; channel = SYSCH_UNRELIABLE; } break; - case Multiplayer::TRANSFER_MODE_RELIABLE: { + case TRANSFER_MODE_RELIABLE: { packet_flags = ENET_PACKET_FLAG_RELIABLE; channel = SYSCH_RELIABLE; } break; diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h index 18eca18e51..3152068d46 100644 --- a/modules/enet/enet_multiplayer_peer.h +++ b/modules/enet/enet_multiplayer_peer.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NETWORKED_MULTIPLAYER_ENET_H -#define NETWORKED_MULTIPLAYER_ENET_H +#ifndef ENET_MULTIPLAYER_PEER_H +#define ENET_MULTIPLAYER_PEER_H #include "core/crypto/crypto.h" -#include "core/multiplayer/multiplayer_peer.h" +#include "scene/main/multiplayer_peer.h" #include "enet_connection.h" #include <enet/enet.h> @@ -135,4 +135,4 @@ public: ~ENetMultiplayerPeer(); }; -#endif // NETWORKED_MULTIPLAYER_ENET_H +#endif // ENET_MULTIPLAYER_PEER_H diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 4b2ea6faa5..8efcd72fb6 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -58,22 +58,23 @@ if env["builtin_freetype"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - thirdparty_brotli_dir = "#thirdparty/brotli/" - thirdparty_brotli_sources = [ - "common/constants.c", - "common/context.c", - "common/dictionary.c", - "common/platform.c", - "common/shared_dictionary.c", - "common/transform.c", - "dec/bit_reader.c", - "dec/decode.c", - "dec/huffman.c", - "dec/state.c", - ] - thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources] - env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"]) - env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"]) + if env["brotli"]: + thirdparty_brotli_dir = "#thirdparty/brotli/" + thirdparty_brotli_sources = [ + "common/constants.c", + "common/context.c", + "common/dictionary.c", + "common/platform.c", + "common/shared_dictionary.c", + "common/transform.c", + "dec/bit_reader.c", + "dec/decode.c", + "dec/huffman.c", + "dec/state.c", + ] + thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources] + env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"]) + env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"]) if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"): env_freetype.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"]) diff --git a/modules/freetype/config.py b/modules/freetype/config.py index d22f9454ed..c0586d5536 100644 --- a/modules/freetype/config.py +++ b/modules/freetype/config.py @@ -2,5 +2,13 @@ def can_build(env, platform): return True +def get_opts(platform): + from SCons.Variables import BoolVariable + + return [ + BoolVariable("brotli", "Enable Brotli decompressor for WOFF2 fonts support", True), + ] + + def configure(env): pass diff --git a/modules/freetype/uwpdef.h b/modules/freetype/uwpdef.h index 05aaae61b5..f85f293171 100644 --- a/modules/freetype/uwpdef.h +++ b/modules/freetype/uwpdef.h @@ -28,6 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef UWPDEF_H +#define UWPDEF_H + // "generic" is a reserved keyword in C++/CX code // this avoids the errors in the variable name from Freetype code #define generic freetype_generic + +#endif // UWPDEF_H diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py index 61ce6185a5..a7d5c406e9 100644 --- a/modules/gdscript/config.py +++ b/modules/gdscript/config.py @@ -1,4 +1,5 @@ def can_build(env, platform): + env.module_add_dependencies("gdscript", ["jsonrpc", "websocket"], True) return True diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index e995cce651..10cf783e73 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -144,6 +144,7 @@ [/codeblock] [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code]. This method is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios. + [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. </description> </method> <method name="preload"> diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index b86e9b386d..a23f19de85 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -55,7 +55,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l bool in_function_args = false; bool in_member_variable = false; bool in_node_path = false; + bool in_node_ref = false; bool in_annotation = false; + bool in_string_name = false; bool is_hex_notation = false; bool is_bin_notation = false; bool expect_type = false; @@ -165,6 +167,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (in_node_path && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { region_color = node_path_color; } + if (in_node_ref && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { + region_color = node_ref_color; + } + if (in_string_name && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { + region_color = string_name_color; + } prev_color = region_color; highlighter_info["color"] = region_color; @@ -387,24 +395,42 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l in_member_variable = false; } - if (!in_node_path && in_region == -1 && (str[j] == '$' || str[j] == '%')) { + if (!in_node_path && in_region == -1 && (str[j] == '^')) { in_node_path = true; } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) { in_node_path = false; } + if (!in_node_ref && in_region == -1 && (str[j] == '$' || str[j] == '%')) { + in_node_ref = true; + } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) { + in_node_ref = false; + } + if (!in_annotation && in_region == -1 && str[j] == '@') { in_annotation = true; } else if (in_region != -1 || is_a_symbol) { in_annotation = false; } + if (!in_string_name && in_region == -1 && str[j] == '&') { + in_string_name = true; + } else if (in_region != -1 || is_a_symbol) { + in_string_name = false; + } + if (in_node_path) { next_type = NODE_PATH; color = node_path_color; + } else if (in_node_ref) { + next_type = NODE_REF; + color = node_ref_color; } else if (in_annotation) { next_type = ANNOTATION; color = annotation_color; + } else if (in_string_name) { + next_type = STRING_NAME; + color = string_name_color; } else if (in_keyword) { next_type = KEYWORD; color = keyword_color; @@ -592,17 +618,23 @@ void GDScriptSyntaxHighlighter::_update_cache() { if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) { function_definition_color = Color(0.4, 0.9, 1.0); - node_path_color = Color(0.39, 0.76, 0.35); + node_path_color = Color(0.72, 0.77, 0.49); + node_ref_color = Color(0.39, 0.76, 0.35); annotation_color = Color(1.0, 0.7, 0.45); + string_name_color = Color(1.0, 0.66, 0.72); } else { - function_definition_color = Color(0.0, 0.65, 0.73); - node_path_color = Color(0.32, 0.55, 0.29); - annotation_color = Color(0.8, 0.5, 0.25); + function_definition_color = Color(0, 0.6, 0.6); + node_path_color = Color(0.18, 0.55, 0); + node_ref_color = Color(0.0, 0.5, 0); + annotation_color = Color(0.8, 0.37, 0); + string_name_color = Color(0.8, 0.46, 0.52); } EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_reference_color", node_ref_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/string_name_color", string_name_color); if (text_edit_color_theme == "Default" || godot_2_theme) { EditorSettings::get_singleton()->set_initial_value( "text_editor/theme/highlighting/gdscript/function_definition_color", @@ -613,14 +645,24 @@ void GDScriptSyntaxHighlighter::_update_cache() { node_path_color, true); EditorSettings::get_singleton()->set_initial_value( + "text_editor/theme/highlighting/gdscript/node_reference_color", + node_ref_color, + true); + EditorSettings::get_singleton()->set_initial_value( "text_editor/theme/highlighting/gdscript/annotation_color", annotation_color, true); + EditorSettings::get_singleton()->set_initial_value( + "text_editor/theme/highlighting/gdscript/string_name_color", + string_name_color, + true); } function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color"); node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color"); + node_ref_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_reference_color"); annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color"); + string_name_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/string_name_color"); type_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color"); } diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 92764e3891..7987582f07 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -54,7 +54,9 @@ private: NONE, REGION, NODE_PATH, + NODE_REF, ANNOTATION, + STRING_NAME, SYMBOL, NUMBER, FUNCTION, @@ -74,7 +76,9 @@ private: Color number_color; Color member_color; Color node_path_color; + Color node_ref_color; Color annotation_color; + Color string_name_color; Color type_color; void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index bf83353ead..dc6bfbb034 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -51,7 +51,7 @@ #endif #ifdef TOOLS_ENABLED -#include "editor/editor_settings.h" +#include "editor/editor_paths.h" #endif /////////////////////////// @@ -278,6 +278,11 @@ void GDScript::_get_script_method_list(List<MethodInfo> *r_list, bool p_include_ GDScriptFunction *func = E.value; MethodInfo mi; mi.name = E.key; + + if (func->is_static()) { + mi.flags |= METHOD_FLAG_STATIC; + } + for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arginfo = func->get_argument_type(i); #ifdef TOOLS_ENABLED @@ -320,16 +325,23 @@ void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_incl for (int i = 0; i < msort.size(); i++) { props.push_front(sptr->member_info[msort[i].name]); } + +#ifdef TOOLS_ENABLED + r_list->push_back(sptr->get_class_category()); +#endif // TOOLS_ENABLED + + for (const PropertyInfo &E : props) { + r_list->push_back(E); + } + + props.clear(); + if (!p_include_base) { break; } sptr = sptr->_base; } - - for (const PropertyInfo &E : props) { - r_list->push_back(E); - } } void GDScript::get_script_property_list(List<PropertyInfo> *r_list) const { @@ -429,10 +441,6 @@ void GDScript::set_source_code(const String &p_code) { #ifdef TOOLS_ENABLED void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) { - if (base_cache.is_valid()) { - base_cache->_update_exports_values(values, propnames); - } - for (const KeyValue<StringName, Variant> &E : member_default_values_cache) { values[E.key] = E.value; } @@ -440,6 +448,10 @@ void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List for (const PropertyInfo &E : members_cache) { propnames.push_back(E); } + + if (base_cache.is_valid()) { + base_cache->_update_exports_values(values, propnames); + } } void GDScript::_add_doc(const DocData::ClassDoc &p_inner_class) { @@ -536,6 +548,9 @@ void GDScript::_update_doc() { List<PropertyInfo> props; _get_script_property_list(&props, false); for (int i = 0; i < props.size(); i++) { + if (props[i].usage & PROPERTY_USAGE_CATEGORY || props[i].usage & PROPERTY_USAGE_GROUP || props[i].usage & PROPERTY_USAGE_SUBGROUP) { + continue; + } ScriptMemberInfo scr_member_info; scr_member_info.propinfo = props[i]; scr_member_info.propinfo.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; @@ -695,6 +710,8 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc member_default_values_cache.clear(); _signals.clear(); + members_cache.push_back(get_class_category()); + for (int i = 0; i < c->members.size(); i++) { const GDScriptParser::ClassNode::Member &member = c->members[i]; @@ -720,6 +737,9 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc } _signals[member.signal->identifier->name] = parameters_names; } break; + case GDScriptParser::ClassNode::Member::GROUP: { + members_cache.push_back(member.annotation->export_info); + } break; default: break; // Nothing. } @@ -840,7 +860,7 @@ Error GDScript::reload(bool p_keep_state) { // Loading a template, don't parse. #ifdef TOOLS_ENABLED - if (EditorSettings::get_singleton() && basedir.begins_with(EditorSettings::get_singleton()->get_project_script_templates_dir())) { + if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) { return OK; } #endif @@ -867,7 +887,7 @@ Error GDScript::reload(bool p_keep_state) { } // TODO: Show all error messages. _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); - ERR_FAIL_V(ERR_PARSE_ERROR); + return ERR_PARSE_ERROR; } GDScriptAnalyzer analyzer(&parser); @@ -883,7 +903,7 @@ Error GDScript::reload(bool p_keep_state) { _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); e = e->next(); } - ERR_FAIL_V(ERR_PARSE_ERROR); + return ERR_PARSE_ERROR; } bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool(); @@ -901,7 +921,7 @@ Error GDScript::reload(bool p_keep_state) { GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); } _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT); - ERR_FAIL_V(ERR_COMPILATION_FAILED); + return ERR_COMPILATION_FAILED; } else { return err; } @@ -946,8 +966,8 @@ void GDScript::get_members(HashSet<StringName> *p_members) { } } -const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const { - return rpc_functions; +const Variant GDScript::get_rpc_config() const { + return rpc_config; } Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { @@ -1204,9 +1224,9 @@ void GDScript::_save_orphaned_subclasses() { void GDScript::_init_rpc_methods_properties() { // Copy the base rpc methods so we don't mask their IDs. - rpc_functions.clear(); + rpc_config.clear(); if (base.is_valid()) { - rpc_functions = base->rpc_functions; + rpc_config = base->rpc_config.duplicate(); } GDScript *cscript = this; @@ -1214,12 +1234,9 @@ void GDScript::_init_rpc_methods_properties() { while (cscript) { // RPC Methods for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) { - Multiplayer::RPCConfig config = E.value->get_rpc_config(); - if (config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { - config.name = E.value->get_name(); - if (rpc_functions.find(config) == -1) { - rpc_functions.push_back(config); - } + Variant config = E.value->get_rpc_config(); + if (config.get_type() != Variant::NIL) { + rpc_config[E.value->get_name()] = config; } } @@ -1233,9 +1250,6 @@ void GDScript::_init_rpc_methods_properties() { cscript = nullptr; } } - - // Sort so we are 100% that they are always the same. - rpc_functions.sort_custom<Multiplayer::SortRPCConfig>(); } GDScript::~GDScript() { @@ -1400,9 +1414,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { while (sl) { HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name); if (E) { - Multiplayer::RPCConfig config; - config.name = p_name; - if (sptr->rpc_functions.find(config) != -1) { + if (sptr->rpc_config.has(p_name)) { r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key))); } else { r_ret = Callable(this->owner, E->key); @@ -1510,11 +1522,17 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const props.push_front(sptr->member_info[msort[i].name]); } - sptr = sptr->_base; - } +#ifdef TOOLS_ENABLED + p_properties->push_back(sptr->get_class_category()); +#endif // TOOLS_ENABLED + + for (const PropertyInfo &prop : props) { + p_properties->push_back(prop); + } - for (const PropertyInfo &E : props) { - p_properties->push_back(E); + props.clear(); + + sptr = sptr->_base; } } @@ -1524,7 +1542,6 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const { for (const KeyValue<StringName, GDScriptFunction *> &E : sptr->member_functions) { MethodInfo mi; mi.name = E.key; - mi.flags |= METHOD_FLAG_FROM_SCRIPT; for (int i = 0; i < E.value->get_argument_count(); i++) { mi.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i))); } @@ -1622,15 +1639,13 @@ ScriptLanguage *GDScriptInstance::get_language() { return GDScriptLanguage::get_singleton(); } -const Vector<Multiplayer::RPCConfig> GDScriptInstance::get_rpc_methods() const { - return script->get_rpc_methods(); +const Variant GDScriptInstance::get_rpc_config() const { + return script->get_rpc_config(); } void GDScriptInstance::reload_members() { #ifdef DEBUG_ENABLED - members.resize(script->member_indices.size()); //resize - Vector<Variant> new_members; new_members.resize(script->member_indices.size()); @@ -1642,6 +1657,8 @@ void GDScriptInstance::reload_members() { } } + members.resize(new_members.size()); //resize + //apply members = new_members; @@ -2381,7 +2398,7 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S } } -Error ResourceFormatSaverGDScript::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<GDScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index e9a206f48b..5123cccddd 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -87,7 +87,7 @@ class GDScript : public Script { HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script. HashMap<StringName, Ref<GDScript>> subclasses; HashMap<StringName, Vector<StringName>> _signals; - Vector<Multiplayer::RPCConfig> rpc_functions; + Dictionary rpc_config; #ifdef TOOLS_ENABLED @@ -250,7 +250,7 @@ public: virtual void get_constants(HashMap<StringName, Variant> *p_constants) override; virtual void get_members(HashSet<StringName> *p_members) override; - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; + virtual const Variant get_rpc_config() const override; #ifdef TOOLS_ENABLED virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; } @@ -304,7 +304,7 @@ public: void reload_members(); - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const; + virtual const Variant get_rpc_config() const; GDScriptInstance(); ~GDScriptInstance(); @@ -524,7 +524,7 @@ public: class ResourceFormatSaverGDScript : public ResourceFormatSaver { public: - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; virtual bool recognize(const Ref<Resource> &p_resource) const; }; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 8b4c245bf6..a07d4855f3 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -3238,12 +3238,12 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid); if (!valid) { push_error(vformat(R"(Cannot get member "%s" from "%s".)", p_subscript->attribute->name, p_subscript->base->reduced_value), p_subscript->index); + result_type.kind = GDScriptParser::DataType::VARIANT; } else { p_subscript->is_constant = true; p_subscript->reduced_value = value; result_type = type_from_variant(value, p_subscript); } - result_type.kind = GDScriptParser::DataType::VARIANT; } else { GDScriptParser::DataType base_type = p_subscript->base->get_datatype(); @@ -3329,8 +3329,11 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::VECTOR2I: case Variant::VECTOR3: case Variant::VECTOR3I: + case Variant::VECTOR4: + case Variant::VECTOR4I: case Variant::TRANSFORM2D: case Variant::TRANSFORM3D: + case Variant::PROJECTION: error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT && index_type.builtin_type != Variant::STRING; break; @@ -3393,6 +3396,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::PACKED_INT64_ARRAY: case Variant::VECTOR2I: case Variant::VECTOR3I: + case Variant::VECTOR4I: result_type.builtin_type = Variant::INT; break; // Return float. @@ -3400,6 +3404,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::PACKED_FLOAT64_ARRAY: case Variant::VECTOR2: case Variant::VECTOR3: + case Variant::VECTOR4: case Variant::QUATERNION: result_type.builtin_type = Variant::FLOAT; break; @@ -3430,6 +3435,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri break; // Depends on the index. case Variant::TRANSFORM3D: + case Variant::PROJECTION: case Variant::PLANE: case Variant::COLOR: case Variant::DICTIONARY: diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 6a1effd680..fa158591fd 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -84,11 +84,14 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type case Variant::VECTOR3: case Variant::VECTOR3I: case Variant::TRANSFORM2D: + case Variant::VECTOR4: + case Variant::VECTOR4I: case Variant::PLANE: case Variant::QUATERNION: case Variant::AABB: case Variant::BASIS: case Variant::TRANSFORM3D: + case Variant::PROJECTION: case Variant::COLOR: case Variant::STRING_NAME: case Variant::NODE_PATH: @@ -155,7 +158,7 @@ void GDScriptByteCodeGenerator::end_parameters() { function->default_arguments.reverse(); } -void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) { +void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) { function = memnew(GDScriptFunction); debug_stack = EngineDebugger::is_active(); @@ -453,6 +456,12 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia case Variant::TRANSFORM2D: append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D, 1); break; + case Variant::VECTOR4: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3, 1); + break; + case Variant::VECTOR4I: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I, 1); + break; case Variant::PLANE: append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1); break; @@ -468,6 +477,9 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia case Variant::TRANSFORM3D: append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D, 1); break; + case Variant::PROJECTION: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_PROJECTION, 1); + break; case Variant::COLOR: append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1); break; @@ -1596,7 +1608,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { // Typed array. const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - Variant script = function->return_type.script_type; + Variant script = element_type.script_type; int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2); diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index f4b402fc96..7dd51845df 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_BYTE_CODEGEN -#define GDSCRIPT_BYTE_CODEGEN +#ifndef GDSCRIPT_BYTE_CODEGEN_H +#define GDSCRIPT_BYTE_CODEGEN_H #include "gdscript_codegen.h" @@ -419,7 +419,7 @@ public: virtual void start_block() override; virtual void end_block() override; - virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) override; + virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) override; virtual GDScriptFunction *write_end() override; #ifdef DEBUG_ENABLED @@ -502,4 +502,4 @@ public: virtual ~GDScriptByteCodeGenerator(); }; -#endif // GDSCRIPT_BYTE_CODEGEN +#endif // GDSCRIPT_BYTE_CODEGEN_H diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index 81fa265aca..5972481c3a 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -28,10 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_CODEGEN -#define GDSCRIPT_CODEGEN +#ifndef GDSCRIPT_CODEGEN_H +#define GDSCRIPT_CODEGEN_H -#include "core/multiplayer/multiplayer.h" #include "core/string/string_name.h" #include "core/variant/variant.h" #include "gdscript_function.h" @@ -80,7 +79,7 @@ public: virtual void start_block() = 0; virtual void end_block() = 0; - virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) = 0; + virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) = 0; virtual GDScriptFunction *write_end() = 0; #ifdef DEBUG_ENABLED @@ -163,4 +162,4 @@ public: virtual ~GDScriptCodeGenerator() {} }; -#endif // GDSCRIPT_CODEGEN +#endif // GDSCRIPT_CODEGEN_H diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index af8e4b3746..00e8223b9a 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -43,7 +43,7 @@ bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringN return false; } - if (codegen.locals.has(p_name)) { + if (codegen.parameters.has(p_name) || codegen.locals.has(p_name)) { return false; //shadowed } @@ -1975,7 +1975,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ StringName func_name; bool is_static = false; - Multiplayer::RPCConfig rpc_config; + Variant rpc_config; GDScriptDataType return_type; return_type.has_type = true; return_type.kind = GDScriptDataType::BUILTIN; diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 726f0efe2b..b38c7c6699 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -639,10 +639,13 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { DISASSEMBLE_PTRCALL(VECTOR3); DISASSEMBLE_PTRCALL(VECTOR3I); DISASSEMBLE_PTRCALL(TRANSFORM2D); + DISASSEMBLE_PTRCALL(VECTOR4); + DISASSEMBLE_PTRCALL(VECTOR4I); DISASSEMBLE_PTRCALL(PLANE); DISASSEMBLE_PTRCALL(AABB); DISASSEMBLE_PTRCALL(BASIS); DISASSEMBLE_PTRCALL(TRANSFORM3D); + DISASSEMBLE_PTRCALL(PROJECTION); DISASSEMBLE_PTRCALL(COLOR); DISASSEMBLE_PTRCALL(STRING_NAME); DISASSEMBLE_PTRCALL(NODE_PATH); @@ -1013,11 +1016,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { DISASSEMBLE_TYPE_ADJUST(VECTOR3); DISASSEMBLE_TYPE_ADJUST(VECTOR3I); DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D); + DISASSEMBLE_TYPE_ADJUST(VECTOR4); + DISASSEMBLE_TYPE_ADJUST(VECTOR4I); DISASSEMBLE_TYPE_ADJUST(PLANE); DISASSEMBLE_TYPE_ADJUST(QUATERNION); DISASSEMBLE_TYPE_ADJUST(AABB); DISASSEMBLE_TYPE_ADJUST(BASIS); DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D); + DISASSEMBLE_TYPE_ADJUST(PROJECTION); DISASSEMBLE_TYPE_ADJUST(COLOR); DISASSEMBLE_TYPE_ADJUST(STRING_NAME); DISASSEMBLE_TYPE_ADJUST(NODE_PATH); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 0a1e1a22fb..d943974ce4 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1473,11 +1473,16 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (callee_type == GDScriptParser::Node::IDENTIFIER || call->is_super) { // Simple call, so base is 'self'. if (p_context.current_class) { - base.type.kind = GDScriptParser::DataType::CLASS; - base.type.type_source = GDScriptParser::DataType::INFERRED; - base.type.is_constant = true; - base.type.class_type = p_context.current_class; - base.value = p_context.base; + if (call->is_super) { + base.type = p_context.current_class->base_type; + base.value = p_context.base; + } else { + base.type.kind = GDScriptParser::DataType::CLASS; + base.type.type_source = GDScriptParser::DataType::INFERRED; + base.type.is_constant = true; + base.type.class_type = p_context.current_class; + base.value = p_context.base; + } } else { break; } @@ -2004,8 +2009,8 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, return false; } - // Check autoloads. - if (ProjectSettings::get_singleton()->has_autoload(p_identifier)) { + // Check global variables (including autoloads). + if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier)) { r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier]); return true; } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 3f1265679b..e44038d6da 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -273,11 +273,14 @@ public: OPCODE_CALL_PTRCALL_VECTOR3, OPCODE_CALL_PTRCALL_VECTOR3I, OPCODE_CALL_PTRCALL_TRANSFORM2D, + OPCODE_CALL_PTRCALL_VECTOR4, + OPCODE_CALL_PTRCALL_VECTOR4I, OPCODE_CALL_PTRCALL_PLANE, OPCODE_CALL_PTRCALL_QUATERNION, OPCODE_CALL_PTRCALL_AABB, OPCODE_CALL_PTRCALL_BASIS, OPCODE_CALL_PTRCALL_TRANSFORM3D, + OPCODE_CALL_PTRCALL_PROJECTION, OPCODE_CALL_PTRCALL_COLOR, OPCODE_CALL_PTRCALL_STRING_NAME, OPCODE_CALL_PTRCALL_NODE_PATH, @@ -363,11 +366,14 @@ public: OPCODE_TYPE_ADJUST_VECTOR3, OPCODE_TYPE_ADJUST_VECTOR3I, OPCODE_TYPE_ADJUST_TRANSFORM2D, + OPCODE_TYPE_ADJUST_VECTOR4, + OPCODE_TYPE_ADJUST_VECTOR4I, OPCODE_TYPE_ADJUST_PLANE, OPCODE_TYPE_ADJUST_QUATERNION, OPCODE_TYPE_ADJUST_AABB, OPCODE_TYPE_ADJUST_BASIS, OPCODE_TYPE_ADJUST_TRANSFORM3D, + OPCODE_TYPE_ADJUST_PROJECTION, OPCODE_TYPE_ADJUST_COLOR, OPCODE_TYPE_ADJUST_STRING_NAME, OPCODE_TYPE_ADJUST_NODE_PATH, @@ -471,7 +477,7 @@ private: int _initial_line = 0; bool _static = false; - Multiplayer::RPCConfig rpc_config; + Variant rpc_config; GDScript *_script = nullptr; @@ -593,7 +599,7 @@ public: void disassemble(const Vector<String> &p_code_lines) const; #endif - _FORCE_INLINE_ Multiplayer::RPCConfig get_rpc_config() const { return rpc_config; } + _FORCE_INLINE_ const Variant get_rpc_config() const { return rpc_config; } GDScriptFunction(); ~GDScriptFunction(); }; diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h index 248176e32c..1954089983 100644 --- a/modules/gdscript/gdscript_lambda_callable.h +++ b/modules/gdscript/gdscript_lambda_callable.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_LAMBDA_CALLABLE -#define GDSCRIPT_LAMBDA_CALLABLE +#ifndef GDSCRIPT_LAMBDA_CALLABLE_H +#define GDSCRIPT_LAMBDA_CALLABLE_H #include "core/object/ref_counted.h" #include "core/templates/vector.h" @@ -87,4 +87,4 @@ public: virtual ~GDScriptLambdaSelfCallable() = default; }; -#endif // GDSCRIPT_LAMBDA_CALLABLE +#endif // GDSCRIPT_LAMBDA_CALLABLE_H diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 6c5d416cf1..6f5397e1a3 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -35,6 +35,7 @@ #include "core/io/resource_loader.h" #include "core/math/math_defs.h" #include "gdscript.h" +#include "scene/main/multiplayer_api.h" #ifdef DEBUG_ENABLED #include "core/os/os.h" @@ -60,11 +61,14 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) { builtin_types["Transform2D"] = Variant::TRANSFORM2D; builtin_types["Vector3"] = Variant::VECTOR3; builtin_types["Vector3i"] = Variant::VECTOR3I; + builtin_types["Vector4"] = Variant::VECTOR4; + builtin_types["Vector4i"] = Variant::VECTOR4I; builtin_types["AABB"] = Variant::AABB; builtin_types["Plane"] = Variant::PLANE; builtin_types["Quaternion"] = Variant::QUATERNION; builtin_types["Basis"] = Variant::BASIS; builtin_types["Transform3D"] = Variant::TRANSFORM3D; + builtin_types["Projection"] = Variant::PROJECTION; builtin_types["Color"] = Variant::COLOR; builtin_types["RID"] = Variant::RID; builtin_types["Object"] = Variant::OBJECT; @@ -142,7 +146,7 @@ GDScriptParser::GDScriptParser() { // Warning annotations. register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true); // Networking. - register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, varray("", "", "", 0), true); + register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::rpc_annotation, varray("", "", "", 0), true); } GDScriptParser::~GDScriptParser() { @@ -3422,7 +3426,16 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String & p_tutorials.append(Pair<String, String>(title, link)); break; case DONE: - return; + break; + } + } + if (current_class->members.size() > 0) { + const ClassNode::Member &m = current_class->members[0]; + int first_member_line = m.get_line(); + if (first_member_line == line) { + p_brief = ""; + p_desc = ""; + p_tutorials.clear(); } } } @@ -3855,16 +3868,21 @@ bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Nod #endif // DEBUG_ENABLED } -template <Multiplayer::RPCMode t_mode> -bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Node *p_node) { - ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE && p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to variables and functions.)", p_annotation->name)); +bool GDScriptParser::rpc_annotation(const AnnotationNode *p_annotation, Node *p_node) { + ERR_FAIL_COND_V_MSG(p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to functions.)", p_annotation->name)); + + FunctionNode *function = static_cast<FunctionNode *>(p_node); + if (function->rpc_config.get_type() != Variant::NIL) { + push_error(R"(RPC annotations can only be used once per function.)", p_annotation); + return false; + } - Multiplayer::RPCConfig rpc_config; - rpc_config.rpc_mode = t_mode; + Dictionary rpc_config; + rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY; if (p_annotation->resolved_arguments.size()) { int last = p_annotation->resolved_arguments.size() - 1; if (p_annotation->resolved_arguments[last].get_type() == Variant::INT) { - rpc_config.channel = p_annotation->resolved_arguments[last].operator int(); + rpc_config["channel"] = p_annotation->resolved_arguments[last].operator int(); last -= 1; } if (last > 3) { @@ -3874,37 +3892,25 @@ bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Nod for (int i = last; i >= 0; i--) { String mode = p_annotation->resolved_arguments[i].operator String(); if (mode == "any_peer") { - rpc_config.rpc_mode = Multiplayer::RPC_MODE_ANY_PEER; + rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER; } else if (mode == "authority") { - rpc_config.rpc_mode = Multiplayer::RPC_MODE_AUTHORITY; + rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY; } else if (mode == "call_local") { - rpc_config.call_local = true; + rpc_config["call_local"] = true; } else if (mode == "call_remote") { - rpc_config.call_local = false; + rpc_config["call_local"] = false; } else if (mode == "reliable") { - rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; + rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; } else if (mode == "unreliable") { - rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE; + rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE; } else if (mode == "unreliable_ordered") { - rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED; + rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED; } else { push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'call_remote' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation); } } } - switch (p_node->type) { - case Node::FUNCTION: { - FunctionNode *function = static_cast<FunctionNode *>(p_node); - if (function->rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { - push_error(R"(RPC annotations can only be used once per function.)", p_annotation); - return false; - } - function->rpc_config = rpc_config; - break; - } - default: - return false; // Unreachable. - } + function->rpc_config = rpc_config; return true; } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 9c97f98fbc..d4efab173b 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -32,7 +32,6 @@ #define GDSCRIPT_PARSER_H #include "core/io/resource.h" -#include "core/multiplayer/multiplayer.h" #include "core/object/ref_counted.h" #include "core/object/script_language.h" #include "core/string/string_name.h" @@ -750,7 +749,7 @@ public: SuiteNode *body = nullptr; bool is_static = false; bool is_coroutine = false; - Multiplayer::RPCConfig rpc_config; + Variant rpc_config; MethodInfo info; LambdaNode *source_lambda = nullptr; #ifdef TOOLS_ENABLED @@ -1371,8 +1370,7 @@ private: template <PropertyUsageFlags t_usage> bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target); bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target); - template <Multiplayer::RPCMode t_mode> - bool network_annotations(const AnnotationNode *p_annotation, Node *p_target); + bool rpc_annotation(const AnnotationNode *p_annotation, Node *p_target); // Statements. Node *parse_statement(); VariableNode *parse_variable(); diff --git a/modules/gdscript/gdscript_rpc_callable.cpp b/modules/gdscript/gdscript_rpc_callable.cpp index 63ebd8acf5..4e12419357 100644 --- a/modules/gdscript/gdscript_rpc_callable.cpp +++ b/modules/gdscript/gdscript_rpc_callable.cpp @@ -76,11 +76,11 @@ GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_m ERR_FAIL_COND_MSG(!node, "RPC can only be defined on class that extends Node."); } -void GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { +Error GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { if (unlikely(!node)) { r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - return; + return ERR_UNCONFIGURED; } r_call_error.error = Callable::CallError::CALL_OK; - node->rpcp(p_peer_id, method, p_arguments, p_argcount); + return node->rpcp(p_peer_id, method, p_arguments, p_argcount); } diff --git a/modules/gdscript/gdscript_rpc_callable.h b/modules/gdscript/gdscript_rpc_callable.h index 2c8734a74b..83b9c7e2df 100644 --- a/modules/gdscript/gdscript_rpc_callable.h +++ b/modules/gdscript/gdscript_rpc_callable.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_RPC_CALLABLE -#define GDSCRIPT_RPC_CALLABLE +#ifndef GDSCRIPT_RPC_CALLABLE_H +#define GDSCRIPT_RPC_CALLABLE_H #include "core/variant/callable.h" #include "core/variant/variant.h" @@ -52,10 +52,10 @@ public: CompareLessFunc get_compare_less_func() const override; ObjectID get_object() const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; - void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override; + Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override; GDScriptRPCCallable(Object *p_object, const StringName &p_method); virtual ~GDScriptRPCCallable() = default; }; -#endif // GDSCRIPT_RPC_CALLABLE +#endif // GDSCRIPT_RPC_CALLABLE_H diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 7fb715f2c8..68b2c6eb1c 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -273,4 +273,4 @@ public: GDScriptTokenizer(); }; -#endif +#endif // GDSCRIPT_TOKENIZER_H diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index a914374985..4b97486cb3 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -115,6 +115,7 @@ struct GDScriptUtilityFunctionsDefinitions { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; + r_error.expected = 1; *r_ret = Variant(); return; } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index e0beed367a..61e2c61abc 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -199,11 +199,14 @@ void (*type_init_function_table[])(Variant *) = { &VariantInitializer<Vector3>::init, // VECTOR3. &VariantInitializer<Vector3i>::init, // VECTOR3I. &VariantInitializer<Transform2D>::init, // TRANSFORM2D. + &VariantInitializer<Vector4>::init, // VECTOR4. + &VariantInitializer<Vector4i>::init, // VECTOR4I. &VariantInitializer<Plane>::init, // PLANE. &VariantInitializer<Quaternion>::init, // QUATERNION. &VariantInitializer<AABB>::init, // AABB. &VariantInitializer<Basis>::init, // BASIS. &VariantInitializer<Transform3D>::init, // TRANSFORM3D. + &VariantInitializer<Projection>::init, // PROJECTION. &VariantInitializer<Color>::init, // COLOR. &VariantInitializer<StringName>::init, // STRING_NAME. &VariantInitializer<NodePath>::init, // NODE_PATH. @@ -282,11 +285,14 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_CALL_PTRCALL_VECTOR3, \ &&OPCODE_CALL_PTRCALL_VECTOR3I, \ &&OPCODE_CALL_PTRCALL_TRANSFORM2D, \ + &&OPCODE_CALL_PTRCALL_VECTOR4, \ + &&OPCODE_CALL_PTRCALL_VECTOR4I, \ &&OPCODE_CALL_PTRCALL_PLANE, \ &&OPCODE_CALL_PTRCALL_QUATERNION, \ &&OPCODE_CALL_PTRCALL_AABB, \ &&OPCODE_CALL_PTRCALL_BASIS, \ &&OPCODE_CALL_PTRCALL_TRANSFORM3D, \ + &&OPCODE_CALL_PTRCALL_PROJECTION, \ &&OPCODE_CALL_PTRCALL_COLOR, \ &&OPCODE_CALL_PTRCALL_STRING_NAME, \ &&OPCODE_CALL_PTRCALL_NODE_PATH, \ @@ -372,11 +378,14 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_TYPE_ADJUST_VECTOR3, \ &&OPCODE_TYPE_ADJUST_VECTOR3I, \ &&OPCODE_TYPE_ADJUST_TRANSFORM2D, \ + &&OPCODE_TYPE_ADJUST_VECTOR4, \ + &&OPCODE_TYPE_ADJUST_VECTOR4I, \ &&OPCODE_TYPE_ADJUST_PLANE, \ &&OPCODE_TYPE_ADJUST_QUATERNION, \ &&OPCODE_TYPE_ADJUST_AABB, \ &&OPCODE_TYPE_ADJUST_BASIS, \ &&OPCODE_TYPE_ADJUST_TRANSFORM3D, \ + &&OPCODE_TYPE_ADJUST_PROJECTION, \ &&OPCODE_TYPE_ADJUST_COLOR, \ &&OPCODE_TYPE_ADJUST_STRING_NAME, \ &&OPCODE_TYPE_ADJUST_NODE_PATH, \ @@ -435,6 +444,8 @@ void (*type_init_function_table[])(Variant *) = { #define OP_GET_VECTOR3 get_vector3 #define OP_GET_VECTOR3I get_vector3i #define OP_GET_RECT2 get_rect2 +#define OP_GET_VECTOR4 get_vector4 +#define OP_GET_VECTOR4I get_vector4i #define OP_GET_RECT2I get_rect2i #define OP_GET_QUATERNION get_quaternion #define OP_GET_COLOR get_color @@ -456,6 +467,7 @@ void (*type_init_function_table[])(Variant *) = { #define OP_GET_PACKED_COLOR_ARRAY get_color_array #define OP_GET_TRANSFORM3D get_transform #define OP_GET_TRANSFORM2D get_transform2d +#define OP_GET_PROJECTION get_projection #define OP_GET_PLANE get_plane #define OP_GET_AABB get_aabb #define OP_GET_BASIS get_basis @@ -1827,11 +1839,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_CALL_PTR(VECTOR3); OPCODE_CALL_PTR(VECTOR3I); OPCODE_CALL_PTR(TRANSFORM2D); + OPCODE_CALL_PTR(VECTOR4); + OPCODE_CALL_PTR(VECTOR4I); OPCODE_CALL_PTR(PLANE); OPCODE_CALL_PTR(QUATERNION); OPCODE_CALL_PTR(AABB); OPCODE_CALL_PTR(BASIS); OPCODE_CALL_PTR(TRANSFORM3D); + OPCODE_CALL_PTR(PROJECTION); OPCODE_CALL_PTR(COLOR); OPCODE_CALL_PTR(STRING_NAME); OPCODE_CALL_PTR(NODE_PATH); @@ -2219,7 +2234,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a retvalue = gdfs; - Error err = sig.connect(callable_bind(Callable(gdfs.ptr(), "_signal_callback"), retvalue), Object::CONNECT_ONESHOT); + Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONESHOT); if (err != OK) { err_text = "Error connecting to signal: " + sig.get_name() + " during await."; OPCODE_BREAK; @@ -3280,6 +3295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a int globalname_idx = _code_ptr[ip + 2]; GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count); const StringName *globalname = &_global_names_ptr[globalname_idx]; + GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname)); GET_INSTRUCTION_ARG(dst, 0); *dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname]; @@ -3308,11 +3324,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_TYPE_ADJUST(VECTOR3, Vector3); OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i); OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D); + OPCODE_TYPE_ADJUST(VECTOR4, Vector4); + OPCODE_TYPE_ADJUST(VECTOR4I, Vector4i); OPCODE_TYPE_ADJUST(PLANE, Plane); OPCODE_TYPE_ADJUST(QUATERNION, Quaternion); OPCODE_TYPE_ADJUST(AABB, AABB); OPCODE_TYPE_ADJUST(BASIS, Basis); OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D); + OPCODE_TYPE_ADJUST(PROJECTION, Projection); OPCODE_TYPE_ADJUST(COLOR, Color); OPCODE_TYPE_ADJUST(STRING_NAME, StringName); OPCODE_TYPE_ADJUST(NODE_PATH, NodePath); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index f47f31aedf..a639e7b44e 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_WARNINGS -#define GDSCRIPT_WARNINGS +#ifndef GDSCRIPT_WARNING_H +#define GDSCRIPT_WARNING_H #ifdef DEBUG_ENABLED @@ -97,4 +97,4 @@ public: #endif // DEBUG_ENABLED -#endif // GDSCRIPT_WARNINGS +#endif // GDSCRIPT_WARNING_H diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 03e93821c7..46a9b33eb0 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -690,9 +690,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio ERR_FAIL_NULL_V(p_func, func); func["name"] = p_func->identifier->name; func["return_type"] = p_func->get_datatype().to_string(); - func["rpc_mode"] = p_func->rpc_config.rpc_mode; - func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode; - func["rpc_transfer_channel"] = p_func->rpc_config.channel; + func["rpc_config"] = p_func->rpc_config; Array parameters; for (int i = 0; i < p_func->parameters.size(); i++) { Dictionary arg; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index 99b0bf45d0..08bba4a2d4 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.h +++ b/modules/gdscript/language_server/gdscript_extend_parser.h @@ -33,7 +33,7 @@ #include "../gdscript_parser.h" #include "core/variant/variant.h" -#include "lsp.hpp" +#include "godot_lsp.h" #ifndef LINE_NUMBER_TO_INDEX #define LINE_NUMBER_TO_INDEX(p_line) ((p_line)-1) @@ -99,4 +99,4 @@ public: Error parse(const String &p_code, const String &p_path); }; -#endif +#endif // GDSCRIPT_EXTEND_PARSER_H diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 7460f8edff..c0d5856be5 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -34,6 +34,7 @@ #include "editor/doc_tools.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 0fed8597f9..3c9cfe512f 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -36,7 +36,7 @@ #include "core/io/tcp_server.h" #include "gdscript_text_document.h" #include "gdscript_workspace.h" -#include "lsp.hpp" +#include "godot_lsp.h" #include "modules/modules_enabled.gen.h" // For jsonrpc. #ifdef MODULE_JSONRPC_ENABLED diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 14337e87da..ead4ef1987 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageServer::GDScriptLanguageServer() { _EDITOR_DEF("network/language_server/remote_host", host); diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 9732765f34..87bc08a34e 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -33,7 +33,7 @@ #include "core/io/file_access.h" #include "core/object/ref_counted.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptTextDocument : public RefCounted { GDCLASS(GDScriptTextDocument, RefCounted) @@ -77,4 +77,4 @@ public: GDScriptTextDocument(); }; -#endif +#endif // GDSCRIPT_TEXT_DOCUMENT_H diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 8d484a43b3..ded2a7b4d4 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_help.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "gdscript_language_protocol.h" #include "scene/resources/packed_scene.h" @@ -499,7 +500,9 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) { String GDScriptWorkspace::get_file_path(const String &p_uri) const { String path = p_uri; - path = path.replace(root_uri + "/", "res://"); + path = path.replace("///", "//"); + path = path.replace("%3A", ":"); + path = path.replacen(root_uri + "/", "res://"); path = path.uri_decode(); return path; } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index 7bff5db81f..88f3aaf957 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -35,7 +35,7 @@ #include "core/variant/variant.h" #include "editor/editor_file_system.h" #include "gdscript_extend_parser.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptWorkspace : public RefCounted { GDCLASS(GDScriptWorkspace, RefCounted); @@ -100,4 +100,4 @@ public: ~GDScriptWorkspace(); }; -#endif +#endif // GDSCRIPT_WORKSPACE_H diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/godot_lsp.h index 1c9349097f..fbd40796c4 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/godot_lsp.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* lsp.hpp */ +/* godot_lsp.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -1975,4 +1975,4 @@ static String marked_documentation(const String &p_bbcode) { } } // namespace lsp -#endif +#endif // GODOT_LSP_H diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index b230c6ba36..059ca703ab 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -52,10 +52,10 @@ GDScriptCache *gdscript_cache = nullptr; #ifdef TOOLS_ENABLED -#include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_translation_parser.h" +#include "editor/export/editor_export.h" #include "editor/gdscript_highlighter.h" #include "editor/gdscript_translation_parser_plugin.h" diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index ff4832bde0..e3b956369d 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -36,6 +36,7 @@ #include "../gdscript_parser.h" #include "core/config/project_settings.h" +#include "core/core_globals.h" #include "core/core_string_names.h" #include "core/io/dir_access.h" #include "core/io/file_access_pack.h" @@ -142,8 +143,8 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l #endif // Enable printing to show results - _print_line_enabled = true; - _print_error_enabled = true; + CoreGlobals::print_line_enabled = true; + CoreGlobals::print_error_enabled = true; } GDScriptTestRunner::~GDScriptTestRunner() { diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h index ee21afd9c9..033d2fcad1 100644 --- a/modules/gdscript/tests/gdscript_test_runner.h +++ b/modules/gdscript/tests/gdscript_test_runner.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_TEST_H -#define GDSCRIPT_TEST_H +#ifndef GDSCRIPT_TEST_RUNNER_H +#define GDSCRIPT_TEST_RUNNER_H #include "../gdscript.h" #include "core/error/error_macros.h" @@ -123,4 +123,4 @@ public: } // namespace GDScriptTests -#endif // GDSCRIPT_TEST_H +#endif // GDSCRIPT_TEST_RUNNER_H diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd index fb0ace6a90..ea744e3027 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd @@ -1,3 +1,5 @@ +const A := 42 + func test(): pass diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd new file mode 100644 index 0000000000..276875dd5a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd @@ -0,0 +1,6 @@ +const Constants = preload("gdscript_to_preload.gd") + +func test(): + var a := Constants.A + print(a) + diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out new file mode 100644 index 0000000000..0982f3718c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out @@ -0,0 +1,2 @@ +GDTEST_OK +42 diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index 64891d9ee8..b1c2140039 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -38,7 +38,8 @@ #include <glslang/Public/ShaderLang.h> #include <glslang/SPIRV/GlslangToSpv.h> -static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice::Capabilities *p_capabilities) { +static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device) { + const RD::Capabilities *capabilities = p_render_device->get_device_capabilities(); Vector<uint8_t> ret; ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret); @@ -58,12 +59,12 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5; glslang::TShader::ForbidIncluder includer; - if (p_capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) { - if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 0) { + if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) { + if (capabilities->version_major == 1 && capabilities->version_minor == 0) { ClientVersion = glslang::EShTargetVulkan_1_0; TargetVersion = glslang::EShTargetSpv_1_0; check_subgroup_support = false; // subgroups are not supported in Vulkan 1.0 - } else if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 1) { + } else if (capabilities->version_major == 1 && capabilities->version_minor == 1) { ClientVersion = glslang::EShTargetVulkan_1_1; TargetVersion = glslang::EShTargetSpv_1_3; } else { @@ -90,34 +91,36 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage if (check_subgroup_support) { uint32_t stage_bit = 1 << p_stage; - if ((p_capabilities->subgroup_in_shaders & stage_bit) == stage_bit) { + uint32_t subgroup_in_shaders = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)); + uint32_t subgroup_operations = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)); + if ((subgroup_in_shaders & stage_bit) == stage_bit) { // stage supports subgroups preamble += "#define has_GL_KHR_shader_subgroup_basic 1\n"; - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_arithmetic 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_shuffle 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_clustered 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n"; } } } - if (p_capabilities->supports_multiview) { + if (p_render_device->has_feature(RD::SUPPORTS_MULTIVIEW)) { preamble += "#define has_VK_KHR_multiview 1\n"; } @@ -184,9 +187,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage return ret; } -static String _get_cache_key_function_glsl(const RenderingDevice::Capabilities *p_capabilities) { +static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) { + const RD::Capabilities *capabilities = p_render_device->get_device_capabilities(); String version; - version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(p_capabilities->version_major) + ", minor=" + itos(p_capabilities->version_minor) + " , subgroup_size=" + itos(p_capabilities->subgroup_operations) + " , subgroup_ops=" + itos(p_capabilities->subgroup_operations) + " , subgroup_in_shaders=" + itos(p_capabilities->subgroup_in_shaders); + version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)); return version; } diff --git a/modules/gltf/README.md b/modules/gltf/README.md new file mode 100644 index 0000000000..5d8966b201 --- /dev/null +++ b/modules/gltf/README.md @@ -0,0 +1,11 @@ +# Godot GLTF import and export module + +In a nutshell, the GLTF module works like this: + +* The [`structures/`](structures/) folder contains GLTF structures, the + small pieces that make up a GLTF file, represented as C++ classes. +* The [`extensions/`](extensions/) folder contains GLTF extensions, which + are optional features that build on top of the base GLTF spec. +* [`GLTFState`](gltf_state.h) holds collections of structures and extensions. +* [`GLTFDocument`](gltf_document.h) operates on GLTFState and its elements. +* The [`editor/`](editor/) folder uses GLTFDocument to import and export 3D models. diff --git a/modules/gltf/SCsub b/modules/gltf/SCsub index 3379404a00..71f3ba58d9 100644 --- a/modules/gltf/SCsub +++ b/modules/gltf/SCsub @@ -5,7 +5,9 @@ Import("env_modules") env_gltf = env_modules.Clone() -# Godot's own source files +# Godot source files env_gltf.add_source_files(env.modules_sources, "*.cpp") +env_gltf.add_source_files(env.modules_sources, "extensions/*.cpp") +env_gltf.add_source_files(env.modules_sources, "structures/*.cpp") if env["tools"]: env_gltf.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 033591a0b9..8002c185c7 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -292,7 +292,7 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { path = path.plus_file("blender"); #endif -#if defined(OSX_ENABLED) +#if defined(MACOS_ENABLED) if (!FileAccess::exists(path)) { path = path.plus_file("Blender"); } @@ -468,7 +468,7 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() { // Autodetect auto_detected_path = ""; -#if defined(OSX_ENABLED) +#if defined(MACOS_ENABLED) { Vector<String> mdfind_paths; diff --git a/modules/gltf/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp index af21a4e804..af21a4e804 100644 --- a/modules/gltf/gltf_light.cpp +++ b/modules/gltf/extensions/gltf_light.cpp diff --git a/modules/gltf/gltf_light.h b/modules/gltf/extensions/gltf_light.h index 25e0835a33..58fa299dfd 100644 --- a/modules/gltf/gltf_light.h +++ b/modules/gltf/extensions/gltf_light.h @@ -33,6 +33,7 @@ #include "core/config/engine.h" #include "core/io/resource.h" +#include "scene/3d/light_3d.h" class GLTFLight : public Resource { GDCLASS(GLTFLight, Resource) diff --git a/modules/gltf/gltf_spec_gloss.cpp b/modules/gltf/extensions/gltf_spec_gloss.cpp index 83af91bfcc..83af91bfcc 100644 --- a/modules/gltf/gltf_spec_gloss.cpp +++ b/modules/gltf/extensions/gltf_spec_gloss.cpp diff --git a/modules/gltf/gltf_spec_gloss.h b/modules/gltf/extensions/gltf_spec_gloss.h index f8a431bdce..a45fa4296c 100644 --- a/modules/gltf/gltf_spec_gloss.h +++ b/modules/gltf/extensions/gltf_spec_gloss.h @@ -64,4 +64,5 @@ public: Ref<Image> get_spec_gloss_img(); void set_spec_gloss_img(Ref<Image> p_spec_gloss_img); }; + #endif // GLTF_SPEC_GLOSS_H diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h new file mode 100644 index 0000000000..c20c87f798 --- /dev/null +++ b/modules/gltf/gltf_defines.h @@ -0,0 +1,87 @@ +/*************************************************************************/ +/* gltf_defines.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 GLTF_DEFINES_H +#define GLTF_DEFINES_H + +// This file should only be included by other headers. + +// Godot classes used by GLTF headers. +class BoneAttachment3D; +class CSGShape3D; +class DirectionalLight3D; +class GridMap; +class Light3D; +class MultiMeshInstance3D; +class Skeleton3D; +class Skin; + +// GLTF classes. +struct GLTFAccessor; +class GLTFAnimation; +class GLTFBufferView; +class GLTFCamera; +class GLTFDocument; +class GLTFDocumentExtension; +class GLTFLight; +class GLTFMesh; +class GLTFNode; +class GLTFSkeleton; +class GLTFSkin; +class GLTFSpecGloss; +class GLTFState; +class GLTFTexture; + +// GLTF index aliases. +using GLTFAccessorIndex = int; +using GLTFAnimationIndex = int; +using GLTFBufferIndex = int; +using GLTFBufferViewIndex = int; +using GLTFCameraIndex = int; +using GLTFImageIndex = int; +using GLTFMaterialIndex = int; +using GLTFMeshIndex = int; +using GLTFLightIndex = int; +using GLTFNodeIndex = int; +using GLTFSkeletonIndex = int; +using GLTFSkinIndex = int; +using GLTFTextureIndex = int; + +enum GLTFType { + TYPE_SCALAR, + TYPE_VEC2, + TYPE_VEC3, + TYPE_VEC4, + TYPE_MAT2, + TYPE_MAT3, + TYPE_MAT4, +}; + +#endif // GLTF_DEFINES_H diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index babdc9f33b..7e90f198f6 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -30,19 +30,10 @@ #include "gltf_document.h" -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_camera.h" +#include "extensions/gltf_spec_gloss.h" #include "gltf_document_extension.h" #include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_spec_gloss.h" #include "gltf_state.h" -#include "gltf_texture.h" #include "core/crypto/crypto_core.h" #include "core/error/error_macros.h" @@ -230,15 +221,21 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { } Error GLTFDocument::_serialize_extensions(Ref<GLTFState> state) const { - const String texture_transform = "KHR_texture_transform"; - const String punctual_lights = "KHR_lights_punctual"; Array extensions_used; - extensions_used.push_back(punctual_lights); - extensions_used.push_back(texture_transform); - state->json["extensionsUsed"] = extensions_used; Array extensions_required; - extensions_required.push_back(texture_transform); - state->json["extensionsRequired"] = extensions_required; + if (!state->lights.is_empty()) { + extensions_used.push_back("KHR_lights_punctual"); + } + if (state->use_khr_texture_transform) { + extensions_used.push_back("KHR_texture_transform"); + extensions_required.push_back("KHR_texture_transform"); + } + if (!extensions_used.is_empty()) { + state->json["extensionsUsed"] = extensions_used; + } + if (!extensions_required.is_empty()) { + state->json["extensionsRequired"] = extensions_required; + } return OK; } @@ -934,58 +931,58 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) { return OK; } -String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type) { - if (p_type == GLTFDocument::TYPE_SCALAR) { +String GLTFDocument::_get_accessor_type_name(const GLTFType p_type) { + if (p_type == GLTFType::TYPE_SCALAR) { return "SCALAR"; } - if (p_type == GLTFDocument::TYPE_VEC2) { + if (p_type == GLTFType::TYPE_VEC2) { return "VEC2"; } - if (p_type == GLTFDocument::TYPE_VEC3) { + if (p_type == GLTFType::TYPE_VEC3) { return "VEC3"; } - if (p_type == GLTFDocument::TYPE_VEC4) { + if (p_type == GLTFType::TYPE_VEC4) { return "VEC4"; } - if (p_type == GLTFDocument::TYPE_MAT2) { + if (p_type == GLTFType::TYPE_MAT2) { return "MAT2"; } - if (p_type == GLTFDocument::TYPE_MAT3) { + if (p_type == GLTFType::TYPE_MAT3) { return "MAT3"; } - if (p_type == GLTFDocument::TYPE_MAT4) { + if (p_type == GLTFType::TYPE_MAT4) { return "MAT4"; } ERR_FAIL_V("SCALAR"); } -GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { +GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { if (p_string == "SCALAR") { - return GLTFDocument::TYPE_SCALAR; + return GLTFType::TYPE_SCALAR; } if (p_string == "VEC2") { - return GLTFDocument::TYPE_VEC2; + return GLTFType::TYPE_VEC2; } if (p_string == "VEC3") { - return GLTFDocument::TYPE_VEC3; + return GLTFType::TYPE_VEC3; } if (p_string == "VEC4") { - return GLTFDocument::TYPE_VEC4; + return GLTFType::TYPE_VEC4; } if (p_string == "MAT2") { - return GLTFDocument::TYPE_MAT2; + return GLTFType::TYPE_MAT2; } if (p_string == "MAT3") { - return GLTFDocument::TYPE_MAT3; + return GLTFType::TYPE_MAT3; } if (p_string == "MAT4") { - return GLTFDocument::TYPE_MAT4; + return GLTFType::TYPE_MAT4; } - ERR_FAIL_V(GLTFDocument::TYPE_SCALAR); + ERR_FAIL_V(GLTFType::TYPE_SCALAR); } Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) { @@ -1536,7 +1533,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_INT; accessor->max = type_max; @@ -1620,7 +1617,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC2; + const GLTFType type = GLTFType::TYPE_VEC2; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1669,7 +1666,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1734,7 +1731,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1781,7 +1778,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; accessor->max = type_max; @@ -1830,7 +1827,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1895,7 +1892,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1941,7 +1938,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC3; + const GLTFType type = GLTFType::TYPE_VEC3; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -2009,7 +2006,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_MAT4; + const GLTFType type = GLTFType::TYPE_MAT4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -3305,7 +3302,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (gltf_texture_index != -1) { bct["index"] = gltf_texture_index; - bct["extensions"] = _serialize_texture_transform_uv1(material); + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + bct["extensions"] = extensions; + state->use_khr_texture_transform = true; + } mr["baseColorTexture"] = bct; } } @@ -3436,7 +3437,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (has_roughness || has_metalness) { mrt["index"] = orm_texture_index; - mrt["extensions"] = _serialize_texture_transform_uv1(material); + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + mrt["extensions"] = extensions; + state->use_khr_texture_transform = true; + } mr["metallicRoughnessTexture"] = mrt; } } @@ -4525,6 +4530,9 @@ void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> state) { } Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { + if (state->lights.is_empty()) { + return OK; + } Array lights; for (GLTFLightIndex i = 0; i < state->lights.size(); i++) { Dictionary d; @@ -4551,10 +4559,6 @@ Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { lights.push_back(d); } - if (!state->lights.size()) { - return OK; - } - Dictionary extensions; if (state->json.has("extensions")) { extensions = state->json["extensions"]; @@ -4934,7 +4938,8 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { if (d.has("name")) { const String name = d["name"]; - if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { + const String name_lower = name.to_lower(); + if (name_lower.begins_with("loop") || name_lower.ends_with("loop") || name_lower.begins_with("cycle") || name_lower.ends_with("cycle")) { animation->set_loop(true); } animation->set_name(_gen_unique_animation_name(state, name)); @@ -5214,7 +5219,7 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_ Ref<GLTFCamera> c; c.instantiate(); - if (p_camera->get_projection() == Camera3D::Projection::PROJECTION_PERSPECTIVE) { + if (p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE) { c->set_perspective(true); } c->set_fov_size(p_camera->get_fov()); @@ -6651,45 +6656,48 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> return OK; } -Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) { - Dictionary extension; - Ref<BaseMaterial3D> mat = p_material; - if (mat.is_valid()) { - Dictionary texture_transform; +Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) { + Dictionary texture_transform; + bool is_offset = p_offset != Vector2(0.0, 0.0); + if (is_offset) { Array offset; offset.resize(2); - offset[0] = mat->get_uv2_offset().x; - offset[1] = mat->get_uv2_offset().y; + offset[0] = p_offset.x; + offset[1] = p_offset.y; texture_transform["offset"] = offset; + } + bool is_scaled = p_scale != Vector2(1.0, 1.0); + if (is_scaled) { Array scale; scale.resize(2); - scale[0] = mat->get_uv2_scale().x; - scale[1] = mat->get_uv2_scale().y; + scale[0] = p_scale.x; + scale[1] = p_scale.y; texture_transform["scale"] = scale; - // Godot doesn't support texture rotation + } + Dictionary extension; + // Note: Godot doesn't support texture rotation. + if (is_offset || is_scaled) { extension["KHR_texture_transform"] = texture_transform; } return extension; } Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) { - Dictionary extension; if (p_material.is_valid()) { - Dictionary texture_transform; - Array offset; - offset.resize(2); - offset[0] = p_material->get_uv1_offset().x; - offset[1] = p_material->get_uv1_offset().y; - texture_transform["offset"] = offset; - Array scale; - scale.resize(2); - scale[0] = p_material->get_uv1_scale().x; - scale[1] = p_material->get_uv1_scale().y; - texture_transform["scale"] = scale; - // Godot doesn't support texture rotation - extension["KHR_texture_transform"] = texture_transform; + Vector3 offset = p_material->get_uv1_offset(); + Vector3 scale = p_material->get_uv1_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); } - return extension; + return Dictionary(); +} + +Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) { + if (p_material.is_valid()) { + Vector3 offset = p_material->get_uv2_offset(); + Vector3 scale = p_material->get_uv2_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); + } + return Dictionary(); } Error GLTFDocument::_serialize_version(Ref<GLTFState> state) { @@ -6929,15 +6937,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32 state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - _convert_scene_node(state, p_node, -1, -1); - if (!state->buffers.size()) { - state->buffers.push_back(Vector<uint8_t>()); - } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; ERR_CONTINUE(ext.is_null()); @@ -6948,7 +6947,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32 if (!state->buffers.size()) { state->buffers.push_back(Vector<uint8_t>()); } - return OK; } diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 2f61210ff9..36a2f94a4e 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -31,48 +31,19 @@ #ifndef GLTF_DOCUMENT_H #define GLTF_DOCUMENT_H -#include "gltf_animation.h" +#include "gltf_defines.h" +#include "structures/gltf_animation.h" #include "scene/3d/bone_attachment_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/material.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. -#include <cstdint> - -class GLTFState; -class GLTFSkin; -class GLTFNode; -class GLTFSpecGloss; -class GLTFSkeleton; -class CSGShape3D; -class GridMap; -class MultiMeshInstance3D; -class GLTFDocumentExtension; - -using GLTFAccessorIndex = int; -using GLTFAnimationIndex = int; -using GLTFBufferIndex = int; -using GLTFBufferViewIndex = int; -using GLTFCameraIndex = int; -using GLTFImageIndex = int; -using GLTFMaterialIndex = int; -using GLTFMeshIndex = int; -using GLTFLightIndex = int; -using GLTFNodeIndex = int; -using GLTFSkeletonIndex = int; -using GLTFSkinIndex = int; -using GLTFTextureIndex = int; - class GLTFDocument : public Resource { GDCLASS(GLTFDocument, Resource); - friend class GLTFState; - friend class GLTFSkin; - friend class GLTFSkeleton; TypedArray<GLTFDocumentExtension> document_extensions; private: @@ -81,15 +52,6 @@ private: public: GLTFDocument(); const int32_t JOINT_GROUP_SIZE = 4; - enum GLTFType { - TYPE_SCALAR, - TYPE_VEC2, - TYPE_VEC3, - TYPE_VEC4, - TYPE_MAT2, - TYPE_MAT3, - TYPE_MAT4, - }; enum { ARRAY_BUFFER = 34962, @@ -118,58 +80,6 @@ public: TypedArray<GLTFDocumentExtension> get_extensions() const; private: - template <class T> - static Array to_array(const Vector<T> &p_inp) { - Array ret; - for (int i = 0; i < p_inp.size(); i++) { - ret.push_back(p_inp[i]); - } - return ret; - } - - template <class T> - static Array to_array(const HashSet<T> &p_inp) { - Array ret; - typename HashSet<T>::Iterator elem = p_inp.begin(); - while (elem) { - ret.push_back(*elem); - ++elem; - } - return ret; - } - - template <class T> - static void set_from_array(Vector<T> &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.push_back(p_inp[i]); - } - } - - template <class T> - static void set_from_array(HashSet<T> &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.insert(p_inp[i]); - } - } - template <class K, class V> - static Dictionary to_dict(const HashMap<K, V> &p_inp) { - Dictionary ret; - for (const KeyValue<K, V> &E : p_inp) { - ret[E.key] = E.value; - } - return ret; - } - - template <class K, class V> - static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) { - r_out.clear(); - Array keys = p_inp.keys(); - for (int i = 0; i < keys.size(); i++) { - r_out[keys[i]] = p_inp[keys[i]]; - } - } void _build_parent_hierachy(Ref<GLTFState> state); double _filter_number(double p_float); String _get_component_type_name(const uint32_t p_component); @@ -177,7 +87,7 @@ private: Error _parse_scenes(Ref<GLTFState> state); Error _parse_nodes(Ref<GLTFState> state); String _get_type_name(const GLTFType p_component); - String _get_accessor_type_name(const GLTFDocument::GLTFType p_type); + String _get_accessor_type_name(const GLTFType p_type); String _gen_unique_name(Ref<GLTFState> state, const String &p_name); String _sanitize_animation_name(const String &name); String _gen_unique_animation_name(Ref<GLTFState> state, const String &p_name); diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/gltf_document_extension.h index 556f79e887..0ef9109584 100644 --- a/modules/gltf/gltf_document_extension.h +++ b/modules/gltf/gltf_document_extension.h @@ -31,9 +31,8 @@ #ifndef GLTF_DOCUMENT_EXTENSION_H #define GLTF_DOCUMENT_EXTENSION_H -#include "gltf_accessor.h" -#include "gltf_node.h" #include "gltf_state.h" +#include "structures/gltf_node.h" class GLTFDocumentExtension : public Resource { GDCLASS(GLTFDocumentExtension, Resource); diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/gltf_document_extension_convert_importer_mesh.h index 4c9e42a00f..00e664e73f 100644 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h +++ b/modules/gltf/gltf_document_extension_convert_importer_mesh.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GLTF_EXTENSION_EDITOR_H -#define GLTF_EXTENSION_EDITOR_H +#ifndef GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H +#define GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H #include "gltf_document_extension.h" @@ -37,8 +37,6 @@ #include "scene/3d/mesh_instance_3d.h" #include "scene/resources/importer_mesh.h" -class GLTFDocumentExtension; -class GLTFDocument; class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension { GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension); @@ -48,4 +46,5 @@ protected: public: Error import_post(Ref<GLTFState> p_state, Node *p_root) override; }; -#endif // GLTF_EXTENSION_EDITOR_H + +#endif // GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 989fa476c2..a5f7bcf9d6 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -150,51 +150,51 @@ void GLTFState::set_use_named_skin_binds(bool p_use_named_skin_binds) { } Array GLTFState::get_nodes() { - return GLTFDocument::to_array(nodes); + return GLTFTemplateConvert::to_array(nodes); } void GLTFState::set_nodes(Array p_nodes) { - GLTFDocument::set_from_array(nodes, p_nodes); + GLTFTemplateConvert::set_from_array(nodes, p_nodes); } Array GLTFState::get_buffers() { - return GLTFDocument::to_array(buffers); + return GLTFTemplateConvert::to_array(buffers); } void GLTFState::set_buffers(Array p_buffers) { - GLTFDocument::set_from_array(buffers, p_buffers); + GLTFTemplateConvert::set_from_array(buffers, p_buffers); } Array GLTFState::get_buffer_views() { - return GLTFDocument::to_array(buffer_views); + return GLTFTemplateConvert::to_array(buffer_views); } void GLTFState::set_buffer_views(Array p_buffer_views) { - GLTFDocument::set_from_array(buffer_views, p_buffer_views); + GLTFTemplateConvert::set_from_array(buffer_views, p_buffer_views); } Array GLTFState::get_accessors() { - return GLTFDocument::to_array(accessors); + return GLTFTemplateConvert::to_array(accessors); } void GLTFState::set_accessors(Array p_accessors) { - GLTFDocument::set_from_array(accessors, p_accessors); + GLTFTemplateConvert::set_from_array(accessors, p_accessors); } Array GLTFState::get_meshes() { - return GLTFDocument::to_array(meshes); + return GLTFTemplateConvert::to_array(meshes); } void GLTFState::set_meshes(Array p_meshes) { - GLTFDocument::set_from_array(meshes, p_meshes); + GLTFTemplateConvert::set_from_array(meshes, p_meshes); } Array GLTFState::get_materials() { - return GLTFDocument::to_array(materials); + return GLTFTemplateConvert::to_array(materials); } void GLTFState::set_materials(Array p_materials) { - GLTFDocument::set_from_array(materials, p_materials); + GLTFTemplateConvert::set_from_array(materials, p_materials); } String GLTFState::get_scene_name() { @@ -206,91 +206,91 @@ void GLTFState::set_scene_name(String p_scene_name) { } Array GLTFState::get_root_nodes() { - return GLTFDocument::to_array(root_nodes); + return GLTFTemplateConvert::to_array(root_nodes); } void GLTFState::set_root_nodes(Array p_root_nodes) { - GLTFDocument::set_from_array(root_nodes, p_root_nodes); + GLTFTemplateConvert::set_from_array(root_nodes, p_root_nodes); } Array GLTFState::get_textures() { - return GLTFDocument::to_array(textures); + return GLTFTemplateConvert::to_array(textures); } void GLTFState::set_textures(Array p_textures) { - GLTFDocument::set_from_array(textures, p_textures); + GLTFTemplateConvert::set_from_array(textures, p_textures); } Array GLTFState::get_images() { - return GLTFDocument::to_array(images); + return GLTFTemplateConvert::to_array(images); } void GLTFState::set_images(Array p_images) { - GLTFDocument::set_from_array(images, p_images); + GLTFTemplateConvert::set_from_array(images, p_images); } Array GLTFState::get_skins() { - return GLTFDocument::to_array(skins); + return GLTFTemplateConvert::to_array(skins); } void GLTFState::set_skins(Array p_skins) { - GLTFDocument::set_from_array(skins, p_skins); + GLTFTemplateConvert::set_from_array(skins, p_skins); } Array GLTFState::get_cameras() { - return GLTFDocument::to_array(cameras); + return GLTFTemplateConvert::to_array(cameras); } void GLTFState::set_cameras(Array p_cameras) { - GLTFDocument::set_from_array(cameras, p_cameras); + GLTFTemplateConvert::set_from_array(cameras, p_cameras); } Array GLTFState::get_lights() { - return GLTFDocument::to_array(lights); + return GLTFTemplateConvert::to_array(lights); } void GLTFState::set_lights(Array p_lights) { - GLTFDocument::set_from_array(lights, p_lights); + GLTFTemplateConvert::set_from_array(lights, p_lights); } Array GLTFState::get_unique_names() { - return GLTFDocument::to_array(unique_names); + return GLTFTemplateConvert::to_array(unique_names); } void GLTFState::set_unique_names(Array p_unique_names) { - GLTFDocument::set_from_array(unique_names, p_unique_names); + GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); } Array GLTFState::get_unique_animation_names() { - return GLTFDocument::to_array(unique_animation_names); + return GLTFTemplateConvert::to_array(unique_animation_names); } void GLTFState::set_unique_animation_names(Array p_unique_animation_names) { - GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names); + GLTFTemplateConvert::set_from_array(unique_animation_names, p_unique_animation_names); } Array GLTFState::get_skeletons() { - return GLTFDocument::to_array(skeletons); + return GLTFTemplateConvert::to_array(skeletons); } void GLTFState::set_skeletons(Array p_skeletons) { - GLTFDocument::set_from_array(skeletons, p_skeletons); + GLTFTemplateConvert::set_from_array(skeletons, p_skeletons); } Dictionary GLTFState::get_skeleton_to_node() { - return GLTFDocument::to_dict(skeleton_to_node); + return GLTFTemplateConvert::to_dict(skeleton_to_node); } void GLTFState::set_skeleton_to_node(Dictionary p_skeleton_to_node) { - GLTFDocument::set_from_dict(skeleton_to_node, p_skeleton_to_node); + GLTFTemplateConvert::set_from_dict(skeleton_to_node, p_skeleton_to_node); } Array GLTFState::get_animations() { - return GLTFDocument::to_array(animations); + return GLTFTemplateConvert::to_array(animations); } void GLTFState::set_animations(Array p_animations) { - GLTFDocument::set_from_array(animations, p_animations); + GLTFTemplateConvert::set_from_array(animations, p_animations); } Node *GLTFState::get_scene_node(GLTFNodeIndex idx) { diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 2fdef19038..d2a4948f06 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -31,18 +31,17 @@ #ifndef GLTF_STATE_H #define GLTF_STATE_H -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_buffer_view.h" -#include "gltf_camera.h" -#include "gltf_document.h" -#include "gltf_document_extension.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_texture.h" +#include "extensions/gltf_light.h" +#include "gltf_template_convert.h" +#include "structures/gltf_accessor.h" +#include "structures/gltf_animation.h" +#include "structures/gltf_buffer_view.h" +#include "structures/gltf_camera.h" +#include "structures/gltf_mesh.h" +#include "structures/gltf_node.h" +#include "structures/gltf_skeleton.h" +#include "structures/gltf_skin.h" +#include "structures/gltf_texture.h" #include "core/templates/rb_map.h" #include "scene/animation/animation_player.h" @@ -60,6 +59,7 @@ class GLTFState : public Resource { Vector<uint8_t> glb_data; bool use_named_skin_binds = false; + bool use_khr_texture_transform = false; bool discard_meshes_and_materials = false; Vector<Ref<GLTFNode>> nodes; @@ -192,4 +192,5 @@ public: // this->material_cache = p_material_cache; //} }; + #endif // GLTF_STATE_H diff --git a/modules/gltf/gltf_template_convert.h b/modules/gltf/gltf_template_convert.h new file mode 100644 index 0000000000..c915d3deb0 --- /dev/null +++ b/modules/gltf/gltf_template_convert.h @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* gltf_template_convert.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 GLTF_TEMPLATE_CONVERT_H +#define GLTF_TEMPLATE_CONVERT_H + +#include "core/templates/hash_set.h" +#include "core/variant/array.h" +#include "core/variant/dictionary.h" + +namespace GLTFTemplateConvert { +template <class T> +static Array to_array(const Vector<T> &p_inp) { + Array ret; + for (int i = 0; i < p_inp.size(); i++) { + ret.push_back(p_inp[i]); + } + return ret; +} + +template <class T> +static Array to_array(const HashSet<T> &p_inp) { + Array ret; + typename HashSet<T>::Iterator elem = p_inp.begin(); + while (elem) { + ret.push_back(*elem); + ++elem; + } + return ret; +} + +template <class T> +static void set_from_array(Vector<T> &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.push_back(p_inp[i]); + } +} + +template <class T> +static void set_from_array(HashSet<T> &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.insert(p_inp[i]); + } +} + +template <class K, class V> +static Dictionary to_dict(const HashMap<K, V> &p_inp) { + Dictionary ret; + for (const KeyValue<K, V> &E : p_inp) { + ret[E.key] = E.value; + } + return ret; +} + +template <class K, class V> +static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) { + r_out.clear(); + Array keys = p_inp.keys(); + for (int i = 0; i < keys.size(); i++) { + r_out[keys[i]] = p_inp[keys[i]]; + } +} +} //namespace GLTFTemplateConvert + +#endif // GLTF_TEMPLATE_CONVERT_H diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index b8bac79584..1e1204aa57 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -32,21 +32,21 @@ #ifndef _3D_DISABLED -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_buffer_view.h" -#include "gltf_camera.h" +#include "extensions/gltf_light.h" +#include "extensions/gltf_spec_gloss.h" #include "gltf_document.h" #include "gltf_document_extension.h" #include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_spec_gloss.h" #include "gltf_state.h" -#include "gltf_texture.h" +#include "structures/gltf_accessor.h" +#include "structures/gltf_animation.h" +#include "structures/gltf_buffer_view.h" +#include "structures/gltf_camera.h" +#include "structures/gltf_mesh.h" +#include "structures/gltf_node.h" +#include "structures/gltf_skeleton.h" +#include "structures/gltf_skin.h" +#include "structures/gltf_texture.h" #ifdef TOOLS_ENABLED #include "core/config/project_settings.h" diff --git a/modules/gltf/gltf_accessor.cpp b/modules/gltf/structures/gltf_accessor.cpp index 1daf2f90a7..1b8911fe72 100644 --- a/modules/gltf/gltf_accessor.cpp +++ b/modules/gltf/structures/gltf_accessor.cpp @@ -30,8 +30,6 @@ #include "gltf_accessor.h" -#include "gltf_document_extension.h" - void GLTFAccessor::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view); ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view); @@ -67,7 +65,7 @@ void GLTFAccessor::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "component_type"), "set_component_type", "get_component_type"); // int ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalized"), "set_normalized", "get_normalized"); // bool ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); // int - ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFDocument::GLTFType + ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFType ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "min"), "set_min", "get_min"); // Vector<real_t> ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "max"), "set_max", "get_max"); // Vector<real_t> ADD_PROPERTY(PropertyInfo(Variant::INT, "sparse_count"), "set_sparse_count", "get_sparse_count"); // int @@ -123,7 +121,7 @@ int GLTFAccessor::get_type() { } void GLTFAccessor::set_type(int p_type) { - type = (GLTFDocument::GLTFType)p_type; // TODO: Register enum + type = (GLTFType)p_type; // TODO: Register enum } Vector<double> GLTFAccessor::get_min() { diff --git a/modules/gltf/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h index f412dc2c7f..bfb71d57fe 100644 --- a/modules/gltf/gltf_accessor.h +++ b/modules/gltf/structures/gltf_accessor.h @@ -33,7 +33,7 @@ #include "core/io/resource.h" -#include "gltf_document.h" +#include "../gltf_defines.h" struct GLTFAccessor : public Resource { GDCLASS(GLTFAccessor, Resource); @@ -45,7 +45,7 @@ private: int component_type = 0; bool normalized = false; int count = 0; - GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + GLTFType type = GLTFType::TYPE_SCALAR; Vector<double> min; Vector<double> max; int sparse_count = 0; @@ -101,4 +101,5 @@ public: int get_sparse_values_byte_offset(); void set_sparse_values_byte_offset(int p_sparse_values_byte_offset); }; + #endif // GLTF_ACCESSOR_H diff --git a/modules/gltf/gltf_animation.cpp b/modules/gltf/structures/gltf_animation.cpp index e598c870ab..e598c870ab 100644 --- a/modules/gltf/gltf_animation.cpp +++ b/modules/gltf/structures/gltf_animation.cpp diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/structures/gltf_animation.h index 8688ddb937..3777f579f6 100644 --- a/modules/gltf/gltf_animation.h +++ b/modules/gltf/structures/gltf_animation.h @@ -71,4 +71,5 @@ private: bool loop = false; HashMap<int, Track> tracks; }; + #endif // GLTF_ANIMATION_H diff --git a/modules/gltf/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp index fc467367c6..ba19ed8628 100644 --- a/modules/gltf/gltf_buffer_view.cpp +++ b/modules/gltf/structures/gltf_buffer_view.cpp @@ -30,7 +30,7 @@ #include "gltf_buffer_view.h" -#include "gltf_document_extension.h" +#include "../gltf_document_extension.h" void GLTFBufferView::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer); diff --git a/modules/gltf/gltf_buffer_view.h b/modules/gltf/structures/gltf_buffer_view.h index 560d56f35c..b1f500de25 100644 --- a/modules/gltf/gltf_buffer_view.h +++ b/modules/gltf/structures/gltf_buffer_view.h @@ -31,8 +31,8 @@ #ifndef GLTF_BUFFER_VIEW_H #define GLTF_BUFFER_VIEW_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFBufferView : public Resource { GDCLASS(GLTFBufferView, Resource); @@ -65,4 +65,5 @@ public: void set_indices(bool p_indices); // matrices need to be transformed to this }; + #endif // GLTF_BUFFER_VIEW_H diff --git a/modules/gltf/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp index f3ea6a1c4c..f3ea6a1c4c 100644 --- a/modules/gltf/gltf_camera.cpp +++ b/modules/gltf/structures/gltf_camera.cpp diff --git a/modules/gltf/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index c696d4cc6b..b7df741825 100644 --- a/modules/gltf/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -55,4 +55,5 @@ public: float get_depth_near() const { return depth_near; } void set_depth_near(float p_val) { depth_near = p_val; } }; + #endif // GLTF_CAMERA_H diff --git a/modules/gltf/gltf_mesh.cpp b/modules/gltf/structures/gltf_mesh.cpp index 3add8304b1..3add8304b1 100644 --- a/modules/gltf/gltf_mesh.cpp +++ b/modules/gltf/structures/gltf_mesh.cpp diff --git a/modules/gltf/gltf_mesh.h b/modules/gltf/structures/gltf_mesh.h index dc26120b48..dc26120b48 100644 --- a/modules/gltf/gltf_mesh.h +++ b/modules/gltf/structures/gltf_mesh.h diff --git a/modules/gltf/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp index 86280603fa..86280603fa 100644 --- a/modules/gltf/gltf_node.cpp +++ b/modules/gltf/structures/gltf_node.cpp diff --git a/modules/gltf/gltf_node.h b/modules/gltf/structures/gltf_node.h index 929ad3eca0..1a57ea32e2 100644 --- a/modules/gltf/gltf_node.h +++ b/modules/gltf/structures/gltf_node.h @@ -31,8 +31,8 @@ #ifndef GLTF_NODE_H #define GLTF_NODE_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFNode : public Resource { GDCLASS(GLTFNode, Resource); @@ -97,4 +97,5 @@ public: GLTFLightIndex get_light(); void set_light(GLTFLightIndex p_light); }; + #endif // GLTF_NODE_H diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/structures/gltf_skeleton.cpp index b813f39a27..90a6b0f50f 100644 --- a/modules/gltf/gltf_skeleton.cpp +++ b/modules/gltf/structures/gltf_skeleton.cpp @@ -30,6 +30,9 @@ #include "gltf_skeleton.h" +#include "../gltf_template_convert.h" +#include "scene/3d/bone_attachment_3d.h" + void GLTFSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_joints"), &GLTFSkeleton::get_joints); ClassDB::bind_method(D_METHOD("set_joints", "joints"), &GLTFSkeleton::set_joints); @@ -70,19 +73,19 @@ Skeleton3D *GLTFSkeleton::get_godot_skeleton() { } Array GLTFSkeleton::get_unique_names() { - return GLTFDocument::to_array(unique_names); + return GLTFTemplateConvert::to_array(unique_names); } void GLTFSkeleton::set_unique_names(Array p_unique_names) { - GLTFDocument::set_from_array(unique_names, p_unique_names); + GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); } Dictionary GLTFSkeleton::get_godot_bone_node() { - return GLTFDocument::to_dict(godot_bone_node); + return GLTFTemplateConvert::to_dict(godot_bone_node); } void GLTFSkeleton::set_godot_bone_node(Dictionary p_indict) { - GLTFDocument::set_from_dict(godot_bone_node, p_indict); + GLTFTemplateConvert::set_from_dict(godot_bone_node, p_indict); } BoneAttachment3D *GLTFSkeleton::get_bone_attachment(int idx) { diff --git a/modules/gltf/gltf_skeleton.h b/modules/gltf/structures/gltf_skeleton.h index 92ee6e6234..db88623213 100644 --- a/modules/gltf/gltf_skeleton.h +++ b/modules/gltf/structures/gltf_skeleton.h @@ -31,8 +31,8 @@ #ifndef GLTF_SKELETON_H #define GLTF_SKELETON_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFSkeleton : public Resource { GDCLASS(GLTFSkeleton, Resource); @@ -98,4 +98,5 @@ public: int32_t get_bone_attachment_count(); }; + #endif // GLTF_SKELETON_H diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/structures/gltf_skin.cpp index e8005aa0c1..2e46ee3be2 100644 --- a/modules/gltf/gltf_skin.cpp +++ b/modules/gltf/structures/gltf_skin.cpp @@ -30,6 +30,9 @@ #include "gltf_skin.h" +#include "../gltf_template_convert.h" +#include "scene/resources/skin.h" + void GLTFSkin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_skin_root"), &GLTFSkin::get_skin_root); ClassDB::bind_method(D_METHOD("set_skin_root", "skin_root"), &GLTFSkin::set_skin_root); @@ -81,11 +84,11 @@ void GLTFSkin::set_joints_original(Vector<GLTFNodeIndex> p_joints_original) { } Array GLTFSkin::get_inverse_binds() { - return GLTFDocument::to_array(inverse_binds); + return GLTFTemplateConvert::to_array(inverse_binds); } void GLTFSkin::set_inverse_binds(Array p_inverse_binds) { - GLTFDocument::set_from_array(inverse_binds, p_inverse_binds); + GLTFTemplateConvert::set_from_array(inverse_binds, p_inverse_binds); } Vector<GLTFNodeIndex> GLTFSkin::get_joints() { @@ -121,11 +124,11 @@ void GLTFSkin::set_skeleton(int p_skeleton) { } Dictionary GLTFSkin::get_joint_i_to_bone_i() { - return GLTFDocument::to_dict(joint_i_to_bone_i); + return GLTFTemplateConvert::to_dict(joint_i_to_bone_i); } void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) { - GLTFDocument::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); + GLTFTemplateConvert::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); } Dictionary GLTFSkin::get_joint_i_to_name() { diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/structures/gltf_skin.h index d946324756..59b6a300ac 100644 --- a/modules/gltf/gltf_skin.h +++ b/modules/gltf/structures/gltf_skin.h @@ -31,8 +31,8 @@ #ifndef GLTF_SKIN_H #define GLTF_SKIN_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFSkin : public Resource { GDCLASS(GLTFSkin, Resource); @@ -106,4 +106,5 @@ public: Ref<Skin> get_godot_skin(); void set_godot_skin(Ref<Skin> p_godot_skin); }; + #endif // GLTF_SKIN_H diff --git a/modules/gltf/gltf_texture.cpp b/modules/gltf/structures/gltf_texture.cpp index 2a21cb3df8..2a21cb3df8 100644 --- a/modules/gltf/gltf_texture.cpp +++ b/modules/gltf/structures/gltf_texture.cpp diff --git a/modules/gltf/gltf_texture.h b/modules/gltf/structures/gltf_texture.h index 54dd61f9a5..b1d12dddfa 100644 --- a/modules/gltf/gltf_texture.h +++ b/modules/gltf/structures/gltf_texture.h @@ -31,8 +31,8 @@ #ifndef GLTF_TEXTURE_H #define GLTF_TEXTURE_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFTexture : public Resource { GDCLASS(GLTFTexture, Resource); diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub index 52777235b8..da3f7d4dd9 100644 --- a/modules/gridmap/SCsub +++ b/modules/gridmap/SCsub @@ -5,7 +5,7 @@ Import("env_modules") env_gridmap = env_modules.Clone() -# Godot's own source files +# Godot source files env_gridmap.add_source_files(env.modules_sources, "*.cpp") if env["tools"]: env_gridmap.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index b694c109e1..09f0ff32f0 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -545,7 +545,7 @@ void GridMapEditor::_update_paste_indicator() { Basis rot; rot.set_orthogonal_index(paste_indicator.orientation); xf.basis = rot * xf.basis; - xf.translate((-center * node->get_cell_size()) / scale); + xf.translate_local((-center * node->get_cell_size()) / scale); RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); @@ -553,7 +553,7 @@ void GridMapEditor::_update_paste_indicator() { xf = Transform3D(); xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size(); xf.basis = rot * xf.basis; - xf.translate(item.grid_offset * node->get_cell_size()); + xf.translate_local(item.grid_offset * node->get_cell_size()); Basis item_rot; item_rot.set_orthogonal_index(item.orientation); @@ -1231,14 +1231,14 @@ GridMapEditor::GridMapEditor() { mode_thumbnail->set_toggle_mode(true); mode_thumbnail->set_pressed(true); hb->add_child(mode_thumbnail); - mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL)); + mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_THUMBNAIL)); mode_list = memnew(Button); mode_list->set_flat(true); mode_list->set_toggle_mode(true); mode_list->set_pressed(false); hb->add_child(mode_list); - mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST)); + mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_LIST)); size_slider = memnew(HSlider); size_slider->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1262,7 +1262,7 @@ GridMapEditor::GridMapEditor() { info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); mesh_library_palette->add_child(info_message); edit_axis = Vector3::AXIS_Y; diff --git a/modules/hdr/SCsub b/modules/hdr/SCsub index a709397c9a..10629bda3c 100644 --- a/modules/hdr/SCsub +++ b/modules/hdr/SCsub @@ -5,5 +5,5 @@ Import("env_modules") env_hdr = env_modules.Clone() -# Godot's own source files +# Godot source files env_hdr.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h index f2d53cc206..16c0816562 100644 --- a/modules/hdr/image_loader_hdr.h +++ b/modules/hdr/image_loader_hdr.h @@ -40,4 +40,4 @@ public: ImageLoaderHDR(); }; -#endif +#endif // IMAGE_LOADER_HDR_H diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index de9700faec..6d631446e7 100644 --- a/modules/jpg/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IMAGE_LOADER_JPG_H -#define IMAGE_LOADER_JPG_H +#ifndef IMAGE_LOADER_JPEGD_H +#define IMAGE_LOADER_JPEGD_H #include "core/io/image_loader.h" @@ -40,4 +40,4 @@ public: ImageLoaderJPG(); }; -#endif +#endif // IMAGE_LOADER_JPEGD_H diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h index f57d6aef42..1d9f2771b2 100644 --- a/modules/jsonrpc/jsonrpc.h +++ b/modules/jsonrpc/jsonrpc.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_JSON_RPC_H -#define GODOT_JSON_RPC_H +#ifndef JSONRPC_H +#define JSONRPC_H #include "core/object/class_db.h" #include "core/variant/variant.h" @@ -67,4 +67,4 @@ public: VARIANT_ENUM_CAST(JSONRPC::ErrorCode); -#endif +#endif // JSONRPC_H diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 2ce3715bea..83ac478a97 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -271,8 +271,8 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ mi.offset.x = best_atlas_offsets[m_i].x; mi.offset.y = best_atlas_offsets[m_i].y; mi.slice = best_atlas_offsets[m_i].z; - albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2(Vector2(), Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height())), mi.offset); - emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2(), Size2i(mi.data.emission_on_uv2->get_width(), mi.data.emission_on_uv2->get_height())), mi.offset); + albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2i(Vector2i(), mi.data.albedo_on_uv2->get_size()), mi.offset); + emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2i(), mi.data.emission_on_uv2->get_size()), mi.offset); } return BAKE_OK; @@ -1420,7 +1420,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d img2.instantiate(); img2->create(2, 2, false, Image::FORMAT_RGBAF, s); img2->convert(Image::FORMAT_RGB8); - img->blit_rect(img2, Rect2(0, 0, 2, 2), Point2((j % 3) * 2, (j / 3) * 2)); + img->blit_rect(img2, Rect2i(0, 0, 2, 2), Point2i((j % 3) * 2, (j / 3) * 2)); } img->save_png("res://3_light_probe_" + itos(i) + ".png"); } diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index 8cb4b58a18..bf6b4399ca 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -183,7 +183,7 @@ class LightmapperRD : public Lightmapper { } }; - void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size); + void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size); struct RasterPushConstant { float atlas_size[2] = {}; @@ -256,4 +256,4 @@ public: LightmapperRD(); }; -#endif // LIGHTMAPPER_H +#endif // LIGHTMAPPER_RD_H diff --git a/modules/lightmapper_rd/register_types.h b/modules/lightmapper_rd/register_types.h index 42e0ebbf77..9b72ff45d7 100644 --- a/modules/lightmapper_rd/register_types.h +++ b/modules/lightmapper_rd/register_types.h @@ -36,4 +36,4 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level); void uninitialize_lightmapper_rd_module(ModuleInitializationLevel p_level); -#endif // XATLAS_UNWRAP_REGISTER_TYPES_H +#endif // LIGHTMAPPER_RD_REGISTER_TYPES_H diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h index 29370062c4..a6626c9f65 100644 --- a/modules/mbedtls/dtls_server_mbedtls.h +++ b/modules/mbedtls/dtls_server_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef MBED_DTLS_SERVER_H -#define MBED_DTLS_SERVER_H +#ifndef DTLS_SERVER_MBEDTLS_H +#define DTLS_SERVER_MBEDTLS_H #include "core/io/dtls_server.h" #include "ssl_context_mbedtls.h" @@ -54,4 +54,4 @@ public: ~DTLSServerMbedTLS(); }; -#endif // MBED_DTLS_SERVER_H +#endif // DTLS_SERVER_MBEDTLS_H diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h index dd49792abd..5883388311 100644 --- a/modules/mbedtls/ssl_context_mbedtls.h +++ b/modules/mbedtls/ssl_context_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SSL_CONTEXT_MBED_TLS_H -#define SSL_CONTEXT_MBED_TLS_H +#ifndef SSL_CONTEXT_MBEDTLS_H +#define SSL_CONTEXT_MBEDTLS_H #include "crypto_mbedtls.h" @@ -90,4 +90,4 @@ public: ~SSLContextMbedTLS(); }; -#endif // SSL_CONTEXT_MBED_TLS_H +#endif // SSL_CONTEXT_MBEDTLS_H diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h index 7660410e04..68b07feea9 100644 --- a/modules/mbedtls/stream_peer_mbedtls.h +++ b/modules/mbedtls/stream_peer_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STREAM_PEER_OPEN_SSL_H -#define STREAM_PEER_OPEN_SSL_H +#ifndef STREAM_PEER_MBEDTLS_H +#define STREAM_PEER_MBEDTLS_H #include "core/io/stream_peer_ssl.h" #include "ssl_context_mbedtls.h" @@ -76,4 +76,4 @@ public: ~StreamPeerMbedTLS(); }; -#endif // STREAM_PEER_SSL_H +#endif // STREAM_PEER_MBEDTLS_H diff --git a/modules/meshoptimizer/register_types.h b/modules/meshoptimizer/register_types.h index 99c71efceb..3a84aab7bc 100644 --- a/modules/meshoptimizer/register_types.h +++ b/modules/meshoptimizer/register_types.h @@ -36,4 +36,4 @@ void initialize_meshoptimizer_module(ModuleInitializationLevel p_level); void uninitialize_meshoptimizer_module(ModuleInitializationLevel p_level); -#endif // PVR_REGISTER_TYPES_H +#endif // MESHOPTIMIZER_REGISTER_TYPES_H diff --git a/modules/minimp3/SCsub b/modules/minimp3/SCsub index f4d1605d55..20e3165f38 100644 --- a/modules/minimp3/SCsub +++ b/modules/minimp3/SCsub @@ -13,5 +13,5 @@ if not env.msvc: else: env_minimp3.Prepend(CPPPATH=[thirdparty_dir]) -# Godot's own source files +# Godot source files env_minimp3.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index c37bea519f..98bcdea8f4 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -46,6 +46,12 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { int frames_mixed_this_step = p_frames; + int beat_length_frames = -1; + bool beat_loop = mp3_stream->has_loop() && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0; + if (beat_loop) { + beat_length_frames = mp3_stream->get_beat_count() * mp3_stream->sample_rate * 60 / mp3_stream->get_bpm(); + } + while (todo && active) { mp3dec_frame_info_t frame_info; mp3d_sample_t *buf_frame = nullptr; @@ -54,8 +60,25 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { if (samples_mixed) { p_buffer[p_frames - todo] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]); + if (loop_fade_remaining < FADE_SIZE) { + p_buffer[p_frames - todo] += loop_fade[loop_fade_remaining] * (float(FADE_SIZE - loop_fade_remaining) / float(FADE_SIZE)); + loop_fade_remaining++; + } --todo; ++frames_mixed; + + if (beat_loop && (int)frames_mixed >= beat_length_frames) { + for (int i = 0; i < FADE_SIZE; i++) { + samples_mixed = mp3dec_ex_read_frame(mp3d, &buf_frame, &frame_info, mp3_stream->channels); + loop_fade[i] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]); + if (!samples_mixed) { + break; + } + } + loop_fade_remaining = 0; + seek(mp3_stream->loop_offset); + loops++; + } } else { @@ -117,6 +140,10 @@ void AudioStreamPlaybackMP3::seek(float p_time) { mp3dec_ex_seek(mp3d, (uint64_t)frames_mixed * mp3_stream->channels); } +void AudioStreamPlaybackMP3::tag_used_streams() { + mp3_stream->tag_used(get_playback_position()); +} + AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { if (mp3d) { mp3dec_ex_close(mp3d); @@ -124,7 +151,7 @@ AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { } } -Ref<AudioStreamPlayback> AudioStreamMP3::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamMP3::instantiate_playback() { Ref<AudioStreamPlaybackMP3> mp3s; ERR_FAIL_COND_V_MSG(data.is_empty(), mp3s, @@ -206,6 +233,36 @@ bool AudioStreamMP3::is_monophonic() const { return false; } +void AudioStreamMP3::set_bpm(double p_bpm) { + ERR_FAIL_COND(p_bpm < 0); + bpm = p_bpm; + emit_changed(); +} + +double AudioStreamMP3::get_bpm() const { + return bpm; +} + +void AudioStreamMP3::set_beat_count(int p_beat_count) { + ERR_FAIL_COND(p_beat_count < 0); + beat_count = p_beat_count; + emit_changed(); +} + +int AudioStreamMP3::get_beat_count() const { + return beat_count; +} + +void AudioStreamMP3::set_bar_beats(int p_bar_beats) { + ERR_FAIL_COND(p_bar_beats < 0); + bar_beats = p_bar_beats; + emit_changed(); +} + +int AudioStreamMP3::get_bar_beats() const { + return bar_beats; +} + void AudioStreamMP3::_bind_methods() { ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamMP3::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamMP3::get_data); @@ -216,7 +273,19 @@ void AudioStreamMP3::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamMP3::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamMP3::get_loop_offset); + ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamMP3::set_bpm); + ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamMP3::get_bpm); + + ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamMP3::set_beat_count); + ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamMP3::get_beat_count); + + ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamMP3::set_bar_beats); + ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamMP3::get_bar_beats); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset"); } diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h index c1a60ddccb..428ac1240e 100644 --- a/modules/minimp3/audio_stream_mp3.h +++ b/modules/minimp3/audio_stream_mp3.h @@ -41,6 +41,12 @@ class AudioStreamMP3; class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled { GDCLASS(AudioStreamPlaybackMP3, AudioStreamPlaybackResampled); + enum { + FADE_SIZE = 256 + }; + AudioFrame loop_fade[FADE_SIZE]; + int loop_fade_remaining = FADE_SIZE; + mp3dec_ex_t *mp3d = nullptr; uint32_t frames_mixed = 0; bool active = false; @@ -64,6 +70,8 @@ public: virtual float get_playback_position() const override; virtual void seek(float p_time) override; + virtual void tag_used_streams() override; + AudioStreamPlaybackMP3() {} ~AudioStreamPlaybackMP3(); }; @@ -85,17 +93,30 @@ class AudioStreamMP3 : public AudioStream { float loop_offset = 0.0; void clear_data(); + double bpm = 0; + int beat_count = 0; + int bar_beats = 4; + protected: static void _bind_methods(); public: void set_loop(bool p_enable); - bool has_loop() const; + virtual bool has_loop() const override; void set_loop_offset(float p_seconds); float get_loop_offset() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + void set_bpm(double p_bpm); + virtual double get_bpm() const override; + + void set_beat_count(int p_beat_count); + virtual int get_beat_count() const override; + + void set_bar_beats(int p_bar_beats); + virtual int get_bar_beats() const override; + + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; void set_data(const Vector<uint8_t> &p_data); diff --git a/modules/minimp3/doc_classes/AudioStreamMP3.xml b/modules/minimp3/doc_classes/AudioStreamMP3.xml index f5f7d3ef17..8f03681c06 100644 --- a/modules/minimp3/doc_classes/AudioStreamMP3.xml +++ b/modules/minimp3/doc_classes/AudioStreamMP3.xml @@ -4,13 +4,42 @@ MP3 audio stream driver. </brief_description> <description> - MP3 audio stream driver. + MP3 audio stream driver. See [member data] if you want to load an MP3 file at run-time. </description> <tutorials> </tutorials> <members> + <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4"> + </member> + <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0"> + </member> + <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0"> + </member> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> Contains the audio data in bytes. + You can load a file without having to import it beforehand using the code snippet below. Keep in mind that this snippet loads the whole file into memory and may not be ideal for huge files (hundreds of megabytes or more). + [codeblocks] + [gdscript] + func load_mp3(path): + var file = File.new() + file.open(path, File.READ) + var sound = AudioStreamMP3.new() + sound.data = file.get_buffer(file.get_length()) + file.close() + return sound + [/gdscript] + [csharp] + public AudioStreamMP3 LoadMP3(string path) + { + var file = new File(); + file.Open(path, File.READ); + var sound = new AudioStreamMP3(); + sound.Data = file.GetBuffer(file.GetLength()); + file.Close(); + return sound; + } + [/csharp] + [/codeblocks] </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> If [code]true[/code], the stream will automatically loop when it reaches the end. diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index e03940f963..7492533094 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -34,6 +34,10 @@ #include "core/io/resource_saver.h" #include "scene/resources/texture.h" +#ifdef TOOLS_ENABLED +#include "editor/import/audio_stream_import_settings.h" +#endif + String ResourceImporterMP3::get_importer_name() const { return "mp3"; } @@ -69,14 +73,26 @@ String ResourceImporterMP3::get_preset_name(int p_idx) const { void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4)); } -Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - bool loop = p_options["loop"]; - float loop_offset = p_options["loop_offset"]; +#ifdef TOOLS_ENABLED +bool ResourceImporterMP3::has_advanced_options() const { + return true; +} +void ResourceImporterMP3::show_advanced_options(const String &p_path) { + Ref<AudioStreamMP3> mp3_stream = import_mp3(p_path); + if (mp3_stream.is_valid()) { + AudioStreamImportSettings::get_singleton()->edit(p_path, "mp3", mp3_stream); + } +} +#endif - Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); - ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN); +Ref<AudioStreamMP3> ResourceImporterMP3::import_mp3(const String &p_path) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(f.is_null(), Ref<AudioStreamMP3>()); uint64_t len = f->get_length(); @@ -90,11 +106,29 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s mp3_stream.instantiate(); mp3_stream->set_data(data); - ERR_FAIL_COND_V(!mp3_stream->get_data().size(), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(!mp3_stream->get_data().size(), Ref<AudioStreamMP3>()); + + return mp3_stream; +} + +Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + bool loop = p_options["loop"]; + float loop_offset = p_options["loop_offset"]; + double bpm = p_options["bpm"]; + float beat_count = p_options["beat_count"]; + float bar_beats = p_options["bar_beats"]; + + Ref<AudioStreamMP3> mp3_stream = import_mp3(p_source_file); + if (mp3_stream.is_null()) { + return ERR_CANT_OPEN; + } mp3_stream->set_loop(loop); mp3_stream->set_loop_offset(loop_offset); + mp3_stream->set_bpm(bpm); + mp3_stream->set_beat_count(beat_count); + mp3_stream->set_bar_beats(bar_beats); - return ResourceSaver::save(p_save_path + ".mp3str", mp3_stream); + return ResourceSaver::save(mp3_stream, p_save_path + ".mp3str"); } ResourceImporterMP3::ResourceImporterMP3() { diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 678a3773bb..38729d68f8 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -50,6 +50,12 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; +#ifdef TOOLS_ENABLED + virtual bool has_advanced_options() const override; + virtual void show_advanced_options(const String &p_path) override; +#endif + static Ref<AudioStreamMP3> import_mp3(const String &p_path); + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterMP3(); diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 5876b6cbf3..b14f5f469c 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -45,7 +45,7 @@ uint32_t MobileVRInterface::get_capabilities() const { Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { // Our magnetometer doesn't give us nice clean data. - // Well it may on Mac OS X because we're getting a calibrated value in the current implementation but Android we're getting raw data. + // Well it may on macOS because we're getting a calibrated value in the current implementation but Android we're getting raw data. // This is a fairly simple adjustment we can do to correct for the magnetometer data being elliptical Vector3 mag_raw = p_magnetometer; @@ -452,10 +452,10 @@ Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Tra return transform_for_eye; }; -CameraMatrix MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { +Projection MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { _THREAD_SAFE_METHOD_ - CameraMatrix eye; + Projection eye; aspect = p_aspect; eye.set_for_hmd(p_view + 1, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index 8ecca3a2ae..b934a09dd3 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -150,7 +150,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override; virtual void process() override; diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 3bafa351a9..d10ebc7b47 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -55,7 +55,7 @@ env_mono.add_source_files(env.modules_sources, "utils/*.cpp") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp") -if env["platform"] in ["osx", "iphone"]: +if env["platform"] in ["macos", "ios"]: env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m") elif env["platform"] == "android": diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 8e441e7e07..e69904c54b 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -63,15 +63,15 @@ def copy_file(src_dir, dst_dir, src_name, dst_name=""): def is_desktop(platform): - return platform in ["windows", "osx", "linuxbsd", "server", "uwp", "haiku"] + return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"] def is_unix_like(platform): - return platform in ["osx", "linuxbsd", "server", "android", "haiku", "iphone"] + return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"] def module_supports_tools_on(platform): - return platform not in ["android", "javascript", "iphone"] + return platform not in ["android", "javascript", "ios"] def find_wasm_src_dir(mono_root): @@ -89,7 +89,7 @@ def configure(env, env_mono): bits = env["bits"] is_android = env["platform"] == "android" is_javascript = env["platform"] == "javascript" - is_ios = env["platform"] == "iphone" + is_ios = env["platform"] == "ios" is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"] tools_enabled = env["tools"] @@ -206,7 +206,7 @@ def configure(env, env_mono): copy_file(mono_bin_path, "#bin", mono_dll_file) else: - is_apple = env["platform"] in ["osx", "iphone"] + is_apple = env["platform"] in ["macos", "ios"] is_macos = is_apple and not is_ios sharedlib_ext = ".dylib" if is_apple else ".so" @@ -221,7 +221,7 @@ def configure(env, env_mono): ) if not mono_root and is_macos: - # Try with some known directories under OSX + # Try with some known directories under macOS hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"] for hint_dir in hint_dirs: if os.path.isdir(hint_dir): @@ -270,7 +270,7 @@ def configure(env, env_mono): def copy_mono_lib(libname_wo_ext): copy_file( - mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch) + mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.ios.%s.a" % (libname_wo_ext, arch) ) # Copy Mono libraries to the output folder. These are meant to be bundled with @@ -539,7 +539,7 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): os.makedirs(target_mono_lib_dir) lib_file_names = [] - if platform == "osx": + if platform == "macos": lib_file_names = [ lib_name + ".dylib" for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"] diff --git a/modules/mono/config.py b/modules/mono/config.py index df02d9a309..d895d2d92d 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -1,56 +1,48 @@ -supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"] +supported_platforms = ["windows", "macos", "linuxbsd", "server", "android", "haiku", "javascript", "ios"] def can_build(env, platform): return not env["arch"].startswith("rv") -def configure(env): - platform = env["platform"] - - if platform not in supported_platforms: - raise RuntimeError("This module does not currently support building for this platform") +def get_opts(platform): + from SCons.Variables import BoolVariable, PathVariable - env.add_module_version_string("mono") - - from SCons.Script import BoolVariable, PathVariable, Variables, Help - - default_mono_static = platform in ["iphone", "javascript"] + default_mono_static = platform in ["ios", "javascript"] default_mono_bundles_zlib = platform in ["javascript"] - envvars = Variables() - envvars.Add( + return [ PathVariable( "mono_prefix", "Path to the Mono installation directory for the target platform and architecture", "", PathVariable.PathAccept, - ) - ) - envvars.Add( + ), PathVariable( "mono_bcl", "Path to a custom Mono BCL (Base Class Library) directory for the target platform", "", PathVariable.PathAccept, - ) - ) - envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static)) - envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True)) - envvars.Add(BoolVariable("build_cil", "Build C# solutions", True)) - envvars.Add( - BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True) - ) - - # TODO: It would be great if this could be detected automatically instead - envvars.Add( + ), + BoolVariable("mono_static", "Statically link Mono", default_mono_static), + BoolVariable("mono_glue", "Build with the Mono glue sources", True), + BoolVariable("build_cil", "Build C# solutions", True), + BoolVariable( + "copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True + ), BoolVariable( "mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib - ) - ) + ), + ] + + +def configure(env): + platform = env["platform"] - envvars.Update(env) - Help(envvars.GenerateHelpText(env)) + if platform not in supported_platforms: + raise RuntimeError("This module does not currently support building for this platform") + + env.add_module_version_string("mono") if env["mono_bundles_zlib"]: # Mono may come with zlib bundled for WASM or on newer version when built with MinGW. diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 3dc26cfbe4..475b483d6c 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -481,11 +481,14 @@ static String variant_type_to_managed_name(const String &p_var_type_name) { Variant::VECTOR3, Variant::VECTOR3I, Variant::TRANSFORM2D, + Variant::VECTOR4, + Variant::VECTOR4I, Variant::PLANE, Variant::QUATERNION, Variant::AABB, Variant::BASIS, Variant::TRANSFORM3D, + Variant::PROJECTION, Variant::COLOR, Variant::STRING_NAME, Variant::NODE_PATH, @@ -1798,9 +1801,7 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { List<PropertyInfo> props; - for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) { - props.push_front(E.value); - } + script->get_script_property_list(&props); // Call _get_property_list @@ -2138,8 +2139,8 @@ bool CSharpInstance::refcount_decremented() { return ref_dying; } -const Vector<Multiplayer::RPCConfig> CSharpInstance::get_rpc_methods() const { - return script->get_rpc_methods(); +const Variant CSharpInstance::get_rpc_config() const { + return script->get_rpc_config(); } void CSharpInstance::notification(int p_notification) { @@ -2332,10 +2333,6 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) #ifdef TOOLS_ENABLED void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) { - if (base_cache.is_valid()) { - base_cache->_update_exports_values(values, propnames); - } - for (const KeyValue<StringName, Variant> &E : exported_members_defval_cache) { values[E.key] = E.value; } @@ -2343,6 +2340,10 @@ void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, for (const PropertyInfo &prop_info : exported_members_cache) { propnames.push_back(prop_info); } + + if (base_cache.is_valid()) { + base_cache->_update_exports_values(values, propnames); + } } void CSharpScript::_update_member_info_no_exports() { @@ -2354,6 +2355,7 @@ void CSharpScript::_update_member_info_no_exports() { member_info.clear(); GDMonoClass *top = script_class; + List<PropertyInfo> props; while (top && top != native) { PropertyInfo prop_info; @@ -2368,7 +2370,7 @@ void CSharpScript::_update_member_info_no_exports() { StringName member_name = field->get_name(); member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); + props.push_front(prop_info); exported_members_defval_cache[member_name] = Variant(); } } @@ -2382,11 +2384,18 @@ void CSharpScript::_update_member_info_no_exports() { StringName member_name = property->get_name(); member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); + props.push_front(prop_info); exported_members_defval_cache[member_name] = Variant(); } } + exported_members_cache.push_back(PropertyInfo(Variant::NIL, top->get_name(), PROPERTY_HINT_NONE, get_path(), PROPERTY_USAGE_CATEGORY)); + for (const PropertyInfo &E : props) { + exported_members_cache.push_back(E); + } + + props.clear(); + top = top->get_parent_class(); } } @@ -2461,6 +2470,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda #endif GDMonoClass *top = script_class; + List<PropertyInfo> props; while (top && top != native) { PropertyInfo prop_info; @@ -2479,7 +2489,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda if (exported) { #ifdef TOOLS_ENABLED if (is_editor) { - exported_members_cache.push_front(prop_info); + props.push_front(prop_info); if (tmp_object) { exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); @@ -2507,7 +2517,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda if (exported) { #ifdef TOOLS_ENABLED if (is_editor) { - exported_members_cache.push_front(prop_info); + props.push_front(prop_info); if (tmp_object) { MonoException *exc = nullptr; MonoObject *ret = property->get_value(tmp_object, &exc); @@ -2528,6 +2538,16 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda } } +#ifdef TOOLS_ENABLED + exported_members_cache.push_back(PropertyInfo(Variant::NIL, top->get_name(), PROPERTY_HINT_NONE, get_path(), PROPERTY_USAGE_CATEGORY)); + + for (const PropertyInfo &E : props) { + exported_members_cache.push_back(E); + } + + props.clear(); +#endif // TOOLS_ENABLED + top = top->get_parent_class(); } @@ -3057,7 +3077,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native); - p_script->rpc_functions.clear(); + p_script->rpc_config.clear(); GDMonoClass *top = p_script->script_class; while (top && top != p_script->native) { @@ -3069,12 +3089,9 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { Vector<GDMonoMethod *> methods = top->get_all_methods(); for (int i = 0; i < methods.size(); i++) { if (!methods[i]->is_static()) { - Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]); - if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { - // RPC annotations can only be used once per method - if (p_script->rpc_functions.find(rpc_config) == -1) { - p_script->rpc_functions.push_back(rpc_config); - } + const Variant rpc_config = p_script->_member_get_rpc_config(methods[i]); + if (rpc_config.get_type() != Variant::NIL) { + p_script->rpc_config[methods[i]->get_name()] = rpc_config; } } } @@ -3083,9 +3100,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { top = top->get_parent_class(); } - // Sort so we are 100% that they are always the same. - p_script->rpc_functions.sort_custom<Multiplayer::SortRPCConfig>(); - p_script->load_script_signals(p_script->script_class, p_script->native); } @@ -3494,9 +3508,15 @@ Ref<Script> CSharpScript::get_base_script() const { void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const { List<PropertyInfo> props; +#ifdef TOOLS_ENABLED + for (const PropertyInfo &E : exported_members_cache) { + props.push_back(E); + } +#else for (const KeyValue<StringName, PropertyInfo> &E : member_info) { props.push_front(E.value); } +#endif // TOOLS_ENABLED for (const PropertyInfo &prop : props) { r_list->push_back(prop); @@ -3508,23 +3528,24 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } -Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const { - Multiplayer::RPCConfig rpc_config; +Variant CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const { + Variant out; MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute)); if (rpc_attribute != nullptr) { - rpc_config.name = p_member->get_name(); - rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute); - rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute); - rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute); - rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute); + Dictionary rpc_config; + rpc_config["rpc_mode"] = CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute); + rpc_config["call_local"] = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute); + rpc_config["transfer_mode"] = CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute); + rpc_config["channel"] = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute); + out = rpc_config; } - return rpc_config; + return out; } -const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const { - return rpc_functions; +const Variant CSharpScript::get_rpc_config() const { + return rpc_config; } Error CSharpScript::load_source_code(const String &p_path) { @@ -3632,7 +3653,7 @@ String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : ""; } -Error ResourceFormatSaverCSharpScript::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverCSharpScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<CSharpScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index b17473470f..48129e69cb 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -136,7 +136,7 @@ private: HashMap<StringName, EventSignal> event_signals; bool signals_invalidated = true; - Vector<Multiplayer::RPCConfig> rpc_functions; + Dictionary rpc_config; #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache @@ -179,7 +179,7 @@ private: static void update_script_class_info(Ref<CSharpScript> p_script); static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native); - Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const; + Variant _member_get_rpc_config(IMonoClassMember *p_member) const; protected: static void _bind_methods(); @@ -234,7 +234,7 @@ public: int get_member_line(const StringName &p_member) const override; - const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; + const Variant get_rpc_config() const override; #ifdef TOOLS_ENABLED bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; } @@ -311,7 +311,7 @@ public: void refcount_incremented() override; bool refcount_decremented() override; - const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; + const Variant get_rpc_config() const override; void notification(int p_notification) override; void _call_notification(int p_notification); @@ -543,7 +543,7 @@ public: class ResourceFormatSaverCSharpScript : public ResourceFormatSaver { public: - Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0) override; + Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override; void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override; bool recognize(const Ref<Resource> &p_resource) const override; }; 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 0128f5c706..5a499742e9 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 @@ -57,7 +57,7 @@ <PropertyGroup Condition=" '$(GodotTargetPlatform)' == '' "> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Linux))' ">linuxbsd</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(FreeBSD))' ">linuxbsd</GodotTargetPlatform> - <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">osx</GodotTargetPlatform> + <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">macos</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Windows))' ">windows</GodotTargetPlatform> </PropertyGroup> @@ -76,12 +76,12 @@ --> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'windows' ">GODOT_WINDOWS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'linuxbsd' ">GODOT_LINUXBSD;GODOT_PC</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'osx' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'macos' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'server' ">GODOT_SERVER;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'uwp' ">GODOT_UWP;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'haiku' ">GODOT_HAIKU;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'android' ">GODOT_ANDROID;GODOT_MOBILE</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'iphone' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'ios' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'javascript' ">GODOT_JAVASCRIPT;GODOT_HTML5;GODOT_WASM;GODOT_WEB</GodotPlatformConstants> <GodotDefineConstants>$(GodotDefineConstants);$(GodotPlatformConstants)</GodotDefineConstants> diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index e2f4d2f5fd..e9718cc82c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -336,10 +336,10 @@ MONO_AOT_MODE_LAST = 1000, // Add the required Mono libraries to the Xcode project - string MonoLibFile(string libFileName) => libFileName + ".iphone.fat.a"; + string MonoLibFile(string libFileName) => libFileName + ".ios.fat.a"; string MonoLibFromTemplate(string libFileName) => - Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName)); + Path.Combine(Internal.FullExportTemplatesDir, "ios-mono-libs", MonoLibFile(libFileName)); exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0")); diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 3e46a89b7c..cca18a2a1f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -337,7 +337,7 @@ namespace GodotTools.Export string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}"; - string templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + string templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); bool validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -347,7 +347,7 @@ namespace GodotTools.Export if (isDebug) { target = "debug"; // Support both 'release_debug' and 'debug' for the template data directory name - templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -380,7 +380,7 @@ namespace GodotTools.Export private static bool PlatformHasTemplateDir(string platform) { - // OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. + // macOS export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform); } @@ -398,13 +398,13 @@ namespace GodotTools.Export private static string GetBclProfileDir(string profile) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; return Path.Combine(templatesDir, "bcl", profile); } private static string DeterminePlatformBclDir(string platform) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; string platformBclDir = Path.Combine(templatesDir, "bcl", platform); if (!File.Exists(Path.Combine(platformBclDir, "mscorlib.dll"))) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 69960bdbeb..b39c3d1c0d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -263,16 +263,16 @@ namespace GodotTools var args = new List<string>(); - bool osxAppBundleInstalled = false; + bool macOSAppBundleInstalled = false; if (OS.IsMacOS) { // The package path is '/Applications/Visual Studio Code.app' const string vscodeBundleId = "com.microsoft.VSCode"; - osxAppBundleInstalled = Internal.IsOsxAppBundleInstalled(vscodeBundleId); + macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(vscodeBundleId); - if (osxAppBundleInstalled) + if (macOSAppBundleInstalled) { args.Add("-b"); args.Add(vscodeBundleId); @@ -307,13 +307,13 @@ namespace GodotTools if (OS.IsMacOS) { - if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) + if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; } - command = osxAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; + command = macOSAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; } else { diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 3f1d5ac3ca..7a0983a8cb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -30,7 +30,7 @@ namespace GodotTools.Ides.MonoDevelop { string bundleId = BundleIds[_editorId]; - if (Internal.IsOsxAppBundleInstalled(bundleId)) + if (Internal.IsMacOSAppBundleInstalled(bundleId)) { command = "open"; diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs index ac29efb716..3440eb701c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs @@ -66,6 +66,9 @@ namespace GodotTools.Ides.Rider if (string.IsNullOrEmpty(path)) return false; + if (path.IndexOfAny(Path.GetInvalidPathChars()) != -1) + return false; + var fileInfo = new FileInfo(path); string filename = fileInfo.Name.ToLowerInvariant(); return filename.StartsWith("rider", StringComparison.Ordinal); diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs index 77370090ec..12c90178c9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs @@ -12,12 +12,12 @@ namespace GodotTools.Internals public static string UpdateApiAssembliesFromPrebuilt(string config) => internal_UpdateApiAssembliesFromPrebuilt(config); - public static string FullTemplatesDir => - internal_FullTemplatesDir(); + public static string FullExportTemplatesDir => + internal_FullExportTemplatesDir(); public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path); - public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId); + public static bool IsMacOSAppBundleInstalled(string bundleId) => internal_IsMacOSAppBundleInstalled(bundleId); public static bool GodotIs32Bits() => internal_GodotIs32Bits(); @@ -57,13 +57,13 @@ namespace GodotTools.Internals private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string internal_FullTemplatesDir(); + private static extern string internal_FullExportTemplatesDir(); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string internal_SimplifyGodotPath(this string path); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool internal_IsOsxAppBundleInstalled(string bundleId); + private static extern bool internal_IsMacOSAppBundleInstalled(string bundleId); [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool internal_GodotIs32Bits(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 2db549c623..5cef6e5c3c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -37,13 +37,13 @@ namespace GodotTools.Utils public static class Platforms { public const string Windows = "windows"; - public const string MacOS = "osx"; + public const string MacOS = "macos"; public const string LinuxBSD = "linuxbsd"; public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; public const string Android = "android"; - public const string iOS = "iphone"; + public const string iOS = "ios"; public const string HTML5 = "javascript"; } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 7cc195201b..2e628cb576 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -917,6 +917,8 @@ void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) { ARRAY_ALL(Vector2i); ARRAY_ALL(Vector3); ARRAY_ALL(Vector3i); + ARRAY_ALL(Vector4); + ARRAY_ALL(Vector4i); #undef ARRAY_ALL #undef ARRAY_IS_EMPTY @@ -3222,6 +3224,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "new %s" + r_iarg.default_argument; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; + case Variant::VECTOR4: + case Variant::VECTOR4I: + r_iarg.default_argument = "new %s" + r_iarg.default_argument; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::OBJECT: ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false, "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value."); @@ -3276,6 +3283,15 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; + case Variant::PROJECTION: { + Projection transform = p_val.operator Projection(); + if (transform == Projection()) { + r_iarg.default_argument = "Projection.Identity"; + } else { + r_iarg.default_argument = "new Projection(new Vector4" + transform.matrix[0].operator String() + ", new Vector4" + transform.matrix[1].operator String() + ", new Vector4" + transform.matrix[2].operator String() + ", new Vector4" + transform.matrix[3].operator String() + ")"; + } + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + } break; case Variant::BASIS: { Basis basis = p_val.operator Basis(); if (basis == Basis()) { diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 1547d0ed2f..ee170e4558 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -590,6 +590,9 @@ class BindingsGenerator { StringName type_Vector2 = StaticCString::create("Vector2"); StringName type_Rect2 = StaticCString::create("Rect2"); StringName type_Vector3 = StaticCString::create("Vector3"); + StringName type_Vector3i = StaticCString::create("Vector3i"); + StringName type_Vector4 = StaticCString::create("Vector4"); + StringName type_Vector4i = StaticCString::create("Vector4i"); // Object not included as it must be checked for all derived classes static constexpr int nullable_types_count = 17; diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index a1789412f4..7bce6f2c21 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -172,7 +172,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr } } break; case CompletionKind::SHADER_PARAMS: { - print_verbose("Shared params completion for C# not implemented."); + print_verbose("Shader uniforms completion for C# is not implemented yet."); } break; case CompletionKind::SIGNALS: { Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index f7f710f3f1..f830c7ffe1 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -39,7 +39,9 @@ #include "core/version.h" #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" #include "main/main.h" @@ -47,7 +49,7 @@ #include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../mono_gd/gd_mono_marshal.h" -#include "../utils/osx_utils.h" +#include "../utils/macos_utils.h" #include "code_completion.h" #include "godotsharp_export.h" @@ -188,8 +190,8 @@ MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_c return GDMonoMarshal::mono_string_from_godot(error_str); } -MonoString *godot_icall_Internal_FullTemplatesDir() { - String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); +MonoString *godot_icall_Internal_FullExportTemplatesDir() { + String full_templates_dir = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG); return GDMonoMarshal::mono_string_from_godot(full_templates_dir); } @@ -198,10 +200,10 @@ MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) { return GDMonoMarshal::mono_string_from_godot(path.simplify_path()); } -MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) { -#ifdef OSX_ENABLED +MonoBoolean godot_icall_Internal_IsMacOSAppBundleInstalled(MonoString *p_bundle_id) { +#ifdef MACOS_ENABLED String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id); - return (MonoBoolean)osx_is_app_bundle_installed(bundle_id); + return (MonoBoolean)macos_is_app_bundle_installed(bundle_id); #else (void)p_bundle_id; // UNUSED return (MonoBoolean) false; @@ -364,9 +366,9 @@ void register_editor_internal_calls() { // Internals GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullExportTemplatesDir", godot_icall_Internal_FullExportTemplatesDir); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsMacOSAppBundleInstalled", godot_icall_Internal_IsMacOSAppBundleInstalled); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration); diff --git a/modules/mono/editor/editor_internal_calls.h b/modules/mono/editor/editor_internal_calls.h index a899634d57..8262ac211a 100644 --- a/modules/mono/editor/editor_internal_calls.h +++ b/modules/mono/editor/editor_internal_calls.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_INTERNAL_CALL_H -#define EDITOR_INTERNAL_CALL_H +#ifndef EDITOR_INTERNAL_CALLS_H +#define EDITOR_INTERNAL_CALLS_H void register_editor_internal_calls(); -#endif // EDITOR_INTERNAL_CALL_H +#endif // EDITOR_INTERNAL_CALLS_H diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs index 0a1c8322d7..fb37838ffa 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs @@ -5,8 +5,8 @@ namespace Godot /// <summary> /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>, /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers). - /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking - /// (and RPCs). + /// See <see cref="MultiplayerAPI.RPCMode"/> and <see cref="MultiplayerPeer.TransferModeEnum"/>. + /// By default, methods are not exposed to networking (and RPCs). /// </summary> [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class RPCAttribute : Attribute @@ -14,7 +14,7 @@ namespace Godot /// <summary> /// RPC mode for the annotated method. /// </summary> - public RPCMode Mode { get; } = RPCMode.Disabled; + public MultiplayerAPI.RPCMode Mode { get; } = MultiplayerAPI.RPCMode.Disabled; /// <summary> /// If the method will also be called locally; otherwise, it is only called remotely. @@ -24,7 +24,7 @@ namespace Godot /// <summary> /// Transfer mode for the annotated method. /// </summary> - public TransferMode TransferMode { get; set; } = TransferMode.Reliable; + public MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.Reliable; /// <summary> /// Transfer channel for the annotated mode. @@ -35,7 +35,7 @@ namespace Godot /// Constructs a <see cref="RPCAttribute"/> instance. /// </summary> /// <param name="mode">The RPC mode to use.</param> - public RPCAttribute(RPCMode mode = RPCMode.Authority) + public RPCAttribute(MultiplayerAPI.RPCMode mode = MultiplayerAPI.RPCMode.Authority) { Mode = mode; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 37bdc42c2d..437878818c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -531,9 +531,9 @@ namespace Godot /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated basis matrix.</returns> - public Basis Rotated(Vector3 axis, real_t phi) + public Basis Rotated(Vector3 axis, real_t angle) { - return new Basis(axis, phi) * this; + return new Basis(axis, angle) * this; } /// <summary> @@ -774,15 +774,15 @@ namespace Godot /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> - public Basis(Vector3 axis, real_t phi) + public Basis(Vector3 axis, real_t angle) { Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); - real_t cosine = Mathf.Cos(phi); + real_t cosine = Mathf.Cos(angle); Row0.x = axisSq.x + cosine * (1.0f - axisSq.x); Row1.y = axisSq.y + cosine * (1.0f - axisSq.y); Row2.z = axisSq.z + cosine * (1.0f - axisSq.z); - real_t sine = Mathf.Sin(phi); + real_t sine = Mathf.Sin(angle); real_t t = 1.0f - cosine; real_t xyzt = axis.x * axis.y * t; @@ -828,6 +828,22 @@ namespace Godot } /// <summary> + /// Constructs a pure scale basis matrix with no rotation or shearing. + /// The scale values are set as the main diagonal of the matrix, + /// and all of the other parts of the matrix are zero. + /// </summary> + /// <param name="scale">The scale Vector3.</param> + /// <returns>A pure scale Basis matrix.</returns> + public static Basis FromScale(Vector3 scale) + { + return new Basis( + scale.x, 0, 0, + 0, scale.y, 0, + 0, 0, scale.z + ); + } + + /// <summary> /// Composes these two basis matrices by multiplying them /// together. This has the effect of transforming the second basis /// (the child) by the first basis (the parent). diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index fc9d40ca48..a6324504fc 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -916,7 +916,7 @@ namespace Godot /// <c>new Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)</c>. /// </summary> /// <param name="color">The color to invert.</param> - /// <returns>The inverted color</returns> + /// <returns>The inverted color.</returns> public static Color operator -(Color color) { return Colors.White - color; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index bb076a9633..236d0666bc 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -239,11 +239,20 @@ namespace Godot } /// <summary> - /// Converts one or more arguments of any type to string in the best way possible and prints them to the console. The following BBCode tags are supported: b, i, u, s, indent, code, url, center, right, color, bgcolor, fgcolor. Color tags only support named colors such as [code]red[/code], [i]not[/i] hexadecimal color codes. Unsupported tags will be left as-is in standard output. - /// When printing to standard output, the supported subset of BBCode is converted to ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes is currently only supported on Linux and macOS. Support for ANSI escape codes may vary across terminal emulators, especially for italic and strikethrough. + /// Converts one or more arguments of any type to string in the best way possible + /// and prints them to the console. + /// The following BBCode tags are supported: b, i, u, s, indent, code, url, center, + /// right, color, bgcolor, fgcolor. + /// Color tags only support named colors such as <c>red</c>, not hexadecimal color codes. + /// Unsupported tags will be left as-is in standard output. + /// When printing to standard output, the supported subset of BBCode is converted to + /// ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes + /// is currently only supported on Linux and macOS. Support for ANSI escape codes may vary + /// across terminal emulators, especially for italic and strikethrough. /// /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/> - /// to print error and warning messages instead of <see cref="Print(object[])"/> or <see cref="PrintRich(object[])"/>. + /// to print error and warning messages instead of <see cref="Print(object[])"/> or + /// <see cref="PrintRich(object[])"/>. /// This distinguishes them from print messages used for debugging purposes, /// while also displaying a stack trace when an error or warning is printed. /// </summary> @@ -253,7 +262,6 @@ namespace Godot /// </code> /// </example> /// <param name="what">Arguments that will be printed.</param> - /// </summary> public static void PrintRich(params object[] what) { godot_icall_GD_print_rich(GetPrintParams(what)); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 63af1c5892..fd97a71e47 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -118,15 +118,15 @@ namespace Godot /// <summary> /// Returns <see langword="true"/> if point is inside the plane. - /// Comparison uses a custom minimum epsilon threshold. + /// Comparison uses a custom minimum tolerance threshold. /// </summary> /// <param name="point">The point to check.</param> - /// <param name="epsilon">The tolerance threshold.</param> + /// <param name="tolerance">The tolerance threshold.</param> /// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns> - public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon) + public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon) { real_t dist = _normal.Dot(point) - D; - return Mathf.Abs(dist) <= epsilon; + return Mathf.Abs(dist) <= tolerance; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs new file mode 100644 index 0000000000..d774021131 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -0,0 +1,820 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Projection : IEquatable<Projection> + { + /// <summary> + /// Enumerated index values for the planes. + /// </summary> + public enum Planes + { + /// <summary> + /// The projection's near plane. + /// </summary> + Near, + /// <summary> + /// The projection's far plane. + /// </summary> + Far, + /// <summary> + /// The projection's left plane. + /// </summary> + Left, + /// <summary> + /// The projection's top plane. + /// </summary> + Top, + /// <summary> + /// The projection's right plane. + /// </summary> + Right, + /// <summary> + /// The projection's bottom plane. + /// </summary> + Bottom, + } + + /// <summary> + /// The projections's X column. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public Vector4 x; + + /// <summary> + /// The projections's Y column. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public Vector4 y; + + /// <summary> + /// The projections's Z column. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public Vector4 z; + + /// <summary> + /// The projections's W column. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public Vector4 w; + + /// <summary> + /// Constructs a projection from 4 vectors (matrix columns). + /// </summary> + /// <param name="x">The X column, or column index 0.</param> + /// <param name="y">The Y column, or column index 1.</param> + /// <param name="z">The Z column, or column index 2.</param> + /// <param name="w">The W column, or column index 3.</param> + public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Projection"/> from an existing <see cref="Projection"/>. + /// </summary> + /// <param name="proj">The existing <see cref="Projection"/>.</param> + public Projection(Projection proj) + { + x = proj.x; + y = proj.y; + z = proj.z; + w = proj.w; + } + + /// <summary> + /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>. + /// </summary> + /// <param name="transform">The <see cref="Transform3D"/>.</param> + public Projection(Transform3D transform) + { + x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0); + y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0); + z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0); + w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1); + } + + /// <summary> + /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>. + /// </summary> + /// <param name="proj">The <see cref="Projection"/>.</param> + public static explicit operator Transform3D(Projection proj) + { + return new Transform3D( + new Basis( + new Vector3(proj.x.x, proj.x.y, proj.x.z), + new Vector3(proj.y.x, proj.y.y, proj.y.z), + new Vector3(proj.z.x, proj.z.y, proj.z.z) + ), + new Vector3(proj.w.x, proj.w.y, proj.w.z) + ); + } + + public static Projection CreateDepthCorrection(bool flipY) + { + return new Projection( + new Vector4(1, 0, 0, 0), + new Vector4(0, flipY ? -1 : 1, 0, 0), + new Vector4(0, 0, (real_t)0.5, 0), + new Vector4(0, 0, (real_t)0.5, 1) + ); + } + + public static Projection CreateFitAabb(AABB aabb) + { + Vector3 min = aabb.Position; + Vector3 max = aabb.Position + aabb.Size; + + return new Projection( + new Vector4(2 / (max.x - min.x), 0, 0, 0), + new Vector4(0, 2 / (max.y - min.y), 0, 0), + new Vector4(0, 0, 2 / (max.z - min.z), 0), + new Vector4(-(max.x + min.x) / (max.x - min.x), -(max.y + min.y) / (max.y - min.y), -(max.z + min.z) / (max.z - min.z), 1) + ); + } + + public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar) + { + real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens; + real_t f2 = ((displayWidth - intraocularDist) * (real_t)0.5) / displayToLens; + real_t f3 = (displayWidth / (real_t)4.0) / displayToLens; + + real_t add = ((f1 + f2) * (oversample - (real_t)1.0)) / (real_t)2.0; + f1 += add; + f2 += add; + f3 *= oversample; + + f3 /= aspect; + + switch (eye) + { + case 1: + return CreateFrustum(-f2 * zNear, f1 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar); + case 2: + return CreateFrustum(-f1 * zNear, f2 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar); + default: + return Zero; + } + } + + public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far) + { + if (right <= left) + { + throw new ArgumentException("right is less or equal to left."); + } + if (top <= bottom) + { + throw new ArgumentException("top is less or equal to bottom."); + } + if (far <= near) + { + throw new ArgumentException("far is less or equal to near."); + } + + real_t x = 2 * near / (right - left); + real_t y = 2 * near / (top - bottom); + + real_t a = (right + left) / (right - left); + real_t b = (top + bottom) / (top - bottom); + real_t c = -(far + near) / (far - near); + real_t d = -2 * far * near / (far - near); + + return new Projection( + new Vector4(x, 0, 0, 0), + new Vector4(0, y, 0, 0), + new Vector4(a, b, c, -1), + new Vector4(0, 0, d, 0) + ); + } + + public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov) + { + if (!flipFov) + { + size *= aspect; + } + return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far); + } + + public static Projection CreateLightAtlasRect(Rect2 rect) + { + return new Projection( + new Vector4(rect.Size.x, 0, 0, 0), + new Vector4(0, rect.Size.y, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(rect.Position.x, rect.Position.y, 0, 1) + ); + } + + public static Projection CreateOrthogonal(real_t left, real_t right, real_t bottom, real_t top, real_t zNear, real_t zFar) + { + Projection proj = Projection.Identity; + proj.x.x = (real_t)2.0 / (right - left); + proj.w.x = -((right + left) / (right - left)); + proj.y.y = (real_t)2.0 / (top - bottom); + proj.w.y = -((top + bottom) / (top - bottom)); + proj.z.z = (real_t)(-2.0) / (zFar - zNear); + proj.w.z = -((zFar + zNear) / (zFar - zNear)); + proj.w.w = (real_t)1.0; + return proj; + } + + public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov) + { + if (!flipFov) + { + size *= aspect; + } + return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar); + } + + public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov) + { + if (flipFov) + { + fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); + } + real_t radians = Mathf.Deg2Rad(fovyDegrees / (real_t)2.0); + real_t deltaZ = zFar - zNear; + real_t sine = Mathf.Sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) + { + return Zero; + } + + real_t cotangent = Mathf.Cos(radians) / sine; + + Projection proj = Projection.Identity; + + proj.x.x = cotangent / aspect; + proj.y.y = cotangent; + proj.z.z = -(zFar + zNear) / deltaZ; + proj.z.w = -1; + proj.w.z = -2 * zNear * zFar / deltaZ; + proj.w.w = 0; + + return proj; + } + + public static Projection CreatePerspectiveHmd(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov, int eye, real_t intraocularDist, real_t convergenceDist) + { + if (flipFov) + { + fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); + } + + real_t ymax = zNear * Mathf.Tan(Mathf.Deg2Rad(fovyDegrees / (real_t)2.0)); + real_t xmax = ymax * aspect; + real_t frustumshift = (intraocularDist / (real_t)2.0) * zNear / convergenceDist; + real_t left; + real_t right; + real_t modeltranslation; + switch (eye) + { + case 1: + left = -xmax + frustumshift; + right = xmax + frustumshift; + modeltranslation = intraocularDist / (real_t)2.0; + break; + case 2: + left = -xmax - frustumshift; + right = xmax - frustumshift; + modeltranslation = -intraocularDist / (real_t)2.0; + break; + default: + left = -xmax; + right = xmax; + modeltranslation = (real_t)0.0; + break; + } + Projection proj = CreateFrustum(left, right, -ymax, ymax, zNear, zFar); + Projection cm = Projection.Identity; + cm.w.x = modeltranslation; + return proj * cm; + } + + public real_t Determinant() + { + return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x - + x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x + + x.z * y.y * z.w * w.x - x.y * y.z * z.w * w.x - + x.w * y.z * z.x * w.y + x.z * y.w * z.x * w.y + + x.w * y.x * z.z * w.y - x.x * y.w * z.z * w.y - + x.z * y.x * z.w * w.y + x.x * y.z * z.w * w.y + + x.w * y.y * z.x * w.z - x.y * y.w * z.x * w.z - + x.w * y.x * z.y * w.z + x.x * y.w * z.y * w.z + + x.y * y.x * z.w * w.z - x.x * y.y * z.w * w.z - + x.z * y.y * z.x * w.w + x.y * y.z * z.x * w.w + + x.z * y.x * z.y * w.w - x.x * y.z * z.y * w.w - + x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w; + } + + public real_t GetAspect() + { + Vector2 vpHe = GetViewportHalfExtents(); + return vpHe.x / vpHe.y; + } + + public real_t GetFov() + { + Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized(); + if (z.x == 0 && z.y == 0) + { + return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; + } + else + { + Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized(); + return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); + } + } + + public static real_t GetFovy(real_t fovx, real_t aspect) + { + return Mathf.Rad2Deg(Mathf.Atan(aspect * Mathf.Tan(Mathf.Deg2Rad(fovx) * (real_t)0.5)) * (real_t)2.0); + } + + public real_t GetLodMultiplier() + { + if (IsOrthogonal()) + { + return GetViewportHalfExtents().x; + } + else + { + real_t zn = GetZNear(); + real_t width = GetViewportHalfExtents().x * (real_t)2.0; + return (real_t)1.0 / (zn / width); + } + } + + public int GetPixelsPerMeter(int forPixelWidth) + { + Vector3 result = Xform(new Vector3(1, 0, -1)); + + return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth); + } + + public Plane GetProjectionPlane(Planes plane) + { + Plane newPlane = plane switch + { + Planes.Near => new Plane(x.w + x.z, y.w + y.z, z.w + z.z, w.w + w.z), + Planes.Far => new Plane(x.w - x.z, y.w - y.z, z.w - z.z, w.w - w.z), + Planes.Left => new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x), + Planes.Top => new Plane(x.w - x.y, y.w - y.y, z.w - z.y, w.w - w.y), + Planes.Right => new Plane(x.w - x.x, y.w - y.x, z.w - z.x, w.w - w.x), + Planes.Bottom => new Plane(x.w + x.y, y.w + y.y, z.w + z.y, w.w + w.y), + _ => new Plane(), + }; + newPlane.Normal = -newPlane.Normal; + return newPlane.Normalized(); + } + + public Vector2 GetFarPlaneHalfExtents() + { + var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); + return new Vector2(res.Value.x, res.Value.y); + } + + public Vector2 GetViewportHalfExtents() + { + var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); + return new Vector2(res.Value.x, res.Value.y); + } + + public real_t GetZFar() + { + return GetProjectionPlane(Planes.Far).D; + } + + public real_t GetZNear() + { + return -GetProjectionPlane(Planes.Near).D; + } + + public Projection FlippedY() + { + Projection proj = this; + proj.y = -proj.y; + return proj; + } + + public Projection PerspectiveZNearAdjusted(real_t newZNear) + { + Projection proj = this; + real_t zFar = GetZFar(); + real_t zNear = newZNear; + real_t deltaZ = zFar - zNear; + proj.z.z = -(zFar + zNear) / deltaZ; + proj.w.z = -2 * zNear * zFar / deltaZ; + return proj; + } + + public Projection JitterOffseted(Vector2 offset) + { + Projection proj = this; + proj.w.x += offset.x; + proj.w.y += offset.y; + return proj; + } + + public Projection Inverse() + { + Projection proj = this; + int i, j, k; + int[] pvt_i = new int[4]; + int[] pvt_j = new int[4]; /* Locations of pivot matrix */ + real_t pvt_val; /* Value of current pivot element */ + real_t hold; /* Temporary storage */ + real_t determinant = 1.0f; + for (k = 0; k < 4; k++) + { + /* Locate k'th pivot element */ + pvt_val = proj[k][k]; /* Initialize for search */ + pvt_i[k] = k; + pvt_j[k] = k; + for (i = k; i < 4; i++) + { + for (j = k; j < 4; j++) + { + if (Mathf.Abs(proj[i][j]) > Mathf.Abs(pvt_val)) + { + pvt_i[k] = i; + pvt_j[k] = j; + pvt_val = proj[i][j]; + } + } + } + + /* Product of pivots, gives determinant when finished */ + determinant *= pvt_val; + if (Mathf.IsZeroApprox(determinant)) + { + return Zero; + } + + /* "Interchange" rows (with sign change stuff) */ + i = pvt_i[k]; + if (i != k) + { /* If rows are different */ + for (j = 0; j < 4; j++) + { + hold = -proj[k][j]; + proj[k, j] = proj[i][j]; + proj[i, j] = hold; + } + } + + /* "Interchange" columns */ + j = pvt_j[k]; + if (j != k) + { /* If columns are different */ + for (i = 0; i < 4; i++) + { + hold = -proj[i][k]; + proj[i, k] = proj[i][j]; + proj[i, j] = hold; + } + } + + /* Divide column by minus pivot value */ + for (i = 0; i < 4; i++) + { + if (i != k) + { + proj[i, k] /= (-pvt_val); + } + } + + /* Reduce the matrix */ + for (i = 0; i < 4; i++) + { + hold = proj[i][k]; + for (j = 0; j < 4; j++) + { + if (i != k && j != k) + { + proj[i, j] += hold * proj[k][j]; + } + } + } + + /* Divide row by pivot */ + for (j = 0; j < 4; j++) + { + if (j != k) + { + proj[k, j] /= pvt_val; + } + } + + /* Replace pivot by reciprocal (at last we can touch it). */ + proj[k, k] = (real_t)1.0 / pvt_val; + } + + /* That was most of the work, one final pass of row/column interchange */ + /* to finish */ + for (k = 4 - 2; k >= 0; k--) + { /* Don't need to work with 1 by 1 corner*/ + i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ + if (i != k) + { /* If rows are different */ + for (j = 0; j < 4; j++) + { + hold = proj[k][j]; + proj[k, j] = -proj[i][j]; + proj[i, j] = hold; + } + } + + j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ + if (j != k) + { /* If columns are different */ + for (i = 0; i < 4; i++) + { + hold = proj[i][k]; + proj[i, k] = -proj[i][j]; + proj[i, j] = hold; + } + } + } + return proj; + } + + public bool IsOrthogonal() + { + return w.w == (real_t)1.0; + } + + /// <summary> + /// Composes these two projections by multiplying them + /// together. This has the effect of applying the right + /// and then the left projection. + /// </summary> + /// <param name="left">The parent transform.</param> + /// <param name="right">The child transform.</param> + /// <returns>The composed projection.</returns> + public static Projection operator *(Projection left, Projection right) + { + return new Projection( + new Vector4( + left.x.x * right.x.x + left.y.x * right.x.y + left.z.x * right.x.z + left.w.x * right.x.w, + left.x.y * right.x.x + left.y.y * right.x.y + left.z.y * right.x.z + left.w.y * right.x.w, + left.x.z * right.x.x + left.y.z * right.x.y + left.z.z * right.x.z + left.w.z * right.x.w, + left.x.w * right.x.x + left.y.w * right.x.y + left.z.w * right.x.z + left.w.w * right.x.w + ), new Vector4( + left.x.x * right.y.x + left.y.x * right.y.y + left.z.x * right.y.z + left.w.x * right.y.w, + left.x.y * right.y.x + left.y.y * right.y.y + left.z.y * right.y.z + left.w.y * right.y.w, + left.x.z * right.y.x + left.y.z * right.y.y + left.z.z * right.y.z + left.w.z * right.y.w, + left.x.w * right.y.x + left.y.w * right.y.y + left.z.w * right.y.z + left.w.w * right.y.w + ), new Vector4( + left.x.x * right.z.x + left.y.x * right.z.y + left.z.x * right.z.z + left.w.x * right.z.w, + left.x.y * right.z.x + left.y.y * right.z.y + left.z.y * right.z.z + left.w.y * right.z.w, + left.x.z * right.z.x + left.y.z * right.z.y + left.z.z * right.z.z + left.w.z * right.z.w, + left.x.w * right.z.x + left.y.w * right.z.y + left.z.w * right.z.z + left.w.w * right.z.w + ), new Vector4( + left.x.x * right.w.x + left.y.x * right.w.y + left.z.x * right.w.z + left.w.x * right.w.w, + left.x.y * right.w.x + left.y.y * right.w.y + left.z.y * right.w.z + left.w.y * right.w.w, + left.x.z * right.w.x + left.y.z * right.w.y + left.z.z * right.w.z + left.w.z * right.w.w, + left.x.w * right.w.x + left.y.w * right.w.y + left.z.w * right.w.z + left.w.w * right.w.w + ) + ); + } + + /// <summary> + /// Returns a vector transformed (multiplied) by this projection. + /// </summary> + /// <param name="proj">The projection to apply.</param> + /// <param name="v">A vector to transform.</param> + /// <returns>The transformed vector.</returns> + public static Vector4 operator *(Projection proj, Vector4 v) + { + return new Vector4( + proj.x.x * v.x + proj.y.x * v.y + proj.z.x * v.z + proj.w.x * v.w, + proj.x.y * v.x + proj.y.y * v.y + proj.z.y * v.z + proj.w.y * v.w, + proj.x.z * v.x + proj.y.z * v.y + proj.z.z * v.z + proj.w.z * v.w, + proj.x.w * v.x + proj.y.w * v.y + proj.z.w * v.z + proj.w.w * v.w + ); + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are exactly equal. + /// </summary> + /// <param name="left">The left projection.</param> + /// <param name="right">The right projection.</param> + /// <returns>Whether or not the projections are exactly equal.</returns> + public static bool operator ==(Projection left, Projection right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are not exactly equal. + /// </summary> + /// <param name="left">The left projection.</param> + /// <param name="right">The right projection.</param> + /// <returns>Whether or not the projections are not exactly equal.</returns> + public static bool operator !=(Projection left, Projection right) + { + return !left.Equals(right); + } + + /// <summary> + /// Access whole columns in the form of <see cref="Vector4"/>. + /// </summary> + /// <param name="column">Which column vector.</param> + public Vector4 this[int column] + { + get + { + switch (column) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (column) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Access single values. + /// </summary> + /// <param name="column">Which column vector.</param> + /// <param name="row">Which row of the column.</param> + public real_t this[int column, int row] + { + get + { + switch (column) + { + case 0: + return x[row]; + case 1: + return y[row]; + case 2: + return z[row]; + case 3: + return w[row]; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (column) + { + case 0: + x[row] = value; + return; + case 1: + y[row] = value; + return; + case 2: + z[row] = value; + return; + case 3: + w[row] = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Returns a vector transformed (multiplied) by this projection. + /// </summary> + /// <param name="v">A vector to transform.</param> + /// <returns>The transformed vector.</returns> + private Vector3 Xform(Vector3 v) + { + Vector3 ret = new Vector3( + x.x * v.x + y.x * v.y + z.x * v.z + w.x, + x.y * v.x + y.y * v.y + z.y * v.z + w.y, + x.z * v.x + y.z * v.y + z.z * v.z + w.z + ); + return ret / (x.w * v.x + y.w * v.y + z.w * v.z + w.w); + } + + // Constants + private static readonly Projection _zero = new Projection( + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0) + ); + private static readonly Projection _identity = new Projection( + new Vector4(1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1) + ); + + /// <summary> + /// Zero projection, a projection with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero)</c>.</value> + public static Projection Zero { get { return _zero; } } + + /// <summary> + /// The identity projection, with no distortion applied. + /// This is used as a replacement for <c>Projection()</c> in GDScript. + /// Do not use <c>new Projection()</c> with no arguments in C#, because it sets all values to zero. + /// </summary> + /// <value>Equivalent to <c>new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1))</c>.</value> + public static Projection Identity { get { return _identity; } } + + /// <summary> + /// Serves as the hash function for <see cref="Projection"/>. + /// </summary> + /// <returns>A hash code for this projection.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Projection"/> to a string. + /// </summary> + /// <returns>A string representation of this projection.</returns> + public override string ToString() + { + return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n"; + } + + /// <summary> + /// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this projection.</returns> + public string ToString(string format) + { + return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" + + $"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" + + $"{z.x.ToString(format)}, {z.y.ToString(format)}, {z.z.ToString(format)}, {z.w.ToString(format)}\n" + + $"{w.x.ToString(format)}, {w.y.ToString(format)}, {w.z.ToString(format)}, {w.w.ToString(format)}\n"; + } + + /// <summary> + /// Returns <see langword="true"/> if the projection is exactly equal + /// to the given object (<see paramref="obj"/>). + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Projection) + { + return Equals((Projection)obj); + } + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are exactly equal. + /// </summary> + /// <param name="other">The other projection.</param> + /// <returns>Whether or not the projections are exactly equal.</returns> + public bool Equals(Projection other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs index 5680c9d55a..da01300586 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs @@ -18,7 +18,7 @@ namespace Godot public StringName Name => _signalName; /// <summary> - /// Creates a new <see cref="Signal"/> with the name <paramref name="name"/> + /// Creates a new <see cref="SignalInfo"/> with the name <paramref name="name"/> /// in the specified <paramref name="owner"/>. /// </summary> /// <param name="owner">Object that contains the signal.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index 89947899cb..68d097eb4e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -297,17 +297,33 @@ namespace Godot } /// <summary> - /// Rotates the transform by <paramref name="angle"/> (in radians), using matrix multiplication. + /// Rotates the transform by <paramref name="angle"/> (in radians). + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform2D Rotated(real_t phi) + public Transform2D Rotated(real_t angle) { - return this * new Transform2D(phi, new Vector2()); + return this * new Transform2D(angle, new Vector2()); } /// <summary> - /// Scales the transform by the given scaling factor, using matrix multiplication. + /// Rotates the transform by <paramref name="angle"/> (in radians). + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="angle">The angle to rotate, in radians.</param> + /// <returns>The rotated transformation matrix.</returns> + public Transform2D RotatedLocal(real_t angle) + { + return new Transform2D(angle, new Vector2()) * this; + } + + /// <summary> + /// Scales the transform by the given scaling factor. + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> @@ -320,12 +336,19 @@ namespace Godot return copy; } - private void ScaleBasis(Vector2 scale) + /// <summary> + /// Scales the transform by the given scaling factor. + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="scale">The scale to introduce.</param> + /// <returns>The scaled transformation matrix.</returns> + public Transform2D ScaledLocal(Vector2 scale) { - x.x *= scale.x; - x.y *= scale.y; - y.x *= scale.x; - y.y *= scale.y; + Transform2D copy = this; + copy.x *= scale; + copy.y *= scale; + return copy; } private real_t Tdotx(Vector2 with) @@ -339,17 +362,29 @@ namespace Godot } /// <summary> - /// Translates the transform by the given <paramref name="offset"/>, - /// relative to the transform's basis vectors. - /// - /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>, - /// this does not use matrix multiplication. + /// Translates the transform by the given <paramref name="offset"/>. + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> public Transform2D Translated(Vector2 offset) { Transform2D copy = this; + copy.origin += offset; + return copy; + } + + /// <summary> + /// Translates the transform by the given <paramref name="offset"/>. + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="offset">The offset to translate by.</param> + /// <returns>The translated matrix.</returns> + public Transform2D TranslatedLocal(Vector2 offset) + { + Transform2D copy = this; copy.origin += copy.BasisXform(offset); return copy; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 7b211b6577..9eaf4f3252 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -186,19 +186,38 @@ namespace Godot } /// <summary> - /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians), - /// using matrix multiplication. The axis must be a normalized vector. + /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians). + /// The axis must be a normalized vector. + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform3D Rotated(Vector3 axis, real_t phi) + public Transform3D Rotated(Vector3 axis, real_t angle) { - return new Transform3D(new Basis(axis, phi), new Vector3()) * this; + return new Transform3D(new Basis(axis, angle), new Vector3()) * this; } /// <summary> - /// Scales the transform by the given 3D scaling factor, using matrix multiplication. + /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians). + /// The axis must be a normalized vector. + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="axis">The axis to rotate around. Must be normalized.</param> + /// <param name="angle">The angle to rotate, in radians.</param> + /// <returns>The rotated transformation matrix.</returns> + public Transform3D RotatedLocal(Vector3 axis, real_t angle) + { + Basis tmpBasis = new Basis(axis, angle); + return new Transform3D(basis * tmpBasis, origin); + } + + /// <summary> + /// Scales the transform by the given 3D <paramref name="scale"/> factor. + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="scale">The scale to introduce.</param> /// <returns>The scaled transformation matrix.</returns> @@ -207,6 +226,19 @@ namespace Godot return new Transform3D(basis.Scaled(scale), origin * scale); } + /// <summary> + /// Scales the transform by the given 3D <paramref name="scale"/> factor. + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="scale">The scale to introduce.</param> + /// <returns>The scaled transformation matrix.</returns> + public Transform3D ScaledLocal(Vector3 scale) + { + Basis tmpBasis = Basis.FromScale(scale); + return new Transform3D(basis * tmpBasis, origin); + } + private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) { // Make rotation matrix @@ -231,21 +263,31 @@ namespace Godot } /// <summary> - /// Translates the transform by the given <paramref name="offset"/>, - /// relative to the transform's basis vectors. - /// - /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>, - /// this does not use matrix multiplication. + /// Translates the transform by the given <paramref name="offset"/>. + /// The operation is done in the parent/global frame, equivalent to + /// multiplying the matrix from the left. /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> public Transform3D Translated(Vector3 offset) { + return new Transform3D(basis, origin + offset); + } + + /// <summary> + /// Translates the transform by the given <paramref name="offset"/>. + /// The operation is done in the local frame, equivalent to + /// multiplying the matrix from the right. + /// </summary> + /// <param name="offset">The offset to translate by.</param> + /// <returns>The translated matrix.</returns> + public Transform3D TranslatedLocal(Vector3 offset) + { return new Transform3D(basis, new Vector3 ( - origin[0] += basis.Row0.Dot(offset), - origin[1] += basis.Row1.Dot(offset), - origin[2] += basis.Row2.Dot(offset) + origin[0] + basis.Row0.Dot(offset), + origin[1] + basis.Row1.Dot(offset), + origin[2] + basis.Row2.Dot(offset) )); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 7bdbe1c28b..67f70390dd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -495,10 +495,10 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector2 Rotated(real_t phi) + public Vector2 Rotated(real_t angle) { - real_t sine = Mathf.Sin(phi); - real_t cosi = Mathf.Cos(phi); + real_t sine = Mathf.Sin(angle); + real_t cosi = Mathf.Cos(angle); return new Vector2( x * cosi - y * sine, x * sine + y * cosi); @@ -534,7 +534,7 @@ namespace Godot /// /// This method also handles interpolating the lengths if the input vectors /// have different lengths. For the special case of one or both input vectors - /// having zero length, this method behaves like <see cref="Lerp"/>. + /// having zero length, this method behaves like <see cref="Lerp(Vector2, real_t)"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 412a885daa..b61954a84c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -461,7 +461,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector2i"/> + /// Divides each component of the <see cref="Vector2i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 480165d44a..67a98efc2d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -515,7 +515,7 @@ namespace Godot /// <param name="axis">The vector to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector3 Rotated(Vector3 axis, real_t phi) + public Vector3 Rotated(Vector3 axis, real_t angle) { #if DEBUG if (!axis.IsNormalized()) @@ -523,7 +523,7 @@ namespace Godot throw new ArgumentException("Argument is not normalized", nameof(axis)); } #endif - return new Basis(axis, phi).Xform(this); + return new Basis(axis, angle).Xform(this); } /// <summary> @@ -574,7 +574,7 @@ namespace Godot /// /// This method also handles interpolating the lengths if the input vectors /// have different lengths. For the special case of one or both input vectors - /// having zero length, this method behaves like <see cref="Lerp"/>. + /// having zero length, this method behaves like <see cref="Lerp(Vector3, real_t)"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> @@ -620,22 +620,6 @@ namespace Godot ); } - /// <summary> - /// Returns a diagonal matrix with the vector as main diagonal. - /// - /// This is equivalent to a <see cref="Basis"/> with no rotation or shearing and - /// this vector's components set as the scale. - /// </summary> - /// <returns>A <see cref="Basis"/> with the vector as its main diagonal.</returns> - public Basis ToDiagonalMatrix() - { - return new Basis( - x, 0, 0, - 0, y, 0, - 0, 0, z - ); - } - // Constants private static readonly Vector3 _zero = new Vector3(0, 0, 0); private static readonly Vector3 _one = new Vector3(1, 1, 1); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index abfd2ae720..0d4894f206 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -449,7 +449,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector3i"/> + /// Divides each component of the <see cref="Vector3i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs new file mode 100644 index 0000000000..72fe9cb16f --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -0,0 +1,730 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + /// <summary> + /// 4-element structure that can be used to represent positions in 4D space or any other pair of numeric values. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector4 : IEquatable<Vector4> + { + /// <summary> + /// Enumerated index values for the axes. + /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>. + /// </summary> + public enum Axis + { + /// <summary> + /// The vector's X axis. + /// </summary> + X = 0, + /// <summary> + /// The vector's Y axis. + /// </summary> + Y, + /// <summary> + /// The vector's Z axis. + /// </summary> + Z, + /// <summary> + /// The vector's W axis. + /// </summary> + W + } + + /// <summary> + /// The vector's X component. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public real_t x; + + /// <summary> + /// The vector's Y component. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public real_t y; + + /// <summary> + /// The vector's Z component. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public real_t z; + + /// <summary> + /// The vector's W component. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public real_t w; + + /// <summary> + /// Access vector components using their index. + /// </summary> + /// <exception cref="IndexOutOfRangeException"> + /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3. + /// </exception> + /// <value> + /// <c>[0]</c> is equivalent to <see cref="x"/>, + /// <c>[1]</c> is equivalent to <see cref="y"/>, + /// <c>[2]</c> is equivalent to <see cref="z"/>. + /// <c>[3]</c> is equivalent to <see cref="w"/>. + /// </value> + public real_t this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w) + { + x = this.x; + y = this.y; + z = this.z; + w = this.w; + } + + internal void Normalize() + { + real_t lengthsq = LengthSquared(); + + if (lengthsq == 0) + { + x = y = z = w = 0f; + } + else + { + real_t length = Mathf.Sqrt(lengthsq); + x /= length; + y /= length; + z /= length; + w /= length; + } + } + + + /// <summary> + /// Returns a new vector with all components in absolute values (i.e. positive). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns> + public Vector4 Abs() + { + return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); + } + + /// <summary> + /// Returns a new vector with all components rounded up (towards positive infinity). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns> + public Vector4 Ceil() + { + return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w)); + } + + /// <summary> + /// Returns a new vector with all components clamped between the + /// components of <paramref name="min"/> and <paramref name="max"/> using + /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>. + /// </summary> + /// <param name="min">The vector with minimum allowed values.</param> + /// <param name="max">The vector with maximum allowed values.</param> + /// <returns>The vector with all components clamped.</returns> + public Vector4 Clamp(Vector4 min, Vector4 max) + { + return new Vector4 + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z), + Mathf.Clamp(w, min.w, max.w) + ); + } + + + /// <summary> + /// Returns a new vector with all components rounded down (towards negative infinity). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns> + public Vector4 Floor() + { + return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w)); + } + + + /// <summary> + /// Returns the dot product of this vector and <paramref name="with"/>. + /// </summary> + /// <param name="with">The other vector to use.</param> + /// <returns>The dot product of the two vectors.</returns> + public real_t Dot(Vector4 with) + { + return (x * with.x) + (y * with.y) + (z * with.z) + (w + with.w); + } + + /// <summary> + /// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>. + /// </summary> + /// <returns>The inverse of this vector.</returns> + public Vector4 Inverse() + { + return new Vector4(1 / x, 1 / y, 1 / z, 1 / w); + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise. + /// </summary> + /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns> + public bool IsNormalized() + { + return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; + } + + /// <summary> + /// Returns the length (magnitude) of this vector. + /// </summary> + /// <seealso cref="LengthSquared"/> + /// <returns>The length of this vector.</returns> + public real_t Length() + { + real_t x2 = x * x; + real_t y2 = y * y; + real_t z2 = z * z; + real_t w2 = w * w; + + return Mathf.Sqrt(x2 + y2 + z2 + w2); + } + + /// <summary> + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than <see cref="Length"/>, so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// </summary> + /// <returns>The squared length of this vector.</returns> + public real_t LengthSquared() + { + real_t x2 = x * x; + real_t y2 = y * y; + real_t z2 = z * z; + real_t w2 = w * w; + + return x2 + y2 + z2 + w2; + } + + /// <summary> + /// Returns the result of the linear interpolation between + /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. + /// </summary> + /// <param name="to">The destination vector for interpolation.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting vector of the interpolation.</returns> + public Vector4 Lerp(Vector4 to, real_t weight) + { + return new Vector4 + ( + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight), + Mathf.Lerp(z, to.z, weight), + Mathf.Lerp(w, to.w, weight) + ); + } + + /// <summary> + /// Returns the axis of the vector's highest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.X"/>. + /// </summary> + /// <returns>The index of the highest axis.</returns> + public Axis MaxAxisIndex() + { + int max_index = 0; + real_t max_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] > max_value) + { + max_index = i; + max_value = this[i]; + } + } + return (Axis)max_index; + } + + /// <summary> + /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.W"/>. + /// </summary> + /// <returns>The index of the lowest axis.</returns> + public Axis MinAxisIndex() + { + int min_index = 0; + real_t min_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] <= min_value) + { + min_index = i; + min_value = this[i]; + } + } + return (Axis)min_index; + } + + /// <summary> + /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>. + /// </summary> + /// <returns>A normalized version of the vector.</returns> + public Vector4 Normalized() + { + Vector4 v = this; + v.Normalize(); + return v; + } + + /// <summary> + /// Returns this vector with all components rounded to the nearest integer, + /// with halfway cases rounded towards the nearest multiple of two. + /// </summary> + /// <returns>The rounded vector.</returns> + public Vector4 Round() + { + return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w)); + } + + /// <summary> + /// Returns a vector with each component set to one or negative one, depending + /// on the signs of this vector's components, or zero if the component is zero, + /// by calling <see cref="Mathf.Sign(real_t)"/> on each component. + /// </summary> + /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> + public Vector4 Sign() + { + Vector4 v; + v.x = Mathf.Sign(x); + v.y = Mathf.Sign(y); + v.z = Mathf.Sign(z); + v.w = Mathf.Sign(w); + return v; + } + + // Constants + private static readonly Vector4 _zero = new Vector4(0, 0, 0, 0); + private static readonly Vector4 _one = new Vector4(1, 1, 1, 1); + private static readonly Vector4 _inf = new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf); + + /// <summary> + /// Zero vector, a vector with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(0, 0, 0, 0)</c>.</value> + public static Vector4 Zero { get { return _zero; } } + /// <summary> + /// One vector, a vector with all components set to <c>1</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(1, 1, 1, 1)</c>.</value> + public static Vector4 One { get { return _one; } } + /// <summary> + /// Infinity vector, a vector with all components set to <see cref="Mathf.Inf"/>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf)</c>.</value> + public static Vector4 Inf { get { return _inf; } } + + /// <summary> + /// Constructs a new <see cref="Vector4"/> with the given components. + /// </summary> + /// <param name="x">The vector's X component.</param> + /// <param name="y">The vector's Y component.</param> + /// <param name="z">The vector's Z component.</param> + /// <param name="w">The vector's W component.</param> + public Vector4(real_t x, real_t y, real_t z, real_t w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4"/> from an existing <see cref="Vector4"/>. + /// </summary> + /// <param name="v">The existing <see cref="Vector4"/>.</param> + public Vector4(Vector4 v) + { + x = v.x; + y = v.y; + z = v.z; + w = v.w; + } + + /// <summary> + /// Adds each component of the <see cref="Vector4"/> + /// with the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> + public static Vector4 operator +(Vector4 left, Vector4 right) + { + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + return left; + } + + /// <summary> + /// Subtracts each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> + public static Vector4 operator -(Vector4 left, Vector4 right) + { + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + return left; + } + + /// <summary> + /// Returns the negative value of the <see cref="Vector4"/>. + /// This is the same as writing <c>new Vector4(-v.x, -v.y, -v.z, -v.w)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// With floats, the number zero can be either positive or negative. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> + public static Vector4 operator -(Vector4 vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + vec.z = -vec.z; + vec.w = -vec.w; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(Vector4 vec, real_t scale) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(real_t scale, Vector4 vec) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(Vector4 left, Vector4 right) + { + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + left.w *= right.w; + return left; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> + public static Vector4 operator /(Vector4 vec, real_t divisor) + { + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; + vec.w /= divisor; + return vec; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> + public static Vector4 operator /(Vector4 vec, Vector4 divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + vec.w /= divisorv.w; + return vec; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> + public static bool operator ==(Vector4 left, Vector4 right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> + public static bool operator !=(Vector4 left, Vector4 right) + { + return !left.Equals(right); + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> + public static bool operator <(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w < right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> + public static bool operator >(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w > right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> + public static bool operator <=(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w <= right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> + public static bool operator >=(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w >= right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Vector4) + { + return Equals((Vector4)obj); + } + + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> + public bool Equals(Vector4 other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + + /// <summary> + /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are approximately equal, + /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component. + /// </summary> + /// <param name="other">The other vector to compare.</param> + /// <returns>Whether or not the vectors are approximately equal.</returns> + public bool IsEqualApprox(Vector4 other) + { + return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w); + } + + /// <summary> + /// Serves as the hash function for <see cref="Vector4"/>. + /// </summary> + /// <returns>A hash code for this vector.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Vector4"/> to a string. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public override string ToString() + { + return $"({x}, {y}, {z}, {w})"; + } + + /// <summary> + /// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public string ToString(string format) + { + return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})"; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs new file mode 100644 index 0000000000..365dcef486 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs @@ -0,0 +1,702 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + /// <summary> + /// 4-element structure that can be used to represent 4D grid coordinates or sets of integers. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector4i : IEquatable<Vector4i> + { + /// <summary> + /// Enumerated index values for the axes. + /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>. + /// </summary> + public enum Axis + { + /// <summary> + /// The vector's X axis. + /// </summary> + X = 0, + /// <summary> + /// The vector's Y axis. + /// </summary> + Y, + /// <summary> + /// The vector's Z axis. + /// </summary> + Z, + /// <summary> + /// The vector's W axis. + /// </summary> + W + } + + /// <summary> + /// The vector's X component. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public int x; + + /// <summary> + /// The vector's Y component. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public int y; + + /// <summary> + /// The vector's Z component. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public int z; + + /// <summary> + /// The vector's W component. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public int w; + + /// <summary> + /// Access vector components using their <paramref name="index"/>. + /// </summary> + /// <exception cref="IndexOutOfRangeException"> + /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3. + /// </exception> + /// <value> + /// <c>[0]</c> is equivalent to <see cref="x"/>, + /// <c>[1]</c> is equivalent to <see cref="y"/>, + /// <c>[2]</c> is equivalent to <see cref="z"/>. + /// <c>[3]</c> is equivalent to <see cref="w"/>. + /// </value> + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y, out int z, out int w) + { + x = this.x; + y = this.y; + z = this.z; + w = this.w; + } + + /// <summary> + /// Returns a new vector with all components in absolute values (i.e. positive). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> + public Vector4i Abs() + { + return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); + } + + /// <summary> + /// Returns a new vector with all components clamped between the + /// components of <paramref name="min"/> and <paramref name="max"/> using + /// <see cref="Mathf.Clamp(int, int, int)"/>. + /// </summary> + /// <param name="min">The vector with minimum allowed values.</param> + /// <param name="max">The vector with maximum allowed values.</param> + /// <returns>The vector with all components clamped.</returns> + public Vector4i Clamp(Vector4i min, Vector4i max) + { + return new Vector4i + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z), + Mathf.Clamp(w, min.w, max.w) + ); + } + + /// <summary> + /// Returns the length (magnitude) of this vector. + /// </summary> + /// <seealso cref="LengthSquared"/> + /// <returns>The length of this vector.</returns> + public real_t Length() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + int w2 = w * w; + + return Mathf.Sqrt(x2 + y2 + z2 + w2); + } + + /// <summary> + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than <see cref="Length"/>, so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// </summary> + /// <returns>The squared length of this vector.</returns> + public int LengthSquared() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + int w2 = w * w; + + return x2 + y2 + z2 + w2; + } + + /// <summary> + /// Returns the axis of the vector's highest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.X"/>. + /// </summary> + /// <returns>The index of the highest axis.</returns> + public Axis MaxAxisIndex() + { + int max_index = 0; + int max_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] > max_value) + { + max_index = i; + max_value = this[i]; + } + } + return (Axis)max_index; + } + + /// <summary> + /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.W"/>. + /// </summary> + /// <returns>The index of the lowest axis.</returns> + public Axis MinAxisIndex() + { + int min_index = 0; + int min_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] <= min_value) + { + min_index = i; + min_value = this[i]; + } + } + return (Axis)min_index; + } + + /// <summary> + /// Returns a vector with each component set to one or negative one, depending + /// on the signs of this vector's components, or zero if the component is zero, + /// by calling <see cref="Mathf.Sign(int)"/> on each component. + /// </summary> + /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> + public Vector4i Sign() + { + return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w)); + } + + // Constants + private static readonly Vector4i _zero = new Vector4i(0, 0, 0, 0); + private static readonly Vector4i _one = new Vector4i(1, 1, 1, 1); + + /// <summary> + /// Zero vector, a vector with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4i(0, 0, 0, 0)</c>.</value> + public static Vector4i Zero { get { return _zero; } } + /// <summary> + /// One vector, a vector with all components set to <c>1</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4i(1, 1, 1, 1)</c>.</value> + public static Vector4i One { get { return _one; } } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> with the given components. + /// </summary> + /// <param name="x">The vector's X component.</param> + /// <param name="y">The vector's Y component.</param> + /// <param name="z">The vector's Z component.</param> + /// <param name="w">The vector's W component.</param> + public Vector4i(int x, int y, int z, int w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4i"/>. + /// </summary> + /// <param name="vi">The existing <see cref="Vector4i"/>.</param> + public Vector4i(Vector4i vi) + { + this.x = vi.x; + this.y = vi.y; + this.z = vi.z; + this.w = vi.w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4"/> + /// by rounding the components via <see cref="Mathf.RoundToInt(real_t)"/>. + /// </summary> + /// <param name="v">The <see cref="Vector4"/> to convert.</param> + public Vector4i(Vector4 v) + { + this.x = Mathf.RoundToInt(v.x); + this.y = Mathf.RoundToInt(v.y); + this.z = Mathf.RoundToInt(v.z); + this.w = Mathf.RoundToInt(v.w); + } + + /// <summary> + /// Adds each component of the <see cref="Vector4i"/> + /// with the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> + public static Vector4i operator +(Vector4i left, Vector4i right) + { + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + return left; + } + + /// <summary> + /// Subtracts each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> + public static Vector4i operator -(Vector4i left, Vector4i right) + { + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + return left; + } + + /// <summary> + /// Returns the negative value of the <see cref="Vector4i"/>. + /// This is the same as writing <c>new Vector4i(-v.x, -v.y, -v.z, -v.w)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> + public static Vector4i operator -(Vector4i vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + vec.z = -vec.z; + vec.w = -vec.w; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(Vector4i vec, int scale) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(int scale, Vector4i vec) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(Vector4i left, Vector4i right) + { + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + left.w *= right.w; + return left; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> + public static Vector4i operator /(Vector4i vec, int divisor) + { + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; + vec.w /= divisor; + return vec; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> + public static Vector4i operator /(Vector4i vec, Vector4i divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + vec.w /= divisorv.w; + return vec; + } + + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector4i"/> + /// with the components of the given <see langword="int"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vecto43i(10, -20, 30, -40) % 7); // Prints "(3, -6, 2, -5)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> + public static Vector4i operator %(Vector4i vec, int divisor) + { + vec.x %= divisor; + vec.y %= divisor; + vec.z %= divisor; + vec.w %= divisor; + return vec; + } + + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector4i"/> + /// with the components of the given <see cref="Vector4i"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector4i(10, -20, 30, -40) % new Vector4i(6, 7, 8, 9)); // Prints "(4, -6, 6, -4)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> + public static Vector4i operator %(Vector4i vec, Vector4i divisorv) + { + vec.x %= divisorv.x; + vec.y %= divisorv.y; + vec.z %= divisorv.z; + vec.w %= divisorv.w; + return vec; + } + + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector4i"/> + /// and the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to AND with.</param> + /// <param name="and">The integer to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> + public static Vector4i operator &(Vector4i vec, int and) + { + vec.x &= and; + vec.y &= and; + vec.z &= and; + vec.w &= and; + return vec; + } + + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector4i"/> + /// and the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="vec">The left vector to AND with.</param> + /// <param name="andv">The right vector to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> + public static Vector4i operator &(Vector4i vec, Vector4i andv) + { + vec.x &= andv.x; + vec.y &= andv.y; + vec.z &= andv.z; + vec.w &= andv.w; + return vec; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> + public static bool operator ==(Vector4i left, Vector4i right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> + public static bool operator !=(Vector4i left, Vector4i right) + { + return !left.Equals(right); + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> + public static bool operator <(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w < right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> + public static bool operator >(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w > right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> + public static bool operator <=(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w <= right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> + public static bool operator >=(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w >= right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a <see cref="Vector4"/>. + /// </summary> + /// <param name="value">The vector to convert.</param> + public static implicit operator Vector4(Vector4i value) + { + return new Vector4(value.x, value.y, value.z, value.w); + } + + /// <summary> + /// Converts a <see cref="Vector4"/> to a <see cref="Vector4i"/>. + /// </summary> + /// <param name="value">The vector to convert.</param> + public static explicit operator Vector4i(Vector4 value) + { + return new Vector4i(value); + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is equal + /// to the given object (<see paramref="obj"/>). + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Vector4i) + { + return Equals((Vector4i)obj); + } + + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> + public bool Equals(Vector4i other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + + /// <summary> + /// Serves as the hash function for <see cref="Vector4i"/>. + /// </summary> + /// <returns>A hash code for this vector.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a string. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public override string ToString() + { + return $"({x}, {y}, {z}, {w})"; + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public string ToString(string format) + { + return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})"; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index e59f45bbf6..4f55ce47e8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -50,6 +50,7 @@ <Compile Include="Core\NodePath.cs" /> <Compile Include="Core\Object.base.cs" /> <Compile Include="Core\Plane.cs" /> + <Compile Include="Core\Projection.cs" /> <Compile Include="Core\Quaternion.cs" /> <Compile Include="Core\Rect2.cs" /> <Compile Include="Core\Rect2i.cs" /> @@ -65,6 +66,8 @@ <Compile Include="Core\Vector2i.cs" /> <Compile Include="Core\Vector3.cs" /> <Compile Include="Core\Vector3i.cs" /> + <Compile Include="Core\Vector4.cs" /> + <Compile Include="Core\Vector4i.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <!-- diff --git a/modules/mono/glue/callable_glue.cpp b/modules/mono/glue/callable_glue.cpp index e59b34313c..521dc3dff7 100644 --- a/modules/mono/glue/callable_glue.cpp +++ b/modules/mono/glue/callable_glue.cpp @@ -49,7 +49,7 @@ MonoObject *godot_icall_Callable_Call(GDMonoMarshal::M_Callable *p_callable, Mon Variant result; Callable::CallError error; - callable.call(args.ptr(), argc, result, error); + callable.callp(args.ptr(), argc, result, error); return GDMonoMarshal::variant_to_mono_object(result); } @@ -68,7 +68,7 @@ void godot_icall_Callable_CallDeferred(GDMonoMarshal::M_Callable *p_callable, Mo args.set(i, &arg_store.get(i)); } - callable.call_deferred(args.ptr(), argc); + callable.call_deferredp(args.ptr(), argc); } void godot_register_callable_icalls() { diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 9638b23410..f9ad1a9893 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GLUE_HEADER_H +#define GLUE_HEADER_H + #ifdef MONO_GLUE_ENABLED #include "../mono_gd/gd_mono_marshal.h" @@ -84,3 +87,5 @@ void godot_register_glue_header_icalls() { #include "arguments_vector.h" #endif // MONO_GLUE_ENABLED + +#endif // GLUE_HEADER_H diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index cb2b60fcce..f17b24e399 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -184,7 +184,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_editor_tools_dir)) { data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools"); } @@ -222,7 +222,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_mono_root_dir)) { data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib"); diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index ab9e508c99..e2aff1d19d 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CSHARP_GC_HANDLE_H -#define CSHARP_GC_HANDLE_H +#ifndef MONO_GC_HANDLE_H +#define MONO_GC_HANDLE_H #include <mono/jit/jit.h> @@ -104,4 +104,4 @@ public: ~MonoGCHandleRef() { release(); } }; -#endif // CSHARP_GC_HANDLE_H +#endif // MONO_GC_HANDLE_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 39a8ef22b7..d3d3bb2bef 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -55,7 +55,7 @@ #ifdef ANDROID_ENABLED #include "android_mono_config.h" #include "support/android_support.h" -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) #include "support/ios_support.h" #endif @@ -188,7 +188,7 @@ MonoDomain *gd_initialize_mono_runtime() { MonoDomain *gd_initialize_mono_runtime() { gd_mono_debug_init(); -#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED) +#if defined(IOS_ENABLED) || defined(ANDROID_ENABLED) // I don't know whether this actually matters or not const char *runtime_version = "mobile"; #else @@ -263,7 +263,7 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { r_config_dir = mono_reg_info.config_dir; } -#elif defined(OSX_ENABLED) +#elif defined(MACOS_ENABLED) const char *c_assembly_rootdir = mono_assembly_getrootdir(); const char *c_config_dir = mono_get_config_dir(); @@ -343,7 +343,7 @@ void GDMono::initialize() { #if defined(ANDROID_ENABLED) gdmono::android::support::initialize(); -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) gdmono::ios::support::initialize(); #endif diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index fd78fae4ad..69d8c7edc9 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -108,9 +108,12 @@ void CachedData::clear_godot_api_cache() { class_Transform2D = nullptr; class_Vector3 = nullptr; class_Vector3i = nullptr; + class_Vector4 = nullptr; + class_Vector4i = nullptr; class_Basis = nullptr; class_Quaternion = nullptr; class_Transform3D = nullptr; + class_Projection = nullptr; class_AABB = nullptr; class_Color = nullptr; class_Plane = nullptr; @@ -239,9 +242,12 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i)); + CACHE_CLASS_AND_CHECK(Vector4, GODOT_API_CLASS(Vector4)); + CACHE_CLASS_AND_CHECK(Vector4i, GODOT_API_CLASS(Vector4i)); CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion)); CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D)); + CACHE_CLASS_AND_CHECK(Projection, GODOT_API_CLASS(Projection)); CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index b3b0865608..e9cc26899e 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -79,9 +79,12 @@ struct CachedData { GDMonoClass *class_Transform2D = nullptr; GDMonoClass *class_Vector3 = nullptr; GDMonoClass *class_Vector3i = nullptr; + GDMonoClass *class_Vector4 = nullptr; + GDMonoClass *class_Vector4i = nullptr; GDMonoClass *class_Basis = nullptr; GDMonoClass *class_Quaternion = nullptr; GDMonoClass *class_Transform3D = nullptr; + GDMonoClass *class_Projection = nullptr; GDMonoClass *class_AABB = nullptr; GDMonoClass *class_Color = nullptr; GDMonoClass *class_Plane = nullptr; diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 333a06c94a..cb025fc67a 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -140,6 +140,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Vector4)) { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + + if (tclass == CACHED_CLASS(Vector4i)) { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(Basis)) { GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis()); mono_field_set_value(p_object, mono_field, &from); @@ -158,6 +170,12 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Projection)) { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(AABB)) { GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB()); mono_field_set_value(p_object, mono_field, &from); @@ -328,6 +346,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + } break; + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::TRANSFORM2D: { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D()); mono_field_set_value(p_object, mono_field, &from); @@ -352,6 +378,10 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color()); mono_field_set_value(p_object, mono_field, &from); diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index 87ef245f3f..1d30f7a369 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOFIELD_H -#define GDMONOFIELD_H +#ifndef GD_MONO_FIELD_H +#define GD_MONO_FIELD_H #include "gd_mono.h" #include "gd_mono_header.h" @@ -75,4 +75,4 @@ public: ~GDMonoField(); }; -#endif // GDMONOFIELD_H +#endif // GD_MONO_FIELD_H diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index 9fc35f8e31..93ba6a410e 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -35,7 +35,7 @@ #include "core/typedefs.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) // We have custom mono log callbacks for WASM and iOS #define GD_MONO_LOG_ENABLED #endif diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 957abca37b..a860442764 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -99,6 +99,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Vector3i)) { return Variant::VECTOR3I; } + if (vtclass == CACHED_CLASS(Vector4)) { + return Variant::VECTOR4; + } + + if (vtclass == CACHED_CLASS(Vector4i)) { + return Variant::VECTOR4I; + } if (vtclass == CACHED_CLASS(Basis)) { return Variant::BASIS; @@ -111,7 +118,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Transform3D)) { return Variant::TRANSFORM3D; } - + if (vtclass == CACHED_CLASS(Projection)) { + return Variant::PROJECTION; + } if (vtclass == CACHED_CLASS(AABB)) { return Variant::AABB; } @@ -539,6 +548,14 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var.operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); } + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_var.operator ::Vector4()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4), &from); + } + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_var.operator ::Vector4i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4i), &from); + } case Variant::PLANE: { GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from); @@ -559,6 +576,10 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from); } + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_var.operator ::Projection()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Projection), &from); + } case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from); diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 778e52b6cb..51f11ab18a 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOMARSHAL_H -#define GDMONOMARSHAL_H +#ifndef GD_MONO_MARSHAL_H +#define GD_MONO_MARSHAL_H #include "core/variant/variant.h" @@ -256,6 +256,18 @@ enum { offsetof(Vector3, y) == (sizeof(real_t) * 1) && offsetof(Vector3, z) == (sizeof(real_t) * 2)), + MATCHES_Vector4 = (MATCHES_real_t && (sizeof(Vector4) == (sizeof(real_t) * 4)) && + offsetof(Vector4, x) == (sizeof(real_t) * 0) && + offsetof(Vector4, y) == (sizeof(real_t) * 1) && + offsetof(Vector4, z) == (sizeof(real_t) * 2) && + offsetof(Vector4, w) == (sizeof(real_t) * 3)), + + MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4)) && + offsetof(Vector4i, x) == (sizeof(int32_t) * 0) && + offsetof(Vector4i, y) == (sizeof(int32_t) * 1) && + offsetof(Vector4i, z) == (sizeof(int32_t) * 2) && + offsetof(Vector4i, w) == (sizeof(int32_t) * 3)), + MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) && offsetof(Vector3i, x) == (sizeof(int32_t) * 0) && offsetof(Vector3i, y) == (sizeof(int32_t) * 1) && @@ -273,6 +285,8 @@ enum { offsetof(Transform3D, basis) == 0 && offsetof(Transform3D, origin) == sizeof(Basis)), + MATCHES_Projection = (MATCHES_Vector4 && (sizeof(Projection) == (sizeof(Vector4) * 4))), + MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) && offsetof(AABB, position) == (sizeof(Vector3) * 0) && offsetof(AABB, size) == (sizeof(Vector3) * 1)), @@ -291,9 +305,9 @@ enum { // In the future we may force this if we want to ref return these structs #ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY /* clang-format off */ -static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && - MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color && - MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i); +static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && MATCHES_Vector4 && + MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_Projection && MATCHES_AABB && MATCHES_Color && + MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i && MATCHES_Vector4i); /* clang-format on */ #endif } // namespace InteropLayout @@ -401,6 +415,32 @@ struct M_Vector3i { } }; +struct M_Vector4 { + real_t x, y, z, w; + + static _FORCE_INLINE_ Vector4 convert_to(const M_Vector4 &p_from) { + return Vector4(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4 convert_from(const Vector4 &p_from) { + M_Vector4 ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + +struct M_Vector4i { + int32_t x, y, z, w; + + static _FORCE_INLINE_ Vector4i convert_to(const M_Vector4i &p_from) { + return Vector4i(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4i convert_from(const Vector4i &p_from) { + M_Vector4i ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + struct M_Basis { M_Vector3 elements[3]; @@ -447,6 +487,22 @@ struct M_Transform3D { } }; +struct M_Projection { + M_Vector4 vec1; + M_Vector4 vec2; + M_Vector4 vec3; + M_Vector4 vec4; + + static _FORCE_INLINE_ Projection convert_to(const M_Projection &p_from) { + return Projection(M_Vector4::convert_to(p_from.vec1), M_Vector4::convert_to(p_from.vec2), M_Vector4::convert_to(p_from.vec3), M_Vector4::convert_to(p_from.vec4)); + } + + static _FORCE_INLINE_ M_Projection convert_from(const Projection &p_from) { + M_Projection ret = { M_Vector4::convert_from(p_from.matrix[0]), M_Vector4::convert_from(p_from.matrix[1]), M_Vector4::convert_from(p_from.matrix[2]), M_Vector4::convert_from(p_from.matrix[3]) }; + return ret; + } +}; + struct M_AABB { M_Vector3 position; M_Vector3 size; @@ -533,8 +589,11 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D) DECL_TYPE_MARSHAL_TEMPLATES(Vector3) DECL_TYPE_MARSHAL_TEMPLATES(Vector3i) DECL_TYPE_MARSHAL_TEMPLATES(Basis) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4i) DECL_TYPE_MARSHAL_TEMPLATES(Quaternion) DECL_TYPE_MARSHAL_TEMPLATES(Transform3D) +DECL_TYPE_MARSHAL_TEMPLATES(Projection) DECL_TYPE_MARSHAL_TEMPLATES(AABB) DECL_TYPE_MARSHAL_TEMPLATES(Color) DECL_TYPE_MARSHAL_TEMPLATES(Plane) @@ -543,4 +602,4 @@ DECL_TYPE_MARSHAL_TEMPLATES(Plane) #define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from)) } // namespace GDMonoMarshal -#endif // GDMONOMARSHAL_H +#endif // GD_MONO_MARSHAL_H diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index bb163b89bc..0180dee3ea 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -39,7 +39,7 @@ #include "gd_mono_method.h" #include "gd_mono_utils.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) #define HAVE_METHOD_THUNKS #endif diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 246a1cd31e..300cacfa4b 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GD_MONOUTILS_H -#define GD_MONOUTILS_H +#ifndef GD_MONO_UTILS_H +#define GD_MONO_UTILS_H #include <mono/metadata/threads.h> @@ -202,4 +202,4 @@ void add_internal_call(const char *p_name, R (*p_func)(P...)) { #define GD_MONO_ASSERT_THREAD_ATTACHED ((void)0) #endif -#endif // GD_MONOUTILS_H +#endif // GD_MONO_UTILS_H diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h index 2f444d5089..03e86df698 100644 --- a/modules/mono/mono_gd/support/ios_support.h +++ b/modules/mono/mono_gd/support/ios_support.h @@ -31,7 +31,7 @@ #ifndef IOS_SUPPORT_H #define IOS_SUPPORT_H -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #include "core/string/ustring.h" @@ -45,6 +45,6 @@ void cleanup(); } // namespace ios } // namespace gdmono -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED #endif // IOS_SUPPORT_H diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm index df97dfba49..7c941b9d1e 100644 --- a/modules/mono/mono_gd/support/ios_support.mm +++ b/modules/mono/mono_gd/support/ios_support.mm @@ -30,7 +30,7 @@ #include "ios_support.h" -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #import <Foundation/Foundation.h> #include <os/log.h> @@ -147,4 +147,4 @@ GD_PINVOKE_EXPORT void xamarin_start_wwan(const char *p_uri) { os_log_error(OS_LOG_DEFAULT, "Not implemented: 'xamarin_start_wwan'"); } -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 618e1b58e0..437c4ca54a 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -44,7 +44,7 @@ Error gd_mono_connect_signal_awaiter(Object *p_source, const StringName &p_signa SignalAwaiterCallable *awaiter_callable = memnew(SignalAwaiterCallable(p_target, p_awaiter, p_signal)); Callable callable = Callable(awaiter_callable); - return p_source->connect(p_signal, callable, Vector<Variant>(), Object::CONNECT_ONESHOT); + return p_source->connect(p_signal, callable, Object::CONNECT_ONESHOT); } bool SignalAwaiterCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/macos_utils.cpp index abb59420eb..cd4f7a827e 100644 --- a/modules/mono/utils/osx_utils.cpp +++ b/modules/mono/utils/macos_utils.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.cpp */ +/* macos_utils.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "osx_utils.h" +#include "macos_utils.h" -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #include "core/string/print_string.h" #import <CoreFoundation/CoreFoundation.h> #import <CoreServices/CoreServices.h> -bool osx_is_app_bundle_installed(const String &p_bundle_id) { +bool macos_is_app_bundle_installed(const String &p_bundle_id) { CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8); CFArrayRef result = LSCopyApplicationURLsForBundleIdentifier(bundle_id, nullptr); CFRelease(bundle_id); diff --git a/modules/mono/utils/osx_utils.h b/modules/mono/utils/macos_utils.h index 2f6c6dad51..ca4957f5a7 100644 --- a/modules/mono/utils/osx_utils.h +++ b/modules/mono/utils/macos_utils.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.h */ +/* macos_utils.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,13 +30,13 @@ #include "core/string/ustring.h" -#ifndef OSX_UTILS_H -#define OSX_UTILS_H +#ifndef MONO_MACOS_UTILS_H +#define MONO_MACOS_UTILS_H -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED -bool osx_is_app_bundle_installed(const String &p_bundle_id); +bool macos_is_app_bundle_installed(const String &p_bundle_id); #endif -#endif // OSX_UTILS_H +#endif // MONO_MACOS_UTILS_H diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h index 2ca1a4cbf1..b7bd9a2495 100644 --- a/modules/mono/utils/macros.h +++ b/modules/mono/utils/macros.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef UTIL_MACROS_H -#define UTIL_MACROS_H +#ifndef MONO_MACROS_H +#define MONO_MACROS_H #define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name #define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c) @@ -69,4 +69,4 @@ public: #define SCOPE_EXIT \ auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() -> void -#endif // UTIL_MACROS_H +#endif // MONO_MACROS_H diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index a8cd8daf04..9a2c757361 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PATH_UTILS_H -#define PATH_UTILS_H +#ifndef MONO_PATH_UTILS_H +#define MONO_PATH_UTILS_H #include "core/string/string_builder.h" #include "core/string/ustring.h" @@ -58,4 +58,4 @@ String realpath(const String &p_path); String relative_to(const String &p_path, const String &p_relative_to); } // namespace path -#endif // PATH_UTILS_H +#endif // MONO_PATH_UTILS_H diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index d79888716a..fa4c5e89f4 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STRING_FORMAT_H -#define STRING_FORMAT_H +#ifndef MONO_STRING_UTILS_H +#define MONO_STRING_UTILS_H #include "core/string/ustring.h" #include "core/variant/variant.h" @@ -59,4 +59,4 @@ String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE char *str_format_new(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2; char *str_format_new(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0; -#endif // STRING_FORMAT_H +#endif // MONO_STRING_UTILS_H diff --git a/modules/msdfgen/SCsub b/modules/msdfgen/SCsub index 227369f4bd..0c269bc7f4 100644 --- a/modules/msdfgen/SCsub +++ b/modules/msdfgen/SCsub @@ -36,7 +36,7 @@ if env["builtin_msdfgen"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_msdfgen.Append(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"]) + env_msdfgen.Prepend(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"]) lib = env_msdfgen.add_library("msdfgen_builtin", thirdparty_sources) thirdparty_obj += lib diff --git a/modules/msdfgen/config.py b/modules/msdfgen/config.py index 653e466a74..631894400d 100644 --- a/modules/msdfgen/config.py +++ b/modules/msdfgen/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env.module_check_dependencies("msdfgen", ["freetype"]) + env.module_add_dependencies("msdfgen", ["freetype"]) + return True def configure(env): diff --git a/modules/multiplayer/SCsub b/modules/multiplayer/SCsub new file mode 100644 index 0000000000..ff33655537 --- /dev/null +++ b/modules/multiplayer/SCsub @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_mp = env_modules.Clone() + +module_obj = [] +env_mp.add_source_files(module_obj, "*.cpp") + +if env["tools"]: + env_mp.add_source_files(module_obj, "editor/*.cpp") + +env.modules_sources += module_obj diff --git a/modules/multiplayer/config.py b/modules/multiplayer/config.py new file mode 100644 index 0000000000..414bf0afcf --- /dev/null +++ b/modules/multiplayer/config.py @@ -0,0 +1,19 @@ +def can_build(env, platform): + return True + + +def configure(env): + pass + + +def get_doc_classes(): + return [ + "SceneReplicationConfig", + "SceneMultiplayer", + "MultiplayerSpawner", + "MultiplayerSynchronizer", + ] + + +def get_doc_path(): + return "doc_classes" diff --git a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml new file mode 100644 index 0000000000..881796ed26 --- /dev/null +++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + Automatically replicates spawnable nodes from the authority to other multiplayer peers. + </brief_description> + <description> + Spawnable scenes can be configured in the editor or through code (see [method add_spawnable_scene]). + Also supports custom node spawns through [method spawn], calling [method _spawn_custom] on all peers. + + Internally, [MultiplayerSpawner] uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way. + </description> + <tutorials> + </tutorials> + <methods> + <method name="_spawn_custom" qualifiers="virtual"> + <return type="Node" /> + <argument index="0" name="data" type="Variant" /> + <description> + Method called on all peers when a custom spawn was requested by the authority using [method spawn]. Should return a [Node] that is not in the scene tree. + + [b]Note:[/b] Spawned nodes should [b]not[/b] be added to the scene with `add_child`. This is done automatically. + </description> + </method> + <method name="add_spawnable_scene"> + <return type="void" /> + <argument index="0" name="path" type="String" /> + <description> + Adds a scene path to spawnable scenes, making it automatically replicated from the multiplayer authority to other peers when added as children of the node pointed by [member spawn_path]. + </description> + </method> + <method name="clear_spawnable_scenes"> + <return type="void" /> + <description> + Clears all spawnable scenes. Does not despawn existing instances on remote peers. + </description> + </method> + <method name="get_spawnable_scene" qualifiers="const"> + <return type="String" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the spawnable scene path by index. + </description> + </method> + <method name="get_spawnable_scene_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the count of spawnable scene paths. + </description> + </method> + <method name="spawn"> + <return type="Node" /> + <argument index="0" name="data" type="Variant" default="null" /> + <description> + Requests a custom spawn, with [code]data[/code] passed to [method _spawn_custom] on all peers. Returns the locally spawned node instance already inside the scene tree, and added as a child of the node pointed by [member spawn_path]. + + [b]Note:[/b] Spawnable scenes are spawned automatically. [method spawn] is only needed for custom spawns. + </description> + </method> + </methods> + <members> + <member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0"> + Maximum nodes that is allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns. + + When set to [code]0[/code] (the default), there is no limit. + </member> + <member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath("")"> + Path to the spawn root. Spawnable scenes that are added as direct children are replicated to other peers. + </member> + </members> + <signals> + <signal name="despawned"> + <argument index="0" name="node" type="Node" /> + <description> + Emitted when a spawnable scene or custom spawn was despawned by the multiplayer authority. Only called on puppets. + </description> + </signal> + <signal name="spawned"> + <argument index="0" name="node" type="Node" /> + <description> + Emitted when a spawnable scene or custom spawn was spawned by the multiplayer authority. Only called on puppets. + </description> + </signal> + </signals> +</class> diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml new file mode 100644 index 0000000000..a2ea64061c --- /dev/null +++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + Synchronizes properties from the multiplayer authority to the remote peers. + </brief_description> + <description> + By default, [MultiplayerSynchronizer] synchronizes configured properties to all peers. + Visiblity can be handled directly with [method set_visibility_for] or as-needed with [method add_visibility_filter] and [method update_visibility]. + + [MultiplayerSpawner]s will handle nodes according to visibility of synchronizers as long as the node at [member root_path] was spawned by one. + + Internally, [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way. + </description> + <tutorials> + </tutorials> + <methods> + <method name="add_visibility_filter"> + <return type="void" /> + <argument index="0" name="filter" type="Callable" /> + <description> + Adds a peer visibility filter for this synchronizer. + + [code]filter[/code] should take a peer id [int] and return a [bool]. + </description> + </method> + <method name="get_visibility_for" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="peer" type="int" /> + <description> + Queries the current visibility for peer [code]peer[/code]. + </description> + </method> + <method name="remove_visibility_filter"> + <return type="void" /> + <argument index="0" name="filter" type="Callable" /> + <description> + Removes a peer visiblity filter from this synchronizer. + </description> + </method> + <method name="set_visibility_for"> + <return type="void" /> + <argument index="0" name="peer" type="int" /> + <argument index="1" name="visible" type="bool" /> + <description> + Sets the visibility of [code]peer[/code] to [code]visible[/code]. If [code]peer[/code] is [code]0[/code], the value of [member public_visibility] will be updated instead. + </description> + </method> + <method name="update_visibility"> + <return type="void" /> + <argument index="0" name="for_peer" type="int" default="0" /> + <description> + Updates the visibility of [code]peer[/code] according to visibility filters. If [code]peer[/code] is [code]0[/code] (the default), all peers' visibilties are updated. + </description> + </method> + </methods> + <members> + <member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true"> + Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options. + </member> + <member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config"> + Resource containing which properties to synchronize. + </member> + <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0"> + Time interval between synchronizes. When set to [code]0.0[/code] (the default), synchronizes happen every network process frame. + </member> + <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("..")"> + Node path that replicated properties are relative to. + If [member root_path] was spawned by a [MultiplayerSpawner], the node will be also be spawned and despawned based on this synchronizer visibility options. + </member> + <member name="visibility_update_mode" type="int" setter="set_visibility_update_mode" getter="get_visibility_update_mode" enum="MultiplayerSynchronizer.VisibilityUpdateMode" default="0"> + Specifies when visibility filters are updated (see [enum VisibilityUpdateMode] for options). + </member> + </members> + <signals> + <signal name="visibility_changed"> + <argument index="0" name="for_peer" type="int" /> + <description> + Emitted when visibility of [code]for_peer[/code] is updated. See [method update_visibility]. + </description> + </signal> + </signals> + <constants> + <constant name="VISIBILITY_PROCESS_IDLE" value="0" enum="VisibilityUpdateMode"> + Visibility filters are updated every idle process frame. + </constant> + <constant name="VISIBILITY_PROCESS_PHYSICS" value="1" enum="VisibilityUpdateMode"> + Visibility filters are updated every physics process frame. + </constant> + <constant name="VISIBILITY_PROCESS_NONE" value="2" enum="VisibilityUpdateMode"> + Visibility filters are not updated automatically, and must be updated manually by calling [method update_visibility]. + </constant> + </constants> +</class> diff --git a/modules/multiplayer/doc_classes/SceneMultiplayer.xml b/modules/multiplayer/doc_classes/SceneMultiplayer.xml new file mode 100644 index 0000000000..0c3ed2d784 --- /dev/null +++ b/modules/multiplayer/doc_classes/SceneMultiplayer.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="SceneMultiplayer" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + High-level multiplayer API implementation. + </brief_description> + <description> + This class is the default implementation of [MultiplayerAPI], used to provide multiplayer functionalities in Godot Engine. + This implementation supports RPCs via [method Node.rpc] and [method Node.rpc_id] and requires [method MultiplayerAPI.rpc] to be passed a [Node] (it will fail for other object types). + This implementation additionally provide [SceneTree] replication via the [MultiplayerSpawner] and [MultiplayerSynchronizer] nodes, and the [SceneReplicationConfig] resource. + [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice. + [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear"> + <return type="void" /> + <description> + Clears the current SceneMultiplayer network state (you shouldn't call this unless you know what you are doing). + </description> + </method> + <method name="send_bytes"> + <return type="int" enum="Error" /> + <argument index="0" name="bytes" type="PackedByteArray" /> + <argument index="1" name="id" type="int" default="0" /> + <argument index="2" name="mode" type="int" enum="MultiplayerPeer.TransferMode" default="2" /> + <argument index="3" name="channel" type="int" default="0" /> + <description> + Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers. + </description> + </method> + </methods> + <members> + <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false"> + If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs. + [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threat such as remote code execution. + </member> + <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false"> + If [code]true[/code], the MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] refuses new incoming connections. + </member> + <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("")"> + The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed. + This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene. + </member> + </members> + <signals> + <signal name="peer_packet"> + <argument index="0" name="id" type="int" /> + <argument index="1" name="packet" type="PackedByteArray" /> + <description> + Emitted when this MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet. + </description> + </signal> + </signals> +</class> diff --git a/doc/classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml index 62c108a477..fc91592c7a 100644 --- a/doc/classes/SceneReplicationConfig.xml +++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Configuration for properties to synchronize with a [MultiplayerSynchronizer]. </brief_description> <description> </description> @@ -12,35 +13,41 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="index" type="int" default="-1" /> <description> + Adds the property identified by the given [code]path[/code] to the list of the properties being synchronized, optionally passing an [code]index[/code]. </description> </method> <method name="get_properties" qualifiers="const"> <return type="NodePath[]" /> <description> + Returns a list of synchronized property [NodePath]s. </description> </method> <method name="has_property" qualifiers="const"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the given [code]path[/code] is configured for synchronization. </description> </method> <method name="property_get_index" qualifiers="const"> <return type="int" /> <argument index="0" name="path" type="NodePath" /> <description> + Finds the index of the given [code]path[/code]. </description> </method> <method name="property_get_spawn"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn. </description> </method> <method name="property_get_sync"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on process. </description> </method> <method name="property_set_spawn"> @@ -48,6 +55,7 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="enabled" type="bool" /> <description> + Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn. </description> </method> <method name="property_set_sync"> @@ -55,12 +63,14 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="enabled" type="bool" /> <description> + Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on process. </description> </method> <method name="remove_property"> <return type="void" /> <argument index="0" name="path" type="NodePath" /> <description> + Removes the property identified by the given [code]path[/code] from the configuration. </description> </method> </methods> diff --git a/editor/plugins/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor_plugin.cpp index 9e495c3aa3..50f1434ad8 100644 --- a/editor/plugins/replication_editor_plugin.cpp +++ b/modules/multiplayer/editor/replication_editor_plugin.cpp @@ -32,10 +32,13 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/inspector_dock.h" +#include "editor/scene_tree_editor.h" +#include "modules/multiplayer/multiplayer_synchronizer.h" #include "scene/gui/dialogs.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" -#include "scene/multiplayer/multiplayer_synchronizer.h" void ReplicationEditor::_pick_node_filter_text_changed(const String &p_newtext) { TreeItem *root_item = pick_node->get_scene_tree()->get_scene_tree()->get_root(); @@ -166,8 +169,8 @@ ReplicationEditor::ReplicationEditor() { set_custom_minimum_size(Size2(0, 200) * EDSCALE); delete_dialog = memnew(ConfirmationDialog); - delete_dialog->connect("cancelled", callable_mp(this, &ReplicationEditor::_dialog_closed), varray(false)); - delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed), varray(true)); + delete_dialog->connect("cancelled", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(false)); + delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(true)); add_child(delete_dialog); error_dialog = memnew(AcceptDialog); @@ -242,7 +245,7 @@ ReplicationEditor::ReplicationEditor() { drop_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); drop_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); tree->add_child(drop_label); - drop_label->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + drop_label->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); tree->set_drag_forwarding(this); } @@ -252,8 +255,6 @@ void ReplicationEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_checked", "property", "column", "checked"), &ReplicationEditor::_update_checked); ClassDB::bind_method("_can_drop_data_fw", &ReplicationEditor::_can_drop_data_fw); ClassDB::bind_method("_drop_data_fw", &ReplicationEditor::_drop_data_fw); - - ADD_SIGNAL(MethodInfo("keying_changed")); } bool ReplicationEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { @@ -319,10 +320,6 @@ void ReplicationEditor::_notification(int p_what) { add_pick_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); pin->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); } break; - - case NOTIFICATION_VISIBILITY_CHANGED: { - update_keying(); - } break; } } @@ -338,28 +335,15 @@ void ReplicationEditor::_add_pressed() { return; } String np_text = np_line_edit->get_text(); - if (np_text.find(":") == -1) { - np_text = ":" + np_text; - } - NodePath prop = NodePath(np_text); - if (prop.is_empty()) { - return; - } - UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action(TTR("Add property")); - config = current->get_replication_config(); - if (config.is_null()) { - config.instantiate(); - current->set_replication_config(config); - undo_redo->add_do_method(current, "set_replication_config", config); - undo_redo->add_undo_method(current, "set_replication_config", Ref<SceneReplicationConfig>()); - _update_config(); + int idx = np_text.find(":"); + if (idx == -1) { + np_text = ".:" + np_text; + } else if (idx == 0) { + np_text = "." + np_text; } - undo_redo->add_do_method(config.ptr(), "add_property", prop); - undo_redo->add_undo_method(config.ptr(), "remove_property", prop); - undo_redo->add_do_method(this, "_update_config"); - undo_redo->add_undo_method(this, "_update_config"); - undo_redo->commit_action(); + NodePath path = NodePath(np_text); + + _add_sync_property(path); } void ReplicationEditor::_tree_item_edited() { @@ -437,32 +421,12 @@ void ReplicationEditor::_update_checked(const NodePath &p_prop, int p_column, bo } } -void ReplicationEditor::update_keying() { - /// TODO make keying usable. -#if 0 - bool keying_enabled = false; - EditorSelectionHistory *editor_history = EditorNode::get_singleton()->get_editor_selection_history(); - if (is_visible_in_tree() && config.is_valid() && editor_history->get_path_size() > 0) { - Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0)); - keying_enabled = Object::cast_to<Node>(obj) != nullptr; - } - - if (keying_enabled == keying) { - return; - } - - keying = keying_enabled; - emit_signal(SNAME("keying_changed")); -#endif -} - void ReplicationEditor::_update_config() { deleting = NodePath(); tree->clear(); tree->create_item(); drop_label->set_visible(true); if (!config.is_valid()) { - update_keying(); return; } TypedArray<NodePath> props = config->get_properties(); @@ -473,7 +437,6 @@ void ReplicationEditor::_update_config() { const NodePath path = props[i]; _add_property(path, config->property_get_spawn(path), config->property_get_sync(path)); } - update_keying(); } void ReplicationEditor::edit(MultiplayerSynchronizer *p_sync) { @@ -529,43 +492,6 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, item->set_editable(2, true); } -void ReplicationEditor::property_keyed(const String &p_property) { - ERR_FAIL_COND(!current || config.is_null()); - Node *root = current->get_node(current->get_root_path()); - ERR_FAIL_COND(!root); - EditorSelectionHistory *history = EditorNode::get_singleton()->get_editor_selection_history(); - ERR_FAIL_COND(history->get_path_size() == 0); - Node *node = Object::cast_to<Node>(ObjectDB::get_instance(history->get_path_object(0))); - ERR_FAIL_COND(!node); - if (node->is_class("MultiplayerSynchronizer")) { - error_dialog->set_text(TTR("Properties of 'MultiplayerSynchronizer' cannot be configured for replication.")); - error_dialog->popup_centered(); - return; - } - if (history->get_path_size() > 1 || p_property.get_slice_count(":") > 1) { - error_dialog->set_text(TTR("Subresources cannot yet be configured for replication.")); - error_dialog->popup_centered(); - return; - } - - String path = root->get_path_to(node); - for (int i = 1; i < history->get_path_size(); i++) { - String prop = history->get_path_property(i); - ERR_FAIL_COND(prop == ""); - path += ":" + prop; - } - path += ":" + p_property; - - NodePath prop = path; - UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action(TTR("Add property")); - undo_redo->add_do_method(config.ptr(), "add_property", prop); - undo_redo->add_undo_method(config.ptr(), "remove_property", prop); - undo_redo->add_do_method(this, "_update_config"); - undo_redo->add_undo_method(this, "_update_config"); - undo_redo->commit_action(); -} - /// ReplicationEditorPlugin ReplicationEditorPlugin::ReplicationEditorPlugin() { repl_editor = memnew(ReplicationEditor); @@ -577,26 +503,9 @@ ReplicationEditorPlugin::ReplicationEditorPlugin() { ReplicationEditorPlugin::~ReplicationEditorPlugin() { } -void ReplicationEditorPlugin::_keying_changed() { - // TODO make lock usable. - //InspectorDock::get_inspector_singleton()->set_keying(repl_editor->has_keying(), this); -} - -void ReplicationEditorPlugin::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { - if (!repl_editor->has_keying()) { - return; - } - repl_editor->property_keyed(p_keyed); -} - void ReplicationEditorPlugin::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - //Node3DEditor::get_singleton()->connect("transform_key_request", callable_mp(this, &AnimationPlayerEditorPlugin::_transform_key_request)); - InspectorDock::get_inspector_singleton()->connect("property_keyed", callable_mp(this, &ReplicationEditorPlugin::_property_keyed)); - repl_editor->connect("keying_changed", callable_mp(this, &ReplicationEditorPlugin::_keying_changed)); - // TODO make lock usable. - //InspectorDock::get_inspector_singleton()->connect("object_inspected", callable_mp(repl_editor, &ReplicationEditor::update_keying)); get_tree()->connect("node_removed", callable_mp(this, &ReplicationEditorPlugin::_node_removed)); } break; } @@ -632,8 +541,6 @@ bool ReplicationEditorPlugin::handles(Object *p_object) const { void ReplicationEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - //editor->hide_animation_player_editors(); - //editor->animation_panel_make_visible(true); button->show(); EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor); } else if (!repl_editor->get_pin()->is_pressed()) { diff --git a/editor/plugins/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor_plugin.h index df3d97f884..e60e49cc25 100644 --- a/editor/plugins/replication_editor_plugin.h +++ b/modules/multiplayer/editor/replication_editor_plugin.h @@ -32,15 +32,17 @@ #define REPLICATION_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "scene/resources/scene_replication_config.h" #include "editor/editor_spin_slider.h" -#include "editor/property_editor.h" #include "editor/property_selector.h" +#include "../scene_replication_config.h" + class ConfirmationDialog; class MultiplayerSynchronizer; +class SceneTreeDialog; class Tree; +class TreeItem; class ReplicationEditor : public VBoxContainer { GDCLASS(ReplicationEditor, VBoxContainer); @@ -59,7 +61,6 @@ private: Ref<SceneReplicationConfig> config; NodePath deleting; Tree *tree = nullptr; - bool keying = false; PropertySelector *prop_selector = nullptr; SceneTreeDialog *pick_node = nullptr; @@ -96,11 +97,8 @@ protected: void _notification(int p_what); public: - void update_keying(); void edit(MultiplayerSynchronizer *p_object); - bool has_keying() const { return keying; } MultiplayerSynchronizer *get_current() const { return current; } - void property_keyed(const String &p_property); Button *get_pin() { return pin; } ReplicationEditor(); @@ -115,8 +113,6 @@ private: ReplicationEditor *repl_editor = nullptr; void _node_removed(Node *p_node); - void _keying_changed(); - void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance); void _pinned(); diff --git a/scene/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index ddd01d0a43..e8f3aecc69 100644 --- a/scene/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -31,7 +31,7 @@ #include "multiplayer_spawner.h" #include "core/io/marshalls.h" -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" @@ -71,7 +71,7 @@ bool MultiplayerSpawner::_get(const StringName &p_name, Variant &r_ret) const { } void MultiplayerSpawner::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::INT, "_spawnable_scene_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Scenes,scenes/")); + p_list->push_back(PropertyInfo(Variant::INT, "_spawnable_scene_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Auto Spawn List,scenes/")); List<String> exts; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &exts); String ext_hint; @@ -126,7 +126,7 @@ void MultiplayerSpawner::_set_spawnable_scenes(const Vector<String> &p_scenes) { void MultiplayerSpawner::_bind_methods() { ClassDB::bind_method(D_METHOD("add_spawnable_scene", "path"), &MultiplayerSpawner::add_spawnable_scene); ClassDB::bind_method(D_METHOD("get_spawnable_scene_count"), &MultiplayerSpawner::get_spawnable_scene_count); - ClassDB::bind_method(D_METHOD("get_spawnable_scene", "path"), &MultiplayerSpawner::get_spawnable_scene); + ClassDB::bind_method(D_METHOD("get_spawnable_scene", "index"), &MultiplayerSpawner::get_spawnable_scene); ClassDB::bind_method(D_METHOD("clear_spawnable_scenes"), &MultiplayerSpawner::clear_spawnable_scenes); ClassDB::bind_method(D_METHOD("_get_spawnable_scenes"), &MultiplayerSpawner::_get_spawnable_scenes); @@ -144,14 +144,10 @@ void MultiplayerSpawner::_bind_methods() { ClassDB::bind_method(D_METHOD("set_spawn_limit", "limit"), &MultiplayerSpawner::set_spawn_limit); ADD_PROPERTY(PropertyInfo(Variant::INT, "spawn_limit", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"), "set_spawn_limit", "get_spawn_limit"); - ClassDB::bind_method(D_METHOD("set_auto_spawning", "enabled"), &MultiplayerSpawner::set_auto_spawning); - ClassDB::bind_method(D_METHOD("is_auto_spawning"), &MultiplayerSpawner::is_auto_spawning); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_spawn"), "set_auto_spawning", "is_auto_spawning"); - GDVIRTUAL_BIND(_spawn_custom, "data"); - ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); } void MultiplayerSpawner::_update_spawn_node() { @@ -169,7 +165,7 @@ void MultiplayerSpawner::_update_spawn_node() { Node *node = spawn_path.is_empty() && is_inside_tree() ? nullptr : get_node_or_null(spawn_path); if (node) { spawn_node = node->get_instance_id(); - if (auto_spawn) { + if (get_spawnable_scene_count() && !GDVIRTUAL_IS_OVERRIDDEN(_spawn_custom)) { node->connect("child_entered_tree", callable_mp(this, &MultiplayerSpawner::_node_added)); } } else { @@ -194,7 +190,7 @@ void MultiplayerSpawner::_notification(int p_what) { if (node->is_connected(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready))) { node->disconnect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready)); } - get_multiplayer()->despawn(node, this); + get_multiplayer()->object_configuration_remove(node, this); } tracked_nodes.clear(); } break; @@ -221,15 +217,6 @@ void MultiplayerSpawner::_node_added(Node *p_node) { _track(p_node, Variant(), id); } -void MultiplayerSpawner::set_auto_spawning(bool p_enabled) { - auto_spawn = p_enabled; - _update_spawn_node(); -} - -bool MultiplayerSpawner::is_auto_spawning() const { - return auto_spawn; -} - NodePath MultiplayerSpawner::get_spawn_path() const { return spawn_path; } @@ -243,13 +230,13 @@ void MultiplayerSpawner::_track(Node *p_node, const Variant &p_argument, int p_s ObjectID oid = p_node->get_instance_id(); if (!tracked_nodes.has(oid)) { tracked_nodes[oid] = SpawnInfo(p_argument.duplicate(true), p_scene_id); - p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit), varray(p_node->get_instance_id()), CONNECT_ONESHOT); - p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready), varray(p_node->get_instance_id()), CONNECT_ONESHOT); + p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONESHOT); + p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready).bind(p_node->get_instance_id()), CONNECT_ONESHOT); } } void MultiplayerSpawner::_node_ready(ObjectID p_id) { - get_multiplayer()->spawn(ObjectDB::get_instance(p_id), this); + get_multiplayer()->object_configuration_add(ObjectDB::get_instance(p_id), this); } void MultiplayerSpawner::_node_exit(ObjectID p_id) { @@ -257,7 +244,7 @@ void MultiplayerSpawner::_node_exit(ObjectID p_id) { ERR_FAIL_COND(!node); if (tracked_nodes.has(p_id)) { tracked_nodes.erase(p_id); - get_multiplayer()->despawn(node, this); + get_multiplayer()->object_configuration_remove(node, this); } } @@ -290,12 +277,11 @@ Node *MultiplayerSpawner::instantiate_scene(int p_id) { Node *MultiplayerSpawner::instantiate_custom(const Variant &p_data) { ERR_FAIL_COND_V_MSG(spawn_limit && spawn_limit <= tracked_nodes.size(), nullptr, "Spawn limit reached!"); - Object *obj = nullptr; Node *node = nullptr; - if (GDVIRTUAL_CALL(_spawn_custom, p_data, obj)) { - node = Object::cast_to<Node>(obj); + if (GDVIRTUAL_CALL(_spawn_custom, p_data, node)) { + return node; } - return node; + ERR_FAIL_V_MSG(nullptr, "Method '_spawn_custom' is not implemented on this peer."); } Node *MultiplayerSpawner::spawn(const Variant &p_data) { diff --git a/scene/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h index e8abe702a0..fc3befc2d4 100644 --- a/scene/multiplayer/multiplayer_spawner.h +++ b/modules/multiplayer/multiplayer_spawner.h @@ -36,7 +36,8 @@ #include "core/templates/local_vector.h" #include "core/variant/typed_array.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/scene_replication_config.h" + +#include "scene_replication_config.h" class MultiplayerSpawner : public Node { GDCLASS(MultiplayerSpawner, Node); @@ -69,7 +70,6 @@ private: ObjectID spawn_node; HashMap<ObjectID, SpawnInfo> tracked_nodes; - bool auto_spawn = false; uint32_t spawn_limit = 0; void _update_spawn_node(); @@ -91,7 +91,9 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; #endif public: - Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; } + Node *get_spawn_node() const { + return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; + } void add_spawnable_scene(const String &p_path); int get_spawnable_scene_count() const; @@ -102,8 +104,6 @@ public: void set_spawn_path(const NodePath &p_path); uint32_t get_spawn_limit() const { return spawn_limit; } void set_spawn_limit(uint32_t p_limit) { spawn_limit = p_limit; } - bool is_auto_spawning() const; - void set_auto_spawning(bool p_enabled); const Variant get_spawn_argument(const ObjectID &p_id) const; int find_spawnable_scene_index_from_object(const ObjectID &p_id) const; @@ -112,7 +112,7 @@ public: Node *instantiate_custom(const Variant &p_data); Node *instantiate_scene(int p_idx); - GDVIRTUAL1R(Object *, _spawn_custom, const Variant &); + GDVIRTUAL1R(Node *, _spawn_custom, const Variant &); MultiplayerSpawner() {} }; diff --git a/scene/multiplayer/multiplayer_synchronizer.cpp b/modules/multiplayer/multiplayer_synchronizer.cpp index 68f6e54fa8..eee1495c14 100644 --- a/scene/multiplayer/multiplayer_synchronizer.cpp +++ b/modules/multiplayer/multiplayer_synchronizer.cpp @@ -31,7 +31,7 @@ #include "multiplayer_synchronizer.h" #include "core/config/engine.h" -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" Object *MultiplayerSynchronizer::_get_prop_target(Object *p_obj, const NodePath &p_path) { if (p_path.get_name_count() == 0) { @@ -43,16 +43,54 @@ Object *MultiplayerSynchronizer::_get_prop_target(Object *p_obj, const NodePath } void MultiplayerSynchronizer::_stop() { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return; + } +#endif Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr; if (node) { - get_multiplayer()->replication_stop(node, this); + get_multiplayer()->object_configuration_remove(node, this); } } void MultiplayerSynchronizer::_start() { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return; + } +#endif Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr; if (node) { - get_multiplayer()->replication_start(node, this); + get_multiplayer()->object_configuration_add(node, this); + _update_process(); + } +} + +void MultiplayerSynchronizer::_update_process() { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return; + } +#endif + Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr; + if (!node) { + return; + } + set_process_internal(false); + set_physics_process_internal(false); + if (!visibility_filters.size()) { + return; + } + switch (visibility_update_mode) { + case VISIBILITY_PROCESS_IDLE: + set_process_internal(true); + break; + case VISIBILITY_PROCESS_PHYSICS: + set_physics_process_internal(true); + break; + case VISIBILITY_PROCESS_NONE: + break; } } @@ -85,6 +123,66 @@ Error MultiplayerSynchronizer::set_state(const List<NodePath> &p_properties, Obj return OK; } +bool MultiplayerSynchronizer::is_visibility_public() const { + return peer_visibility.has(0); +} + +void MultiplayerSynchronizer::set_visibility_public(bool p_visible) { + set_visibility_for(0, p_visible); +} + +bool MultiplayerSynchronizer::is_visible_to(int p_peer) { + if (visibility_filters.size()) { + Variant arg = p_peer; + const Variant *argv[1] = { &arg }; + for (Callable filter : visibility_filters) { + Variant ret; + Callable::CallError err; + filter.callp(argv, 1, ret, err); + ERR_FAIL_COND_V(err.error != Callable::CallError::CALL_OK || ret.get_type() != Variant::BOOL, false); + if (!ret.operator bool()) { + return false; + } + } + } + return peer_visibility.has(0) || peer_visibility.has(p_peer); +} + +void MultiplayerSynchronizer::add_visibility_filter(Callable p_callback) { + visibility_filters.insert(p_callback); + _update_process(); +} + +void MultiplayerSynchronizer::remove_visibility_filter(Callable p_callback) { + visibility_filters.erase(p_callback); + _update_process(); +} + +void MultiplayerSynchronizer::set_visibility_for(int p_peer, bool p_visible) { + if (peer_visibility.has(p_peer) == p_visible) { + return; + } + if (p_visible) { + peer_visibility.insert(p_peer); + } else { + peer_visibility.erase(p_peer); + } + update_visibility(p_peer); +} + +bool MultiplayerSynchronizer::get_visibility_for(int p_peer) const { + return peer_visibility.has(p_peer); +} + +void MultiplayerSynchronizer::set_visibility_update_mode(VisibilityUpdateMode p_mode) { + visibility_update_mode = p_mode; + _update_process(); +} + +MultiplayerSynchronizer::VisibilityUpdateMode MultiplayerSynchronizer::get_visibility_update_mode() const { + return visibility_update_mode; +} + void MultiplayerSynchronizer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerSynchronizer::set_root_path); ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerSynchronizer::get_root_path); @@ -95,9 +193,29 @@ void MultiplayerSynchronizer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_replication_config", "config"), &MultiplayerSynchronizer::set_replication_config); ClassDB::bind_method(D_METHOD("get_replication_config"), &MultiplayerSynchronizer::get_replication_config); + ClassDB::bind_method(D_METHOD("set_visibility_update_mode", "mode"), &MultiplayerSynchronizer::set_visibility_update_mode); + ClassDB::bind_method(D_METHOD("get_visibility_update_mode"), &MultiplayerSynchronizer::get_visibility_update_mode); + ClassDB::bind_method(D_METHOD("update_visibility", "for_peer"), &MultiplayerSynchronizer::update_visibility, DEFVAL(0)); + + ClassDB::bind_method(D_METHOD("set_visibility_public", "visible"), &MultiplayerSynchronizer::set_visibility_public); + ClassDB::bind_method(D_METHOD("is_visibility_public"), &MultiplayerSynchronizer::is_visibility_public); + + ClassDB::bind_method(D_METHOD("add_visibility_filter", "filter"), &MultiplayerSynchronizer::add_visibility_filter); + ClassDB::bind_method(D_METHOD("remove_visibility_filter", "filter"), &MultiplayerSynchronizer::remove_visibility_filter); + ClassDB::bind_method(D_METHOD("set_visibility_for", "peer", "visible"), &MultiplayerSynchronizer::set_visibility_for); + ClassDB::bind_method(D_METHOD("get_visibility_for", "peer"), &MultiplayerSynchronizer::get_visibility_for); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "replication_interval", PROPERTY_HINT_RANGE, "0,5,0.001,suffix:s"), "set_replication_interval", "get_replication_interval"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replication_config", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig"), "set_replication_config", "get_replication_config"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replication_config", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig", PROPERTY_USAGE_NO_EDITOR), "set_replication_config", "get_replication_config"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,None"), "set_visibility_update_mode", "get_visibility_update_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "public_visibility"), "set_visibility_public", "is_visibility_public"); + + BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_IDLE); + BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_PHYSICS); + BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_NONE); + + ADD_SIGNAL(MethodInfo("visibility_changed", PropertyInfo(Variant::INT, "for_peer"))); } void MultiplayerSynchronizer::_notification(int p_what) { @@ -118,6 +236,11 @@ void MultiplayerSynchronizer::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { _stop(); } break; + + case NOTIFICATION_INTERNAL_PROCESS: + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + update_visibility(0); + } break; } } @@ -142,6 +265,18 @@ Ref<SceneReplicationConfig> MultiplayerSynchronizer::get_replication_config() { return replication_config; } +void MultiplayerSynchronizer::update_visibility(int p_for_peer) { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return; + } +#endif + Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr; + if (node && get_multiplayer()->has_multiplayer_peer() && is_multiplayer_authority()) { + emit_signal(SNAME("visibility_changed"), p_for_peer); + } +} + void MultiplayerSynchronizer::set_root_path(const NodePath &p_path) { _stop(); root_path = p_path; @@ -158,7 +293,12 @@ void MultiplayerSynchronizer::set_multiplayer_authority(int p_peer_id, bool p_re Node::set_multiplayer_authority(p_peer_id, p_recursive); return; } - get_multiplayer()->replication_stop(node, this); + get_multiplayer()->object_configuration_remove(node, this); Node::set_multiplayer_authority(p_peer_id, p_recursive); - get_multiplayer()->replication_start(node, this); + get_multiplayer()->object_configuration_add(node, this); +} + +MultiplayerSynchronizer::MultiplayerSynchronizer() { + // Publicly visible by default. + peer_visibility.insert(0); } diff --git a/scene/multiplayer/multiplayer_synchronizer.h b/modules/multiplayer/multiplayer_synchronizer.h index f61ef459da..e84d41db86 100644 --- a/scene/multiplayer/multiplayer_synchronizer.h +++ b/modules/multiplayer/multiplayer_synchronizer.h @@ -33,19 +33,30 @@ #include "scene/main/node.h" -#include "scene/resources/scene_replication_config.h" +#include "scene_replication_config.h" class MultiplayerSynchronizer : public Node { GDCLASS(MultiplayerSynchronizer, Node); +public: + enum VisibilityUpdateMode { + VISIBILITY_PROCESS_IDLE, + VISIBILITY_PROCESS_PHYSICS, + VISIBILITY_PROCESS_NONE, + }; + private: Ref<SceneReplicationConfig> replication_config; NodePath root_path = NodePath(".."); // Start with parent, like with AnimationPlayer. uint64_t interval_msec = 0; + VisibilityUpdateMode visibility_update_mode = VISIBILITY_PROCESS_IDLE; + HashSet<Callable> visibility_filters; + HashSet<int> peer_visibility; static Object *_get_prop_target(Object *p_obj, const NodePath &p_prop); void _start(); void _stop(); + void _update_process(); protected: static void _bind_methods(); @@ -66,7 +77,20 @@ public: NodePath get_root_path() const; virtual void set_multiplayer_authority(int p_peer_id, bool p_recursive = true) override; - MultiplayerSynchronizer() {} + bool is_visibility_public() const; + void set_visibility_public(bool p_public); + bool is_visible_to(int p_peer); + void set_visibility_for(int p_peer, bool p_visible); + bool get_visibility_for(int p_peer) const; + void update_visibility(int p_for_peer); + void set_visibility_update_mode(VisibilityUpdateMode p_mode); + void add_visibility_filter(Callable p_callback); + void remove_visibility_filter(Callable p_callback); + VisibilityUpdateMode get_visibility_update_mode() const; + + MultiplayerSynchronizer(); }; +VARIANT_ENUM_CAST(MultiplayerSynchronizer::VisibilityUpdateMode); + #endif // MULTIPLAYER_SYNCHRONIZER_H diff --git a/modules/multiplayer/register_types.cpp b/modules/multiplayer/register_types.cpp new file mode 100644 index 0000000000..a2c524da80 --- /dev/null +++ b/modules/multiplayer/register_types.cpp @@ -0,0 +1,60 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "register_types.h" + +#include "multiplayer_spawner.h" +#include "multiplayer_synchronizer.h" +#include "scene_multiplayer.h" +#include "scene_replication_interface.h" +#include "scene_rpc_interface.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_plugin.h" +#include "editor/replication_editor_plugin.h" +#endif + +void initialize_multiplayer_module(ModuleInitializationLevel p_level) { + if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { + GDREGISTER_CLASS(SceneReplicationConfig); + GDREGISTER_CLASS(MultiplayerSpawner); + GDREGISTER_CLASS(MultiplayerSynchronizer); + GDREGISTER_CLASS(SceneMultiplayer); + MultiplayerAPI::set_default_interface("SceneMultiplayer"); + } +#ifdef TOOLS_ENABLED + if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { + EditorPlugins::add_by_type<ReplicationEditorPlugin>(); + } +#endif +} + +void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) { +} diff --git a/modules/multiplayer/register_types.h b/modules/multiplayer/register_types.h new file mode 100644 index 0000000000..aca6cf46ed --- /dev/null +++ b/modules/multiplayer/register_types.h @@ -0,0 +1,39 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 MULTIPLAYER_REGISTER_TYPES_H +#define MULTIPLAYER_REGISTER_TYPES_H + +#include "modules/register_module_types.h" + +void initialize_multiplayer_module(ModuleInitializationLevel p_level); +void uninitialize_multiplayer_module(ModuleInitializationLevel p_level); + +#endif // MULTIPLAYER_REGISTER_TYPES_H diff --git a/scene/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp index 7c271341db..b3b642f815 100644 --- a/scene/multiplayer/scene_cache_interface.cpp +++ b/modules/multiplayer/scene_cache_interface.cpp @@ -34,13 +34,7 @@ #include "scene/main/node.h" #include "scene/main/window.h" -MultiplayerCacheInterface *SceneCacheInterface::_create(MultiplayerAPI *p_multiplayer) { - return memnew(SceneCacheInterface(p_multiplayer)); -} - -void SceneCacheInterface::make_default() { - MultiplayerAPI::create_default_cache_interface = _create; -} +#include "scene_multiplayer.h" void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) { if (p_connected) { @@ -98,7 +92,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac Vector<uint8_t> packet; packet.resize(1 + 1 + len); - packet.write[0] = MultiplayerAPI::NETWORK_COMMAND_CONFIRM_PATH; + packet.write[0] = SceneMultiplayer::NETWORK_COMMAND_CONFIRM_PATH; packet.write[1] = valid_rpc_checksum; encode_cstring(pname.get_data(), &packet.write[2]); @@ -110,7 +104,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac #endif multiplayer_peer->set_transfer_channel(0); - multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE); + multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE); multiplayer_peer->set_target_peer(p_from); multiplayer_peer->put_packet(packet.ptr(), packet.size()); } @@ -150,7 +144,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat packet.resize(1 + 4 + path_len + methods_md5_len); int ofs = 0; - packet.write[ofs] = MultiplayerAPI::NETWORK_COMMAND_SIMPLIFY_PATH; + packet.write[ofs] = SceneMultiplayer::NETWORK_COMMAND_SIMPLIFY_PATH; ofs += 1; ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]); @@ -170,7 +164,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat for (int peer_id : p_peers) { multiplayer_peer->set_target_peer(peer_id); multiplayer_peer->set_transfer_channel(0); - multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE); + multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE); err = multiplayer_peer->put_packet(packet.ptr(), packet.size()); ERR_FAIL_COND_V(err != OK, err); // Insert into confirmed, but as false since it was not confirmed. @@ -187,18 +181,29 @@ bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) { return F->value; } -bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int p_peer_id, int &r_id) { +int SceneCacheInterface::make_object_cache(Object *p_obj) { Node *node = Object::cast_to<Node>(p_obj); - ERR_FAIL_COND_V(!node, false); + ERR_FAIL_COND_V(!node, -1); + NodePath for_path = multiplayer->get_root_path().rel_path_to(node->get_path()); // See if the path is cached. - PathSentCache *psc = path_send_cache.getptr(p_path); + PathSentCache *psc = path_send_cache.getptr(for_path); if (!psc) { // Path is not cached, create. - path_send_cache[p_path] = PathSentCache(); - psc = path_send_cache.getptr(p_path); + path_send_cache[for_path] = PathSentCache(); + psc = path_send_cache.getptr(for_path); psc->id = last_send_cache_id++; } - r_id = psc->id; + return psc->id; +} + +bool SceneCacheInterface::send_object_cache(Object *p_obj, int p_peer_id, int &r_id) { + Node *node = Object::cast_to<Node>(p_obj); + ERR_FAIL_COND_V(!node, false); + + r_id = make_object_cache(p_obj); + ERR_FAIL_COND_V(r_id < 0, false); + NodePath for_path = multiplayer->get_root_path().rel_path_to(node->get_path()); + PathSentCache *psc = path_send_cache.getptr(for_path); bool has_all_peers = true; List<int> peers_to_add; // If one is missing, take note to add it. @@ -218,9 +223,6 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int if (p_peer_id < 0 && E == -p_peer_id) { continue; // Continue, excluded. } - if (p_peer_id > 0 && E != p_peer_id) { - continue; // Continue, not for this peer. - } HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(E); if (!F) { @@ -233,7 +235,7 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int } if (peers_to_add.size()) { - _send_confirm_path(node, p_path, psc, peers_to_add); + _send_confirm_path(node, for_path, psc, peers_to_add); } return has_all_peers; diff --git a/scene/multiplayer/scene_cache_interface.h b/modules/multiplayer/scene_cache_interface.h index 3116233b5b..1e80792fe7 100644 --- a/scene/multiplayer/scene_cache_interface.h +++ b/modules/multiplayer/scene_cache_interface.h @@ -31,13 +31,15 @@ #ifndef SCENE_CACHE_INTERFACE_H #define SCENE_CACHE_INTERFACE_H -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" -class SceneCacheInterface : public MultiplayerCacheInterface { - GDCLASS(SceneCacheInterface, MultiplayerCacheInterface); +class SceneMultiplayer; + +class SceneCacheInterface : public RefCounted { + GDCLASS(SceneCacheInterface, RefCounted); private: - MultiplayerAPI *multiplayer = nullptr; + SceneMultiplayer *multiplayer = nullptr; //path sent caches struct PathSentCache { @@ -61,22 +63,20 @@ private: protected: Error _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers); - static MultiplayerCacheInterface *_create(MultiplayerAPI *p_multiplayer); public: - static void make_default(); - - virtual void clear() override; - virtual void on_peer_change(int p_id, bool p_connected) override; - virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) override; - virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) override; + void clear(); + void on_peer_change(int p_id, bool p_connected); + void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len); + void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len); // Returns true if all peers have cached path. - virtual bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id) override; - virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) override; - virtual bool is_cache_confirmed(NodePath p_path, int p_peer) override; + bool send_object_cache(Object *p_obj, int p_target, int &p_id); + int make_object_cache(Object *p_obj); + Object *get_cached_object(int p_from, uint32_t p_cache_id); + bool is_cache_confirmed(NodePath p_path, int p_peer); - SceneCacheInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; } + SceneCacheInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; } }; #endif // SCENE_CACHE_INTERFACE_H diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp new file mode 100644 index 0000000000..3fc1eef366 --- /dev/null +++ b/modules/multiplayer/scene_multiplayer.cpp @@ -0,0 +1,332 @@ +/*************************************************************************/ +/* scene_multiplayer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "scene_multiplayer.h" + +#include "core/debugger/engine_debugger.h" +#include "core/io/marshalls.h" + +#include <stdint.h> + +#ifdef DEBUG_ENABLED +#include "core/os/os.h" +#endif + +#ifdef DEBUG_ENABLED +void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) { + if (EngineDebugger::is_profiling("multiplayer")) { + Array values; + values.push_back(p_inout); + values.push_back(OS::get_singleton()->get_ticks_msec()); + values.push_back(p_size); + EngineDebugger::profiler_add_frame_data("multiplayer", values); + } +} +#endif + +Error SceneMultiplayer::poll() { + if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) { + return ERR_UNCONFIGURED; + } + + multiplayer_peer->poll(); + + if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here. + return OK; + } + + while (multiplayer_peer->get_available_packet_count()) { + int sender = multiplayer_peer->get_packet_peer(); + const uint8_t *packet; + int len; + + Error err = multiplayer_peer->get_packet(&packet, len); + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err)); + + remote_sender_id = sender; + _process_packet(sender, packet, len); + remote_sender_id = 0; + + if (!multiplayer_peer.is_valid()) { + return OK; // It's also possible that a packet or RPC caused a disconnection, so also check here. + } + } + replicator->on_network_process(); + return OK; +} + +void SceneMultiplayer::clear() { + connected_peers.clear(); + packet_cache.clear(); + cache->clear(); +} + +void SceneMultiplayer::set_root_path(const NodePath &p_path) { + ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "SceneMultiplayer root path must be absolute."); + root_path = p_path; +} + +NodePath SceneMultiplayer::get_root_path() const { + return root_path; +} + +void SceneMultiplayer::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) { + if (p_peer == multiplayer_peer) { + return; // Nothing to do + } + + ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED, + "Supplied MultiplayerPeer must be connecting or connected."); + + if (multiplayer_peer.is_valid()) { + multiplayer_peer->disconnect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer)); + multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer)); + multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server)); + multiplayer_peer->disconnect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed)); + multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected)); + clear(); + } + + multiplayer_peer = p_peer; + + if (multiplayer_peer.is_valid()) { + multiplayer_peer->connect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer)); + multiplayer_peer->connect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer)); + multiplayer_peer->connect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server)); + multiplayer_peer->connect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed)); + multiplayer_peer->connect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected)); + } + replicator->on_reset(); +} + +Ref<MultiplayerPeer> SceneMultiplayer::get_multiplayer_peer() { + return multiplayer_peer; +} + +void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { + ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via SceneMultiplayer.set_root_path before using it."); + ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small."); + +#ifdef DEBUG_ENABLED + profile_bandwidth("in", p_packet_len); +#endif + + // Extract the `packet_type` from the LSB three bits: + uint8_t packet_type = p_packet[0] & CMD_MASK; + + switch (packet_type) { + case NETWORK_COMMAND_SIMPLIFY_PATH: { + cache->process_simplify_path(p_from, p_packet, p_packet_len); + } break; + + case NETWORK_COMMAND_CONFIRM_PATH: { + cache->process_confirm_path(p_from, p_packet, p_packet_len); + } break; + + case NETWORK_COMMAND_REMOTE_CALL: { + rpc->process_rpc(p_from, p_packet, p_packet_len); + } break; + + case NETWORK_COMMAND_RAW: { + _process_raw(p_from, p_packet, p_packet_len); + } break; + case NETWORK_COMMAND_SPAWN: { + replicator->on_spawn_receive(p_from, p_packet, p_packet_len); + } break; + case NETWORK_COMMAND_DESPAWN: { + replicator->on_despawn_receive(p_from, p_packet, p_packet_len); + } break; + case NETWORK_COMMAND_SYNC: { + replicator->on_sync_receive(p_from, p_packet, p_packet_len); + } break; + } +} + +void SceneMultiplayer::_add_peer(int p_id) { + connected_peers.insert(p_id); + cache->on_peer_change(p_id, true); + replicator->on_peer_change(p_id, true); + emit_signal(SNAME("peer_connected"), p_id); +} + +void SceneMultiplayer::_del_peer(int p_id) { + replicator->on_peer_change(p_id, false); + cache->on_peer_change(p_id, false); + connected_peers.erase(p_id); + emit_signal(SNAME("peer_disconnected"), p_id); +} + +void SceneMultiplayer::_connected_to_server() { + emit_signal(SNAME("connected_to_server")); +} + +void SceneMultiplayer::_connection_failed() { + emit_signal(SNAME("connection_failed")); +} + +void SceneMultiplayer::_server_disconnected() { + replicator->on_reset(); + emit_signal(SNAME("server_disconnected")); +} + +Error SceneMultiplayer::send_bytes(Vector<uint8_t> p_data, int p_to, MultiplayerPeer::TransferMode p_mode, int p_channel) { + ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet."); + ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active."); + ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected."); + + if (packet_cache.size() < p_data.size() + 1) { + packet_cache.resize(p_data.size() + 1); + } + + const uint8_t *r = p_data.ptr(); + packet_cache.write[0] = NETWORK_COMMAND_RAW; + memcpy(&packet_cache.write[1], &r[0], p_data.size()); + + multiplayer_peer->set_target_peer(p_to); + multiplayer_peer->set_transfer_channel(p_channel); + multiplayer_peer->set_transfer_mode(p_mode); + + return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1); +} + +void SceneMultiplayer::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) { + ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); + + Vector<uint8_t> out; + int len = p_packet_len - 1; + out.resize(len); + { + uint8_t *w = out.ptrw(); + memcpy(&w[0], &p_packet[1], len); + } + emit_signal(SNAME("peer_packet"), p_from, out); +} + +int SceneMultiplayer::get_unique_id() { + ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID."); + return multiplayer_peer->get_unique_id(); +} + +void SceneMultiplayer::set_refuse_new_connections(bool p_refuse) { + ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'."); + multiplayer_peer->set_refuse_new_connections(p_refuse); +} + +bool SceneMultiplayer::is_refusing_new_connections() const { + ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'."); + return multiplayer_peer->is_refusing_new_connections(); +} + +Vector<int> SceneMultiplayer::get_peer_ids() { + ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected."); + + Vector<int> ret; + for (const int &E : connected_peers) { + ret.push_back(E); + } + + return ret; +} + +void SceneMultiplayer::set_allow_object_decoding(bool p_enable) { + allow_object_decoding = p_enable; +} + +bool SceneMultiplayer::is_object_decoding_allowed() const { + return allow_object_decoding; +} + +String SceneMultiplayer::get_rpc_md5(const Object *p_obj) { + return rpc->get_rpc_md5(p_obj); +} + +Error SceneMultiplayer::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { + return rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount); +} + +Error SceneMultiplayer::object_configuration_add(Object *p_obj, Variant p_config) { + if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) { + set_root_path(p_config); + return OK; + } + MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object()); + MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); + if (spawner) { + return replicator->on_spawn(p_obj, p_config); + } else if (sync) { + return replicator->on_replication_start(p_obj, p_config); + } + return ERR_INVALID_PARAMETER; +} + +Error SceneMultiplayer::object_configuration_remove(Object *p_obj, Variant p_config) { + if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) { + ERR_FAIL_COND_V(root_path != p_config.operator NodePath(), ERR_INVALID_PARAMETER); + set_root_path(NodePath()); + return OK; + } + MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object()); + MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); + if (spawner) { + return replicator->on_despawn(p_obj, p_config); + } + if (sync) { + return replicator->on_replication_stop(p_obj, p_config); + } + return ERR_INVALID_PARAMETER; +} + +void SceneMultiplayer::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_root_path", "path"), &SceneMultiplayer::set_root_path); + ClassDB::bind_method(D_METHOD("get_root_path"), &SceneMultiplayer::get_root_path); + ClassDB::bind_method(D_METHOD("clear"), &SceneMultiplayer::clear); + ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &SceneMultiplayer::set_refuse_new_connections); + ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &SceneMultiplayer::is_refusing_new_connections); + ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &SceneMultiplayer::set_allow_object_decoding); + ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &SceneMultiplayer::is_object_decoding_allowed); + ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &SceneMultiplayer::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections"); + ADD_PROPERTY_DEFAULT("refuse_new_connections", false); + + ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet"))); +} + +SceneMultiplayer::SceneMultiplayer() { + replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this))); + rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this))); + cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this))); +} + +SceneMultiplayer::~SceneMultiplayer() { + clear(); +} diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h new file mode 100644 index 0000000000..a99cca7b21 --- /dev/null +++ b/modules/multiplayer/scene_multiplayer.h @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* scene_multiplayer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 SCENE_MULTIPLAYER_H +#define SCENE_MULTIPLAYER_H + +#include "scene/main/multiplayer_api.h" + +#include "scene_cache_interface.h" +#include "scene_replication_interface.h" +#include "scene_rpc_interface.h" + +class SceneMultiplayer : public MultiplayerAPI { + GDCLASS(SceneMultiplayer, MultiplayerAPI); + +public: + enum NetworkCommands { + NETWORK_COMMAND_REMOTE_CALL = 0, + NETWORK_COMMAND_SIMPLIFY_PATH, + NETWORK_COMMAND_CONFIRM_PATH, + NETWORK_COMMAND_RAW, + NETWORK_COMMAND_SPAWN, + NETWORK_COMMAND_DESPAWN, + NETWORK_COMMAND_SYNC, + }; + + // For each command, the 4 MSB can contain custom flags, as defined by subsystems. + enum { + CMD_FLAG_0_SHIFT = 4, + CMD_FLAG_1_SHIFT = 5, + CMD_FLAG_2_SHIFT = 6, + CMD_FLAG_3_SHIFT = 7, + }; + + // This is the mask that will be used to extract the command. + enum { + CMD_MASK = 7, // 0x7 -> 0b00001111 + }; + +private: + Ref<MultiplayerPeer> multiplayer_peer; + HashSet<int> connected_peers; + int remote_sender_id = 0; + int remote_sender_override = 0; + + Vector<uint8_t> packet_cache; + + NodePath root_path; + bool allow_object_decoding = false; + + Ref<SceneCacheInterface> cache; + Ref<SceneReplicationInterface> replicator; + Ref<SceneRPCInterface> rpc; + +protected: + static void _bind_methods(); + + void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len); + void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len); + + void _add_peer(int p_id); + void _del_peer(int p_id); + void _connected_to_server(); + void _connection_failed(); + void _server_disconnected(); + +public: + virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override; + virtual Ref<MultiplayerPeer> get_multiplayer_peer() override; + + virtual Error poll() override; + virtual int get_unique_id() override; + virtual Vector<int> get_peer_ids() override; + virtual int get_remote_sender_id() override { return remote_sender_override ? remote_sender_override : remote_sender_id; } + + virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override; + + virtual Error object_configuration_add(Object *p_obj, Variant p_config) override; + virtual Error object_configuration_remove(Object *p_obj, Variant p_config) override; + + void clear(); + + // Usually from object_configuration_add/remove + void set_root_path(const NodePath &p_path); + NodePath get_root_path() const; + + Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE, int p_channel = 0); + String get_rpc_md5(const Object *p_obj); + + const HashSet<int> get_connected_peers() const { return connected_peers; } + + void set_remote_sender_override(int p_id) { remote_sender_override = p_id; } + void set_refuse_new_connections(bool p_refuse); + bool is_refusing_new_connections() const; + + void set_allow_object_decoding(bool p_enable); + bool is_object_decoding_allowed() const; + + Ref<SceneCacheInterface> get_path_cache() { return cache; } + +#ifdef DEBUG_ENABLED + void profile_bandwidth(const String &p_inout, int p_size); +#endif + + SceneMultiplayer(); + ~SceneMultiplayer(); +}; + +#endif // SCENE_MULTIPLAYER_H diff --git a/scene/resources/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp index 6789f9f7d5..ae06516b7b 100644 --- a/scene/resources/scene_replication_config.cpp +++ b/modules/multiplayer/scene_replication_config.cpp @@ -30,7 +30,7 @@ #include "scene_replication_config.h" -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" #include "scene/main/node.h" bool SceneReplicationConfig::_set(const StringName &p_name, const Variant &p_value) { diff --git a/scene/resources/scene_replication_config.h b/modules/multiplayer/scene_replication_config.h index ab3658d2a7..ab3658d2a7 100644 --- a/scene/resources/scene_replication_config.h +++ b/modules/multiplayer/scene_replication_config.h diff --git a/scene/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp index e4715ceb88..6e3dbfab47 100644 --- a/scene/multiplayer/scene_replication_interface.cpp +++ b/modules/multiplayer/scene_replication_interface.cpp @@ -32,21 +32,15 @@ #include "core/io/marshalls.h" #include "scene/main/node.h" -#include "scene/multiplayer/multiplayer_spawner.h" -#include "scene/multiplayer/multiplayer_synchronizer.h" + +#include "multiplayer_spawner.h" +#include "multiplayer_synchronizer.h" +#include "scene_multiplayer.h" #define MAKE_ROOM(m_amount) \ if (packet_cache.size() < m_amount) \ packet_cache.resize(m_amount); -MultiplayerReplicationInterface *SceneReplicationInterface::_create(MultiplayerAPI *p_multiplayer) { - return memnew(SceneReplicationInterface(p_multiplayer)); -} - -void SceneReplicationInterface::make_default() { - MultiplayerAPI::create_default_replication_interface = _create; -} - void SceneReplicationInterface::_free_remotes(int p_id) { const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id); for (const KeyValue<uint32_t, ObjectID> &E : remotes) { @@ -60,14 +54,13 @@ void SceneReplicationInterface::on_peer_change(int p_id, bool p_connected) { if (p_connected) { rep_state->on_peer_change(p_id, p_connected); for (const ObjectID &oid : rep_state->get_spawned_nodes()) { - _send_spawn(rep_state->get_node(oid), rep_state->get_spawner(oid), p_id); + _update_spawn_visibility(p_id, oid); } - for (const ObjectID &oid : rep_state->get_path_only_nodes()) { - Node *node = rep_state->get_node(oid); + for (const ObjectID &oid : rep_state->get_synced_nodes()) { MultiplayerSynchronizer *sync = rep_state->get_synchronizer(oid); - ERR_CONTINUE(!node || !sync); + ERR_CONTINUE(!sync); // ERR_BUG if (sync->is_multiplayer_authority()) { - rep_state->peer_add_node(p_id, oid); + _update_sync_visibility(p_id, oid); } } } else { @@ -97,7 +90,13 @@ Error SceneReplicationInterface::on_spawn(Object *p_obj, Variant p_config) { ERR_FAIL_COND_V(!spawner, ERR_INVALID_PARAMETER); Error err = rep_state->config_add_spawn(node, spawner); ERR_FAIL_COND_V(err != OK, err); - return _send_spawn(node, spawner, 0); + const ObjectID oid = node->get_instance_id(); + if (multiplayer->has_multiplayer_peer() && spawner->is_multiplayer_authority()) { + rep_state->ensure_net_id(oid); + _update_spawn_visibility(0, oid); + } + ERR_FAIL_COND_V(err != OK, err); + return OK; } Error SceneReplicationInterface::on_despawn(Object *p_obj, Variant p_config) { @@ -105,9 +104,19 @@ Error SceneReplicationInterface::on_despawn(Object *p_obj, Variant p_config) { ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object()); ERR_FAIL_COND_V(!p_obj || !spawner, ERR_INVALID_PARAMETER); - Error err = rep_state->config_del_spawn(node, spawner); - ERR_FAIL_COND_V(err != OK, err); - return _send_despawn(node, 0); + // Forcibly despawn to all peers that knowns me. + int len = 0; + Error err = _make_despawn_packet(node, len); + ERR_FAIL_COND_V(err != OK, ERR_BUG); + const ObjectID oid = p_obj->get_instance_id(); + for (int pid : rep_state->get_peers()) { + if (!rep_state->is_peer_spawn(pid, oid)) { + continue; + } + _send_raw(packet_cache.ptr(), len, pid, true); + } + // Also remove spawner tracking from the replication state. + return rep_state->config_del_spawn(node, spawner); } Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_config) { @@ -115,7 +124,15 @@ Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_c ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER); + + // Add to synchronizer list and setup visibility. rep_state->config_add_sync(node, sync); + const ObjectID oid = node->get_instance_id(); + sync->connect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed).bind(oid)); + if (multiplayer->has_multiplayer_peer() && sync->is_multiplayer_authority()) { + _update_sync_visibility(0, oid); + } + // Try to apply initial state if spawning (hack to apply if before ready). if (pending_spawn == p_obj->get_instance_id()) { pending_spawn = ObjectID(); // Make sure this only happens once. @@ -127,9 +144,6 @@ Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_c ERR_FAIL_COND_V(err, err); err = MultiplayerSynchronizer::set_state(props, node, vars); ERR_FAIL_COND_V(err, err); - } else if (multiplayer->has_multiplayer_peer() && sync->is_multiplayer_authority()) { - // Either it's a spawn or a static sync, in any case add it to the list of known nodes. - rep_state->peer_add_node(0, p_obj->get_instance_id()); } return OK; } @@ -138,10 +152,103 @@ Error SceneReplicationInterface::on_replication_stop(Object *p_obj, Variant p_co Node *node = Object::cast_to<Node>(p_obj); ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); - ERR_FAIL_COND_V(!p_obj || !sync, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER); + sync->disconnect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed)); return rep_state->config_del_sync(node, sync); } +void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_oid) { + if (rep_state->is_spawned_node(p_oid)) { + _update_spawn_visibility(p_peer, p_oid); + } + if (rep_state->is_synced_node(p_oid)) { + _update_sync_visibility(p_peer, p_oid); + } +} + +Error SceneReplicationInterface::_update_sync_visibility(int p_peer, const ObjectID &p_oid) { + MultiplayerSynchronizer *sync = rep_state->get_synchronizer(p_oid); + ERR_FAIL_COND_V(!sync || !sync->is_multiplayer_authority(), ERR_BUG); + bool is_visible = sync->is_visible_to(p_peer); + if (p_peer == 0) { + for (int pid : rep_state->get_peers()) { + // Might be visible to this specific peer. + is_visible = is_visible || sync->is_visible_to(pid); + if (rep_state->is_peer_sync(pid, p_oid) == is_visible) { + continue; + } + if (is_visible) { + rep_state->peer_add_sync(pid, p_oid); + } else { + rep_state->peer_del_sync(pid, p_oid); + } + } + return OK; + } else { + if (is_visible == rep_state->is_peer_sync(p_peer, p_oid)) { + return OK; + } + if (is_visible) { + return rep_state->peer_add_sync(p_peer, p_oid); + } else { + return rep_state->peer_del_sync(p_peer, p_oid); + } + } +} + +Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const ObjectID &p_oid) { + MultiplayerSpawner *spawner = rep_state->get_spawner(p_oid); + MultiplayerSynchronizer *sync = rep_state->get_synchronizer(p_oid); + Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_oid)); + ERR_FAIL_COND_V(!node || !spawner || !spawner->is_multiplayer_authority(), ERR_BUG); + bool is_visible = !sync || sync->is_visible_to(p_peer); + // Spawn (and despawn) when needed. + HashSet<int> to_spawn; + HashSet<int> to_despawn; + if (p_peer) { + if (is_visible == rep_state->is_peer_spawn(p_peer, p_oid)) { + return OK; + } + if (is_visible) { + to_spawn.insert(p_peer); + } else { + to_despawn.insert(p_peer); + } + } else { + // Check visibility for each peers. + for (int pid : rep_state->get_peers()) { + bool peer_visible = is_visible || sync->is_visible_to(pid); + if (peer_visible == rep_state->is_peer_spawn(pid, p_oid)) { + continue; + } + if (peer_visible) { + to_spawn.insert(pid); + } else { + to_despawn.insert(pid); + } + } + } + if (to_spawn.size()) { + int len = 0; + _make_spawn_packet(node, len); + for (int pid : to_spawn) { + int path_id; + multiplayer->get_path_cache()->send_object_cache(spawner, pid, path_id); + _send_raw(packet_cache.ptr(), len, pid, true); + rep_state->peer_add_spawn(pid, p_oid); + } + } + if (to_despawn.size()) { + int len = 0; + _make_despawn_packet(node, len); + for (int pid : to_despawn) { + rep_state->peer_del_spawn(pid, p_oid); + _send_raw(packet_cache.ptr(), len, pid, true); + } + } + return OK; +} + Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable) { ERR_FAIL_COND_V(!p_buffer || p_size < 1, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!multiplayer, ERR_UNCONFIGURED); @@ -154,22 +261,24 @@ Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer(); peer->set_target_peer(p_peer); peer->set_transfer_channel(0); - peer->set_transfer_mode(p_reliable ? Multiplayer::TRANSFER_MODE_RELIABLE : Multiplayer::TRANSFER_MODE_UNRELIABLE); + peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE); return peer->put_packet(p_buffer, p_size); } -Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p_spawner, int p_peer) { - ERR_FAIL_COND_V(p_peer < 0, ERR_BUG); +Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, int &r_len) { ERR_FAIL_COND_V(!multiplayer, ERR_BUG); - ERR_FAIL_COND_V(!p_spawner || !p_node, ERR_BUG); const ObjectID oid = p_node->get_instance_id(); - uint32_t nid = rep_state->ensure_net_id(oid); + MultiplayerSpawner *spawner = rep_state->get_spawner(oid); + ERR_FAIL_COND_V(!spawner || !p_node, ERR_BUG); + + uint32_t nid = rep_state->get_net_id(oid); + ERR_FAIL_COND_V(!nid, ERR_UNCONFIGURED); // Prepare custom arg and scene_id - uint8_t scene_id = p_spawner->find_spawnable_scene_index_from_object(oid); + uint8_t scene_id = spawner->find_spawnable_scene_index_from_object(oid); bool is_custom = scene_id == MultiplayerSpawner::INVALID_ID; - Variant spawn_arg = p_spawner->get_spawn_argument(oid); + Variant spawn_arg = spawner->get_spawn_argument(oid); int spawn_arg_size = 0; if (is_custom) { Error err = MultiplayerAPI::encode_and_compress_variant(spawn_arg, nullptr, spawn_arg_size, false); @@ -181,7 +290,8 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p Vector<Variant> state_vars; Vector<const Variant *> state_varp; MultiplayerSynchronizer *synchronizer = rep_state->get_synchronizer(oid); - if (synchronizer && synchronizer->get_replication_config().is_valid()) { + if (synchronizer) { + ERR_FAIL_COND_V(synchronizer->get_replication_config().is_null(), ERR_BUG); const List<NodePath> props = synchronizer->get_replication_config()->get_spawn_properties(); Error err = MultiplayerSynchronizer::get_state(props, p_node, state_vars, state_varp); ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to retrieve spawn state."); @@ -189,18 +299,13 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to encode spawn state."); } - // Prepare simplified path. - NodePath rel_path = multiplayer->get_root_path().rel_path_to(p_spawner->get_path()); - - int path_id = 0; - multiplayer->send_object_cache(p_spawner, rel_path, p_peer, path_id); - - // Encode name and parent ID. + // Encode scene ID, path ID, net ID, node name. + int path_id = multiplayer->get_path_cache()->make_object_cache(spawner); CharString cname = p_node->get_name().operator String().utf8(); int nlen = encode_cstring(cname.get_data(), nullptr); MAKE_ROOM(1 + 1 + 4 + 4 + 4 + nlen + (is_custom ? 4 + spawn_arg_size : 0) + state_size); uint8_t *ptr = packet_cache.ptrw(); - ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_SPAWN; + ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_SPAWN; ptr[1] = scene_id; int ofs = 2; ofs += encode_uint32(path_id, &ptr[ofs]); @@ -220,22 +325,20 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p ERR_FAIL_COND_V(err, err); ofs += state_size; } - Error err = _send_raw(ptr, ofs, p_peer, true); - ERR_FAIL_COND_V(err, err); - return rep_state->peer_add_node(p_peer, oid); + r_len = ofs; + return OK; } -Error SceneReplicationInterface::_send_despawn(Node *p_node, int p_peer) { +Error SceneReplicationInterface::_make_despawn_packet(Node *p_node, int &r_len) { const ObjectID oid = p_node->get_instance_id(); MAKE_ROOM(5); uint8_t *ptr = packet_cache.ptrw(); - ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_DESPAWN; + ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_DESPAWN; int ofs = 1; uint32_t nid = rep_state->get_net_id(oid); ofs += encode_uint32(nid, &ptr[ofs]); - Error err = _send_raw(ptr, ofs, p_peer, true); - ERR_FAIL_COND_V(err, err); - return rep_state->peer_del_node(p_peer, oid); + r_len = ofs; + return OK; } Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { @@ -245,7 +348,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b ofs += 1; uint32_t node_target = decode_uint32(&p_buffer[ofs]); ofs += 4; - MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_cached_object(p_from, node_target)); + MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_path_cache()->get_cached_object(p_from, node_target)); ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST); ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED); @@ -293,6 +396,8 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b pending_buffer_size = state_len; } parent->add_child(node); + spawner->emit_signal(SNAME("spawned"), node); + pending_spawn = ObjectID(); pending_buffer = nullptr; pending_buffer_size = 0; @@ -308,33 +413,55 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p Error err = rep_state->peer_del_remote(p_from, net_id, &node); ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(!node, ERR_BUG); + + MultiplayerSpawner *spawner = rep_state->get_spawner(node->get_instance_id()); + ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST); + ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED); + if (node->get_parent() != nullptr) { node->get_parent()->remove_child(node); } node->queue_delete(); + spawner->emit_signal(SNAME("despawned"), node); + return OK; } void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) { - const HashSet<ObjectID> &known = rep_state->get_known_nodes(p_peer); - if (known.is_empty()) { + const HashSet<ObjectID> &to_sync = rep_state->get_peer_sync_nodes(p_peer); + if (to_sync.is_empty()) { return; } MAKE_ROOM(sync_mtu); uint8_t *ptr = packet_cache.ptrw(); - ptr[0] = MultiplayerAPI::NETWORK_COMMAND_SYNC; + ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC; int ofs = 1; ofs += encode_uint16(rep_state->peer_sync_next(p_peer), &ptr[1]); // Can only send updates for already notified nodes. // This is a lazy implementation, we could optimize much more here with by grouping by replication config. - for (const ObjectID &oid : known) { + for (const ObjectID &oid : to_sync) { if (!rep_state->update_sync_time(oid, p_msec)) { continue; // nothing to sync. } MultiplayerSynchronizer *sync = rep_state->get_synchronizer(oid); - ERR_CONTINUE(!sync); + ERR_CONTINUE(!sync || !sync->get_replication_config().is_valid()); Node *node = rep_state->get_node(oid); ERR_CONTINUE(!node); + uint32_t net_id = rep_state->get_net_id(oid); + if (net_id == 0 || (net_id & 0x80000000)) { + int path_id = 0; + bool verified = multiplayer->get_path_cache()->send_object_cache(sync, p_peer, path_id); + ERR_CONTINUE_MSG(path_id < 0, "This should never happen!"); + if (net_id == 0) { + // First time path based ID. + net_id = path_id | 0x80000000; + rep_state->set_net_id(oid, net_id | 0x80000000); + } + if (!verified) { + // The path based sync is not yet confirmed, skipping. + continue; + } + } int size; Vector<Variant> vars; Vector<const Variant *> varp; @@ -351,16 +478,6 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) { ofs = 3; } if (size) { - uint32_t net_id = rep_state->get_net_id(oid); - if (net_id == 0 || (net_id & 0x80000000)) { - // First time path based ID. - NodePath rel_path = multiplayer->get_root_path().rel_path_to(sync->get_path()); - int path_id = 0; - multiplayer->send_object_cache(sync, rel_path, p_peer, path_id); - ERR_CONTINUE_MSG(net_id && net_id != (uint32_t(path_id) | 0x80000000), "This should never happen!"); - net_id = path_id; - rep_state->set_net_id(oid, net_id | 0x80000000); - } ofs += encode_uint32(rep_state->get_net_id(oid), &ptr[ofs]); ofs += encode_uint32(size, &ptr[ofs]); MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), &ptr[ofs], size); @@ -385,7 +502,7 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu ofs += 4; Node *node = nullptr; if (net_id & 0x80000000) { - MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_cached_object(p_from, net_id & 0x7FFFFFFF)); + MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_path_cache()->get_cached_object(p_from, net_id & 0x7FFFFFFF)); ERR_FAIL_COND_V(!sync || sync->get_multiplayer_authority() != p_from, ERR_UNAUTHORIZED); node = sync->get_node(sync->get_root_path()); } else { diff --git a/scene/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h index 60ac95c93c..8981647429 100644 --- a/scene/multiplayer/scene_replication_interface.h +++ b/modules/multiplayer/scene_replication_interface.h @@ -28,26 +28,31 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_TREE_REPLICATOR_INTERFACE_H -#define SCENE_TREE_REPLICATOR_INTERFACE_H +#ifndef SCENE_REPLICATION_INTERFACE_H +#define SCENE_REPLICATION_INTERFACE_H -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" -#include "scene/multiplayer/scene_replication_state.h" +#include "scene_replication_state.h" -class SceneReplicationInterface : public MultiplayerReplicationInterface { - GDCLASS(SceneReplicationInterface, MultiplayerReplicationInterface); +class SceneMultiplayer; + +class SceneReplicationInterface : public RefCounted { + GDCLASS(SceneReplicationInterface, RefCounted); private: void _send_sync(int p_peer, uint64_t p_msec); - Error _send_spawn(Node *p_node, MultiplayerSpawner *p_spawner, int p_peer); - Error _send_despawn(Node *p_node, int p_peer); + Error _make_spawn_packet(Node *p_node, int &r_len); + Error _make_despawn_packet(Node *p_node, int &r_len); Error _send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable); + void _visibility_changed(int p_peer, ObjectID p_oid); + Error _update_sync_visibility(int p_peer, const ObjectID &p_oid); + Error _update_spawn_visibility(int p_peer, const ObjectID &p_oid); void _free_remotes(int p_peer); Ref<SceneReplicationState> rep_state; - MultiplayerAPI *multiplayer = nullptr; + SceneMultiplayer *multiplayer = nullptr; PackedByteArray packet_cache; int sync_mtu = 1350; // Highly dependent on underlying protocol. @@ -56,29 +61,26 @@ private: const uint8_t *pending_buffer = nullptr; int pending_buffer_size = 0; -protected: - static MultiplayerReplicationInterface *_create(MultiplayerAPI *p_multiplayer); - public: static void make_default(); - virtual void on_reset() override; - virtual void on_peer_change(int p_id, bool p_connected) override; + void on_reset(); + void on_peer_change(int p_id, bool p_connected); - virtual Error on_spawn(Object *p_obj, Variant p_config) override; - virtual Error on_despawn(Object *p_obj, Variant p_config) override; - virtual Error on_replication_start(Object *p_obj, Variant p_config) override; - virtual Error on_replication_stop(Object *p_obj, Variant p_config) override; - virtual void on_network_process() override; + Error on_spawn(Object *p_obj, Variant p_config); + Error on_despawn(Object *p_obj, Variant p_config); + Error on_replication_start(Object *p_obj, Variant p_config); + Error on_replication_stop(Object *p_obj, Variant p_config); + void on_network_process(); - virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override; - virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override; - virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override; + Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len); + Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len); + Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len); - SceneReplicationInterface(MultiplayerAPI *p_multiplayer) { + SceneReplicationInterface(SceneMultiplayer *p_multiplayer) { rep_state.instantiate(); multiplayer = p_multiplayer; } }; -#endif // SCENE_TREE_REPLICATOR_INTERFACE_H +#endif // SCENE_REPLICATION_INTERFACE_H diff --git a/scene/multiplayer/scene_replication_state.cpp b/modules/multiplayer/scene_replication_state.cpp index 937b30cb36..25442bb7fa 100644 --- a/scene/multiplayer/scene_replication_state.cpp +++ b/modules/multiplayer/scene_replication_state.cpp @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/multiplayer/scene_replication_state.h" +#include "scene_replication_state.h" -#include "core/multiplayer/multiplayer_api.h" -#include "scene/multiplayer/multiplayer_spawner.h" -#include "scene/multiplayer/multiplayer_synchronizer.h" #include "scene/scene_string_names.h" +#include "multiplayer_spawner.h" +#include "multiplayer_synchronizer.h" + SceneReplicationState::TrackedNode &SceneReplicationState::_track(const ObjectID &p_id) { if (!tracked_nodes.has(p_id)) { tracked_nodes[p_id] = TrackedNode(p_id); Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id)); - node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack), varray(p_id), Node::CONNECT_ONESHOT); + node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack).bind(p_id), Node::CONNECT_ONESHOT); } return tracked_nodes[p_id]; } @@ -56,7 +56,8 @@ void SceneReplicationState::_untrack(const ObjectID &p_id) { // If we spawned or synced it, we need to remove it from any peer it was sent to. if (net_id || peer == 0) { for (KeyValue<int, PeerInfo> &E : peers_info) { - E.value.known_nodes.erase(p_id); + E.value.sync_nodes.erase(p_id); + E.value.spawn_nodes.erase(p_id); } } } @@ -93,11 +94,6 @@ bool SceneReplicationState::update_sync_time(const ObjectID &p_id, uint64_t p_ms return false; } -const HashSet<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) { - ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>()); - return peers_info[p_peer].known_nodes; -} - uint32_t SceneReplicationState::get_net_id(const ObjectID &p_id) const { const TrackedNode *tnode = tracked_nodes.getptr(p_id); ERR_FAIL_COND_V(!tnode, 0); @@ -147,8 +143,6 @@ Error SceneReplicationState::config_add_spawn(Node *p_node, MultiplayerSpawner * ERR_FAIL_COND_V(tobj.spawner != ObjectID(), ERR_ALREADY_IN_USE); tobj.spawner = p_spawner->get_instance_id(); spawned_nodes.insert(oid); - // The spawner may be notified after the synchronizer. - path_only_nodes.erase(oid); return OK; } @@ -159,6 +153,9 @@ Error SceneReplicationState::config_del_spawn(Node *p_node, MultiplayerSpawner * ERR_FAIL_COND_V(tobj.spawner != p_spawner->get_instance_id(), ERR_INVALID_PARAMETER); tobj.spawner = ObjectID(); spawned_nodes.erase(oid); + for (KeyValue<int, PeerInfo> &E : peers_info) { + E.value.spawn_nodes.erase(oid); + } return OK; } @@ -167,10 +164,7 @@ Error SceneReplicationState::config_add_sync(Node *p_node, MultiplayerSynchroniz TrackedNode &tobj = _track(oid); ERR_FAIL_COND_V(tobj.synchronizer != ObjectID(), ERR_ALREADY_IN_USE); tobj.synchronizer = p_sync->get_instance_id(); - // If it doesn't have a spawner, we might need to assign ID for this node using it's path. - if (tobj.spawner.is_null()) { - path_only_nodes.insert(oid); - } + synced_nodes.insert(oid); return OK; } @@ -180,38 +174,57 @@ Error SceneReplicationState::config_del_sync(Node *p_node, MultiplayerSynchroniz TrackedNode &tobj = _track(oid); ERR_FAIL_COND_V(tobj.synchronizer != p_sync->get_instance_id(), ERR_INVALID_PARAMETER); tobj.synchronizer = ObjectID(); - if (path_only_nodes.has(oid)) { - p_node->disconnect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack)); - _untrack(oid); - path_only_nodes.erase(oid); + synced_nodes.erase(oid); + for (KeyValue<int, PeerInfo> &E : peers_info) { + E.value.sync_nodes.erase(oid); } return OK; } -Error SceneReplicationState::peer_add_node(int p_peer, const ObjectID &p_id) { - if (p_peer) { - ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); - peers_info[p_peer].known_nodes.insert(p_id); - } else { - for (KeyValue<int, PeerInfo> &E : peers_info) { - E.value.known_nodes.insert(p_id); - } - } +Error SceneReplicationState::peer_add_sync(int p_peer, const ObjectID &p_id) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); + peers_info[p_peer].sync_nodes.insert(p_id); return OK; } -Error SceneReplicationState::peer_del_node(int p_peer, const ObjectID &p_id) { - if (p_peer) { - ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); - peers_info[p_peer].known_nodes.erase(p_id); - } else { - for (KeyValue<int, PeerInfo> &E : peers_info) { - E.value.known_nodes.erase(p_id); - } - } +Error SceneReplicationState::peer_del_sync(int p_peer, const ObjectID &p_id) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); + peers_info[p_peer].sync_nodes.erase(p_id); + return OK; +} + +const HashSet<ObjectID> SceneReplicationState::get_peer_sync_nodes(int p_peer) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>()); + return peers_info[p_peer].sync_nodes; +} + +bool SceneReplicationState::is_peer_sync(int p_peer, const ObjectID &p_id) const { + ERR_FAIL_COND_V(!peers_info.has(p_peer), false); + return peers_info[p_peer].sync_nodes.has(p_id); +} + +Error SceneReplicationState::peer_add_spawn(int p_peer, const ObjectID &p_id) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); + peers_info[p_peer].spawn_nodes.insert(p_id); + return OK; +} + +Error SceneReplicationState::peer_del_spawn(int p_peer, const ObjectID &p_id) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); + peers_info[p_peer].spawn_nodes.erase(p_id); return OK; } +const HashSet<ObjectID> SceneReplicationState::get_peer_spawn_nodes(int p_peer) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>()); + return peers_info[p_peer].spawn_nodes; +} + +bool SceneReplicationState::is_peer_spawn(int p_peer, const ObjectID &p_id) const { + ERR_FAIL_COND_V(!peers_info.has(p_peer), false); + return peers_info[p_peer].spawn_nodes.has(p_id); +} + Node *SceneReplicationState::peer_get_remote(int p_peer, uint32_t p_net_id) { PeerInfo *info = peers_info.getptr(p_peer); return info && info->recv_nodes.has(p_net_id) ? Object::cast_to<Node>(ObjectDB::get_instance(info->recv_nodes[p_net_id])) : nullptr; diff --git a/scene/multiplayer/scene_replication_state.h b/modules/multiplayer/scene_replication_state.h index 60a6c5d70c..bdff6ae3b7 100644 --- a/scene/multiplayer/scene_replication_state.h +++ b/modules/multiplayer/scene_replication_state.h @@ -28,11 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_REPLICATON_STATE_H -#define SCENE_REPLICATON_STATE_H +#ifndef SCENE_REPLICATION_STATE_H +#define SCENE_REPLICATION_STATE_H #include "core/object/ref_counted.h" +#include "multiplayer_spawner.h" +#include "multiplayer_synchronizer.h" + class MultiplayerSpawner; class MultiplayerSynchronizer; class Node; @@ -62,7 +65,8 @@ private: }; struct PeerInfo { - HashSet<ObjectID> known_nodes; + HashSet<ObjectID> sync_nodes; + HashSet<ObjectID> spawn_nodes; HashMap<uint32_t, ObjectID> recv_nodes; uint16_t last_sent_sync = 0; uint16_t last_recv_sync = 0; @@ -73,7 +77,7 @@ private: HashMap<ObjectID, TrackedNode> tracked_nodes; HashMap<int, PeerInfo> peers_info; HashSet<ObjectID> spawned_nodes; - HashSet<ObjectID> path_only_nodes; + HashSet<ObjectID> synced_nodes; TrackedNode &_track(const ObjectID &p_id); void _untrack(const ObjectID &p_id); @@ -82,7 +86,9 @@ private: public: const HashSet<int> get_peers() const { return known_peers; } const HashSet<ObjectID> &get_spawned_nodes() const { return spawned_nodes; } - const HashSet<ObjectID> &get_path_only_nodes() const { return path_only_nodes; } + bool is_spawned_node(const ObjectID &p_id) const { return spawned_nodes.has(p_id); } + const HashSet<ObjectID> &get_synced_nodes() const { return synced_nodes; } + bool is_synced_node(const ObjectID &p_id) const { return synced_nodes.has(p_id); } MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; } MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; } @@ -90,7 +96,6 @@ public: bool update_last_node_sync(const ObjectID &p_id, uint16_t p_time); bool update_sync_time(const ObjectID &p_id, uint64_t p_msec); - const HashSet<ObjectID> get_known_nodes(int p_peer); uint32_t get_net_id(const ObjectID &p_id) const; void set_net_id(const ObjectID &p_id, uint32_t p_net_id); uint32_t ensure_net_id(const ObjectID &p_id); @@ -104,8 +109,17 @@ public: Error config_add_sync(Node *p_node, MultiplayerSynchronizer *p_sync); Error config_del_sync(Node *p_node, MultiplayerSynchronizer *p_sync); - Error peer_add_node(int p_peer, const ObjectID &p_id); - Error peer_del_node(int p_peer, const ObjectID &p_id); + Error peer_add_sync(int p_peer, const ObjectID &p_id); + Error peer_del_sync(int p_peer, const ObjectID &p_id); + + const HashSet<ObjectID> get_peer_sync_nodes(int p_peer); + bool is_peer_sync(int p_peer, const ObjectID &p_id) const; + + Error peer_add_spawn(int p_peer, const ObjectID &p_id); + Error peer_del_spawn(int p_peer, const ObjectID &p_id); + + const HashSet<ObjectID> get_peer_spawn_nodes(int p_peer); + bool is_peer_spawn(int p_peer, const ObjectID &p_id) const; const HashMap<uint32_t, ObjectID> peer_get_remotes(int p_peer) const; Node *peer_get_remote(int p_peer, uint32_t p_net_id); @@ -118,4 +132,4 @@ public: SceneReplicationState() {} }; -#endif // SCENE_REPLICATON_STATE_H +#endif // SCENE_REPLICATION_STATE_H diff --git a/scene/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp index 84700a82f3..65090b9316 100644 --- a/scene/multiplayer/scene_rpc_interface.cpp +++ b/modules/multiplayer/scene_rpc_interface.cpp @@ -28,21 +28,28 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/multiplayer/scene_rpc_interface.h" +#include "scene_rpc_interface.h" #include "core/debugger/engine_debugger.h" #include "core/io/marshalls.h" -#include "core/multiplayer/multiplayer_api.h" +#include "scene/main/multiplayer_api.h" #include "scene/main/node.h" #include "scene/main/window.h" -MultiplayerRPCInterface *SceneRPCInterface::_create(MultiplayerAPI *p_multiplayer) { - return memnew(SceneRPCInterface(p_multiplayer)); -} +#include "scene_multiplayer.h" -void SceneRPCInterface::make_default() { - MultiplayerAPI::create_default_rpc_interface = _create; -} +// The RPC meta is composed by a single byte that contains (starting from the least significant bit): +// - `NetworkCommands` in the first four bits. +// - `NetworkNodeIdCompression` in the next 2 bits. +// - `NetworkNameIdCompression` in the next 1 bit. +// - `byte_only_or_no_args` in the next 1 bit. +#define NODE_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_0_SHIFT +#define NAME_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_2_SHIFT +#define BYTE_ONLY_OR_NO_ARGS_SHIFT SceneMultiplayer::CMD_FLAG_3_SHIFT + +#define NODE_ID_COMPRESSION_FLAG ((1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1))) +#define NAME_ID_COMPRESSION_FLAG (1 << NAME_ID_COMPRESSION_SHIFT) +#define BYTE_ONLY_OR_NO_ARGS_FLAG (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT) #ifdef DEBUG_ENABLED _FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) { @@ -67,50 +74,58 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) { } } -const Multiplayer::RPCConfig _get_rpc_config(const Node *p_node, const StringName &p_method, uint16_t &r_id) { - const Vector<Multiplayer::RPCConfig> node_config = p_node->get_node_rpc_methods(); - for (int i = 0; i < node_config.size(); i++) { - if (node_config[i].name == p_method) { - r_id = ((uint16_t)i) | (1 << 15); - return node_config[i]; - } +void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache) { + if (p_config.get_type() == Variant::NIL) { + return; } - if (p_node->get_script_instance()) { - const Vector<Multiplayer::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods(); - for (int i = 0; i < script_config.size(); i++) { - if (script_config[i].name == p_method) { - r_id = (uint16_t)i; - return script_config[i]; - } + ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY); + const Dictionary config = p_config; + Array names = config.keys(); + names.sort(); // Ensure ID order + for (int i = 0; i < names.size(); i++) { + ERR_CONTINUE(names[i].get_type() != Variant::STRING); + String name = names[i].operator String(); + ERR_CONTINUE(config[name].get_type() != Variant::DICTIONARY); + ERR_CONTINUE(!config[name].operator Dictionary().has("rpc_mode")); + Dictionary dict = config[name]; + RPCConfig cfg; + cfg.name = name; + cfg.rpc_mode = ((MultiplayerAPI::RPCMode)dict.get("rpc_mode", MultiplayerAPI::RPC_MODE_AUTHORITY).operator int()); + cfg.transfer_mode = ((MultiplayerPeer::TransferMode)dict.get("transfer_mode", MultiplayerPeer::TRANSFER_MODE_RELIABLE).operator int()); + cfg.call_local = dict.get("call_local", false).operator bool(); + cfg.channel = dict.get("channel", 0).operator int(); + uint16_t id = ((uint16_t)i); + if (p_for_node) { + id |= (1 << 15); } + r_cache.configs[id] = cfg; + r_cache.ids[name] = id; } - return Multiplayer::RPCConfig(); } -const Multiplayer::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_id) { - Vector<Multiplayer::RPCConfig> config; - uint16_t id = p_id; - if (id & (1 << 15)) { - id = id & ~(1 << 15); - config = p_node->get_node_rpc_methods(); - } else if (p_node->get_script_instance()) { - config = p_node->get_script_instance()->get_rpc_methods(); +const SceneRPCInterface::RPCConfigCache &SceneRPCInterface::_get_node_config(const Node *p_node) { + const ObjectID oid = p_node->get_instance_id(); + if (rpc_cache.has(oid)) { + return rpc_cache[oid]; } - if (id < config.size()) { - return config[id]; + RPCConfigCache cache; + _parse_rpc_config(p_node->get_node_rpc_config(), true, cache); + if (p_node->get_script_instance()) { + _parse_rpc_config(p_node->get_script_instance()->get_rpc_config(), false, cache); } - return Multiplayer::RPCConfig(); + rpc_cache[oid] = cache; + return rpc_cache[oid]; } -_FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int p_remote_id) { +_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) { switch (mode) { - case Multiplayer::RPC_MODE_DISABLED: { + case MultiplayerAPI::RPC_MODE_DISABLED: { return false; } break; - case Multiplayer::RPC_MODE_ANY_PEER: { + case MultiplayerAPI::RPC_MODE_ANY_PEER: { return true; } break; - case Multiplayer::RPC_MODE_AUTHORITY: { + case MultiplayerAPI::RPC_MODE_AUTHORITY: { return !p_node->is_multiplayer_authority() && p_remote_id == p_node->get_multiplayer_authority(); } break; } @@ -118,19 +133,13 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int return false; } -String SceneRPCInterface::get_rpc_md5(const Object *p_obj) const { +String SceneRPCInterface::get_rpc_md5(const Object *p_obj) { const Node *node = Object::cast_to<Node>(p_obj); ERR_FAIL_COND_V(!node, ""); + const RPCConfigCache cache = _get_node_config(node); String rpc_list; - const Vector<Multiplayer::RPCConfig> node_config = node->get_node_rpc_methods(); - for (int i = 0; i < node_config.size(); i++) { - rpc_list += String(node_config[i].name); - } - if (node->get_script_instance()) { - const Vector<Multiplayer::RPCConfig> script_config = node->get_script_instance()->get_rpc_methods(); - for (int i = 0; i < script_config.size(); i++) { - rpc_list += String(script_config[i].name); - } + for (const KeyValue<uint16_t, RPCConfig> &config : cache.configs) { + rpc_list += String(config.value.name); } return rpc_list.md5_text(); } @@ -159,7 +168,7 @@ Node *SceneRPCInterface::_process_get_node(int p_from, const uint8_t *p_packet, return node; } else { // Use cached path. - return Object::cast_to<Node>(multiplayer->get_cached_object(p_from, p_node_target)); + return Object::cast_to<Node>(multiplayer->get_path_cache()->get_cached_object(p_from, p_node_target)); } } @@ -240,8 +249,9 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. - const Multiplayer::RPCConfig config = _get_rpc_config_by_id(p_node, p_rpc_method_id); - ERR_FAIL_COND(config.name == StringName()); + const RPCConfigCache &cache_config = _get_node_config(p_node); + ERR_FAIL_COND(!cache_config.configs.has(p_rpc_method_id)); + const RPCConfig &config = cache_config.configs[p_rpc_method_id]; bool can_call = _can_call_mode(p_node, config.rpc_mode, p_from); ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(config.name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)config.rpc_mode) + ", authority is " + itos(p_node->get_multiplayer_authority()) + "."); @@ -286,7 +296,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i } } -void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) { +void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) { Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer(); ERR_FAIL_COND_MSG(peer.is_null(), "Attempt to call RPC without active multiplayer peer."); @@ -297,17 +307,14 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments (>255)."); if (p_to != 0 && !multiplayer->get_connected_peers().has(ABS(p_to))) { - ERR_FAIL_COND_MSG(p_to == peer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(peer->get_unique_id()) + "."); + ERR_FAIL_COND_MSG(p_to == multiplayer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(multiplayer->get_unique_id()) + "."); ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + "."); } - NodePath from_path = multiplayer->get_root_path().rel_path_to(p_from->get_path()); - ERR_FAIL_COND_MSG(from_path.is_empty(), "Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!"); - // See if all peers have cached path (if so, call can be fast). int psc_id; - const bool has_all_peers = multiplayer->send_object_cache(p_from, from_path, p_to, psc_id); + const bool has_all_peers = multiplayer->get_path_cache()->send_object_cache(p_from, p_to, psc_id); // Create base packet, lots of hardcode because it must be tight. @@ -318,7 +325,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con packet_cache.resize(m_amount); // Encode meta. - uint8_t command_type = MultiplayerAPI::NETWORK_COMMAND_REMOTE_CALL; + uint8_t command_type = SceneMultiplayer::NETWORK_COMMAND_REMOTE_CALL; uint8_t node_id_compression = UINT8_MAX; uint8_t name_id_compression = UINT8_MAX; bool byte_only_or_no_args = false; @@ -414,6 +421,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con // Not all verified path, so send one by one. // Append path at the end, since we will need it for some packets. + NodePath from_path = multiplayer->get_root_path().rel_path_to(p_from->get_path()); CharString pname = String(from_path).utf8(); int path_len = encode_cstring(pname.get_data(), nullptr); MAKE_ROOM(ofs + path_len); @@ -428,7 +436,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con continue; // Continue, not for this peer. } - bool confirmed = multiplayer->is_cache_confirmed(from_path, P); + bool confirmed = multiplayer->get_path_cache()->is_cache_confirmed(from_path, P); peer->set_target_peer(P); // To this one specifically. @@ -445,22 +453,25 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con } } -void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { +Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer(); - ERR_FAIL_COND_MSG(!peer.is_valid(), "Trying to call an RPC while no multiplayer peer is active."); + ERR_FAIL_COND_V_MSG(!peer.is_valid(), ERR_UNCONFIGURED, "Trying to call an RPC while no multiplayer peer is active."); Node *node = Object::cast_to<Node>(p_obj); - ERR_FAIL_COND(!node); - ERR_FAIL_COND_MSG(!node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree."); - ERR_FAIL_COND_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a multiplayer peer which is not connected."); + ERR_FAIL_COND_V_MSG(!node || !node->is_inside_tree(), ERR_INVALID_PARAMETER, "The object must be a valid Node inside the SceneTree"); + ERR_FAIL_COND_V_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_CONNECTION_ERROR, "Trying to call an RPC via a multiplayer peer which is not connected."); - int node_id = peer->get_unique_id(); + int caller_id = multiplayer->get_unique_id(); bool call_local_native = false; bool call_local_script = false; - uint16_t rpc_id = UINT16_MAX; - const Multiplayer::RPCConfig config = _get_rpc_config(node, p_method, rpc_id); - ERR_FAIL_COND_MSG(config.name == StringName(), + const RPCConfigCache &config_cache = _get_node_config(node); + uint16_t rpc_id = config_cache.ids.has(p_method) ? config_cache.ids[p_method] : UINT16_MAX; + ERR_FAIL_COND_V_MSG(rpc_id == UINT16_MAX, ERR_INVALID_PARAMETER, vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is missing or not marked for RPCs in the local script.", p_method, node->get_path())); - if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { + const RPCConfig &config = config_cache.configs[rpc_id]; + + ERR_FAIL_COND_V_MSG(p_peer_id == caller_id && !config.call_local, ERR_INVALID_PARAMETER, "RPC '" + p_method + "' on yourself is not allowed by selected mode."); + + if (p_peer_id == 0 || p_peer_id == caller_id || (p_peer_id < 0 && p_peer_id != -caller_id)) { if (rpc_id & (1 << 15)) { call_local_native = config.call_local; } else { @@ -468,7 +479,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m } } - if (p_peer_id != node_id) { + if (p_peer_id != caller_id) { #ifdef DEBUG_ENABLED _profile_node_data("rpc_out", node->get_instance_id()); #endif @@ -479,7 +490,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m if (call_local_native) { Callable::CallError ce; - multiplayer->set_remote_sender_override(peer->get_unique_id()); + multiplayer->set_remote_sender_override(multiplayer->get_unique_id()); node->callp(p_method, p_arg, p_argcount, ce); multiplayer->set_remote_sender_override(0); @@ -487,7 +498,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in local call: - " + error + "."; ERR_PRINT(error); - return; + return FAILED; } } @@ -495,7 +506,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m Callable::CallError ce; ce.error = Callable::CallError::CALL_OK; - multiplayer->set_remote_sender_override(peer->get_unique_id()); + multiplayer->set_remote_sender_override(multiplayer->get_unique_id()); node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce); multiplayer->set_remote_sender_override(0); @@ -503,9 +514,8 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in script local call: - " + error + "."; ERR_PRINT(error); - return; + return FAILED; } } - - ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode."); + return OK; } diff --git a/scene/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h index 86e1d0d280..aa9be525a2 100644 --- a/scene/multiplayer/scene_rpc_interface.h +++ b/modules/multiplayer/scene_rpc_interface.h @@ -31,13 +31,40 @@ #ifndef SCENE_RPC_INTERFACE_H #define SCENE_RPC_INTERFACE_H -#include "core/multiplayer/multiplayer.h" -#include "core/multiplayer/multiplayer_api.h" +#include "core/object/ref_counted.h" +#include "scene/main/multiplayer_api.h" -class SceneRPCInterface : public MultiplayerRPCInterface { - GDCLASS(SceneRPCInterface, MultiplayerRPCInterface); +class SceneMultiplayer; +class Node; + +class SceneRPCInterface : public RefCounted { + GDCLASS(SceneRPCInterface, RefCounted); private: + struct RPCConfig { + StringName name; + MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; + bool call_local = false; + MultiplayerPeer::TransferMode transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE; + int channel = 0; + + bool operator==(RPCConfig const &p_other) const { + return name == p_other.name; + } + }; + + struct RPCConfigCache { + HashMap<uint16_t, RPCConfig> configs; + HashMap<StringName, uint16_t> ids; + }; + + struct SortRPCConfig { + StringName::AlphCompare compare; + bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const { + return compare(p_a.name, p_b.name); + } + }; + enum NetworkNodeIdCompression { NETWORK_NODE_ID_COMPRESSION_8 = 0, NETWORK_NODE_ID_COMPRESSION_16, @@ -49,43 +76,27 @@ private: NETWORK_NAME_ID_COMPRESSION_16, }; - // The RPC meta is composed by a single byte that contains (starting from the least significant bit): - // - `NetworkCommands` in the first four bits. - // - `NetworkNodeIdCompression` in the next 2 bits. - // - `NetworkNameIdCompression` in the next 1 bit. - // - `byte_only_or_no_args` in the next 1 bit. - enum { - NODE_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_0_SHIFT, // 2 bits for this. - NAME_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_2_SHIFT, - BYTE_ONLY_OR_NO_ARGS_SHIFT = MultiplayerAPI::CMD_FLAG_3_SHIFT, - }; - - enum { - NODE_ID_COMPRESSION_FLAG = (1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1)), // 2 bits for this. - NAME_ID_COMPRESSION_FLAG = (1 << NAME_ID_COMPRESSION_SHIFT), - BYTE_ONLY_OR_NO_ARGS_FLAG = (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT), - }; - - MultiplayerAPI *multiplayer = nullptr; + SceneMultiplayer *multiplayer = nullptr; Vector<uint8_t> packet_cache; -protected: - static MultiplayerRPCInterface *_create(MultiplayerAPI *p_multiplayer); + HashMap<ObjectID, RPCConfigCache> rpc_cache; +protected: _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id); void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); - void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount); + void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount); Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len); -public: - static void make_default(); + void _parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache); + const RPCConfigCache &_get_node_config(const Node *p_node); - virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override; - virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) override; - virtual String get_rpc_md5(const Object *p_obj) const override; +public: + Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); + void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len); + String get_rpc_md5(const Object *p_obj); - SceneRPCInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; } + SceneRPCInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; } }; #endif // SCENE_RPC_INTERFACE_H diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index bcbc721dbb..2cdb5b7cb4 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -249,8 +249,10 @@ Array GodotNavigationServer::map_get_regions(RID p_map) const { Array regions_rids; const NavMap *map = map_owner.get_or_null(p_map); ERR_FAIL_COND_V(map == nullptr, regions_rids); - for (NavRegion *region : map->get_regions()) { - regions_rids.push_back(region->get_self()); + const LocalVector<NavRegion *> regions = map->get_regions(); + regions_rids.resize(regions.size()); + for (uint32_t i = 0; i < regions.size(); i++) { + regions_rids[i] = regions[i]->get_self(); } return regions_rids; } @@ -259,8 +261,10 @@ Array GodotNavigationServer::map_get_agents(RID p_map) const { Array agents_rids; const NavMap *map = map_owner.get_or_null(p_map); ERR_FAIL_COND_V(map == nullptr, agents_rids); - for (RvoAgent *agent : map->get_agents()) { - agents_rids.push_back(agent->get_self()); + const LocalVector<RvoAgent *> agents = map->get_agents(); + agents_rids.resize(agents.size()); + for (uint32_t i = 0; i < agents.size(); i++) { + agents_rids[i] = agents[i]->get_self(); } return agents_rids; } @@ -539,15 +543,15 @@ COMMAND_1(free, RID, p_object) { NavMap *map = map_owner.get_or_null(p_object); // Removes any assigned region - std::vector<NavRegion *> regions = map->get_regions(); - for (size_t i(0); i < regions.size(); i++) { + LocalVector<NavRegion *> regions = map->get_regions(); + for (uint32_t i = 0; i < regions.size(); i++) { map->remove_region(regions[i]); regions[i]->set_map(nullptr); } // Remove any assigned agent - std::vector<RvoAgent *> agents = map->get_agents(); - for (size_t i(0); i < agents.size(); i++) { + LocalVector<RvoAgent *> agents = map->get_agents(); + for (uint32_t i = 0; i < agents.size(); i++) { map->remove_agent(agents[i]); agents[i]->set_map(nullptr); } diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 8e7e99888c..da1f8cba0b 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -69,7 +69,7 @@ class GodotNavigationServer : public NavigationServer3D { /// Mutex used to make any operation threadsafe. Mutex operations_mutex; - std::vector<SetCommand *> commands; + LocalVector<SetCommand *> commands; mutable RID_Owner<NavMap> map_owner; mutable RID_Owner<NavRegion> region_owner; diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 17d6e0a0a1..49029b5513 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -30,9 +30,9 @@ #include "nav_map.h" +#include "core/object/worker_thread_pool.h" #include "nav_region.h" #include "rvo_agent.h" - #include <algorithm> #define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a))) @@ -117,7 +117,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } // List of all reachable navigation polys. - std::vector<gd::NavigationPoly> navigation_polys; + LocalVector<gd::NavigationPoly> navigation_polys; navigation_polys.reserve(polygons.size() * 0.75); // Add the start polygon to the reachable navigation polygons. @@ -170,20 +170,18 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway); const float new_distance = (least_cost_poly->entry.distance_to(new_entry) * region_travel_cost) + region_enter_cost + least_cost_poly->traveled_distance; - const std::vector<gd::NavigationPoly>::iterator it = std::find( - navigation_polys.begin(), - navigation_polys.end(), - gd::NavigationPoly(connection.polygon)); + int64_t already_visited_polygon_index = navigation_polys.find(gd::NavigationPoly(connection.polygon)); - if (it != navigation_polys.end()) { + if (already_visited_polygon_index != -1) { // Polygon already visited, check if we can reduce the travel cost. - if (new_distance < it->traveled_distance) { - it->back_navigation_poly_id = least_cost_id; - it->back_navigation_edge = connection.edge; - it->back_navigation_edge_pathway_start = connection.pathway_start; - it->back_navigation_edge_pathway_end = connection.pathway_end; - it->traveled_distance = new_distance; - it->entry = new_entry; + gd::NavigationPoly &avp = navigation_polys[already_visited_polygon_index]; + if (new_distance < avp.traveled_distance) { + avp.back_navigation_poly_id = least_cost_id; + avp.back_navigation_edge = connection.edge; + avp.back_navigation_edge_pathway_start = connection.pathway_start; + avp.back_navigation_edge_pathway_end = connection.pathway_end; + avp.traveled_distance = new_distance; + avp.entry = new_entry; } } else { // Add the neighbour polygon to the reachable ones. @@ -470,15 +468,15 @@ void NavMap::add_region(NavRegion *p_region) { } void NavMap::remove_region(NavRegion *p_region) { - const std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region); - if (it != regions.end()) { - regions.erase(it); + int64_t region_index = regions.find(p_region); + if (region_index != -1) { + regions.remove_at_unordered(region_index); regenerate_links = true; } } bool NavMap::has_agent(RvoAgent *agent) const { - return std::find(agents.begin(), agents.end(), agent) != agents.end(); + return (agents.find(agent) != -1); } void NavMap::add_agent(RvoAgent *agent) { @@ -490,15 +488,15 @@ void NavMap::add_agent(RvoAgent *agent) { void NavMap::remove_agent(RvoAgent *agent) { remove_agent_as_controlled(agent); - const std::vector<RvoAgent *>::iterator it = std::find(agents.begin(), agents.end(), agent); - if (it != agents.end()) { - agents.erase(it); + int64_t agent_index = agents.find(agent); + if (agent_index != -1) { + agents.remove_at_unordered(agent_index); agents_dirty = true; } } void NavMap::set_agent_as_controlled(RvoAgent *agent) { - const bool exist = std::find(controlled_agents.begin(), controlled_agents.end(), agent) != controlled_agents.end(); + const bool exist = (controlled_agents.find(agent) != -1); if (!exist) { ERR_FAIL_COND(!has_agent(agent)); controlled_agents.push_back(agent); @@ -506,22 +504,23 @@ void NavMap::set_agent_as_controlled(RvoAgent *agent) { } void NavMap::remove_agent_as_controlled(RvoAgent *agent) { - const std::vector<RvoAgent *>::iterator it = std::find(controlled_agents.begin(), controlled_agents.end(), agent); - if (it != controlled_agents.end()) { - controlled_agents.erase(it); + int64_t active_avoidance_agent_index = controlled_agents.find(agent); + if (active_avoidance_agent_index != -1) { + controlled_agents.remove_at_unordered(active_avoidance_agent_index); + agents_dirty = true; } } void NavMap::sync() { // Check if we need to update the links. if (regenerate_polygons) { - for (size_t r(0); r < regions.size(); r++) { + for (uint32_t r = 0; r < regions.size(); r++) { regions[r]->scratch_polygons(); } regenerate_links = true; } - for (size_t r(0); r < regions.size(); r++) { + for (uint32_t r = 0; r < regions.size(); r++) { if (regions[r]->sync()) { regenerate_links = true; } @@ -529,33 +528,33 @@ void NavMap::sync() { if (regenerate_links) { // Remove regions connections. - for (size_t r(0); r < regions.size(); r++) { + for (uint32_t r = 0; r < regions.size(); r++) { regions[r]->get_connections().clear(); } // Resize the polygon count. int count = 0; - for (size_t r(0); r < regions.size(); r++) { + for (uint32_t r = 0; r < regions.size(); r++) { count += regions[r]->get_polygons().size(); } polygons.resize(count); // Copy all region polygons in the map. count = 0; - for (size_t r(0); r < regions.size(); r++) { - std::copy( - regions[r]->get_polygons().data(), - regions[r]->get_polygons().data() + regions[r]->get_polygons().size(), - polygons.begin() + count); + for (uint32_t r = 0; r < regions.size(); r++) { + const LocalVector<gd::Polygon> &polygons_source = regions[r]->get_polygons(); + for (uint32_t n = 0; n < polygons_source.size(); n++) { + polygons[count + n] = polygons_source[n]; + } count += regions[r]->get_polygons().size(); } // Group all edges per key. HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections; - for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) { + for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) { gd::Polygon &poly(polygons[poly_id]); - for (size_t p(0); p < poly.points.size(); p++) { + for (uint32_t p = 0; p < poly.points.size(); p++) { int next_point = (p + 1) % poly.points.size(); gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key); @@ -662,6 +661,7 @@ void NavMap::sync() { // Update agents tree. if (agents_dirty) { + // cannot use LocalVector here as RVO library expects std::vector to build KdTree std::vector<RVO::Agent *> raw_agents; raw_agents.reserve(agents.size()); for (size_t i(0); i < agents.size(); i++) { @@ -683,14 +683,8 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) { void NavMap::step(real_t p_deltatime) { deltatime = p_deltatime; if (controlled_agents.size() > 0) { - if (step_work_pool.get_thread_count() == 0) { - step_work_pool.init(); - } - step_work_pool.do_work( - controlled_agents.size(), - this, - &NavMap::compute_single_step, - controlled_agents.data()); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &NavMap::compute_single_step, controlled_agents.ptr(), controlled_agents.size(), -1, true, SNAME("NavigationMapAgents")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } } @@ -700,7 +694,7 @@ void NavMap::dispatch_callbacks() { } } -void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const { +void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const { Vector3 from = path[path.size() - 1]; if (from.is_equal_approx(p_to_point)) { @@ -736,5 +730,4 @@ NavMap::NavMap() { } NavMap::~NavMap() { - step_work_pool.finish(); } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 2036dbecd7..e50a1afbe9 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -34,8 +34,8 @@ #include "nav_rid.h" #include "core/math/math_defs.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/rb_map.h" -#include "core/templates/thread_work_pool.h" #include "nav_utils.h" #include <KdTree.h> @@ -58,10 +58,10 @@ class NavMap : public NavRid { bool regenerate_polygons = true; bool regenerate_links = true; - std::vector<NavRegion *> regions; + LocalVector<NavRegion *> regions; /// Map polygons - std::vector<gd::Polygon> polygons; + LocalVector<gd::Polygon> polygons; /// Rvo world RVO::KdTree rvo; @@ -70,10 +70,10 @@ class NavMap : public NavRid { bool agents_dirty = false; /// All the Agents (even the controlled one) - std::vector<RvoAgent *> agents; + LocalVector<RvoAgent *> agents; /// Controlled agents - std::vector<RvoAgent *> controlled_agents; + LocalVector<RvoAgent *> controlled_agents; /// Physics delta time real_t deltatime = 0.0; @@ -81,9 +81,6 @@ class NavMap : public NavRid { /// Change the id each time the map is updated. uint32_t map_update_id = 0; - /// Pooled threads for computing steps - ThreadWorkPool step_work_pool; - public: NavMap(); ~NavMap(); @@ -114,14 +111,14 @@ public: void add_region(NavRegion *p_region); void remove_region(NavRegion *p_region); - const std::vector<NavRegion *> &get_regions() const { + const LocalVector<NavRegion *> &get_regions() const { return regions; } bool has_agent(RvoAgent *agent) const; void add_agent(RvoAgent *agent); void remove_agent(RvoAgent *agent); - const std::vector<RvoAgent *> &get_agents() const { + const LocalVector<RvoAgent *> &get_agents() const { return agents; } @@ -138,7 +135,7 @@ public: private: void compute_single_step(uint32_t index, RvoAgent **agent); - void clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const; + void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const; }; #endif // NAV_MAP_H diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h index 484856ae36..c9d2d80f6c 100644 --- a/modules/navigation/nav_region.h +++ b/modules/navigation/nav_region.h @@ -53,7 +53,7 @@ class NavRegion : public NavRid { bool polygons_dirty = true; /// Cache - std::vector<gd::Polygon> polygons; + LocalVector<gd::Polygon> polygons; public: NavRegion() {} @@ -93,7 +93,7 @@ public: Vector3 get_connection_pathway_start(int p_connection_id) const; Vector3 get_connection_pathway_end(int p_connection_id) const; - std::vector<gd::Polygon> const &get_polygons() const { + LocalVector<gd::Polygon> const &get_polygons() const { return polygons; } diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h index a9f4e0e2fc..47f04b6a75 100644 --- a/modules/navigation/nav_utils.h +++ b/modules/navigation/nav_utils.h @@ -34,7 +34,7 @@ #include "core/math/vector3.h" #include "core/templates/hash_map.h" #include "core/templates/hashfuncs.h" -#include "core/templates/vector.h" +#include "core/templates/local_vector.h" #include <vector> class NavRegion; @@ -96,13 +96,13 @@ struct Polygon { NavRegion *owner = nullptr; /// The points of this `Polygon` - std::vector<Point> points; + LocalVector<Point> points; /// Are the points clockwise ? bool clockwise; /// The edges of this `Polygon` - std::vector<Edge> edges; + LocalVector<Edge> edges; /// The center of this `Polygon` Vector3 center; @@ -124,6 +124,8 @@ struct NavigationPoly { /// The distance to the destination. float traveled_distance = 0.0; + NavigationPoly() { poly = nullptr; } + NavigationPoly(const Polygon *p_poly) : poly(p_poly) {} diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 6e8ac77f79..848e554fb0 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -42,6 +42,7 @@ #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/cylinder_shape_3d.h" +#include "scene/resources/height_map_shape_3d.h" #include "scene/resources/primitive_meshes.h" #include "scene/resources/shape_3d.h" #include "scene/resources/sphere_shape_3d.h" @@ -275,6 +276,50 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans _add_faces(faces, transform, p_vertices, p_indices); } } + + HeightMapShape3D *heightmap_shape = Object::cast_to<HeightMapShape3D>(*s); + if (heightmap_shape) { + int heightmap_depth = heightmap_shape->get_map_depth(); + int heightmap_width = heightmap_shape->get_map_width(); + + if (heightmap_depth >= 2 && heightmap_width >= 2) { + const Vector<real_t> &map_data = heightmap_shape->get_map_data(); + + Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1); + Vector2 start = heightmap_gridsize * -0.5; + + Vector<Vector3> vertex_array; + vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6); + int map_data_current_index = 0; + + for (int d = 0; d < heightmap_depth - 1; d++) { + for (int w = 0; w < heightmap_width - 1; w++) { + if (map_data_current_index + 1 + heightmap_depth < map_data.size()) { + float top_left_height = map_data[map_data_current_index]; + float top_right_height = map_data[map_data_current_index + 1]; + float bottom_left_height = map_data[map_data_current_index + heightmap_depth]; + float bottom_right_height = map_data[map_data_current_index + 1 + heightmap_depth]; + + Vector3 top_left = Vector3(start.x + w, top_left_height, start.y + d); + Vector3 top_right = Vector3(start.x + w + 1.0, top_right_height, start.y + d); + Vector3 bottom_left = Vector3(start.x + w, bottom_left_height, start.y + d + 1.0); + Vector3 bottom_right = Vector3(start.x + w + 1.0, bottom_right_height, start.y + d + 1.0); + + vertex_array.push_back(top_right); + vertex_array.push_back(bottom_left); + vertex_array.push_back(top_left); + vertex_array.push_back(top_right); + vertex_array.push_back(bottom_right); + vertex_array.push_back(bottom_left); + } + map_data_current_index += 1; + } + } + if (vertex_array.size() > 0) { + _add_faces(vertex_array, transform, p_vertices, p_indices); + } + } + } } } } @@ -362,6 +407,50 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans PackedVector3Array faces = Variant(dict["faces"]); _add_faces(faces, shapes[i], p_vertices, p_indices); } break; + case PhysicsServer3D::SHAPE_HEIGHTMAP: { + Dictionary dict = data; + ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" + int heightmap_depth = dict["depth"]; + int heightmap_width = dict["width"]; + + if (heightmap_depth >= 2 && heightmap_width >= 2) { + const Vector<real_t> &map_data = dict["heights"]; + + Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1); + Vector2 start = heightmap_gridsize * -0.5; + + Vector<Vector3> vertex_array; + vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6); + int map_data_current_index = 0; + + for (int d = 0; d < heightmap_depth - 1; d++) { + for (int w = 0; w < heightmap_width - 1; w++) { + if (map_data_current_index + 1 + heightmap_depth < map_data.size()) { + float top_left_height = map_data[map_data_current_index]; + float top_right_height = map_data[map_data_current_index + 1]; + float bottom_left_height = map_data[map_data_current_index + heightmap_depth]; + float bottom_right_height = map_data[map_data_current_index + 1 + heightmap_depth]; + + Vector3 top_left = Vector3(start.x + w, top_left_height, start.y + d); + Vector3 top_right = Vector3(start.x + w + 1.0, top_right_height, start.y + d); + Vector3 bottom_left = Vector3(start.x + w, bottom_left_height, start.y + d + 1.0); + Vector3 bottom_right = Vector3(start.x + w + 1.0, bottom_right_height, start.y + d + 1.0); + + vertex_array.push_back(top_right); + vertex_array.push_back(bottom_left); + vertex_array.push_back(top_left); + vertex_array.push_back(top_right); + vertex_array.push_back(bottom_right); + vertex_array.push_back(bottom_left); + } + map_data_current_index += 1; + } + } + if (vertex_array.size() > 0) { + _add_faces(vertex_array, shapes[i], p_vertices, p_indices); + } + } + } break; default: { WARN_PRINT("Unsupported collision shape type."); } break; diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp index 32c3f0aad4..27a86f45b5 100644 --- a/modules/noise/editor/noise_editor_plugin.cpp +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -54,7 +54,7 @@ public: set_custom_minimum_size(Size2(0, EDSCALE * PREVIEW_HEIGHT)); _texture_rect = memnew(TextureRect); - _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); _texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_COVERED); add_child(_texture_rect); diff --git a/modules/ogg/config.py b/modules/ogg/config.py index 5a417ba8dd..f7ec4de6be 100644 --- a/modules/ogg/config.py +++ b/modules/ogg/config.py @@ -8,8 +8,8 @@ def configure(env): def get_doc_classes(): return [ - "OGGPacketSequence", - "OGGPacketSequencePlayback", + "OggPacketSequence", + "OggPacketSequencePlayback", ] diff --git a/modules/ogg/doc_classes/OGGPacketSequence.xml b/modules/ogg/doc_classes/OggPacketSequence.xml index bff3691ce0..d3bd4455d8 100644 --- a/modules/ogg/doc_classes/OGGPacketSequence.xml +++ b/modules/ogg/doc_classes/OggPacketSequence.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OGGPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="OggPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> - A sequence of OGG packets. + A sequence of Ogg packets. </brief_description> <description> - A sequence of OGG packets. + A sequence of Ogg packets. </description> <tutorials> </tutorials> @@ -21,7 +21,7 @@ Contains the granule positions for each page in this packet sequence. </member> <member name="packet_data" type="Array" setter="set_packet_data" getter="get_packet_data" default="[]"> - Contains the raw packets that make up this OGGPacketSequence. + Contains the raw packets that make up this OggPacketSequence. </member> <member name="sampling_rate" type="float" setter="set_sampling_rate" getter="get_sampling_rate" default="0.0"> Holds sample rate information about this sequence. Must be set by another class that actually understands the codec. diff --git a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml index 11fc1f4cb6..5c0d75278b 100644 --- a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml +++ b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OGGPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="OggPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> </brief_description> <description> diff --git a/modules/ogg/ogg_packet_sequence.cpp b/modules/ogg/ogg_packet_sequence.cpp index da52ecfdd5..de8bf4a087 100644 --- a/modules/ogg/ogg_packet_sequence.cpp +++ b/modules/ogg/ogg_packet_sequence.cpp @@ -31,7 +31,7 @@ #include "ogg_packet_sequence.h" #include "core/variant/typed_array.h" -void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) { +void OggPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) { Vector<PackedByteArray> data_stored; for (int i = 0; i < p_data.size(); i++) { data_stored.push_back(p_data[i]); @@ -41,7 +41,7 @@ void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByte data_version++; } -void OGGPacketSequence::set_packet_data(const Array &p_data) { +void OggPacketSequence::set_packet_data(const Array &p_data) { data_version++; // Update the data version so old playbacks know that they can't rely on us anymore. page_data.clear(); for (int page_idx = 0; page_idx < p_data.size(); page_idx++) { @@ -54,7 +54,7 @@ void OGGPacketSequence::set_packet_data(const Array &p_data) { } } -Array OGGPacketSequence::get_packet_data() const { +Array OggPacketSequence::get_packet_data() const { Array ret; for (const Vector<PackedByteArray> &page : page_data) { Array page_variant; @@ -66,7 +66,7 @@ Array OGGPacketSequence::get_packet_data() const { return ret; } -void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) { +void OggPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) { data_version++; // Update the data version so old playbacks know that they can't rely on us anymore. page_granule_positions.clear(); for (int page_idx = 0; page_idx < p_granule_positions.size(); page_idx++) { @@ -75,7 +75,7 @@ void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_posi } } -Array OGGPacketSequence::get_packet_granule_positions() const { +Array OggPacketSequence::get_packet_granule_positions() const { Array ret; for (int64_t granule_pos : page_granule_positions) { ret.push_back(granule_pos); @@ -83,22 +83,22 @@ Array OGGPacketSequence::get_packet_granule_positions() const { return ret; } -void OGGPacketSequence::set_sampling_rate(float p_sampling_rate) { +void OggPacketSequence::set_sampling_rate(float p_sampling_rate) { sampling_rate = p_sampling_rate; } -float OGGPacketSequence::get_sampling_rate() const { +float OggPacketSequence::get_sampling_rate() const { return sampling_rate; } -int64_t OGGPacketSequence::get_final_granule_pos() const { +int64_t OggPacketSequence::get_final_granule_pos() const { if (!page_granule_positions.is_empty()) { return page_granule_positions[page_granule_positions.size() - 1]; } return -1; } -float OGGPacketSequence::get_length() const { +float OggPacketSequence::get_length() const { int64_t granule_pos = get_final_granule_pos(); if (granule_pos < 0) { return 0; @@ -106,33 +106,33 @@ float OGGPacketSequence::get_length() const { return granule_pos / sampling_rate; } -Ref<OGGPacketSequencePlayback> OGGPacketSequence::instance_playback() { - Ref<OGGPacketSequencePlayback> playback; +Ref<OggPacketSequencePlayback> OggPacketSequence::instantiate_playback() { + Ref<OggPacketSequencePlayback> playback; playback.instantiate(); - playback->ogg_packet_sequence = Ref<OGGPacketSequence>(this); + playback->ogg_packet_sequence = Ref<OggPacketSequence>(this); playback->data_version = data_version; return playback; } -void OGGPacketSequence::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OGGPacketSequence::set_packet_data); - ClassDB::bind_method(D_METHOD("get_packet_data"), &OGGPacketSequence::get_packet_data); +void OggPacketSequence::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OggPacketSequence::set_packet_data); + ClassDB::bind_method(D_METHOD("get_packet_data"), &OggPacketSequence::get_packet_data); - ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OGGPacketSequence::set_packet_granule_positions); - ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OGGPacketSequence::get_packet_granule_positions); + ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OggPacketSequence::set_packet_granule_positions); + ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OggPacketSequence::get_packet_granule_positions); - ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OGGPacketSequence::set_sampling_rate); - ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OGGPacketSequence::get_sampling_rate); + ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OggPacketSequence::set_sampling_rate); + ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OggPacketSequence::get_sampling_rate); - ClassDB::bind_method(D_METHOD("get_length"), &OGGPacketSequence::get_length); + ClassDB::bind_method(D_METHOD("get_length"), &OggPacketSequence::get_length); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "packet_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_data", "get_packet_data"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "granule_positions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_granule_positions", "get_packet_granule_positions"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sampling_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_sampling_rate", "get_sampling_rate"); } -bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const { +bool OggPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const { ERR_FAIL_COND_V(data_version != ogg_packet_sequence->data_version, false); ERR_FAIL_COND_V(ogg_packet_sequence->page_data.is_empty(), false); ERR_FAIL_COND_V(ogg_packet_sequence->page_granule_positions.is_empty(), false); @@ -161,7 +161,7 @@ bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const { return true; } -uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) { +uint32_t OggPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) { // FIXME: This function needs better corner case handling. if (before_page_inclusive == after_page_inclusive) { return before_page_inclusive; @@ -198,7 +198,7 @@ uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t } } -bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) { +bool OggPacketSequencePlayback::seek_page(int64_t p_granule_pos) { int correct_page = seek_page_internal(p_granule_pos, 0, ogg_packet_sequence->page_data.size() - 1); if (correct_page == -1) { return false; @@ -213,10 +213,10 @@ bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) { return true; } -OGGPacketSequencePlayback::OGGPacketSequencePlayback() { +OggPacketSequencePlayback::OggPacketSequencePlayback() { packet = new ogg_packet(); } -OGGPacketSequencePlayback::~OGGPacketSequencePlayback() { +OggPacketSequencePlayback::~OggPacketSequencePlayback() { delete packet; } diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h index 73e3cb4fff..efd3b64a39 100644 --- a/modules/ogg/ogg_packet_sequence.h +++ b/modules/ogg/ogg_packet_sequence.h @@ -38,12 +38,12 @@ #include "core/variant/variant.h" #include "thirdparty/libogg/ogg/ogg.h" -class OGGPacketSequencePlayback; +class OggPacketSequencePlayback; -class OGGPacketSequence : public Resource { - GDCLASS(OGGPacketSequence, Resource); +class OggPacketSequence : public Resource { + GDCLASS(OggPacketSequence, Resource); - friend class OGGPacketSequencePlayback; + friend class OggPacketSequencePlayback; // List of pages, each of which is a list of packets on that page. The innermost PackedByteArrays contain complete ogg packets. Vector<Vector<PackedByteArray>> page_data; @@ -73,7 +73,7 @@ public: void set_packet_granule_positions(const Array &p_granule_positions); Array get_packet_granule_positions() const; - // Sets a sampling rate associated with this object. OGGPacketSequence doesn't understand codecs, + // Sets a sampling rate associated with this object. OggPacketSequence doesn't understand codecs, // so this value is naively stored as a convenience. void set_sampling_rate(float p_sampling_rate); @@ -86,18 +86,18 @@ public: // Returns the granule position of the last page in this sequence. int64_t get_final_granule_pos() const; - Ref<OGGPacketSequencePlayback> instance_playback(); + Ref<OggPacketSequencePlayback> instantiate_playback(); - OGGPacketSequence() {} - virtual ~OGGPacketSequence() {} + OggPacketSequence() {} + virtual ~OggPacketSequence() {} }; -class OGGPacketSequencePlayback : public RefCounted { - GDCLASS(OGGPacketSequencePlayback, RefCounted); +class OggPacketSequencePlayback : public RefCounted { + GDCLASS(OggPacketSequencePlayback, RefCounted); - friend class OGGPacketSequence; + friend class OggPacketSequence; - Ref<OGGPacketSequence> ogg_packet_sequence; + Ref<OggPacketSequence> ogg_packet_sequence; mutable int64_t page_cursor = 0; mutable int32_t packet_cursor = 0; @@ -121,8 +121,8 @@ public: // Returns true on success, false on failure. bool seek_page(int64_t p_granule_pos); - OGGPacketSequencePlayback(); - virtual ~OGGPacketSequencePlayback(); + OggPacketSequencePlayback(); + virtual ~OggPacketSequencePlayback(); }; #endif // OGG_PACKET_SEQUENCE_H diff --git a/modules/ogg/register_types.cpp b/modules/ogg/register_types.cpp index 01f04aa3d5..aca6d1e1f8 100644 --- a/modules/ogg/register_types.cpp +++ b/modules/ogg/register_types.cpp @@ -37,8 +37,8 @@ void initialize_ogg_module(ModuleInitializationLevel p_level) { return; } - GDREGISTER_CLASS(OGGPacketSequence); - GDREGISTER_CLASS(OGGPacketSequencePlayback); + GDREGISTER_CLASS(OggPacketSequence); + GDREGISTER_CLASS(OggPacketSequencePlayback); } void uninitialize_ogg_module(ModuleInitializationLevel p_level) { diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index 8783e061d2..593d1ff3c1 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -35,7 +35,11 @@ if env["platform"] == "android": # may need to include java parts of the openxr loader elif env["platform"] == "linuxbsd": - env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX", "XR_USE_PLATFORM_XLIB"]) + env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX"]) + + if env["x11"]: + env_thirdparty.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"]) + # FIXME: Review what needs to be set for Android and macOS. env_thirdparty.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"]) elif env["platform"] == "windows": diff --git a/modules/openxr/action_map/openxr_action.h b/modules/openxr/action_map/openxr_action.h index 5e57f89133..a7c1c9988c 100644 --- a/modules/openxr/action_map/openxr_action.h +++ b/modules/openxr/action_map/openxr_action.h @@ -84,4 +84,4 @@ public: VARIANT_ENUM_CAST(OpenXRAction::ActionType); -#endif // !OPENXR_ACTION_H +#endif // OPENXR_ACTION_H diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h index dcd8fc71aa..8659cd3942 100644 --- a/modules/openxr/action_map/openxr_action_map.h +++ b/modules/openxr/action_map/openxr_action_map.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OPENXR_ACTION_SETS_H -#define OPENXR_ACTION_SETS_H +#ifndef OPENXR_ACTION_MAP_H +#define OPENXR_ACTION_MAP_H #include "core/io/resource.h" @@ -79,4 +79,4 @@ public: ~OpenXRActionMap(); }; -#endif // !OPENXR_ACTION_SETS_H +#endif // OPENXR_ACTION_MAP_H diff --git a/modules/openxr/action_map/openxr_action_set.h b/modules/openxr/action_map/openxr_action_set.h index b1d7168894..2ef7ba4c32 100644 --- a/modules/openxr/action_map/openxr_action_set.h +++ b/modules/openxr/action_map/openxr_action_set.h @@ -72,4 +72,4 @@ public: ~OpenXRActionSet(); }; -#endif // !OPENXR_ACTION_SET_H +#endif // OPENXR_ACTION_SET_H diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h index 9bdd9a6ded..446e6eb9c6 100644 --- a/modules/openxr/action_map/openxr_defs.h +++ b/modules/openxr/action_map/openxr_defs.h @@ -121,4 +121,4 @@ public: static PackedStringArray get_interaction_profile_paths(); }; -#endif // !OPENXR_DEFS_H +#endif // OPENXR_DEFS_H diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index 342c36cdff..99d7a17acf 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -40,7 +40,7 @@ void OpenXRIPBinding::_bind_methods() { ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_paths", "get_paths"); - ClassDB::bind_method(D_METHOD("has_path"), &OpenXRIPBinding::has_path); + ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path); ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path); ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path); } diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h index 46b1bda50f..c77fd490bb 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.h +++ b/modules/openxr/action_map/openxr_interaction_profile.h @@ -98,4 +98,4 @@ public: ~OpenXRInteractionProfile(); }; -#endif // !OPENXR_INTERACTION_PROFILE_H +#endif // OPENXR_INTERACTION_PROFILE_H diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml index 9e1176874a..f96637f2f5 100644 --- a/modules/openxr/doc_classes/OpenXRIPBinding.xml +++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml @@ -24,7 +24,7 @@ </method> <method name="has_path" qualifiers="const"> <return type="bool" /> - <argument index="0" name="arg0" type="String" /> + <argument index="0" name="path" type="String" /> <description> Returns [code]true[/code] if this input/output path is part of this binding. </description> diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 74f708bc95..25bf496de9 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -5,10 +5,10 @@ </brief_description> <description> The OpenXR interface allows Godot to interact with OpenXR runtimes and make it possible to create XR experiences and games. - Due to the needs of OpenXR this interface works slightly different then other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset. + Due to the needs of OpenXR this interface works slightly different than other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset. </description> <tutorials> - <link title="OpenXR documentation">$DOCS_URL/tutorials/vr/openxr/index.html</link> + <link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link> </tutorials> <signals> <signal name="pose_recentered"> diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 6e1b7ab779..6cf098cf08 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -64,4 +64,4 @@ public: OpenXRActionEditor(Ref<OpenXRAction> p_action); }; -#endif // !OPENXR_ACTION_EDITOR_H +#endif // OPENXR_ACTION_EDITOR_H diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp index 87b7f50224..0a2d0a3110 100644 --- a/modules/openxr/editor/openxr_action_map_editor.cpp +++ b/modules/openxr/editor/openxr_action_map_editor.cpp @@ -258,7 +258,7 @@ void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_ } void OpenXRActionMapEditor::_on_save_action_map() { - Error err = ResourceSaver::save(edited_path, action_map); + Error err = ResourceSaver::save(action_map, edited_path); if (err != OK) { EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), edited_path)); return; diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h index dfc941b500..a19bc90f56 100644 --- a/modules/openxr/editor/openxr_action_map_editor.h +++ b/modules/openxr/editor/openxr_action_map_editor.h @@ -97,4 +97,4 @@ public: ~OpenXRActionMapEditor(); }; -#endif // !OPENXR_ACTION_MAP_EDITOR_H +#endif // OPENXR_ACTION_MAP_EDITOR_H diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index f3960dcbf9..d8c85d03dd 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -85,4 +85,4 @@ public: OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set); }; -#endif // !OPENXR_ACTION_SET_EDITOR_H +#endif // OPENXR_ACTION_SET_EDITOR_H diff --git a/modules/openxr/editor/openxr_editor_plugin.h b/modules/openxr/editor/openxr_editor_plugin.h index af8ee7d54c..ce230ee95b 100644 --- a/modules/openxr/editor/openxr_editor_plugin.h +++ b/modules/openxr/editor/openxr_editor_plugin.h @@ -50,4 +50,4 @@ public: ~OpenXREditorPlugin(); }; -#endif // !OPENXR_EDITOR_PLUGIN_H +#endif // OPENXR_EDITOR_PLUGIN_H diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp index 24ac5494dd..e2dc2d1b74 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp +++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp @@ -169,9 +169,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Button *path_add = memnew(Button); path_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); path_add->set_flat(true); - Vector<Variant> add_binds; - add_binds.push_back(String(p_io_path->openxr_path)); - path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for), add_binds); + path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path))); path_hb->add_child(path_add); if (interaction_profile.is_valid()) { @@ -198,10 +196,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Button *action_rem = memnew(Button); action_rem->set_flat(true); action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - Vector<Variant> remove_binds; - remove_binds.push_back(action->get_name_with_set()); - remove_binds.push_back(String(p_io_path->openxr_path)); - action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding), remove_binds); + action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding).bind(action->get_name_with_set(), String(p_io_path->openxr_path))); action_hb->add_child(action_rem); } } diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h index f50da1a003..20a37a80eb 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.h +++ b/modules/openxr/editor/openxr_interaction_profile_editor.h @@ -80,4 +80,4 @@ public: OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile); }; -#endif // !OPENXR_INTERACTION_PROFILE_EDITOR_H +#endif // OPENXR_INTERACTION_PROFILE_EDITOR_H diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp index c2a2965200..80e58044d5 100644 --- a/modules/openxr/editor/openxr_select_action_dialog.cpp +++ b/modules/openxr/editor/openxr_select_action_dialog.cpp @@ -96,11 +96,9 @@ void OpenXRSelectActionDialog::open() { Button *action_button = memnew(Button); String action_name = action->get_name_with_set(); - Vector<Variant> binds; - binds.push_back(action_name); action_button->set_flat(true); action_button->set_text(action->get_name() + ": " + action->get_localized_name()); - action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action), binds); + action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action).bind(action_name)); action_hb->add_child(action_button); action_buttons[action_name] = action_button->get_path(); diff --git a/modules/openxr/editor/openxr_select_action_dialog.h b/modules/openxr/editor/openxr_select_action_dialog.h index ea2c30373b..cbe1380e18 100644 --- a/modules/openxr/editor/openxr_select_action_dialog.h +++ b/modules/openxr/editor/openxr_select_action_dialog.h @@ -64,4 +64,4 @@ public: OpenXRSelectActionDialog(Ref<OpenXRActionMap> p_action_map); }; -#endif // !OPENXR_SELECT_ACTION_DIALOG_H +#endif // OPENXR_SELECT_ACTION_DIALOG_H diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp index 12b110f146..23b025db08 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp @@ -80,11 +80,9 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu String path = interaction_profiles[i]; if (!p_do_not_include.has(path)) { Button *ip_button = memnew(Button); - Vector<Variant> binds; - binds.push_back(path); ip_button->set_flat(true); ip_button->set_text(OpenXRDefs::get_profile(path)->display_name); - ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile), binds); + ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path)); main_vb->add_child(ip_button); ip_buttons[path] = ip_button->get_path(); diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h index d177861ff3..54bfe3120a 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h @@ -63,4 +63,4 @@ public: OpenXRSelectInteractionProfileDialog(); }; -#endif // !OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H +#endif // OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H diff --git a/modules/openxr/extensions/openxr_android_extension.h b/modules/openxr/extensions/openxr_android_extension.h index e102197a55..88b0e310e7 100644 --- a/modules/openxr/extensions/openxr_android_extension.h +++ b/modules/openxr/extensions/openxr_android_extension.h @@ -44,4 +44,4 @@ private: static OpenXRAndroidExtension *singleton; }; -#endif // !OPENXR_ANDROID_EXTENSION_H +#endif // OPENXR_ANDROID_EXTENSION_H diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index 0f7c0ba0bc..ecc6e0dd4e 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -32,7 +32,7 @@ #define OPENXR_EXTENSION_WRAPPER_H #include "core/error/error_macros.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/hash_map.h" #include "core/templates/rid.h" @@ -97,11 +97,11 @@ public: virtual String get_swapchain_format_name(int64_t p_swapchain_format) const = 0; virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) = 0; virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) = 0; - virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) = 0; + virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) = 0; virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) = 0; OpenXRGraphicsExtensionWrapper(OpenXRAPI *p_openxr_api) : OpenXRExtensionWrapper(p_openxr_api){}; }; -#endif // ~OPENXR_EXTENSION_WRAPPER_H +#endif // OPENXR_EXTENSION_WRAPPER_H diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h index 7670bc074b..7f37351f27 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h @@ -49,4 +49,4 @@ private: bool available = false; }; -#endif // !OPENXR_HTC_VIVE_TRACKER_EXTENSION_H +#endif // OPENXR_HTC_VIVE_TRACKER_EXTENSION_H diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp index 3d3d4de5b6..2608c4ac17 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.cpp +++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp @@ -420,7 +420,7 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in return true; } -bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) { +bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) { // Even though this is a Vulkan renderer we're using OpenGL coordinate systems XrMatrix4x4f matrix; XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far); diff --git a/modules/openxr/extensions/openxr_vulkan_extension.h b/modules/openxr/extensions/openxr_vulkan_extension.h index 1e34fe1f80..5dddc4b9c9 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.h +++ b/modules/openxr/extensions/openxr_vulkan_extension.h @@ -63,7 +63,7 @@ public: virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override; virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override; virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override; - virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) override; + virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override; virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) override; private: @@ -90,4 +90,4 @@ private: XrResult xrCreateVulkanDeviceKHR(XrInstance p_instance, const XrVulkanDeviceCreateInfoKHR *p_create_info, VkDevice *r_device, VkResult *r_result); }; -#endif // !OPENXR_VULKAN_EXTENSION_H +#endif // OPENXR_VULKAN_EXTENSION_H diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 5e35942012..92d074cb75 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -58,19 +58,14 @@ bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) { // @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled" if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) { -#ifdef TOOLS_ENABLED // Disabled for now, using XR inside of the editor we'll be working on during the coming months. return false; - - // bool enabled = GLOBAL_GET("xr/openxr/in_editor"); // EDITOR_GET("xr/openxr/in_editor"); - // return enabled; -#else - // we should never get here, editor hint won't be true if the editor isn't compiled in. - return false; -#endif } else { - bool enabled = GLOBAL_GET("xr/openxr/enabled"); - return enabled; + if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) { + return GLOBAL_GET("xr/openxr/enabled"); + } else { + return XRServer::get_xr_mode() == XRServer::XRMODE_ON; + } } } @@ -1180,7 +1175,7 @@ bool OpenXRAPI::get_view_transform(uint32_t p_view, Transform3D &r_transform) { return true; } -bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix) { +bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix) { ERR_FAIL_COND_V(!running, false); ERR_FAIL_NULL_V(graphics_extension, false); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index fe9e2937b2..dc224c4237 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OPENXR_DRIVER_H -#define OPENXR_DRIVER_H +#ifndef OPENXR_API_H +#define OPENXR_API_H #include "core/error/error_macros.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/math/transform_3d.h" #include "core/math/vector2.h" #include "core/os/memory.h" @@ -249,7 +249,7 @@ public: Size2 get_recommended_target_size(); XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity); bool get_view_transform(uint32_t p_view, Transform3D &r_transform); - bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix); + bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix); bool process(); void pre_render(); @@ -292,4 +292,4 @@ public: ~OpenXRAPI(); }; -#endif // !OPENXR_DRIVER_H +#endif // OPENXR_API_H diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 9dfa005600..6c2f08e21d 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -123,7 +123,7 @@ void OpenXRInterface::_load_action_map() { #ifdef TOOLS_ENABLED // Save our action sets so our user can action_map->set_path(default_tres_name, true); - ResourceSaver::save(default_tres_name, action_map); + ResourceSaver::save(action_map, default_tres_name); #endif } } @@ -631,8 +631,8 @@ Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Trans return p_cam_transform * xr_server->get_reference_frame() * t; } -CameraMatrix OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix cm; +Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection cm; if (openxr_api) { if (openxr_api->get_view_projection(p_view, p_z_near, p_z_far, cm)) { diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index a223acfed0..a99012fd1d 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -121,7 +121,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual void process() override; virtual void pre_render() override; @@ -140,4 +140,4 @@ public: ~OpenXRInterface(); }; -#endif // !OPENXR_INTERFACE_H +#endif // OPENXR_INTERFACE_H diff --git a/modules/openxr/openxr_util.h b/modules/openxr/openxr_util.h index 4371b74d2f..a5cc7cd512 100644 --- a/modules/openxr/openxr_util.h +++ b/modules/openxr/openxr_util.h @@ -44,4 +44,4 @@ public: static String make_xr_version_string(XrVersion p_version); }; -#endif // !OPENXR_UTIL_H +#endif // OPENXR_UTIL_H diff --git a/modules/raycast/lightmap_raycaster.h b/modules/raycast/lightmap_raycaster.h index 4266b46ea8..2e9f59dda4 100644 --- a/modules/raycast/lightmap_raycaster.h +++ b/modules/raycast/lightmap_raycaster.h @@ -74,4 +74,4 @@ public: ~LightmapRaycasterEmbree(); }; -#endif +#endif // LIGHTMAP_RAYCASTER_H diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 89e75f774e..13824c3830 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -30,6 +30,7 @@ #include "raycast_occlusion_cull.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" #ifdef __SSE2__ @@ -78,9 +79,9 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) { memset(camera_ray_masks.ptr(), ~0, camera_rays_tile_count * TILE_RAYS * sizeof(uint32_t)); } -void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) { +void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { CameraRayThreadData td; - td.thread_count = p_thread_work_pool.get_thread_count(); + td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count(); td.z_near = p_cam_projection.get_z_near(); td.z_far = p_cam_projection.get_z_far() * 1.05f; @@ -88,7 +89,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D td.camera_dir = -p_cam_transform.basis.get_column(2); td.camera_orthogonal = p_cam_orthogonal; - CameraMatrix inv_camera_matrix = p_cam_projection.inverse(); + Projection inv_camera_matrix = p_cam_projection.inverse(); Vector3 camera_corner_proj = Vector3(-1.0f, -1.0f, -1.0f); Vector3 camera_corner_view = inv_camera_matrix.xform(camera_corner_proj); td.pixel_corner = p_cam_transform.xform(camera_corner_view); @@ -106,7 +107,8 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D debug_tex_range = td.z_far; - p_thread_work_pool.do_work(td.thread_count, this, &RaycastHZBuffer::_camera_rays_threaded, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RaycastHZBuffer::_camera_rays_threaded, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCullUpdateCamera")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thread, const CameraRayThreadData *p_data) { @@ -331,10 +333,10 @@ void RaycastOcclusionCull::scenario_remove_instance(RID p_scenario, RID p_instan } void RaycastOcclusionCull::Scenario::_update_dirty_instance_thread(int p_idx, RID *p_instances) { - _update_dirty_instance(p_idx, p_instances, nullptr); + _update_dirty_instance(p_idx, p_instances); } -void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool) { +void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances) { OccluderInstance *occ_inst = instances.getptr(p_instances[p_idx]); if (!occ_inst) { @@ -355,14 +357,16 @@ void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_in const Vector3 *read_ptr = occ->vertices.ptr(); Vector3 *write_ptr = occ_inst->xformed_vertices.ptr(); - if (p_thread_pool && vertices_size > 1024) { + if (vertices_size > 1024) { TransformThreadData td; td.xform = occ_inst->xform; td.read = read_ptr; td.write = write_ptr; td.vertex_count = vertices_size; - td.thread_count = p_thread_pool->get_thread_count(); - p_thread_pool->do_work(td.thread_count, this, &Scenario::_transform_vertices_thread, &td); + td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count(); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_transform_vertices_thread, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCull")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { _transform_vertices_range(read_ptr, write_ptr, occ_inst->xform, 0, vertices_size); } @@ -392,7 +396,7 @@ void RaycastOcclusionCull::Scenario::_commit_scene(void *p_ud) { scenario->commit_done = true; } -bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) { +bool RaycastOcclusionCull::Scenario::update() { ERR_FAIL_COND_V(singleton == nullptr, false); if (commit_thread == nullptr) { @@ -426,13 +430,15 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) { instances.erase(removed_instances[i]); } - if (dirty_instances_array.size() / p_thread_pool.get_thread_count() > 128) { + if (dirty_instances_array.size() / WorkerThreadPool::get_singleton()->get_thread_count() > 128) { // Lots of instances, use per-instance threading - p_thread_pool.do_work(dirty_instances_array.size(), this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr()); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr(), dirty_instances_array.size(), -1, true, SNAME("RaycastOcclusionCullUpdate")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { // Few instances, use threading on the vertex transforms for (unsigned int i = 0; i < dirty_instances_array.size(); i++) { - _update_dirty_instance(i, dirty_instances_array.ptr(), &p_thread_pool); + _update_dirty_instance(i, dirty_instances_array.ptr()); } } @@ -484,7 +490,7 @@ void RaycastOcclusionCull::Scenario::_raycast(uint32_t p_idx, const RaycastThrea rtcIntersect16((const int *)&p_raycast_data->masks[p_idx * TILE_RAYS], ebr_scene[current_scene_idx], &ctx, &p_raycast_data->rays[p_idx]); } -void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const { +void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const { ERR_FAIL_COND(singleton == nullptr); if (raycast_singleton->ebr_device == nullptr) { return; // Embree is initialized on demand when there is some scenario with occluders in it. @@ -498,7 +504,8 @@ void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32 td.rays = r_rays; td.masks = p_valid_masks; - p_thread_pool.do_work(p_tile_count, this, &Scenario::_raycast, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_raycast, &td, p_tile_count, -1, true, SNAME("RaycastOcclusionCullRaycast")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } //////////////////////////////////////////////////////// @@ -524,7 +531,7 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size) buffers[p_buffer].resize(p_size); } -void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) { +void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { if (!buffers.has(p_buffer)) { return; } @@ -537,16 +544,16 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ Scenario &scenario = scenarios[buffer.scenario_rid]; - bool removed = scenario.update(p_thread_pool); + bool removed = scenario.update(); if (removed) { scenarios.erase(buffer.scenario_rid); return; } - buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_thread_pool); + buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal); - scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count, p_thread_pool); + scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count); buffer.sort_rays(-p_cam_transform.basis.get_column(2), p_cam_orthogonal); buffer.update_mips(); } diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index 6562c4e9c4..056b808640 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OCCLUSION_CULL_RAYCASTER_H -#define OCCLUSION_CULL_RAYCASTER_H +#ifndef RAYCAST_OCCLUSION_CULL_H +#define RAYCAST_OCCLUSION_CULL_H #include "core/io/image.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/object/object.h" #include "core/object/ref_counted.h" #include "core/templates/local_vector.h" @@ -76,7 +76,7 @@ public: virtual void clear() override; virtual void resize(const Size2i &p_size) override; void sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal); - void update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool); + void update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal); ~RaycastHZBuffer(); }; @@ -143,14 +143,14 @@ private: LocalVector<RID> removed_instances; void _update_dirty_instance_thread(int p_idx, RID *p_instances); - void _update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool); + void _update_dirty_instance(int p_idx, RID *p_instances); void _transform_vertices_thread(uint32_t p_thread, TransformThreadData *p_data); void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to); static void _commit_scene(void *p_ud); - bool update(ThreadWorkPool &p_thread_pool); + bool update(); void _raycast(uint32_t p_thread, const RaycastThreadData *p_raycast_data) const; - void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const; + void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const; }; static RaycastOcclusionCull *raycast_singleton; @@ -183,7 +183,8 @@ public: virtual HZBuffer *buffer_get_ptr(RID p_buffer) override; virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) override; virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) override; - virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) override; + virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) override; + virtual RID buffer_get_debug_texture(RID p_buffer) override; virtual void set_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality) override; @@ -192,4 +193,4 @@ public: ~RaycastOcclusionCull(); }; -#endif // OCCLUSION_CULL_RAYCASTER_H +#endif // RAYCAST_OCCLUSION_CULL_H diff --git a/modules/raycast/static_raycaster.h b/modules/raycast/static_raycaster.h index e2909f9b56..607a392683 100644 --- a/modules/raycast/static_raycaster.h +++ b/modules/raycast/static_raycaster.h @@ -61,4 +61,4 @@ public: ~StaticRaycasterEmbree(); }; -#endif +#endif // STATIC_RAYCASTER_H diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml index deabc5ccd3..52a7fe492f 100644 --- a/modules/regex/doc_classes/RegEx.xml +++ b/modules/regex/doc_classes/RegEx.xml @@ -62,6 +62,13 @@ Compiles and assign the search pattern to use. Returns [constant OK] if the compilation is successful. If an error is encountered, details are printed to standard output and an error is returned. </description> </method> + <method name="create_from_string" qualifiers="static"> + <return type="RegEx" /> + <argument index="0" name="pattern" type="String" /> + <description> + Creates and compiles a new [RegEx] object. + </description> + </method> <method name="get_group_count" qualifiers="const"> <return type="int" /> <description> @@ -96,7 +103,7 @@ </description> </method> <method name="search_all" qualifiers="const"> - <return type="Array" /> + <return type="RegExMatch[]" /> <argument index="0" name="subject" type="String" /> <argument index="1" name="offset" type="int" default="0" /> <argument index="2" name="end" type="int" default="-1" /> diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index bbe92139e0..569066867a 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -159,6 +159,13 @@ void RegEx::_pattern_info(uint32_t what, void *where) const { pcre2_pattern_info_32((pcre2_code_32 *)code, what, where); } +Ref<RegEx> RegEx::create_from_string(const String &p_pattern) { + Ref<RegEx> ret; + ret.instantiate(); + ret->compile(p_pattern); + return ret; +} + void RegEx::clear() { if (code) { pcre2_code_free_32((pcre2_code_32 *)code); @@ -194,6 +201,7 @@ Error RegEx::compile(const String &p_pattern) { Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) const { ERR_FAIL_COND_V(!is_valid(), nullptr); + ERR_FAIL_COND_V_MSG(p_offset < 0, nullptr, "RegEx search offset must be >= 0"); Ref<RegExMatch> result = memnew(RegExMatch); @@ -257,9 +265,11 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) return result; } -Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const { +TypedArray<RegExMatch> RegEx::search_all(const String &p_subject, int p_offset, int p_end) const { + ERR_FAIL_COND_V_MSG(p_offset < 0, Array(), "RegEx search offset must be >= 0"); + int last_end = -1; - Array result; + TypedArray<RegExMatch> result; Ref<RegExMatch> match = search(p_subject, p_offset, p_end); while (match.is_valid()) { if (last_end == match->get_end(0)) { @@ -274,6 +284,7 @@ Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_all, int p_offset, int p_end) const { ERR_FAIL_COND_V(!is_valid(), String()); + ERR_FAIL_COND_V_MSG(p_offset < 0, String(), "RegEx sub offset must be >= 0"); // safety_zone is the number of chars we allocate in addition to the number of chars expected in order to // guard against the PCRE API writing one additional \0 at the end. PCRE's API docs are unclear on whether @@ -380,6 +391,8 @@ RegEx::~RegEx() { } void RegEx::_bind_methods() { + ClassDB::bind_static_method("RegEx", D_METHOD("create_from_string", "pattern"), &RegEx::create_from_string); + ClassDB::bind_method(D_METHOD("clear"), &RegEx::clear); ClassDB::bind_method(D_METHOD("compile", "pattern"), &RegEx::compile); ClassDB::bind_method(D_METHOD("search", "subject", "offset", "end"), &RegEx::search, DEFVAL(0), DEFVAL(-1)); diff --git a/modules/regex/regex.h b/modules/regex/regex.h index 1455188670..9296de929f 100644 --- a/modules/regex/regex.h +++ b/modules/regex/regex.h @@ -37,6 +37,7 @@ #include "core/templates/vector.h" #include "core/variant/array.h" #include "core/variant/dictionary.h" +#include "core/variant/typed_array.h" class RegExMatch : public RefCounted { GDCLASS(RegExMatch, RefCounted); @@ -81,11 +82,13 @@ protected: static void _bind_methods(); public: + static Ref<RegEx> create_from_string(const String &p_pattern); + void clear(); Error compile(const String &p_pattern); Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const; - Array search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const; + TypedArray<RegExMatch> search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const; String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const; bool is_valid() const; diff --git a/modules/regex/tests/test_regex.h b/modules/regex/tests/test_regex.h index 3f500e7b2f..91af393db1 100644 --- a/modules/regex/tests/test_regex.h +++ b/modules/regex/tests/test_regex.h @@ -130,16 +130,6 @@ TEST_CASE("[RegEx] Empty Pattern") { CHECK(re.is_valid()); } -TEST_CASE("[RegEx] Invalid offset") { - const String s = "Godot"; - - RegEx re("o"); - REQUIRE(re.is_valid()); - CHECK(re.search(s, -1) == nullptr); - CHECK(re.search_all(s, -1).size() == 0); - CHECK(re.sub(s, "", true, -1) == ""); -} - TEST_CASE("[RegEx] Invalid end position") { const String s = "Godot"; diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index dcb1f1d744..87e2fae2d0 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -80,8 +80,8 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin float fw, fh; picture->size(&fw, &fh); - uint32_t width = MIN(fw * p_scale, 16 * 1024); - uint32_t height = MIN(fh * p_scale, 16 * 1024); + uint32_t width = MIN(round(fw * p_scale), 16 * 1024); + uint32_t height = MIN(round(fh * p_scale), 16 * 1024); picture->size(width, height); std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen(); diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 2d764a4006..c6678307af 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -36,8 +36,8 @@ def make_icu_data(target, source, env): # Thirdparty source files thirdparty_obj = [] -freetype_enabled = env.module_check_dependencies("text_server_adv", ["freetype"], True) -msdfgen_enabled = env.module_check_dependencies("text_server_adv", ["msdfgen"], True) +freetype_enabled = "freetype" in env.module_list +msdfgen_enabled = "msdfgen" in env.module_list if env["builtin_harfbuzz"]: env_harfbuzz = env_modules.Clone() @@ -113,15 +113,18 @@ if env["builtin_harfbuzz"]: if freetype_enabled: thirdparty_sources += [ "src/hb-ft.cc", - "src/hb-graphite2.cc", ] + if env["graphite"]: + thirdparty_sources += [ + "src/hb-graphite2.cc", + ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_harfbuzz.Append(CPPPATH=["#thirdparty/harfbuzz/src"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"]) env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"]) if env["builtin_icu"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"]) env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"]) if freetype_enabled: @@ -132,9 +135,9 @@ if env["builtin_harfbuzz"]: ] ) if env["builtin_freetype"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/freetype/include"]) - if env["builtin_graphite"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/graphite/include"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/freetype/include"]) + if env["builtin_graphite"] and env["graphite"]: + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/graphite/include"]) env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"]) if env["platform"] == "android" or env["platform"] == "linuxbsd": @@ -146,7 +149,7 @@ if env["builtin_harfbuzz"]: else: env_harfbuzz.Append(CCFLAGS=["-DHB_NO_MT"]) - env_text_server_adv.Append(CPPPATH=["#thirdparty/harfbuzz/src"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"]) lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources) thirdparty_obj += lib @@ -165,7 +168,7 @@ if env["builtin_harfbuzz"]: env.Append(LIBS=[lib]) -if env["builtin_graphite"] and freetype_enabled: +if env["builtin_graphite"] and freetype_enabled and env["graphite"]: env_graphite = env_modules.Clone() env_graphite.disable_warnings() @@ -209,7 +212,7 @@ if env["builtin_graphite"] and freetype_enabled: thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_graphite.Append(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"]) + env_graphite.Prepend(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"]) env_graphite.Append( CCFLAGS=[ "-DGRAPHITE2_STATIC", @@ -439,6 +442,10 @@ if env["builtin_icu"]: "common/uvectr32.cpp", "common/uvectr64.cpp", "common/wintz.cpp", + "i18n/scriptset.cpp", + "i18n/ucln_in.cpp", + "i18n/uspoof.cpp", + "i18n/uspoof_impl.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] @@ -447,11 +454,11 @@ if env["builtin_icu"]: if env_icu["tools"]: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) env_icu.Command("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name, make_icu_data) - env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/"]) else: thirdparty_sources += ["icu_data/icudata_stub.cpp"] - env_icu.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"]) env_icu.Append( CXXFLAGS=[ "-DU_STATIC_IMPLEMENTATION", @@ -463,6 +470,7 @@ if env["builtin_icu"]: "-DUCONFIG_NO_IDNA", "-DUCONFIG_NO_FILE_IO", "-DUCONFIG_NO_TRANSLITERATION", + "-DUCONFIG_NO_REGULAR_EXPRESSIONS", "-DPKGDATA_MODE=static", "-DU_ENABLE_DYLOAD=0", "-DU_HAVE_LIB_SUFFIX=1", @@ -480,7 +488,7 @@ if env["builtin_icu"]: if env_text_server_adv["tools"]: env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"]) - env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"]) lib = env_icu.add_library("icu_builtin", thirdparty_sources) thirdparty_obj += lib @@ -504,13 +512,14 @@ if env["builtin_icu"]: module_obj = [] if env["builtin_msdfgen"] and msdfgen_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/msdfgen"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"]) if env["builtin_freetype"] and freetype_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/freetype/include"]) + env_text_server_adv.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/freetype/include"]) -if env["builtin_graphite"] and freetype_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/graphite/include"]) +if env["builtin_graphite"] and freetype_enabled and env["graphite"]: + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/graphite/include"]) env_text_server_adv.add_source_files(module_obj, "*.cpp") env.modules_sources += module_obj diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py index 8c8df9b05e..179a2ff378 100644 --- a/modules/text_server_adv/config.py +++ b/modules/text_server_adv/config.py @@ -2,6 +2,14 @@ def can_build(env, platform): return True +def get_opts(platform): + from SCons.Variables import BoolVariable + + return [ + BoolVariable("graphite", "Enable SIL Graphite smart fonts support", True), + ] + + def configure(env): pass diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 69848a9e52..0170c007ae 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -624,15 +624,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"]) env.Append(CPPPATH=["../"]) sources = Glob("../*.cpp") -if env["platform"] == "osx": - methods.write_osx_plist( - f'./bin/libtextserver_advanced.osx.{env["target"]}.framework', - f'libtextserver_advanced.osx.{env["target"]}', +if env["platform"] == "macos": + methods.write_macos_plist( + f'./bin/libtextserver_advanced.macos.{env["target"]}.framework', + f'libtextserver_advanced.macos.{env["target"]}', "org.godotengine.textserver_advanced", "ICU / HarfBuzz / Graphite Text Server", ) library = env.SharedLibrary( - f'./bin/libtextserver_advanced.osx.{env["target"]}.framework/libtextserver_advanced.osx.{env["target"]}', + f'./bin/libtextserver_advanced.macos.{env["target"]}.framework/libtextserver_advanced.macos.{env["target"]}', source=sources, ) else: diff --git a/modules/text_server_adv/gdextension_build/methods.py b/modules/text_server_adv/gdextension_build/methods.py index d404f2851e..3c5229462c 100644 --- a/modules/text_server_adv/gdextension_build/methods.py +++ b/modules/text_server_adv/gdextension_build/methods.py @@ -98,7 +98,7 @@ def make_icu_data(target, source, env): g.write("#endif") -def write_osx_plist(target, binary_name, identifier, name): +def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resourece/", exist_ok=True) f = open(f"{target}/Resourece/Info.plist", "w") diff --git a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension index 5956476a5e..11ed271ae9 100644 --- a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension +++ b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension @@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_advanced.linux.debug.64.so" linux.64.release = "bin/libtextserver_advanced.linux.release.64.so" windows.64.debug = "bin/libtextserver_advanced.windows.debug.64.dll" windows.64.release = "bin/libtextserver_advanced.windows.release.64.dll" -macos.debug = "bin/libtextserver_advanced.osx.debug.framework" -macos.release = "bin/libtextserver_advanced.osx.release.framework" +macos.debug = "bin/libtextserver_advanced.macos.debug.framework" +macos.release = "bin/libtextserver_advanced.macos.release.framework" diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 2bd045b91a..025b62c6fb 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -75,4 +75,4 @@ public: ScriptIterator(const String &p_string, int p_start, int p_length); }; -#endif //SCRIPT_ITERATOR_H +#endif // SCRIPT_ITERATOR_H diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 6076b87203..73dbf2f443 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "text_server_adv.h" +#include "core/object/worker_thread_pool.h" #ifdef GDEXTENSION // Headers for building as GDExtension plug-in. @@ -345,6 +346,8 @@ bool TextServerAdvanced::has_feature(Feature p_feature) const { case FEATURE_FONT_VARIABLE: case FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION: case FEATURE_USE_SUPPORT_DATA: + case FEATURE_UNICODE_IDENTIFIERS: + case FEATURE_UNICODE_SECURITY: return true; default: { } @@ -1039,10 +1042,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; - if (p_font_data->work_pool.get_thread_count() == 0) { - p_font_data->work_pool.init(); - } - p_font_data->work_pool.do_work(h, this, &TextServerAdvanced::_generateMTSDF_threaded, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerAdvanced::_generateMTSDF_threaded, &td, h, -1, true, SNAME("FontServerRasterizeMSDF")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); @@ -1360,7 +1361,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f fd->underline_position = (-FT_MulFix(fd->face->underline_position, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; +#if HB_VERSION_ATLEAST(3, 3, 0) hb_font_set_synthetic_slant(fd->hb_handle, p_font_data->transform[0][1]); +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 3.3.0, synthetic slant offset correction disabled. +#endif +#endif if (!p_font_data->face_init) { // Get style flags and name. @@ -1372,13 +1379,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f } p_font_data->style_flags = 0; if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { - p_font_data->style_flags |= FONT_BOLD; + p_font_data->style_flags.set_flag(FONT_BOLD); } if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { - p_font_data->style_flags |= FONT_ITALIC; + p_font_data->style_flags.set_flag(FONT_ITALIC); } if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { - p_font_data->style_flags |= FONT_FIXED_WIDTH; + p_font_data->style_flags.set_flag(FONT_FIXED_WIDTH); } hb_face_t *hb_face = hb_font_get_face(fd->hb_handle); @@ -1627,14 +1634,21 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f for (unsigned int i = 0; i < count; i++) { Dictionary ftr; +#if HB_VERSION_ATLEAST(2, 1, 0) hb_ot_name_id_t lbl_id; if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GSUB, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { - String lbl; + PackedInt32Array lbl; unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1; lbl.resize(text_size); + memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * text_size); hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); - ftr["label"] = lbl; + ftr["label"] = String((const char32_t *)lbl.ptr()); } +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled. +#endif +#endif ftr["type"] = _get_tag_type(feature_tags[i]); ftr["hidden"] = _get_tag_hidden(feature_tags[i]); @@ -1649,14 +1663,21 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f for (unsigned int i = 0; i < count; i++) { Dictionary ftr; +#if HB_VERSION_ATLEAST(2, 1, 0) hb_ot_name_id_t lbl_id; if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GPOS, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { - String lbl; + PackedInt32Array lbl; unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1; lbl.resize(text_size); + memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * text_size); hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); - ftr["label"] = lbl; + ftr["label"] = String((const char32_t *)lbl.ptr()); } +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled. +#endif +#endif ftr["type"] = _get_tag_type(feature_tags[i]); ftr["hidden"] = _get_tag_hidden(feature_tags[i]); @@ -1842,7 +1863,7 @@ int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const { return face_count; } -void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { +void TextServerAdvanced::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -1852,7 +1873,7 @@ void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontSty fd->style_flags = p_style; } -int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid) const { +BitField<TextServer::FontStyle> TextServerAdvanced::font_get_style(const RID &p_font_rid) const { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); @@ -3992,7 +4013,7 @@ RID TextServerAdvanced::shaped_text_get_parent(const RID &p_shaped) const { return sd->parent; } -double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) { +double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) { ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.0); @@ -4008,7 +4029,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double int start_pos = 0; int end_pos = sd->glyphs.size() - 1; - if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) { + if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) { int start, end, delta; if (sd->para_direction == DIRECTION_LTR) { start = sd->glyphs.size() - 1; @@ -4034,7 +4055,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } double justification_width; - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { if (sd->overrun_trim_data.trim_pos >= 0) { if (sd->para_direction == DIRECTION_RTL) { start_pos = sd->overrun_trim_data.trim_pos; @@ -4049,7 +4070,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double justification_width = sd->width; } - if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) { + if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) { // Trim spaces. while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat; @@ -4088,7 +4109,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } } - if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) { + if ((elongation_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_KASHIDA)) { double delta_width_per_kashida = (p_width - justification_width) / elongation_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; @@ -4109,7 +4130,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } } } - if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { + if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) { double delta_width_per_space = (p_width - justification_width) / space_count; double adv_remain = 0; for (int i = start_pos; i <= end_pos; i++) { @@ -4142,7 +4163,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double sd->fit_width_minimum_reached = true; } - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { sd->width = justification_width; } @@ -4205,7 +4226,7 @@ double TextServerAdvanced::shaped_text_tab_align(const RID &p_shaped, const Pack return 0.0; } -void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { +void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) { ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid."); @@ -4217,10 +4238,10 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l sd->text_trimmed = false; sd->overrun_trim_data.ellipsis_glyph_buf.clear(); - bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS; - bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY; - bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS; - bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE; + bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); + bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); + bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptrw(); @@ -4685,7 +4706,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape for (int i = 0; i < sd_size; i++) { if (sd_glyphs[i].count > 0) { char32_t c = sd->text[sd_glyphs[i].start - sd->start]; - if (c == 0x0640) { + if (c == 0x0640 && sd_glyphs[i].start == sd_glyphs[i].end - 1) { sd_glyphs[i].flags |= GRAPHEME_IS_ELONGATION; } if (sd->jstops.has(sd_glyphs[i].start)) { @@ -4697,6 +4718,11 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape if (sd_glyphs[i].font_rid != RID()) { Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size); if ((sd_glyphs[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) { +#if HB_VERSION_ATLEAST(5, 1, 0) + if ((i > 0) && ((sd_glyphs[i - 1].flags & GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL) != GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL)) { + continue; + } +#endif gl.start = sd_glyphs[i].start; gl.end = sd_glyphs[i].end; gl.repeat = 0; @@ -4887,11 +4913,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star hb_buffer_clear_contents(p_sd->hb_buffer); hb_buffer_set_direction(p_sd->hb_buffer, p_direction); + int flags = (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0); if (p_sd->preserve_control) { - hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0))); + flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES; } else { - hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_DEFAULT | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0))); + flags |= HB_BUFFER_FLAG_DEFAULT; } +#if HB_VERSION_ATLEAST(5, 1, 0) + flags |= HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL; +#endif + hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)flags); hb_buffer_set_script(p_sd->hb_buffer, p_script); if (p_sd->spans[p_span].language.is_empty()) { @@ -4955,10 +4986,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star gl.font_rid = p_fonts[p_fb_index]; gl.font_size = fs; - if (glyph_info[i].mask & HB_GLYPH_FLAG_DEFINED) { + if (glyph_info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) { gl.flags |= GRAPHEME_IS_CONNECTED; } +#if HB_VERSION_ATLEAST(5, 1, 0) + if (glyph_info[i].mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) { + gl.flags |= GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL; + } +#endif + gl.index = glyph_info[i].codepoint; if (gl.index != 0) { _ensure_glyph(fd, fss, gl.index); @@ -5620,6 +5657,68 @@ String TextServerAdvanced::percent_sign(const String &p_language) const { return "%"; } +int TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const { + UErrorCode status = U_ZERO_ERROR; + int match_index = -1; + + Char16String utf16 = p_string.utf16(); + Vector<UChar *> skeletons; + skeletons.resize(p_dict.size()); + + USpoofChecker *sc = uspoof_open(&status); + uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status); + for (int i = 0; i < p_dict.size(); i++) { + Char16String word = p_dict[i].utf16(); + int32_t len = uspoof_getSkeleton(sc, 0, word.get_data(), -1, NULL, 0, &status); + skeletons.write[i] = (UChar *)memalloc(++len * sizeof(UChar)); + status = U_ZERO_ERROR; + uspoof_getSkeleton(sc, 0, word.get_data(), -1, skeletons.write[i], len, &status); + } + + int32_t len = uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, NULL, 0, &status); + UChar *skel = (UChar *)memalloc(++len * sizeof(UChar)); + status = U_ZERO_ERROR; + uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, skel, len, &status); + for (int i = 0; i < skeletons.size(); i++) { + if (u_strcmp(skel, skeletons[i]) == 0) { + match_index = i; + break; + } + } + memfree(skel); + + for (int i = 0; i < skeletons.size(); i++) { + memfree(skeletons.write[i]); + } + uspoof_close(sc); + + ERR_FAIL_COND_V_MSG(U_FAILURE(status), -1, u_errorName(status)); + + return match_index; +} + +bool TextServerAdvanced::spoof_check(const String &p_string) const { + UErrorCode status = U_ZERO_ERROR; + Char16String utf16 = p_string.utf16(); + + USet *allowed = uset_openEmpty(); + uset_addAll(allowed, uspoof_getRecommendedSet(&status)); + uset_addAll(allowed, uspoof_getInclusionSet(&status)); + + USpoofChecker *sc = uspoof_open(&status); + uspoof_setAllowedChars(sc, allowed, &status); + uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE); + + int32_t bitmask = uspoof_check(sc, utf16.get_data(), -1, NULL, &status); + + uspoof_close(sc); + uset_close(allowed); + + ERR_FAIL_COND_V_MSG(U_FAILURE(status), false, u_errorName(status)); + + return (bitmask != 0); +} + String TextServerAdvanced::strip_diacritics(const String &p_string) const { UErrorCode err = U_ZERO_ERROR; @@ -5738,6 +5837,191 @@ PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_stri return ret; } +bool TextServerAdvanced::is_valid_identifier(const String &p_string) const { + enum UAX31SequenceStatus { + SEQ_NOT_STARTED, + SEQ_STARTED, + SEQ_STARTED_VIR, + SEQ_NEAR_END, + }; + + const char32_t *str = p_string.ptr(); + int len = p_string.length(); + + if (len == 0) { + return false; // Empty string. + } + + UErrorCode err = U_ZERO_ERROR; + Char16String utf16 = p_string.utf16(); + const UNormalizer2 *norm_c = unorm2_getNFCInstance(&err); + if (U_FAILURE(err)) { + return false; // Failed to load normalizer. + } + bool isnurom = unorm2_isNormalized(norm_c, utf16.ptr(), utf16.length(), &err); + if (U_FAILURE(err) || !isnurom) { + return false; // Do not conform to Normalization Form C. + } + + UAX31SequenceStatus A1_sequence_status = SEQ_NOT_STARTED; + UScriptCode A1_scr = USCRIPT_INHERITED; + UAX31SequenceStatus A2_sequence_status = SEQ_NOT_STARTED; + UScriptCode A2_scr = USCRIPT_INHERITED; + UAX31SequenceStatus B_sequence_status = SEQ_NOT_STARTED; + UScriptCode B_scr = USCRIPT_INHERITED; + + for (int i = 0; i < len; i++) { + err = U_ZERO_ERROR; + UScriptCode scr = uscript_getScript(str[i], &err); + if (U_FAILURE(err)) { + return false; // Invalid script. + } + if (uscript_getUsage(scr) != USCRIPT_USAGE_RECOMMENDED) { + return false; // Not a recommended script. + } + uint8_t cat = u_charType(str[i]); + int32_t jt = u_getIntPropertyValue(str[i], UCHAR_JOINING_TYPE); + + // UAX #31 section 2.3 subsections A1, A2 and B, check ZWNJ and ZWJ usage. + switch (A1_sequence_status) { + case SEQ_NEAR_END: { + if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) { + return false; // Mixed script. + } + if (jt == U_JT_RIGHT_JOINING || jt == U_JT_DUAL_JOINING) { + A1_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset. + } else if (jt != U_JT_TRANSPARENT) { + return false; // Invalid end of sequence. + } + } break; + case SEQ_STARTED: { + if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) { + A1_sequence_status = SEQ_NOT_STARTED; // Reset. + } else { + if (jt != U_JT_TRANSPARENT) { + if (str[i] == 0x200C /*ZWNJ*/) { + A1_sequence_status = SEQ_NEAR_END; + continue; + } else { + A1_sequence_status = SEQ_NOT_STARTED; // Reset. + } + } + } + } break; + default: + break; + } + if (A1_sequence_status == SEQ_NOT_STARTED) { + if (jt == U_JT_LEFT_JOINING || jt == U_JT_DUAL_JOINING) { + A1_sequence_status = SEQ_STARTED; + A1_scr = scr; + } + }; + + switch (A2_sequence_status) { + case SEQ_NEAR_END: { + if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) { + return false; // Mixed script. + } + if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) { + A2_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset. + } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) { + return false; // Invalid end of sequence. + } + } break; + case SEQ_STARTED_VIR: { + if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) { + A2_sequence_status = SEQ_NOT_STARTED; // Reset. + } else { + if (str[i] == 0x200C /*ZWNJ*/) { + A2_sequence_status = SEQ_NEAR_END; + continue; + } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) { + A2_sequence_status = SEQ_NOT_STARTED; // Reset. + } + } + } break; + case SEQ_STARTED: { + if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) { + A2_sequence_status = SEQ_NOT_STARTED; // Reset. + } else { + if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) { + A2_sequence_status = SEQ_STARTED_VIR; + } else if (cat != U_MODIFIER_LETTER) { + A2_sequence_status = SEQ_NOT_STARTED; // Reset. + } + } + } break; + default: + break; + } + if (A2_sequence_status == SEQ_NOT_STARTED) { + if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) { + A2_sequence_status = SEQ_STARTED; + A2_scr = scr; + } + } + + switch (B_sequence_status) { + case SEQ_NEAR_END: { + if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) { + return false; // Mixed script. + } + if (u_getIntPropertyValue(str[i], UCHAR_INDIC_SYLLABIC_CATEGORY) != U_INSC_VOWEL_DEPENDENT) { + B_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset. + } else { + return false; // Invalid end of sequence. + } + } break; + case SEQ_STARTED_VIR: { + if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) { + B_sequence_status = SEQ_NOT_STARTED; // Reset. + } else { + if (str[i] == 0x200D /*ZWJ*/) { + B_sequence_status = SEQ_NEAR_END; + continue; + } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) { + B_sequence_status = SEQ_NOT_STARTED; // Reset. + } + } + } break; + case SEQ_STARTED: { + if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) { + B_sequence_status = SEQ_NOT_STARTED; // Reset. + } else { + if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) { + B_sequence_status = SEQ_STARTED_VIR; + } else if (cat != U_MODIFIER_LETTER) { + B_sequence_status = SEQ_NOT_STARTED; // Reset. + } + } + } break; + default: + break; + } + if (B_sequence_status == SEQ_NOT_STARTED) { + if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) { + B_sequence_status = SEQ_STARTED; + B_scr = scr; + } + } + + if (u_hasBinaryProperty(str[i], UCHAR_PATTERN_SYNTAX) || u_hasBinaryProperty(str[i], UCHAR_PATTERN_WHITE_SPACE) || u_hasBinaryProperty(str[i], UCHAR_NONCHARACTER_CODE_POINT)) { + return false; // Not a XID_Start or XID_Continue character. + } + if (i == 0) { + if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || str[0] == 0x2118 || str[0] == 0x212E || str[0] == 0x309B || str[0] == 0x309C || str[0] == 0x005F)) { + return false; // Not a XID_Start character. + } + } else { + if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK || cat == U_DECIMAL_DIGIT_NUMBER || cat == U_CONNECTOR_PUNCTUATION || str[i] == 0x2118 || str[i] == 0x212E || str[i] == 0x309B || str[i] == 0x309C || str[i] == 0x1369 || str[i] == 0x1371 || str[i] == 0x00B7 || str[i] == 0x0387 || str[i] == 0x19DA || str[i] == 0x0E33 || str[i] == 0x0EB3 || str[i] == 0xFF9E || str[i] == 0xFF9F)) { + return false; // Not a XID_Continue character. + } + } + } + return true; +} + TextServerAdvanced::TextServerAdvanced() { _insert_num_systems_lang(); _insert_feature_sets(); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 87582e8bac..7ae329d616 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -65,11 +65,12 @@ #include <godot_cpp/classes/image.hpp> #include <godot_cpp/classes/image_texture.hpp> #include <godot_cpp/classes/ref.hpp> +#include <godot_cpp/classes/worker_thread_pool.hpp> #include <godot_cpp/templates/hash_map.hpp> #include <godot_cpp/templates/hash_set.hpp> #include <godot_cpp/templates/rid_owner.hpp> -#include <godot_cpp/templates/thread_work_pool.hpp> + #include <godot_cpp/templates/vector.hpp> using namespace godot; @@ -77,9 +78,9 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/object/worker_thread_pool.h" #include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" -#include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" #include "servers/text/text_server_extension.h" @@ -100,6 +101,7 @@ using namespace godot; #include <unicode/uloc.h> #include <unicode/unorm2.h> #include <unicode/uscript.h> +#include <unicode/uspoof.h> #include <unicode/ustring.h> #include <unicode/utypes.h> @@ -111,7 +113,10 @@ using namespace godot; #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H #include FT_BBOX_H - +#include FT_CONFIG_OPTIONS_H +#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER) +#warning FreeType is configured without Brotli support, built-in fonts will not be available. +#endif #include <hb-ft.h> #include <hb-ot.h> #endif @@ -232,7 +237,7 @@ class TextServerAdvanced : public TextServerExtension { double embolden = 0.0; Transform2D transform; - uint32_t style_flags = 0; + BitField<TextServer::FontStyle> style_flags = 0; String font_name; String style_name; @@ -252,10 +257,8 @@ class TextServerAdvanced : public TextServerExtension { const uint8_t *data_ptr; size_t data_size; int face_index = 0; - mutable ThreadWorkPool work_pool; ~FontAdvanced() { - work_pool.finish(); for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : cache) { memdelete(E.value); } @@ -486,8 +489,8 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const override; - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override; virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_style_name(const RID &p_font_rid) const override; @@ -664,7 +667,7 @@ public: virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; virtual RID shaped_text_get_parent(const RID &p_shaped) const override; - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; virtual bool shaped_text_shape(const RID &p_shaped) override; @@ -676,7 +679,7 @@ public: virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override; - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override; virtual bool shaped_text_is_ready(const RID &p_shaped) const override; @@ -702,7 +705,11 @@ public: virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override; + virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override; + virtual bool spoof_check(const String &p_string) const override; + virtual String strip_diacritics(const String &p_string) const override; + virtual bool is_valid_identifier(const String &p_string) const override; virtual String string_to_upper(const String &p_string, const String &p_language = "") const override; virtual String string_to_lower(const String &p_string, const String &p_language = "") const override; diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub index 121f38fcd5..429d2e1fdc 100644 --- a/modules/text_server_fb/SCsub +++ b/modules/text_server_fb/SCsub @@ -3,15 +3,16 @@ Import("env") Import("env_modules") -freetype_enabled = env.module_check_dependencies("text_server_fb", ["freetype"], True) -msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], True) +freetype_enabled = "freetype" in env.module_list +msdfgen_enabled = "msdfgen" in env.module_list env_text_server_fb = env_modules.Clone() if env["builtin_msdfgen"] and msdfgen_enabled: - env_text_server_fb.Append(CPPPATH=["#thirdparty/msdfgen"]) + env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"]) if env["builtin_freetype"] and freetype_enabled: - env_text_server_fb.Append(CPPPATH=["#thirdparty/freetype/include"]) + env_text_server_fb.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"]) + env_text_server_fb.Prepend(CPPPATH=["#thirdparty/freetype/include"]) env_text_server_fb.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index 6c9e10db18..de0a549900 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -184,15 +184,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"]) env.Append(CPPPATH=["../"]) sources = Glob("../*.cpp") -if env["platform"] == "osx": - methods.write_osx_plist( - f'./bin/libtextserver_fallback.osx.{env["target"]}.framework', - f'libtextserver_fallback.osx.{env["target"]}', +if env["platform"] == "macos": + methods.write_macos_plist( + f'./bin/libtextserver_fallback.macos.{env["target"]}.framework', + f'libtextserver_fallback.macos.{env["target"]}', "org.godotengine.textserver_fallback", "Fallback Text Server", ) library = env.SharedLibrary( - f'./bin/libtextserver_fallback.osx.{env["target"]}.framework/libtextserver_fallback.osx.{env["target"]}', + f'./bin/libtextserver_fallback.macos.{env["target"]}.framework/libtextserver_fallback.macos.{env["target"]}', source=sources, ) else: diff --git a/modules/text_server_fb/gdextension_build/methods.py b/modules/text_server_fb/gdextension_build/methods.py index d404f2851e..3c5229462c 100644 --- a/modules/text_server_fb/gdextension_build/methods.py +++ b/modules/text_server_fb/gdextension_build/methods.py @@ -98,7 +98,7 @@ def make_icu_data(target, source, env): g.write("#endif") -def write_osx_plist(target, binary_name, identifier, name): +def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resourece/", exist_ok=True) f = open(f"{target}/Resourece/Info.plist", "w") diff --git a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension index 1026c6cb85..9236555d63 100644 --- a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension +++ b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension @@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_fallback.linux.debug.64.so" linux.64.release = "bin/libtextserver_fallback.linux.release.64.so" windows.64.debug = "bin/libtextserver_fallback.windows.debug.64.dll" windows.64.release = "bin/libtextserver_fallback.windows.release.64.dll" -macos.debug = "bin/libtextserver_fallback.osx.debug.framework" -macos.release = "bin/libtextserver_fallback.osx.release.framework" +macos.debug = "bin/libtextserver_fallback.macos.debug.framework" +macos.release = "bin/libtextserver_fallback.macos.release.framework" diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 7ccc9e3533..55d912a10a 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -461,10 +461,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; - if (p_font_data->work_pool.get_thread_count() == 0) { - p_font_data->work_pool.init(); - } - p_font_data->work_pool.do_work(h, this, &TextServerFallback::_generateMTSDF_threaded, &td); + WorkerThreadPool::GroupID group_id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerFallback::_generateMTSDF_threaded, &td, h, -1, true, SNAME("TextServerFBRenderMSDF")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_id); msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); @@ -791,13 +789,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f } p_font_data->style_flags = 0; if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { - p_font_data->style_flags |= FONT_BOLD; + p_font_data->style_flags.set_flag(FONT_BOLD); } if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { - p_font_data->style_flags |= FONT_ITALIC; + p_font_data->style_flags.set_flag(FONT_ITALIC); } if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { - p_font_data->style_flags |= FONT_FIXED_WIDTH; + p_font_data->style_flags.set_flag(FONT_FIXED_WIDTH); } // Read OpenType variations. p_font_data->supported_varaitions.clear(); @@ -891,7 +889,7 @@ void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t fd->data_size = p_data_size; } -void TextServerFallback::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { +void TextServerFallback::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) { FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -964,7 +962,7 @@ int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const { return face_count; } -int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) const { +BitField<TextServer::FontStyle> TextServerFallback::font_get_style(const RID &p_font_rid) const { FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); @@ -2950,7 +2948,7 @@ RID TextServerFallback::shaped_text_get_parent(const RID &p_shaped) const { return sd->parent; } -double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) { +double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<JustificationFlag> p_jst_flags) { ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.0); @@ -2965,7 +2963,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double int start_pos = 0; int end_pos = sd->glyphs.size() - 1; - if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) { + if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) { int start, end, delta; if (sd->para_direction == DIRECTION_LTR) { start = sd->glyphs.size() - 1; @@ -2991,7 +2989,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double } double justification_width; - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { if (sd->overrun_trim_data.trim_pos >= 0) { end_pos = sd->overrun_trim_data.trim_pos; justification_width = sd->width_trimmed; @@ -3002,7 +3000,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double justification_width = sd->width; } - if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) { + if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) { // Trim spaces. while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat; @@ -3034,7 +3032,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double } } - if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { + if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) { double delta_width_per_space = (p_width - justification_width) / space_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; @@ -3052,7 +3050,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double sd->fit_width_minimum_reached = true; } - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { sd->width = justification_width; } @@ -3187,7 +3185,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(const RID &p_shape return true; } -void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { +void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) { ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped_line); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid."); @@ -3199,10 +3197,10 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l sd->text_trimmed = false; sd->overrun_trim_data.ellipsis_glyph_buf.clear(); - bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS; - bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY; - bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS; - bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE; + bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); + bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); + bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptrw(); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 8b10c9e99e..fef19d442b 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEXT_SERVER_FALLBACK_H -#define TEXT_SERVER_FALLBACK_H +#ifndef TEXT_SERVER_FB_H +#define TEXT_SERVER_FB_H /*************************************************************************/ /* Fallback Text Server provides simplified TS functionality, without */ @@ -79,9 +79,9 @@ using namespace godot; #include "servers/text/text_server_extension.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" -#include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" #include "modules/modules_enabled.gen.h" // For freetype, msdfgen. @@ -98,6 +98,10 @@ using namespace godot; #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H #include FT_BBOX_H +#include FT_CONFIG_OPTIONS_H +#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER) +#warning FreeType is configured without Brotli support, built-in fonts will not be available. +#endif #endif /*************************************************************************/ @@ -189,7 +193,7 @@ class TextServerFallback : public TextServerExtension { double embolden = 0.0; Transform2D transform; - uint32_t style_flags = 0; + BitField<TextServer::FontStyle> style_flags = 0; String font_name; String style_name; @@ -208,10 +212,7 @@ class TextServerFallback : public TextServerExtension { size_t data_size; int face_index = 0; - mutable ThreadWorkPool work_pool; - ~FontFallback() { - work_pool.finish(); for (const KeyValue<Vector2i, FontForSizeFallback *> &E : cache) { memdelete(E.value); } @@ -368,8 +369,8 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const override; - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override; virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_style_name(const RID &p_font_rid) const override; @@ -545,7 +546,7 @@ public: virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; virtual RID shaped_text_get_parent(const RID &p_shaped) const override; - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; virtual bool shaped_text_shape(const RID &p_shaped) override; @@ -557,7 +558,7 @@ public: virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override; - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override; virtual bool shaped_text_is_ready(const RID &p_shaped) const override; @@ -586,4 +587,4 @@ public: ~TextServerFallback(); }; -#endif // TEXT_SERVER_FALLBACK_H +#endif // TEXT_SERVER_FB_H diff --git a/modules/tga/SCsub b/modules/tga/SCsub index 067caa6ea0..ccd7d2ee37 100644 --- a/modules/tga/SCsub +++ b/modules/tga/SCsub @@ -5,5 +5,5 @@ Import("env_modules") env_tga = env_modules.Clone() -# Godot's own source files +# Godot source files env_tga.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/theora/config.py b/modules/theora/config.py index 7f354a8fda..9a27e8e132 100644 --- a/modules/theora/config.py +++ b/modules/theora/config.py @@ -1,7 +1,8 @@ def can_build(env, platform): if env["arch"].startswith("rv"): return False - return env.module_check_dependencies("theora", ["ogg", "vorbis"]) + env.module_add_dependencies("theora", ["ogg", "vorbis"]) + return True def configure(env): diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 8940ed6aff..00d799dc24 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -170,7 +170,7 @@ protected: static void _bind_methods(); public: - Ref<VideoStreamPlayback> instance_playback() override { + Ref<VideoStreamPlayback> instantiate_playback() override { Ref<VideoStreamPlaybackTheora> pb = memnew(VideoStreamPlaybackTheora); pb->set_audio_track(audio_track); pb->set_file(file); @@ -192,4 +192,4 @@ public: virtual String get_resource_type(const String &p_path) const; }; -#endif +#endif // VIDEO_STREAM_THEORA_H diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h index c147861c26..0d3de93956 100644 --- a/modules/tinyexr/image_loader_tinyexr.h +++ b/modules/tinyexr/image_loader_tinyexr.h @@ -40,4 +40,4 @@ public: ImageLoaderTinyEXR(); }; -#endif +#endif // IMAGE_LOADER_TINYEXR_H diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index 6d87b42c56..be7ede3ee0 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_UPNP_H -#define GODOT_UPNP_H +#ifndef UPNP_H +#define UPNP_H #include "core/object/ref_counted.h" @@ -121,4 +121,4 @@ public: VARIANT_ENUM_CAST(UPNP::UPNPResult) -#endif // GODOT_UPNP_H +#endif // UPNP_H diff --git a/modules/upnp/upnp_device.h b/modules/upnp/upnp_device.h index 18491dce27..1c9dc82df5 100644 --- a/modules/upnp/upnp_device.h +++ b/modules/upnp/upnp_device.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_UPNP_DEVICE_H -#define GODOT_UPNP_DEVICE_H +#ifndef UPNP_DEVICE_H +#define UPNP_DEVICE_H #include "core/object/ref_counted.h" @@ -90,4 +90,4 @@ private: VARIANT_ENUM_CAST(UPNPDevice::IGDStatus) -#endif // GODOT_UPNP_DEVICE_H +#endif // UPNP_DEVICE_H diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index d9419292ba..7f8e9d8254 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -42,10 +42,32 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/check_button.h" +#include "scene/gui/graph_edit.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #ifdef TOOLS_ENABLED + +void VisualScriptEditedProperty::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualScriptEditedProperty::set_edited_property); + ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualScriptEditedProperty::get_edited_property); + + ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property"); +} + +void VisualScriptEditedProperty::set_edited_property(Variant p_variant) { + edited_property = p_variant; +} + +Variant VisualScriptEditedProperty::get_edited_property() const { + return edited_property; +} + +///////////////// + class VisualScriptEditorSignalEdit : public Object { GDCLASS(VisualScriptEditorSignalEdit, Object); @@ -376,6 +398,12 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { case Variant::VECTOR3I: color = Color(0.84, 0.49, 0.93); break; + case Variant::VECTOR4: + color = Color(0.84, 0.49, 0.94); + break; + case Variant::VECTOR4I: + color = Color(0.84, 0.49, 0.94); + break; case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break; @@ -681,8 +709,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_meta("__vnode", node); gnode->set_name(itos(E)); - gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E)); - gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E), CONNECT_DEFERRED); + gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved).bind(E)); + gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node).bind(E), CONNECT_DEFERRED); { Ref<VisualScriptFunction> v = node; @@ -702,7 +730,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Button *btn = memnew(Button); btn->set_text(TTR("Add Input Port")); hbnc->add_child(btn); - btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E), CONNECT_DEFERRED); + btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port).bind(E), CONNECT_DEFERRED); } if (nd_list->is_output_port_editable()) { if (nd_list->is_input_port_editable()) { @@ -712,7 +740,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Button *btn = memnew(Button); btn->set_text(TTR("Add Output Port")); hbnc->add_child(btn); - btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E), CONNECT_DEFERRED); + btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port).bind(E), CONNECT_DEFERRED); } gnode->add_child(hbnc); } else if (Object::cast_to<VisualScriptExpression>(node.ptr())) { @@ -722,7 +750,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { line_edit->set_expand_to_text_length_enabled(true); line_edit->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts"))); gnode->add_child(line_edit); - line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E)); + line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed).bind(E)); } else { String text = node->get_text(); if (!text.is_empty()) { @@ -738,7 +766,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_comment(true); gnode->set_resizable(true); gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE); - gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E)); + gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized).bind(E)); } if (node_styles.has(node->get_category())) { @@ -841,8 +869,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); name_box->set_text(left_name); name_box->set_expand_to_text_length_enabled(true); - name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E)); - name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, true)); + name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size).bind(E)); + name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out).bind(name_box, E, i, true)); } else { hbc->add_child(memnew(Label(left_name))); } @@ -855,13 +883,13 @@ void VisualScriptEditor::_update_graph(int p_only_id) { opbtn->select(left_type); opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); hbc->add_child(opbtn); - opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, true), CONNECT_DEFERRED); + opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type).bind(E, i, true), CONNECT_DEFERRED); } Button *rmbtn = memnew(Button); rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); hbc->add_child(rmbtn); - rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E, i), CONNECT_DEFERRED); + rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port).bind(E, i), CONNECT_DEFERRED); } else { hbc->add_child(memnew(Label(left_name))); } @@ -880,7 +908,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { if (left_type == Variant::COLOR) { button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button), varray(button, value)); + button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button).bind(button, value)); } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { Ref<Resource> res = value; Array arr; @@ -935,7 +963,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } else { button->set_text(value); } - button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E, i)); + button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited).bind(button, E, i)); hbc2->add_child(button); } } else { @@ -959,7 +987,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Button *rmbtn = memnew(Button); rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); hbc->add_child(rmbtn); - rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E, i), CONNECT_DEFERRED); + rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port).bind(E, i), CONNECT_DEFERRED); if (nd_list->is_output_port_type_editable()) { OptionButton *opbtn = memnew(OptionButton); @@ -969,7 +997,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { opbtn->select(right_type); opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); hbc->add_child(opbtn); - opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, false), CONNECT_DEFERRED); + opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type).bind(E, i, false), CONNECT_DEFERRED); } if (nd_list->is_output_port_name_editable()) { @@ -978,8 +1006,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); name_box->set_text(right_name); name_box->set_expand_to_text_length_enabled(true); - name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E)); - name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, false)); + name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size).bind(E)); + name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out).bind(name_box, E, i, false)); } else { hbc->add_child(memnew(Label(right_name))); } @@ -1227,7 +1255,7 @@ void VisualScriptEditor::_member_selected() { selected = ti->get_metadata(0); if (ti->get_parent() == members->get_root()->get_first_child()) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); #else bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -1464,7 +1492,7 @@ void VisualScriptEditor::_add_func_input() { func_input_vbox->add_child(hbox); hbox->set_meta("id", hbox->get_index()); - delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input), varray(hbox)); + delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input).bind(hbox)); name_box->select_all(); name_box->grab_focus(); @@ -2208,7 +2236,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & String(d["type"]) == "files" || String(d["type"]) == "nodes")) { if (String(d["type"]) == "obj_property") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature.")); @@ -2216,7 +2244,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "nodes") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a simple reference to the node.")); @@ -2224,7 +2252,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "visual_script_variable_drag") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Variable Setter.")); @@ -2287,7 +2315,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "visual_script_variable_drag") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_set = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_set = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2396,7 +2424,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "files") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_preload = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_preload = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2459,7 +2487,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da return; } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_node = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_node = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2524,7 +2552,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Node *node = Object::cast_to<Node>(obj); Vector2 pos = _get_pos_in_graph(p_point); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_get = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_get = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -3378,7 +3406,7 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua } void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); #else bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -3892,14 +3920,14 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V return new_id; } -void VisualScriptEditor::_default_value_changed() { +void VisualScriptEditor::_default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) { Ref<VisualScriptNode> vsn = script->get_node(editing_id); if (vsn.is_null()) { return; } undo_redo->create_action(TTR("Change Input Value")); - undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, default_value_edit->get_variant()); + undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, p_value); undo_redo->add_undo_method(vsn.ptr(), "set_default_input_value", editing_input, vsn->get_default_input_value(editing_input)); undo_redo->add_do_method(this, "_update_graph", editing_id); @@ -3922,9 +3950,6 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i Variant::construct(pinfo.type, existing, &existingp, 1, ce); } - default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y) * graph->get_zoom()); - default_value_edit->reset_size(); - if (pinfo.type == Variant::NODE_PATH) { Node *edited_scene = get_tree()->get_edited_scene_root(); if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open). @@ -3942,11 +3967,33 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i } } - if (default_value_edit->edit(nullptr, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) { - if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) { - default_value_edit->popup_centered_ratio(); + edited_default_property_holder->set_edited_property(existing); + + if (default_property_editor) { + default_property_editor->disconnect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + default_property_editor_popup->remove_child(default_property_editor); + } + + default_property_editor = EditorInspector::instantiate_property_editor(edited_default_property_holder.ptr(), pinfo.type, "edited_property", pinfo.hint, pinfo.hint_string, PROPERTY_USAGE_NONE); + if (default_property_editor) { + default_property_editor->set_object_and_property(edited_default_property_holder.ptr(), "edited_property"); + default_property_editor->update_property(); + default_property_editor->set_name_split_ratio(0); + default_property_editor_popup->add_child(default_property_editor); + + default_property_editor->connect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + + Button *button = Object::cast_to<Button>(p_button); + if (button) { + default_property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom()); + } + + default_property_editor_popup->reset_size(); + + if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT || !button) { + default_property_editor_popup->popup_centered_ratio(); } else { - default_value_edit->popup(); + default_property_editor_popup->popup(); } } @@ -3982,9 +4029,9 @@ void VisualScriptEditor::_notification(int p_what) { case NOTIFICATION_READY: { variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members)); - variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED); + variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph).bind(-1), CONNECT_DEFERRED); signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members)); - signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED); + signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph).bind(-1), CONNECT_DEFERRED); [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { @@ -4602,7 +4649,7 @@ VisualScriptEditor::VisualScriptEditor() { members->set_hide_root(true); members->connect("button_clicked", callable_mp(this, &VisualScriptEditor::_member_button)); members->connect("item_edited", callable_mp(this, &VisualScriptEditor::_member_edited)); - members->connect("cell_selected", callable_mp(this, &VisualScriptEditor::_member_selected), varray(), CONNECT_DEFERRED); + members->connect("cell_selected", callable_mp(this, &VisualScriptEditor::_member_selected), CONNECT_DEFERRED); members->connect("gui_input", callable_mp(this, &VisualScriptEditor::_members_gui_input)); members->connect("item_mouse_selected", callable_mp(this, &VisualScriptEditor::_member_rmb_selected)); members->set_allow_rmb_select(true); @@ -4628,7 +4675,7 @@ VisualScriptEditor::VisualScriptEditor() { graph = memnew(GraphEdit); add_child(graph); graph->set_v_size_flags(Control::SIZE_EXPAND_FILL); - graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + graph->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); graph->set_show_zoom_label(true); graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected)); graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); @@ -4789,9 +4836,11 @@ VisualScriptEditor::VisualScriptEditor() { set_process_input(true); - default_value_edit = memnew(CustomPropertyEditor); - add_child(default_value_edit); - default_value_edit->connect("variant_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + default_property_editor_popup = memnew(PopupPanel); + default_property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE); + add_child(default_property_editor_popup); + + edited_default_property_holder.instantiate(); new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); @@ -4821,12 +4870,15 @@ VisualScriptEditor::VisualScriptEditor() { base_type_map.insert("Rect2i", Variant::RECT2I); base_type_map.insert("Vector3", Variant::VECTOR3); base_type_map.insert("Vector3i", Variant::VECTOR3I); + base_type_map.insert("Vector4", Variant::VECTOR4); + base_type_map.insert("Vector4i", Variant::VECTOR4I); base_type_map.insert("Transform2D", Variant::TRANSFORM2D); base_type_map.insert("Plane", Variant::PLANE); base_type_map.insert("Quaternion", Variant::QUATERNION); base_type_map.insert("AABB", Variant::AABB); base_type_map.insert("Basis", Variant::BASIS); base_type_map.insert("Transform3D", Variant::TRANSFORM3D); + base_type_map.insert("Projection", Variant::PROJECTION); base_type_map.insert("Color", Variant::COLOR); base_type_map.insert("NodePath", Variant::NODE_PATH); base_type_map.insert("RID", Variant::RID); diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index fd59d22cbe..6b337e52f6 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -28,21 +28,37 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPT_EDITOR_H -#define VISUALSCRIPT_EDITOR_H +#ifndef VISUAL_SCRIPT_EDITOR_H +#define VISUAL_SCRIPT_EDITOR_H #include "../visual_script.h" #include "editor/create_dialog.h" #include "editor/plugins/script_editor_plugin.h" -#include "editor/property_editor.h" -#include "scene/gui/graph_edit.h" #include "visual_script_property_selector.h" +class GraphEdit; + class VisualScriptEditorSignalEdit; class VisualScriptEditorVariableEdit; #ifdef TOOLS_ENABLED +class VisualScriptEditedProperty : public RefCounted { + GDCLASS(VisualScriptEditedProperty, RefCounted); + +private: + Variant edited_property; + +protected: + static void _bind_methods(); + +public: + void set_edited_property(Variant p_variant); + Variant get_edited_property() const; + + VisualScriptEditedProperty() {} +}; + // TODO: Maybe this class should be refactored. // See https://github.com/godotengine/godot/issues/51913 class VisualScriptEditor : public ScriptEditorBase { @@ -115,7 +131,9 @@ class VisualScriptEditor : public ScriptEditorBase { AcceptDialog *edit_variable_dialog = nullptr; EditorInspector *edit_variable_edit = nullptr; - CustomPropertyEditor *default_value_edit = nullptr; + PopupPanel *default_property_editor_popup = nullptr; + EditorProperty *default_property_editor = nullptr; + Ref<VisualScriptEditedProperty> edited_default_property_holder; UndoRedo *undo_redo = nullptr; @@ -276,7 +294,7 @@ class VisualScriptEditor : public ScriptEditorBase { int data_disconnect_node = 0; int data_disconnect_port = 0; - void _default_value_changed(); + void _default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing); void _default_value_edited(Node *p_button, int p_id, int p_input_port); void _menu_option(int p_what); @@ -374,4 +392,4 @@ public: #endif -#endif // VISUALSCRIPT_EDITOR_H +#endif // VISUAL_SCRIPT_EDITOR_H diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index f98ce5bb26..712c89368b 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -39,6 +39,7 @@ #include "editor/doc_tools.h" #include "editor/editor_feature_profile.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/main/node.h" #include "scene/main/window.h" diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 91d81bba47..4de626467e 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPT_PROPERTYSELECTOR_H -#define VISUALSCRIPT_PROPERTYSELECTOR_H +#ifndef VISUAL_SCRIPT_PROPERTY_SELECTOR_H +#define VISUAL_SCRIPT_PROPERTY_SELECTOR_H #include "../visual_script.h" #include "editor/editor_help.h" -#include "editor/property_editor.h" #include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" class VisualScriptPropertySelector : public ConfirmationDialog { GDCLASS(VisualScriptPropertySelector, ConfirmationDialog); @@ -226,4 +226,4 @@ public: SearchRunner(VisualScriptPropertySelector *p_selector_ui, Tree *p_results_tree); }; -#endif // VISUALSCRIPT_PROPERTYSELECTOR_H +#endif // VISUAL_SCRIPT_PROPERTY_SELECTOR_H diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 742fa75bb7..73249371cd 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -279,7 +279,7 @@ void VisualScript::add_node(int p_id, const Ref<VisualScriptNode> &p_node, const nd.pos = p_pos; Ref<VisualScriptNode> vsn = p_node; - vsn->connect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed), varray(p_id)); + vsn->connect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed).bind(p_id)); vsn->script_used = Ref<VisualScript>(this); vsn->validate_input_default_values(); // Validate when fully loaded. @@ -948,7 +948,7 @@ bool VisualScript::are_subnodes_edited() const { } #endif -const Vector<Multiplayer::RPCConfig> VisualScript::get_rpc_methods() const { +const Variant VisualScript::get_rpc_config() const { return rpc_functions; } @@ -1012,22 +1012,16 @@ void VisualScript::_set_data(const Dictionary &p_data) { for (const KeyValue<StringName, Function> &E : functions) { if (E.value.func_id >= 0 && nodes.has(E.value.func_id)) { Ref<VisualScriptFunction> vsf = nodes[E.value.func_id].node; - if (vsf.is_valid()) { - if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) { - Multiplayer::RPCConfig nd; - nd.name = E.key; - nd.rpc_mode = vsf->get_rpc_mode(); - nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO - if (rpc_functions.find(nd) == -1) { - rpc_functions.push_back(nd); - } - } + if (!vsf.is_valid() || vsf->get_rpc_mode() == MultiplayerAPI::RPC_MODE_DISABLED) { + continue; } + Dictionary nd; + nd["rpc_mode"] = vsf->get_rpc_mode(); + nd["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO + nd["call_local"] = false; // TODO + rpc_functions[E.key] = nd; } } - - // Sort so we are 100% that they are always the same. - rpc_functions.sort_custom<Multiplayer::SortRPCConfig>(); } Dictionary VisualScript::_get_data() const { @@ -1212,6 +1206,10 @@ bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { +#ifdef TOOLS_ENABLED + p_properties->push_back(script->get_class_category()); +#endif // TOOLS_ENABLED + for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) { if (!E.value._export) { continue; @@ -1811,8 +1809,8 @@ Ref<Script> VisualScriptInstance::get_script() const { return script; } -const Vector<Multiplayer::RPCConfig> VisualScriptInstance::get_rpc_methods() const { - return script->get_rpc_methods(); +const Variant VisualScriptInstance::get_rpc_config() const { + return script->get_rpc_config(); } void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) { @@ -2128,7 +2126,14 @@ void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p binds.push_back(p_binds[i]); } binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing - p_obj->connect(p_signal, Callable(this, "_signal_callback"), binds, CONNECT_ONESHOT); + + Vector<const Variant *> bind_ptrs; + bind_ptrs.resize(p_binds.size()); + for (int i = 0; i < bind_ptrs.size(); i++) { + bind_ptrs.write[i] = &binds.write[i]; + } + + p_obj->connect(p_signal, Callable(this, "_signal_callback").bindp((const Variant **)bind_ptrs.ptr(), bind_ptrs.size()), CONNECT_ONESHOT); } bool VisualScriptFunctionState::is_valid() const { diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 716310f59b..14cb14e8d9 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -235,7 +235,7 @@ private: HashMap<StringName, Function> functions; HashMap<StringName, Variable> variables; HashMap<StringName, Vector<Argument>> custom_signals; - Vector<Multiplayer::RPCConfig> rpc_functions; + Dictionary rpc_functions; HashMap<Object *, VisualScriptInstance *> instances; @@ -363,7 +363,7 @@ public: virtual int get_member_line(const StringName &p_member) const override; - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; + virtual const Variant get_rpc_config() const override; #ifdef TOOLS_ENABLED virtual bool are_subnodes_edited() const; @@ -444,7 +444,7 @@ public: virtual ScriptLanguage *get_language(); - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const; + virtual const Variant get_rpc_config() const; VisualScriptInstance(); ~VisualScriptInstance(); diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h index c93eb0686b..7e10f98f36 100644 --- a/modules/visual_script/visual_script_expression.h +++ b/modules/visual_script/visual_script_expression.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPTEXPRESSION_H -#define VISUALSCRIPTEXPRESSION_H +#ifndef VISUAL_SCRIPT_EXPRESSION_H +#define VISUAL_SCRIPT_EXPRESSION_H #include "visual_script.h" #include "visual_script_builtin_funcs.h" @@ -281,4 +281,4 @@ public: void register_visual_script_expression_node(); -#endif // VISUALSCRIPTEXPRESSION_H +#endif // VISUAL_SCRIPT_EXPRESSION_H diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 2dfc6da181..5907e6a489 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -90,7 +90,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value } if (p_name == "rpc/mode") { - rpc_mode = Multiplayer::RPCMode(int(p_value)); + rpc_mode = MultiplayerAPI::RPCMode(int(p_value)); return true; } @@ -261,11 +261,11 @@ int VisualScriptFunction::get_argument_count() const { return arguments.size(); } -void VisualScriptFunction::set_rpc_mode(Multiplayer::RPCMode p_mode) { +void VisualScriptFunction::set_rpc_mode(MultiplayerAPI::RPCMode p_mode) { rpc_mode = p_mode; } -Multiplayer::RPCMode VisualScriptFunction::get_rpc_mode() const { +MultiplayerAPI::RPCMode VisualScriptFunction::get_rpc_mode() const { return rpc_mode; } @@ -311,14 +311,14 @@ void VisualScriptFunction::reset_state() { stack_size = 256; stack_less = false; sequenced = true; - rpc_mode = Multiplayer::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; } VisualScriptFunction::VisualScriptFunction() { stack_size = 256; stack_less = false; sequenced = true; - rpc_mode = Multiplayer::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; } void VisualScriptFunction::set_stack_less(bool p_enable) { @@ -4025,6 +4025,8 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4), create_node_deconst_typed<Variant::Type::VECTOR4>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4I), create_node_deconst_typed<Variant::Type::VECTOR4I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>); @@ -4034,6 +4036,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM3D), create_node_deconst_typed<Variant::Type::TRANSFORM3D>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PROJECTION), create_node_deconst_typed<Variant::Type::PROJECTION>); VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>); for (int i = 1; i < Variant::VARIANT_MAX; i++) { diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 18573f8682..35e3c490cd 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -33,6 +33,7 @@ #include "core/object/gdvirtual.gen.inc" #include "core/object/script_language.h" +#include "scene/main/multiplayer_api.h" #include "visual_script.h" class VisualScriptFunction : public VisualScriptNode { @@ -49,7 +50,7 @@ class VisualScriptFunction : public VisualScriptNode { bool stack_less; int stack_size; - Multiplayer::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; bool sequenced; protected: @@ -90,8 +91,8 @@ public: void set_stack_size(int p_size); int get_stack_size() const; - void set_rpc_mode(Multiplayer::RPCMode p_mode); - Multiplayer::RPCMode get_rpc_mode() const; + void set_rpc_mode(MultiplayerAPI::RPCMode p_mode); + MultiplayerAPI::RPCMode get_rpc_mode() const; virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override; diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 89a6b03ff8..8315eea614 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -34,7 +34,7 @@ #include "core/variant/typed_array.h" #include "thirdparty/libogg/ogg/ogg.h" -int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) { +int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) { ERR_FAIL_COND_V(!ready, 0); if (!active) { @@ -43,28 +43,93 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram int todo = p_frames; - int start_buffer = 0; + int beat_length_frames = -1; + bool beat_loop = vorbis_stream->has_loop(); + if (beat_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) { + beat_length_frames = vorbis_stream->get_beat_count() * vorbis_data->get_sampling_rate() * 60 / vorbis_stream->get_bpm(); + } while (todo > 0 && active) { AudioFrame *buffer = p_buffer; - if (start_buffer > 0) { - buffer = buffer + start_buffer; + buffer += p_frames - todo; + + int to_mix = todo; + if (beat_length_frames >= 0 && (beat_length_frames - (int)frames_mixed) < to_mix) { + to_mix = MAX(0, beat_length_frames - (int)frames_mixed); } - int mixed = _mix_frames_vorbis(buffer, todo); + + int mixed = _mix_frames_vorbis(buffer, to_mix); ERR_FAIL_COND_V(mixed < 0, 0); todo -= mixed; frames_mixed += mixed; - start_buffer += mixed; + + if (loop_fade_remaining < FADE_SIZE) { + int to_fade = loop_fade_remaining + MIN(FADE_SIZE - loop_fade_remaining, mixed); + for (int i = loop_fade_remaining; i < to_fade; i++) { + buffer[i - loop_fade_remaining] += loop_fade[i] * (float(FADE_SIZE - i) / float(FADE_SIZE)); + } + loop_fade_remaining = to_fade; + } + + if (beat_length_frames >= 0) { + /** + * Length determined by beat length + * This code is commented out because, in practice, it is prefered that the fade + * is done by the transitioner and this stream just goes on until it ends while fading out. + * + * End fade implementation is left here for reference in case at some point this feature + * is desired. + + if (!beat_loop && (int)frames_mixed > beat_length_frames - FADE_SIZE) { + print_line("beat length fade/after mix?"); + //No loop, just fade and finish + for (int i = 0; i < mixed; i++) { + int idx = frames_mixed + i - mixed; + buffer[i] *= 1.0 - float(MAX(0, (idx - (beat_length_frames - FADE_SIZE)))) / float(FADE_SIZE); + } + if ((int)frames_mixed == beat_length_frames) { + for (int i = p_frames - todo; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + active = false; + break; + } + } else + **/ + + if (beat_loop && beat_length_frames <= (int)frames_mixed) { + // End of file when doing beat-based looping. <= used instead of == because importer editing + if (!have_packets_left && !have_samples_left) { + //Nothing remaining, so do nothing. + loop_fade_remaining = FADE_SIZE; + } else { + // Add some loop fade; + int faded_mix = _mix_frames_vorbis(loop_fade, FADE_SIZE); + + for (int i = faded_mix; i < FADE_SIZE; i++) { + // In case lesss was mixed, pad with zeros + loop_fade[i] = AudioFrame(0, 0); + } + loop_fade_remaining = 0; + } + + seek(vorbis_stream->loop_offset); + loops++; + // We still have buffer to fill, start from this element in the next iteration. + continue; + } + } + if (!have_packets_left && !have_samples_left) { - //end of file! + // Actual end of file! bool is_not_empty = mixed > 0 || vorbis_stream->get_length() > 0; if (vorbis_stream->loop && is_not_empty) { //loop seek(vorbis_stream->loop_offset); loops++; - // we still have buffer to fill, start from this element in the next iteration. - start_buffer = p_frames - todo; + // We still have buffer to fill, start from this element in the next iteration. + } else { for (int i = p_frames - todo; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); @@ -76,7 +141,7 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram return p_frames - todo; } -int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) { +int AudioStreamPlaybackOggVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) { ERR_FAIL_COND_V(!ready, 0); if (!have_samples_left) { ogg_packet *packet = nullptr; @@ -119,18 +184,18 @@ int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p return frames; } -float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() { +float AudioStreamPlaybackOggVorbis::get_stream_sampling_rate() { return vorbis_data->get_sampling_rate(); } -bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() { +bool AudioStreamPlaybackOggVorbis::_alloc_vorbis() { vorbis_info_init(&info); info_is_allocated = true; vorbis_comment_init(&comment); comment_is_allocated = true; ERR_FAIL_COND_V(vorbis_data.is_null(), false); - vorbis_data_playback = vorbis_data->instance_playback(); + vorbis_data_playback = vorbis_data->instantiate_playback(); ogg_packet *packet; int err; @@ -158,31 +223,36 @@ bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() { return true; } -void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) { +void AudioStreamPlaybackOggVorbis::start(float p_from_pos) { ERR_FAIL_COND(!ready); + loop_fade_remaining = FADE_SIZE; active = true; seek(p_from_pos); loops = 0; begin_resample(); } -void AudioStreamPlaybackOGGVorbis::stop() { +void AudioStreamPlaybackOggVorbis::stop() { active = false; } -bool AudioStreamPlaybackOGGVorbis::is_playing() const { +bool AudioStreamPlaybackOggVorbis::is_playing() const { return active; } -int AudioStreamPlaybackOGGVorbis::get_loop_count() const { +int AudioStreamPlaybackOggVorbis::get_loop_count() const { return loops; } -float AudioStreamPlaybackOGGVorbis::get_playback_position() const { +float AudioStreamPlaybackOggVorbis::get_playback_position() const { return float(frames_mixed) / vorbis_data->get_sampling_rate(); } -void AudioStreamPlaybackOGGVorbis::seek(float p_time) { +void AudioStreamPlaybackOggVorbis::tag_used_streams() { + vorbis_stream->tag_used(get_playback_position()); +} + +void AudioStreamPlaybackOggVorbis::seek(float p_time) { ERR_FAIL_COND(!ready); ERR_FAIL_COND(vorbis_stream.is_null()); if (!active) { @@ -300,7 +370,7 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) { } } -AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { +AudioStreamPlaybackOggVorbis::~AudioStreamPlaybackOggVorbis() { if (block_is_allocated) { vorbis_block_clear(&block); } @@ -315,13 +385,13 @@ AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { } } -Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { - Ref<AudioStreamPlaybackOGGVorbis> ovs; +Ref<AudioStreamPlayback> AudioStreamOggVorbis::instantiate_playback() { + Ref<AudioStreamPlaybackOggVorbis> ovs; ERR_FAIL_COND_V(packet_sequence.is_null(), nullptr); ovs.instantiate(); - ovs->vorbis_stream = Ref<AudioStreamOGGVorbis>(this); + ovs->vorbis_stream = Ref<AudioStreamOggVorbis>(this); ovs->vorbis_data = packet_sequence; ovs->frames_mixed = 0; ovs->active = false; @@ -333,11 +403,11 @@ Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { return nullptr; } -String AudioStreamOGGVorbis::get_stream_name() const { +String AudioStreamOggVorbis::get_stream_name() const { return ""; //return stream_name; } -void AudioStreamOGGVorbis::maybe_update_info() { +void AudioStreamOggVorbis::maybe_update_info() { ERR_FAIL_COND(packet_sequence.is_null()); vorbis_info info; @@ -347,7 +417,7 @@ void AudioStreamOGGVorbis::maybe_update_info() { vorbis_info_init(&info); vorbis_comment_init(&comment); - Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instance_playback(); + Ref<OggPacketSequencePlayback> packet_sequence_playback = packet_sequence->instantiate_playback(); for (int i = 0; i < 3; i++) { ogg_packet *packet; @@ -373,57 +443,99 @@ void AudioStreamOGGVorbis::maybe_update_info() { vorbis_info_clear(&info); } -void AudioStreamOGGVorbis::set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence) { +void AudioStreamOggVorbis::set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence) { packet_sequence = p_packet_sequence; if (packet_sequence.is_valid()) { maybe_update_info(); } } -Ref<OGGPacketSequence> AudioStreamOGGVorbis::get_packet_sequence() const { +Ref<OggPacketSequence> AudioStreamOggVorbis::get_packet_sequence() const { return packet_sequence; } -void AudioStreamOGGVorbis::set_loop(bool p_enable) { +void AudioStreamOggVorbis::set_loop(bool p_enable) { loop = p_enable; } -bool AudioStreamOGGVorbis::has_loop() const { +bool AudioStreamOggVorbis::has_loop() const { return loop; } -void AudioStreamOGGVorbis::set_loop_offset(float p_seconds) { +void AudioStreamOggVorbis::set_loop_offset(float p_seconds) { loop_offset = p_seconds; } -float AudioStreamOGGVorbis::get_loop_offset() const { +float AudioStreamOggVorbis::get_loop_offset() const { return loop_offset; } -float AudioStreamOGGVorbis::get_length() const { +float AudioStreamOggVorbis::get_length() const { ERR_FAIL_COND_V(packet_sequence.is_null(), 0); return packet_sequence->get_length(); } -bool AudioStreamOGGVorbis::is_monophonic() const { +void AudioStreamOggVorbis::set_bpm(double p_bpm) { + ERR_FAIL_COND(p_bpm < 0); + bpm = p_bpm; + emit_changed(); +} + +double AudioStreamOggVorbis::get_bpm() const { + return bpm; +} + +void AudioStreamOggVorbis::set_beat_count(int p_beat_count) { + ERR_FAIL_COND(p_beat_count < 0); + beat_count = p_beat_count; + emit_changed(); +} + +int AudioStreamOggVorbis::get_beat_count() const { + return beat_count; +} + +void AudioStreamOggVorbis::set_bar_beats(int p_bar_beats) { + ERR_FAIL_COND(p_bar_beats < 2); + bar_beats = p_bar_beats; + emit_changed(); +} + +int AudioStreamOggVorbis::get_bar_beats() const { + return bar_beats; +} + +bool AudioStreamOggVorbis::is_monophonic() const { return false; } -void AudioStreamOGGVorbis::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOGGVorbis::set_packet_sequence); - ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOGGVorbis::get_packet_sequence); +void AudioStreamOggVorbis::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOggVorbis::set_packet_sequence); + ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOggVorbis::get_packet_sequence); + + ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOggVorbis::set_loop); + ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOggVorbis::has_loop); + + ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOggVorbis::set_loop_offset); + ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOggVorbis::get_loop_offset); + + ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamOggVorbis::set_bpm); + ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamOggVorbis::get_bpm); - ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOGGVorbis::set_loop); - ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOGGVorbis::has_loop); + ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamOggVorbis::set_beat_count); + ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamOggVorbis::get_beat_count); - ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset); - ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset); + ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamOggVorbis::set_bar_beats); + ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamOggVorbis::get_bar_beats); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_sequence", "get_packet_sequence"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset"); } -AudioStreamOGGVorbis::AudioStreamOGGVorbis() {} +AudioStreamOggVorbis::AudioStreamOggVorbis() {} -AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {} +AudioStreamOggVorbis::~AudioStreamOggVorbis() {} diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index b09ef9ff5d..0350e1f761 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -28,23 +28,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIO_STREAM_LIBVORBIS_H -#define AUDIO_STREAM_LIBVORBIS_H +#ifndef AUDIO_STREAM_OGG_VORBIS_H +#define AUDIO_STREAM_OGG_VORBIS_H #include "core/variant/variant.h" #include "modules/ogg/ogg_packet_sequence.h" #include "servers/audio/audio_stream.h" #include "thirdparty/libvorbis/vorbis/codec.h" -class AudioStreamOGGVorbis; +class AudioStreamOggVorbis; -class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled { - GDCLASS(AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled); +class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled { + GDCLASS(AudioStreamPlaybackOggVorbis, AudioStreamPlaybackResampled); uint32_t frames_mixed = 0; bool active = false; int loops = 0; + enum { + FADE_SIZE = 256 + }; + AudioFrame loop_fade[FADE_SIZE]; + int loop_fade_remaining = FADE_SIZE; + vorbis_info info; vorbis_comment comment; vorbis_dsp_state dsp_state; @@ -60,12 +66,13 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled { bool have_samples_left = false; bool have_packets_left = false; - friend class AudioStreamOGGVorbis; + friend class AudioStreamOggVorbis; - Ref<OGGPacketSequence> vorbis_data; - Ref<OGGPacketSequencePlayback> vorbis_data_playback; - Ref<AudioStreamOGGVorbis> vorbis_stream; + Ref<OggPacketSequence> vorbis_data; + Ref<OggPacketSequencePlayback> vorbis_data_playback; + Ref<AudioStreamOggVorbis> vorbis_stream; + int _mix_frames(AudioFrame *p_buffer, int p_frames); int _mix_frames_vorbis(AudioFrame *p_buffer, int p_frames); // Allocates vorbis data structures. Returns true upon success, false on failure. @@ -85,16 +92,18 @@ public: virtual float get_playback_position() const override; virtual void seek(float p_time) override; - AudioStreamPlaybackOGGVorbis() {} - ~AudioStreamPlaybackOGGVorbis(); + virtual void tag_used_streams() override; + + AudioStreamPlaybackOggVorbis() {} + ~AudioStreamPlaybackOggVorbis(); }; -class AudioStreamOGGVorbis : public AudioStream { - GDCLASS(AudioStreamOGGVorbis, AudioStream); +class AudioStreamOggVorbis : public AudioStream { + GDCLASS(AudioStreamOggVorbis, AudioStream); OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged. RES_BASE_EXTENSION("oggvorbisstr"); - friend class AudioStreamPlaybackOGGVorbis; + friend class AudioStreamPlaybackOggVorbis; int channels = 1; float length = 0.0; @@ -105,30 +114,43 @@ class AudioStreamOGGVorbis : public AudioStream { // Also causes allocation and deallocation. void maybe_update_info(); - Ref<OGGPacketSequence> packet_sequence; + Ref<OggPacketSequence> packet_sequence; + + double bpm = 0; + int beat_count = 0; + int bar_beats = 4; protected: static void _bind_methods(); public: void set_loop(bool p_enable); - bool has_loop() const; + virtual bool has_loop() const override; void set_loop_offset(float p_seconds); float get_loop_offset() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + void set_bpm(double p_bpm); + virtual double get_bpm() const override; + + void set_beat_count(int p_beat_count); + virtual int get_beat_count() const override; + + void set_bar_beats(int p_bar_beats); + virtual int get_bar_beats() const override; + + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; - void set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence); - Ref<OGGPacketSequence> get_packet_sequence() const; + void set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence); + Ref<OggPacketSequence> get_packet_sequence() const; virtual float get_length() const override; //if supported, otherwise return 0 virtual bool is_monophonic() const override; - AudioStreamOGGVorbis(); - virtual ~AudioStreamOGGVorbis(); + AudioStreamOggVorbis(); + virtual ~AudioStreamOggVorbis(); }; -#endif // AUDIO_STREAM_LIBVORBIS_H +#endif // AUDIO_STREAM_OGG_VORBIS_H diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py index 978eccb29f..a231ef179d 100644 --- a/modules/vorbis/config.py +++ b/modules/vorbis/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env.module_check_dependencies("vorbis", ["ogg"]) + env.module_add_dependencies("vorbis", ["ogg"]) + return True def configure(env): @@ -8,8 +9,8 @@ def configure(env): def get_doc_classes(): return [ - "AudioStreamOGGVorbis", - "AudioStreamPlaybackOGGVorbis", + "AudioStreamOggVorbis", + "AudioStreamPlaybackOggVorbis", ] diff --git a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml index 2f210a6cb4..225ea4e6ae 100644 --- a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamOGGVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="AudioStreamOggVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> </brief_description> <description> @@ -7,14 +7,20 @@ <tutorials> </tutorials> <members> + <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4"> + </member> + <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0"> + </member> + <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0"> + </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> If [code]true[/code], the stream will automatically loop when it reaches the end. </member> <member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset" default="0.0"> Time in seconds at which the stream starts after being looped. </member> - <member name="packet_sequence" type="OGGPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence"> - Contains the raw OGG data for this stream. + <member name="packet_sequence" type="OggPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence"> + Contains the raw Ogg data for this stream. </member> </members> </class> diff --git a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml index 68aa46147f..0879c773ac 100644 --- a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml +++ b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamPlaybackOGGVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="AudioStreamPlaybackOggVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> </brief_description> <description> diff --git a/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp index 7f81f88cdb..84a71fe82d 100644 --- a/modules/vorbis/register_types.cpp +++ b/modules/vorbis/register_types.cpp @@ -40,13 +40,13 @@ void initialize_vorbis_module(ModuleInitializationLevel p_level) { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - Ref<ResourceImporterOGGVorbis> ogg_vorbis_importer; + Ref<ResourceImporterOggVorbis> ogg_vorbis_importer; ogg_vorbis_importer.instantiate(); ResourceFormatImporter::get_singleton()->add_importer(ogg_vorbis_importer); } #endif - GDREGISTER_CLASS(AudioStreamOGGVorbis); - GDREGISTER_CLASS(AudioStreamPlaybackOGGVorbis); + GDREGISTER_CLASS(AudioStreamOggVorbis); + GDREGISTER_CLASS(AudioStreamPlaybackOggVorbis); } void uninitialize_vorbis_module(ModuleInitializationLevel p_level) { diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 7ee6446313..bf5f7206b8 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -30,56 +30,59 @@ #include "resource_importer_ogg_vorbis.h" -#include "audio_stream_ogg_vorbis.h" #include "core/io/file_access.h" #include "core/io/resource_saver.h" #include "scene/resources/texture.h" #include "thirdparty/libogg/ogg/ogg.h" #include "thirdparty/libvorbis/vorbis/codec.h" -String ResourceImporterOGGVorbis::get_importer_name() const { +#ifdef TOOLS_ENABLED +#include "editor/import/audio_stream_import_settings.h" +#endif + +String ResourceImporterOggVorbis::get_importer_name() const { return "oggvorbisstr"; } -String ResourceImporterOGGVorbis::get_visible_name() const { +String ResourceImporterOggVorbis::get_visible_name() const { return "oggvorbisstr"; } -void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const { +void ResourceImporterOggVorbis::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("ogg"); } -String ResourceImporterOGGVorbis::get_save_extension() const { +String ResourceImporterOggVorbis::get_save_extension() const { return "oggvorbisstr"; } -String ResourceImporterOGGVorbis::get_resource_type() const { - return "AudioStreamOGGVorbis"; +String ResourceImporterOggVorbis::get_resource_type() const { + return "AudioStreamOggVorbis"; } -bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { +bool ResourceImporterOggVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } -int ResourceImporterOGGVorbis::get_preset_count() const { +int ResourceImporterOggVorbis::get_preset_count() const { return 0; } -String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const { +String ResourceImporterOggVorbis::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterOggVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4)); } -Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - bool loop = p_options["loop"]; - float loop_offset = p_options["loop_offset"]; - - Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'."); +Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const String &p_path) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOggVorbis>(), "Cannot open file '" + p_path + "'."); uint64_t len = f->get_length(); @@ -89,10 +92,10 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin f->get_buffer(w, len); - Ref<AudioStreamOGGVorbis> ogg_vorbis_stream; + Ref<AudioStreamOggVorbis> ogg_vorbis_stream; ogg_vorbis_stream.instantiate(); - Ref<OGGPacketSequence> ogg_packet_sequence; + Ref<OggPacketSequence> ogg_packet_sequence; ogg_packet_sequence.instantiate(); ogg_stream_state stream_state; @@ -107,16 +110,16 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin size_t packet_count = 0; bool done = false; while (!done) { - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err)); while (ogg_sync_pageout(&sync_state, &page) != 1) { if (cursor >= len) { done = true; break; } - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err)); char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE); - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); - ERR_FAIL_COND_V(cursor > len, Error::ERR_INVALID_DATA); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOggVorbis>()); size_t copy_size = len - cursor; if (copy_size > OGG_SYNC_BUFFER_SIZE) { copy_size = OGG_SYNC_BUFFER_SIZE; @@ -124,22 +127,22 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin memcpy(sync_buf, &file_data[cursor], copy_size); ogg_sync_wrote(&sync_state, copy_size); cursor += copy_size; - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err)); } if (done) { break; } - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err)); // Have a page now. if (!initialized_stream) { if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) { - ERR_FAIL_V_MSG(Error::ERR_OUT_OF_MEMORY, "Failed allocating memory for OGG Vorbis stream."); + ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Failed allocating memory for Ogg Vorbis stream."); } initialized_stream = true; } ogg_stream_pagein(&stream_state, &page); - ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Error::ERR_INVALID_DATA, "Ogg stream error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Ref<AudioStreamOggVorbis>(), "Ogg stream error " + itos(err)); int desync_iters = 0; Vector<Vector<uint8_t>> packet_data; @@ -150,7 +153,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin if (err == -1) { // According to the docs this is usually recoverable, but don't sit here spinning forever. desync_iters++; - ERR_FAIL_COND_V_MSG(desync_iters > 100, Error::ERR_INVALID_DATA, "Packet sync issue during ogg import"); + ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref<AudioStreamOggVorbis>(), "Packet sync issue during Ogg import"); continue; } else if (err == 0) { // Not enough data to fully reconstruct a packet. Go on to the next page. @@ -183,15 +186,48 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin ogg_sync_clear(&sync_state); if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) { - ERR_FAIL_V_MSG(Error::ERR_FILE_CORRUPT, "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream."); + ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Ogg Vorbis decoding failed. Check that your data is a valid Ogg Vorbis audio stream."); } ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence); + + return ogg_vorbis_stream; +} + +#ifdef TOOLS_ENABLED + +bool ResourceImporterOggVorbis::has_advanced_options() const { + return true; +} + +void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) { + Ref<AudioStreamOggVorbis> ogg_stream = import_ogg_vorbis(p_path); + if (ogg_stream.is_valid()) { + AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream); + } +} +#endif + +Error ResourceImporterOggVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + bool loop = p_options["loop"]; + float loop_offset = p_options["loop_offset"]; + double bpm = p_options["bpm"]; + int beat_count = p_options["beat_count"]; + int bar_beats = p_options["bar_beats"]; + + Ref<AudioStreamOggVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file); + if (ogg_vorbis_stream.is_null()) { + return ERR_CANT_OPEN; + } + ogg_vorbis_stream->set_loop(loop); ogg_vorbis_stream->set_loop_offset(loop_offset); + ogg_vorbis_stream->set_bpm(bpm); + ogg_vorbis_stream->set_beat_count(beat_count); + ogg_vorbis_stream->set_bar_beats(bar_beats); - return ResourceSaver::save(p_save_path + ".oggvorbisstr", ogg_vorbis_stream); + return ResourceSaver::save(ogg_vorbis_stream, p_save_path + ".oggvorbisstr"); } -ResourceImporterOGGVorbis::ResourceImporterOGGVorbis() { +ResourceImporterOggVorbis::ResourceImporterOggVorbis() { } diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index 3b4a68a1fd..a1a970e2cc 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -31,10 +31,11 @@ #ifndef RESOURCE_IMPORTER_OGG_VORBIS_H #define RESOURCE_IMPORTER_OGG_VORBIS_H +#include "audio_stream_ogg_vorbis.h" #include "core/io/resource_importer.h" -class ResourceImporterOGGVorbis : public ResourceImporter { - GDCLASS(ResourceImporterOGGVorbis, ResourceImporter); +class ResourceImporterOggVorbis : public ResourceImporter { + GDCLASS(ResourceImporterOggVorbis, ResourceImporter); enum { OGG_SYNC_BUFFER_SIZE = 8192, @@ -43,7 +44,13 @@ class ResourceImporterOGGVorbis : public ResourceImporter { private: // virtual int get_samples_in_packet(Vector<uint8_t> p_packet) = 0; + static Ref<AudioStreamOggVorbis> import_ogg_vorbis(const String &p_path); + public: +#ifdef TOOLS_ENABLED + virtual bool has_advanced_options() const override; + virtual void show_advanced_options(const String &p_path) override; +#endif virtual void get_recognized_extensions(List<String> *p_extensions) const override; virtual String get_save_extension() const override; virtual String get_resource_type() const override; @@ -56,7 +63,7 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - ResourceImporterOGGVorbis(); + ResourceImporterOggVorbis(); }; #endif // RESOURCE_IMPORTER_OGG_VORBIS_H diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index 448f683eb3..9a5dc6cd7c 100644 --- a/modules/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h @@ -40,4 +40,4 @@ public: ImageLoaderWebP(); }; -#endif +#endif // IMAGE_LOADER_WEBP_H diff --git a/modules/webp/resource_saver_webp.cpp b/modules/webp/resource_saver_webp.cpp index d270d39163..bd71c2869a 100644 --- a/modules/webp/resource_saver_webp.cpp +++ b/modules/webp/resource_saver_webp.cpp @@ -35,7 +35,7 @@ #include "scene/resources/texture.h" #include "webp_common.h" -Error ResourceSaverWebP::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceSaverWebP::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<ImageTexture> texture = p_resource; ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as WEBP."); diff --git a/modules/webp/resource_saver_webp.h b/modules/webp/resource_saver_webp.h index 59e944efa0..cbd5864463 100644 --- a/modules/webp/resource_saver_webp.h +++ b/modules/webp/resource_saver_webp.h @@ -39,7 +39,7 @@ public: static Error save_image(const String &p_path, const Ref<Image> &p_img, const bool p_lossy = false, const float p_quality = 0.75f); static Vector<uint8_t> save_image_to_buffer(const Ref<Image> &p_img, const bool p_lossy = false, const float p_quality = 0.75f); - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml index 3996a002ed..df92097135 100644 --- a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml +++ b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml @@ -57,7 +57,7 @@ Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647). If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted. If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED]. - You can optionally specify a [code]channels_config[/code] array of [enum TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel). + You can optionally specify a [code]channels_config[/code] array of [enum MultiplayerPeer.TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel). </description> </method> <method name="remove_peer"> diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h index 75e29283ec..9d20ad3266 100644 --- a/modules/webrtc/webrtc_data_channel.h +++ b/modules/webrtc/webrtc_data_channel.h @@ -81,4 +81,5 @@ public: VARIANT_ENUM_CAST(WebRTCDataChannel::WriteMode); VARIANT_ENUM_CAST(WebRTCDataChannel::ChannelState); + #endif // WEBRTC_DATA_CHANNEL_H diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp index 6f68b84ad3..e03b6b2473 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.cpp +++ b/modules/webrtc/webrtc_multiplayer_peer.cpp @@ -197,14 +197,14 @@ Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat, Arr cfg["ordered"] = true; switch (mode) { - case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED: + case TRANSFER_MODE_UNRELIABLE_ORDERED: cfg["maxPacketLifetime"] = 1; break; - case Multiplayer::TRANSFER_MODE_UNRELIABLE: + case TRANSFER_MODE_UNRELIABLE: cfg["maxPacketLifetime"] = 1; cfg["ordered"] = false; break; - case Multiplayer::TRANSFER_MODE_RELIABLE: + case TRANSFER_MODE_RELIABLE: break; default: ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("The 'channels_config' array must contain only enum values from 'MultiplayerPeer.Multiplayer::TransferMode'. Got: %d", mode)); @@ -339,13 +339,13 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si int ch = get_transfer_channel(); if (ch == 0) { switch (get_transfer_mode()) { - case Multiplayer::TRANSFER_MODE_RELIABLE: + case TRANSFER_MODE_RELIABLE: ch = CH_RELIABLE; break; - case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED: + case TRANSFER_MODE_UNRELIABLE_ORDERED: ch = CH_ORDERED; break; - case Multiplayer::TRANSFER_MODE_UNRELIABLE: + case TRANSFER_MODE_UNRELIABLE: ch = CH_UNRELIABLE; break; } diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h index 97550a3e9d..ea7c60036b 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.h +++ b/modules/webrtc/webrtc_multiplayer_peer.h @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBRTC_MULTIPLAYER_H -#define WEBRTC_MULTIPLAYER_H +#ifndef WEBRTC_MULTIPLAYER_PEER_H +#define WEBRTC_MULTIPLAYER_PEER_H -#include "core/multiplayer/multiplayer_peer.h" +#include "scene/main/multiplayer_peer.h" #include "webrtc_peer_connection.h" class WebRTCMultiplayerPeer : public MultiplayerPeer { @@ -106,4 +106,4 @@ public: ConnectionStatus get_connection_status() const override; }; -#endif // WEBRTC_MULTIPLAYER_H +#endif // WEBRTC_MULTIPLAYER_PEER_H diff --git a/modules/webrtc/webrtc_peer_connection.h b/modules/webrtc/webrtc_peer_connection.h index 8c324d0942..122ea3d00f 100644 --- a/modules/webrtc/webrtc_peer_connection.h +++ b/modules/webrtc/webrtc_peer_connection.h @@ -74,4 +74,5 @@ public: }; VARIANT_ENUM_CAST(WebRTCPeerConnection::ConnectionState); + #endif // WEBRTC_PEER_CONNECTION_H diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index ca327a56fa..b71fd78124 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMWSCLIENT_H -#define EMWSCLIENT_H +#ifndef EMWS_CLIENT_H +#define EMWS_CLIENT_H #ifdef JAVASCRIPT_ENABLED @@ -68,4 +68,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // EMWSCLIENT_H +#endif // EMWS_CLIENT_H diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index 6bb4552c37..f52f615c35 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMWSPEER_H -#define EMWSPEER_H +#ifndef EMWS_PEER_H +#define EMWS_PEER_H #ifdef JAVASCRIPT_ENABLED @@ -90,4 +90,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // LSWPEER_H +#endif // EMWS_PEER_H diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h deleted file mode 100644 index ae31d9dbb0..0000000000 --- a/modules/websocket/emws_server.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************/ -/* emws_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 EMWSSERVER_H -#define EMWSSERVER_H - -#ifdef JAVASCRIPT_ENABLED - -#include "core/object/ref_counted.h" -#include "emws_peer.h" -#include "websocket_server.h" - -class EMWSServer : public WebSocketServer { - GDCIIMPL(EMWSServer, WebSocketServer); - -public: - Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override; - void set_extra_headers(const Vector<String> &p_headers) override; - Error listen(int p_port, Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) override; - void stop() override; - bool is_listening() const override; - bool has_peer(int p_id) const override; - Ref<WebSocketPeer> get_peer(int p_id) const override; - IPAddress get_peer_address(int p_peer_id) const override; - int get_peer_port(int p_peer_id) const override; - void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") override; - int get_max_packet_size() const override; - virtual void poll() override; - virtual Vector<String> get_protocols() const; - - EMWSServer(); - ~EMWSServer(); -}; - -#endif - -#endif // LWSSERVER_H diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp index f562de111f..056111ec92 100644 --- a/modules/websocket/register_types.cpp +++ b/modules/websocket/register_types.cpp @@ -33,11 +33,13 @@ #include "core/config/project_settings.h" #include "core/error/error_macros.h" +#include "websocket_client.h" +#include "websocket_server.h" + #ifdef JAVASCRIPT_ENABLED #include "emscripten.h" #include "emws_client.h" #include "emws_peer.h" -#include "emws_server.h" #else #include "wsl_client.h" #include "wsl_server.h" @@ -60,7 +62,6 @@ void initialize_websocket_module(ModuleInitializationLevel p_level) { #ifdef JAVASCRIPT_ENABLED EMWSPeer::make_default(); EMWSClient::make_default(); - EMWSServer::make_default(); #else WSLPeer::make_default(); WSLClient::make_default(); diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h index db529a669d..3259e78b3b 100644 --- a/modules/websocket/websocket_multiplayer_peer.h +++ b/modules/websocket/websocket_multiplayer_peer.h @@ -32,8 +32,8 @@ #define WEBSOCKET_MULTIPLAYER_PEER_H #include "core/error/error_list.h" -#include "core/multiplayer/multiplayer_peer.h" #include "core/templates/list.h" +#include "scene/main/multiplayer_peer.h" #include "websocket_peer.h" class WebSocketMultiplayerPeer : public MultiplayerPeer { diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index 13fef2424f..22099f7258 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBSOCKETPEER_H -#define WEBSOCKETPEER_H +#ifndef WEBSOCKET_PEER_H +#define WEBSOCKET_PEER_H #include "core/error/error_list.h" #include "core/io/packet_peer.h" @@ -66,4 +66,5 @@ public: }; VARIANT_ENUM_CAST(WebSocketPeer::WriteMode); -#endif // WEBSOCKETPEER_H + +#endif // WEBSOCKET_PEER_H diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 7bd80851f5..ac04c4e57e 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBSOCKET_H -#define WEBSOCKET_H +#ifndef WEBSOCKET_SERVER_H +#define WEBSOCKET_SERVER_H #include "core/crypto/crypto.h" #include "core/object/ref_counted.h" @@ -87,4 +87,4 @@ public: ~WebSocketServer(); }; -#endif // WEBSOCKET_H +#endif // WEBSOCKET_SERVER_H diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h index 22d7ffa839..58b867fbe4 100644 --- a/modules/websocket/wsl_client.h +++ b/modules/websocket/wsl_client.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLCLIENT_H -#define WSLCLIENT_H +#ifndef WSL_CLIENT_H +#define WSL_CLIENT_H #ifndef JAVASCRIPT_ENABLED @@ -88,4 +88,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // WSLCLIENT_H +#endif // WSL_CLIENT_H diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index abeecdd537..aabd3fd43e 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLPEER_H -#define WSLPEER_H +#ifndef WSL_PEER_H +#define WSL_PEER_H #ifndef JAVASCRIPT_ENABLED @@ -112,4 +112,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // LSWPEER_H +#endif // WSL_PEER_H diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index a920e9c665..ec7567c732 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLSERVER_H -#define WSLSERVER_H +#ifndef WSL_SERVER_H +#define WSL_SERVER_H #ifndef JAVASCRIPT_ENABLED @@ -95,4 +95,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // WSLSERVER_H +#endif // WSL_SERVER_H diff --git a/modules/webxr/godot_webxr.h b/modules/webxr/godot_webxr.h index 34225df001..52104895d4 100644 --- a/modules/webxr/godot_webxr.h +++ b/modules/webxr/godot_webxr.h @@ -82,4 +82,4 @@ extern int *godot_webxr_get_bounds_geometry(); } #endif -#endif /* GODOT_WEBXR_H */ +#endif // GODOT_WEBXR_H diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 74e744402b..07e6760555 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -363,8 +363,8 @@ Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Tran return p_cam_transform * xr_server->get_reference_frame() * transform_for_eye; }; -CameraMatrix WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix eye; +Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection eye; float *js_matrix = godot_webxr_get_projection_for_eye(p_view + 1); if (!initialized || js_matrix == nullptr) { diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h index 31858194f6..f1ffedba46 100644 --- a/modules/webxr/webxr_interface_js.h +++ b/modules/webxr/webxr_interface_js.h @@ -87,7 +87,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override; virtual void process() override; diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 3be220d110..b51dd18af6 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -221,12 +221,12 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const { return true; } -void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) { +void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) { GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); ERR_FAIL_NULL(godot_io_java); if (godot_io_java->has_vk()) { - godot_io_java->show_vk(p_existing_text, p_multiline, p_max_length, p_cursor_start, p_cursor_end); + godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_length, p_cursor_start, p_cursor_end); } else { ERR_PRINT("Virtual keyboard not available"); } @@ -276,9 +276,9 @@ void DisplayServerAndroid::_window_callback(const Callable &p_callable, const Va Variant ret; Callable::CallError ce; if (p_deferred) { - p_callable.call((const Variant **)&argp, 1, ret, ce); + p_callable.callp((const Variant **)&argp, 1, ret, ce); } else { - p_callable.call_deferred((const Variant **)&argp, 1); + p_callable.call_deferredp((const Variant **)&argp, 1); } } } @@ -482,7 +482,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) { Variant ret; Callable::CallError ce; - rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce); + rect_changed_callback.callp(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce); } DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 65bf2ec1a8..2f30642319 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -122,7 +122,7 @@ public: virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; + virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; virtual void virtual_keyboard_hide() override; virtual int virtual_keyboard_get_height() const override; diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 560f188b82..5bbe0ffab6 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -30,10 +30,10 @@ #include "export.h" -#include "export_plugin.h" - #include "core/os/os.h" #include "editor/editor_settings.h" +#include "editor/export/editor_export.h" +#include "export_plugin.h" void register_android_exporter() { EDITOR_DEF("export/android/android_sdk_path", ""); diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 2cfb152804..6f1b4bde40 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1671,7 +1671,7 @@ Vector<String> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExp return enabled_abis; } -void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { +void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); if (driver == "opengl3") { r_features->push_back("etc"); @@ -1705,6 +1705,8 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio } plugins_changed.clear(); + // Android supports multiple architectures in an app bundle, so + // we expose each option as a checkbox in the export dialog. const Vector<String> abis = get_abis(); for (int i = 0; i < abis.size(); ++i) { const String abi = abis[i]; @@ -3109,7 +3111,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP CLEANUP_AND_RETURN(OK); } -void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) { +void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) const { r_features->push_back("mobile"); r_features->push_back("android"); } diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 15ac8091be..1da3f68f9a 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -35,7 +35,7 @@ #include "core/io/zip_io.h" #include "core/os/os.h" -#include "editor/editor_export.h" +#include "editor/export/editor_export_platform.h" const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> @@ -156,7 +156,7 @@ public: 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; + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; @@ -231,7 +231,7 @@ public: Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags); - virtual void get_platform_features(List<String> *r_features) override; + virtual void get_platform_features(List<String> *r_features) const override; virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override; diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 7896392d16..232b4458c6 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_GRADLE_EXPORT_UTIL_H -#define GODOT_GRADLE_EXPORT_UTIL_H +#ifndef ANDROID_GRADLE_EXPORT_UTIL_H +#define ANDROID_GRADLE_EXPORT_UTIL_H #include "core/io/dir_access.h" #include "core/io/file_access.h" #include "core/io/zip_io.h" #include "core/os/os.h" -#include "editor/editor_export.h" +#include "editor/export/editor_export.h" const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="utf-8"?> <!--WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME--> @@ -106,4 +106,4 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset); String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission); -#endif // GODOT_GRADLE_EXPORT_UTIL_H +#endif // ANDROID_GRADLE_EXPORT_UTIL_H diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index e6fd8c857b..8d7ade8ead 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -49,34 +49,34 @@ class FileAccessAndroid : public FileAccess { public: static AAssetManager *asset_manager; - virtual Error _open(const String &p_path, int p_mode_flags); // open a file - virtual bool is_open() const; // true when file is open + virtual Error _open(const String &p_path, int p_mode_flags) override; // open a file + virtual bool is_open() const override; // true when file is open /// returns the path for the current open file - virtual String get_path() const; + virtual String get_path() const override; /// returns the absolute path for the current open file - virtual String get_path_absolute() const; + virtual String get_path_absolute() const override; - virtual void seek(uint64_t p_position); // seek to a given position - virtual void seek_end(int64_t p_position = 0); // seek from the end of file - virtual uint64_t get_position() const; // get position in the file - virtual uint64_t get_length() const; // get size of the file + virtual void seek(uint64_t p_position) override; // seek to a given position + virtual void seek_end(int64_t p_position = 0) override; // seek from the end of file + virtual uint64_t get_position() const override; // get position in the file + virtual uint64_t get_length() const override; // get size of the file - virtual bool eof_reached() const; // reading passed EOF + virtual bool eof_reached() const override; // reading passed EOF - virtual uint8_t get_8() const; // get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; + virtual uint8_t get_8() const override; // get a byte + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; - virtual Error get_error() const; // get last error + virtual Error get_error() const override; // get last error - virtual void flush(); - virtual void store_8(uint8_t p_dest); // store a byte + virtual void flush() override; + virtual void store_8(uint8_t p_dest) override; // store a byte - virtual bool file_exists(const String &p_path); // return true if a file exists + virtual bool file_exists(const String &p_path) override; // return true if a file exists - virtual uint64_t _get_modified_time(const String &p_file) { return 0; } - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } + virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } + virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } + virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } ~FileAccessAndroid(); }; diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp index c1a48e025e..6b21c18d59 100644 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ b/platform/android/file_access_filesystem_jandroid.cpp @@ -29,8 +29,11 @@ /*************************************************************************/ #include "file_access_filesystem_jandroid.h" + #include "core/os/os.h" +#include "core/templates/local_vector.h" #include "thread_jandroid.h" + #include <unistd.h> jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr; @@ -166,6 +169,51 @@ uint8_t FileAccessFilesystemJAndroid::get_8() const { return byte; } +String FileAccessFilesystemJAndroid::get_line() const { + ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use."); + + const size_t buffer_size_limit = 2048; + const uint64_t file_size = get_length(); + const uint64_t start_position = get_position(); + + String result; + LocalVector<uint8_t> line_buffer; + size_t current_buffer_size = 0; + uint64_t line_buffer_position = 0; + + while (true) { + size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position()); + if (line_buffer_size <= 0) { + break; + } + + current_buffer_size += line_buffer_size; + line_buffer.resize(current_buffer_size); + + uint64_t bytes_read = get_buffer(&line_buffer[line_buffer_position], current_buffer_size - line_buffer_position); + if (bytes_read <= 0) { + break; + } + + for (; bytes_read > 0; line_buffer_position++, bytes_read--) { + uint8_t elem = line_buffer[line_buffer_position]; + if (elem == '\n' || elem == '\0') { + // Found the end of the line + const_cast<FileAccessFilesystemJAndroid *>(this)->seek(start_position + line_buffer_position + 1); + if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { + return String(); + } + return result; + } + } + } + + if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { + return String(); + } + return result; +} + uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { if (_file_read) { ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h index 18d5df1628..7deb8de37b 100644 --- a/platform/android/file_access_filesystem_jandroid.h +++ b/platform/android/file_access_filesystem_jandroid.h @@ -74,6 +74,7 @@ public: virtual bool eof_reached() const override; ///< reading passed EOF virtual uint8_t get_8() const override; ///< get a byte + virtual String get_line() const override; ///< get a line virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; virtual Error get_error() const override; ///< get last error diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index 0434efdf4c..d283de8ce8 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -203,9 +203,10 @@ public class GodotIO { return result; } - public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { - if (edit != null) - edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + public void showKeyboard(String p_existing_text, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + if (edit != null) { + edit.showKeyboard(p_existing_text, GodotEditText.VirtualKeyboardType.values()[p_type], p_max_input_length, p_cursor_start, p_cursor_end); + } //InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); //inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java index ecb2af0a7b..7925b54fc4 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java @@ -52,6 +52,18 @@ public class GodotEditText extends EditText { private final static int HANDLER_OPEN_IME_KEYBOARD = 2; private final static int HANDLER_CLOSE_IME_KEYBOARD = 3; + // Enum must be kept up-to-date with DisplayServer::VirtualKeyboardType + public enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + } + // =========================================================== // Fields // =========================================================== @@ -60,7 +72,7 @@ public class GodotEditText extends EditText { private EditHandler sHandler = new EditHandler(this); private String mOriginText; private int mMaxInputLength = Integer.MAX_VALUE; - private boolean mMultiline = false; + private VirtualKeyboardType mKeyboardType = VirtualKeyboardType.KEYBOARD_TYPE_DEFAULT; private static class EditHandler extends Handler { private final WeakReference<GodotEditText> mEdit; @@ -100,8 +112,8 @@ public class GodotEditText extends EditText { setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE); } - public boolean isMultiline() { - return mMultiline; + public VirtualKeyboardType getKeyboardType() { + return mKeyboardType; } private void handleMessage(final Message msg) { @@ -122,8 +134,31 @@ public class GodotEditText extends EditText { } int inputType = InputType.TYPE_CLASS_TEXT; - if (edit.isMultiline()) { - inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE; + switch (edit.getKeyboardType()) { + case KEYBOARD_TYPE_DEFAULT: + inputType = InputType.TYPE_CLASS_TEXT; + break; + case KEYBOARD_TYPE_MULTILINE: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE; + break; + case KEYBOARD_TYPE_NUMBER: + inputType = InputType.TYPE_CLASS_NUMBER; + break; + case KEYBOARD_TYPE_NUMBER_DECIMAL: + inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED; + break; + case KEYBOARD_TYPE_PHONE: + inputType = InputType.TYPE_CLASS_PHONE; + break; + case KEYBOARD_TYPE_EMAIL_ADDRESS: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; + break; + case KEYBOARD_TYPE_PASSWORD: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD; + break; + case KEYBOARD_TYPE_URL: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI; + break; } edit.setInputType(inputType); @@ -201,7 +236,7 @@ public class GodotEditText extends EditText { // =========================================================== // Methods // =========================================================== - public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + public void showKeyboard(String p_existing_text, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length; if (p_cursor_start == -1) { // cursor position not given this.mOriginText = p_existing_text; @@ -214,7 +249,7 @@ public class GodotEditText extends EditText { this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end); } - this.mMultiline = p_multiline; + this.mKeyboardType = p_type; final Message msg = new Message(); msg.what = HANDLER_OPEN_IME_KEYBOARD; diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java index 5882753e9d..c959b5f28c 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java @@ -111,7 +111,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene } for (int i = 0; i < count; ++i) { int key = newChars[i]; - if ((key == '\n') && !mEdit.isMultiline()) { + if ((key == '\n') && !(mEdit.getKeyboardType() == GodotEditText.VirtualKeyboardType.KEYBOARD_TYPE_MULTILINE)) { // Return keys are handled through action events continue; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt index c7bd55b620..c9282dd247 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt @@ -54,11 +54,19 @@ internal enum class StorageScope { */ UNKNOWN; - companion object { + class Identifier(context: Context) { + + private val internalAppDir: String? = context.filesDir.canonicalPath + private val internalCacheDir: String? = context.cacheDir.canonicalPath + private val externalAppDir: String? = context.getExternalFilesDir(null)?.canonicalPath + private val sharedDir : String? = Environment.getExternalStorageDirectory().canonicalPath + private val downloadsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath + private val documentsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath + /** * Determines which [StorageScope] the given path falls under. */ - fun getStorageScope(context: Context, path: String?): StorageScope { + fun identifyStorageScope(path: String?): StorageScope { if (path == null) { return UNKNOWN } @@ -70,23 +78,19 @@ internal enum class StorageScope { val canonicalPathFile = pathFile.canonicalPath - val internalAppDir = context.filesDir.canonicalPath ?: return UNKNOWN - if (canonicalPathFile.startsWith(internalAppDir)) { + if (internalAppDir != null && canonicalPathFile.startsWith(internalAppDir)) { return APP } - val internalCacheDir = context.cacheDir.canonicalPath ?: return UNKNOWN - if (canonicalPathFile.startsWith(internalCacheDir)) { + if (internalCacheDir != null && canonicalPathFile.startsWith(internalCacheDir)) { return APP } - val externalAppDir = context.getExternalFilesDir(null)?.canonicalPath ?: return UNKNOWN - if (canonicalPathFile.startsWith(externalAppDir)) { + if (externalAppDir != null && canonicalPathFile.startsWith(externalAppDir)) { return APP } - val sharedDir = Environment.getExternalStorageDirectory().canonicalPath ?: return UNKNOWN - if (canonicalPathFile.startsWith(sharedDir)) { + if (sharedDir != null && canonicalPathFile.startsWith(sharedDir)) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { // Before R, apps had access to shared storage so long as they have the right // permissions (and flag on Q). @@ -95,13 +99,8 @@ internal enum class StorageScope { // Post R, access is limited based on the target destination // 'Downloads' and 'Documents' are still accessible - val downloadsSharedDir = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath - ?: return SHARED - val documentsSharedDir = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath - ?: return SHARED - if (canonicalPathFile.startsWith(downloadsSharedDir) || canonicalPathFile.startsWith(documentsSharedDir)) { + if ((downloadsSharedDir != null && canonicalPathFile.startsWith(downloadsSharedDir)) + || (documentsSharedDir != null && canonicalPathFile.startsWith(documentsSharedDir))) { return APP } diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt index c3acf42568..54fc56fa3e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt @@ -54,6 +54,7 @@ internal class FilesystemDirectoryAccess(private val context: Context): private data class DirData(val dirFile: File, val files: Array<File>, var current: Int = 0) + private val storageScopeIdentifier = StorageScope.Identifier(context) private val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager private var lastDirId = STARTING_DIR_ID private val dirs = SparseArray<DirData>() @@ -62,7 +63,7 @@ internal class FilesystemDirectoryAccess(private val context: Context): // Directory access is available for shared storage on Android 11+ // On Android 10, access is also available as long as the `requestLegacyExternalStorage` // tag is available. - return StorageScope.getStorageScope(context, path) != StorageScope.UNKNOWN + return storageScopeIdentifier.identifyStorageScope(path) != StorageScope.UNKNOWN } override fun hasDirId(dirId: Int) = dirs.indexOfKey(dirId) >= 0 @@ -102,7 +103,7 @@ internal class FilesystemDirectoryAccess(private val context: Context): } } - override fun fileExists(path: String) = FileAccessHandler.fileExists(context, path) + override fun fileExists(path: String) = FileAccessHandler.fileExists(context, storageScopeIdentifier, path) override fun dirNext(dirId: Int): String { val dirData = dirs[dirId] @@ -199,7 +200,7 @@ internal class FilesystemDirectoryAccess(private val context: Context): if (fromFile.isDirectory) { fromFile.renameTo(File(to)) } else { - FileAccessHandler.renameFile(context, from, to) + FileAccessHandler.renameFile(context, storageScopeIdentifier, from, to) } } catch (e: SecurityException) { false @@ -218,7 +219,7 @@ internal class FilesystemDirectoryAccess(private val context: Context): if (deleteFile.isDirectory) { deleteFile.delete() } else { - FileAccessHandler.removeFile(context, filename) + FileAccessHandler.removeFile(context, storageScopeIdentifier, filename) } } else { true diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt index aef1bed8ce..463dabfb23 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt @@ -161,8 +161,9 @@ internal abstract class DataAccess(private val filePath: String) { fun read(buffer: ByteBuffer): Int { return try { val readBytes = fileChannel.read(buffer) + endOfFile = readBytes == -1 + || (fileChannel.position() >= fileChannel.size() && fileChannel.size() > 0) if (readBytes == -1) { - endOfFile = true 0 } else { readBytes diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt index a4e0a82d6e..04b6772c45 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt @@ -49,8 +49,8 @@ class FileAccessHandler(val context: Context) { private const val INVALID_FILE_ID = 0 private const val STARTING_FILE_ID = 1 - fun fileExists(context: Context, path: String?): Boolean { - val storageScope = StorageScope.getStorageScope(context, path) + internal fun fileExists(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean { + val storageScope = storageScopeIdentifier.identifyStorageScope(path) if (storageScope == StorageScope.UNKNOWN) { return false } @@ -62,8 +62,8 @@ class FileAccessHandler(val context: Context) { } } - fun removeFile(context: Context, path: String?): Boolean { - val storageScope = StorageScope.getStorageScope(context, path) + internal fun removeFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean { + val storageScope = storageScopeIdentifier.identifyStorageScope(path) if (storageScope == StorageScope.UNKNOWN) { return false } @@ -75,8 +75,8 @@ class FileAccessHandler(val context: Context) { } } - fun renameFile(context: Context, from: String?, to: String?): Boolean { - val storageScope = StorageScope.getStorageScope(context, from) + internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String?, to: String?): Boolean { + val storageScope = storageScopeIdentifier.identifyStorageScope(from) if (storageScope == StorageScope.UNKNOWN) { return false } @@ -89,13 +89,14 @@ class FileAccessHandler(val context: Context) { } } + private val storageScopeIdentifier = StorageScope.Identifier(context) private val files = SparseArray<DataAccess>() private var lastFileId = STARTING_FILE_ID private fun hasFileId(fileId: Int) = files.indexOfKey(fileId) >= 0 fun fileOpen(path: String?, modeFlags: Int): Int { - val storageScope = StorageScope.getStorageScope(context, path) + val storageScope = storageScopeIdentifier.identifyStorageScope(path) if (storageScope == StorageScope.UNKNOWN) { return INVALID_FILE_ID } @@ -162,10 +163,10 @@ class FileAccessHandler(val context: Context) { files[fileId].flush() } - fun fileExists(path: String?) = Companion.fileExists(context, path) + fun fileExists(path: String?) = Companion.fileExists(context, storageScopeIdentifier, path) fun fileLastModified(filepath: String?): Long { - val storageScope = StorageScope.getStorageScope(context, filepath) + val storageScope = storageScopeIdentifier.identifyStorageScope(filepath) if (storageScope == StorageScope.UNKNOWN) { return 0L } diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index b71c6ef1e6..5877c15114 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -61,7 +61,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _get_scaled_density = p_env->GetMethodID(cls, "getScaledDensity", "()F"); _get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D"); _get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;"); - _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V"); + _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;IIII)V"); _hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V"); _set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V"); _get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I"); @@ -214,12 +214,12 @@ bool GodotIOJavaWrapper::has_vk() { return (_show_keyboard != nullptr) && (_hide_keyboard != nullptr); } -void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (_show_keyboard) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); jstring jStr = env->NewStringUTF(p_existing.utf8().get_data()); - env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end); } } diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index aec7d1db97..dc68f4d90d 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -82,7 +82,7 @@ public: Rect2i get_display_safe_area(); String get_unique_id(); bool has_vk(); - void show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end); + void show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end); void hide_vk(); int get_vk_height(); void set_vk_height(int p_height); diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h index b1f258bbb5..c52f459d64 100644 --- a/platform/android/java_godot_view_wrapper.h +++ b/platform/android/java_godot_view_wrapper.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_JAVA_GODOT_VIEW_WRAPPER_H -#define GODOT_JAVA_GODOT_VIEW_WRAPPER_H +#ifndef JAVA_GODOT_VIEW_WRAPPER_H +#define JAVA_GODOT_VIEW_WRAPPER_H #include <android/log.h> #include <jni.h> @@ -57,4 +57,4 @@ public: ~GodotJavaViewWrapper(); }; -#endif // GODOT_JAVA_GODOT_VIEW_WRAPPER_H +#endif // JAVA_GODOT_VIEW_WRAPPER_H diff --git a/platform/iphone/SCsub b/platform/ios/SCsub index 5e10bf5646..bf12ab6dd7 100644 --- a/platform/iphone/SCsub +++ b/platform/ios/SCsub @@ -2,16 +2,16 @@ Import("env") -iphone_lib = [ - "godot_iphone.mm", - "os_iphone.mm", +ios_lib = [ + "godot_ios.mm", + "os_ios.mm", "main.m", "app_delegate.mm", "view_controller.mm", "ios.mm", - "vulkan_context_iphone.mm", - "display_server_iphone.mm", - "joypad_iphone.mm", + "vulkan_context_ios.mm", + "display_server_ios.mm", + "joypad_ios.mm", "godot_view.mm", "tts_ios.mm", "display_layer.mm", @@ -23,7 +23,7 @@ iphone_lib = [ ] env_ios = env.Clone() -ios_lib = env_ios.add_library("iphone", iphone_lib) +ios_lib = env_ios.add_library("ios", ios_lib) # (iOS) Enable module support env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) @@ -32,9 +32,9 @@ env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) def combine_libs(target=None, source=None, env=None): lib_path = target[0].srcnode().abspath if "osxcross" in env: - libtool = "$IPHONEPATH/usr/bin/${ios_triple}libtool" + libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}libtool" else: - libtool = "$IPHONEPATH/usr/bin/libtool" + libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/libtool" env.Execute( libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) ) diff --git a/platform/iphone/api/api.cpp b/platform/ios/api/api.cpp index f2e6fd7a7a..00c76a9256 100644 --- a/platform/iphone/api/api.cpp +++ b/platform/ios/api/api.cpp @@ -30,19 +30,19 @@ #include "api.h" -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) -void register_iphone_api() { +void register_ios_api() { godot_ios_plugins_initialize(); } -void unregister_iphone_api() { +void unregister_ios_api() { godot_ios_plugins_deinitialize(); } #else -void register_iphone_api() {} -void unregister_iphone_api() {} +void register_ios_api() {} +void unregister_ios_api() {} #endif diff --git a/platform/iphone/api/api.h b/platform/ios/api/api.h index ece91a9f1a..c7fd4ce77b 100644 --- a/platform/iphone/api/api.h +++ b/platform/ios/api/api.h @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IPHONE_API_H -#define IPHONE_API_H +#ifndef IOS_API_H +#define IOS_API_H -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) extern void godot_ios_plugins_initialize(); extern void godot_ios_plugins_deinitialize(); #endif -void register_iphone_api(); -void unregister_iphone_api(); +void register_ios_api(); +void unregister_ios_api(); -#endif // IPHONE_API_H +#endif // IOS_API_H diff --git a/platform/iphone/app_delegate.h b/platform/ios/app_delegate.h index 0ec1dc071b..0ec1dc071b 100644 --- a/platform/iphone/app_delegate.h +++ b/platform/ios/app_delegate.h diff --git a/platform/iphone/app_delegate.mm b/platform/ios/app_delegate.mm index c5c9b5a5f9..fb183d52d4 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/ios/app_delegate.mm @@ -34,7 +34,7 @@ #include "drivers/coreaudio/audio_driver_coreaudio.h" #import "godot_view.h" #include "main/main.h" -#include "os_iphone.h" +#include "os_ios.h" #import "view_controller.h" #import <AVFoundation/AVFoundation.h> @@ -45,8 +45,8 @@ extern int gargc; extern char **gargv; -extern int iphone_main(int, char **, String, String); -extern void iphone_finish(); +extern int ios_main(int, char **, String, String); +extern void ios_finish(); @implementation AppDelegate @@ -71,7 +71,7 @@ static ViewController *mainViewController = nil; paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *cacheDirectory = [paths objectAtIndex:0]; - int err = iphone_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String])); + int err = ios_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String])); if (err != 0) { // bail, things did not go very well for us, should probably output a message on screen with our error code... @@ -106,10 +106,10 @@ static ViewController *mainViewController = nil; if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) { if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) { NSLog(@"Audio interruption began"); - OSIPhone::get_singleton()->on_focus_out(); + OS_IOS::get_singleton()->on_focus_out(); } else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) { NSLog(@"Audio interruption ended"); - OSIPhone::get_singleton()->on_focus_in(); + OS_IOS::get_singleton()->on_focus_in(); } } } @@ -121,7 +121,7 @@ static ViewController *mainViewController = nil; } - (void)applicationWillTerminate:(UIApplication *)application { - iphone_finish(); + ios_finish(); } // When application goes to background (e.g. user switches to another app or presses Home), @@ -135,11 +135,11 @@ static ViewController *mainViewController = nil; // notification panel by swiping from the upper part of the screen. - (void)applicationWillResignActive:(UIApplication *)application { - OSIPhone::get_singleton()->on_focus_out(); + OS_IOS::get_singleton()->on_focus_out(); } - (void)applicationDidBecomeActive:(UIApplication *)application { - OSIPhone::get_singleton()->on_focus_in(); + OS_IOS::get_singleton()->on_focus_in(); } - (void)dealloc { diff --git a/platform/iphone/detect.py b/platform/ios/detect.py index 862f1fe50b..67c90b10a0 100644 --- a/platform/iphone/detect.py +++ b/platform/ios/detect.py @@ -23,11 +23,11 @@ def get_opts(): return [ ( - "IPHONEPATH", - "Path to iPhone toolchain", + "IOS_TOOLCHAIN_PATH", + "Path to iOS toolchain", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", ), - ("IPHONESDK", "Path to the iPhone SDK", ""), + ("IOS_SDK_PATH", "Path to the iOS SDK", ""), BoolVariable("ios_simulator", "Build for iOS Simulator", False), BoolVariable("ios_exceptions", "Enable exceptions", False), ("ios_triple", "Triple for ios toolchain", ""), @@ -75,10 +75,10 @@ def configure(env): if "OSXCROSS_IOS" in os.environ: env["osxcross"] = True - env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] + env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] - compiler_path = "$IPHONEPATH/usr/bin/${ios_triple}" - s_compiler_path = "$IPHONEPATH/Developer/usr/bin/" + compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}" + s_compiler_path = "$IOS_TOOLCHAIN_PATH/Developer/usr/bin/" ccache_path = os.environ.get("CCACHE") if ccache_path is None: @@ -97,12 +97,12 @@ def configure(env): ## Compile flags if env["ios_simulator"]: - detect_darwin_sdk_path("iphonesimulator", env) + detect_darwin_sdk_path("iossimulator", env) env.Append(ASFLAGS=["-mios-simulator-version-min=13.0"]) env.Append(CCFLAGS=["-mios-simulator-version-min=13.0"]) env.extra_suffix = ".simulator" + env.extra_suffix else: - detect_darwin_sdk_path("iphone", env) + detect_darwin_sdk_path("ios", env) env.Append(ASFLAGS=["-miphoneos-version-min=11.0"]) env.Append(CCFLAGS=["-miphoneos-version-min=11.0"]) @@ -112,7 +112,7 @@ def configure(env): CCFLAGS=( "-fobjc-arc -arch x86_64" " -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks" - " -fasm-blocks -isysroot $IPHONESDK" + " -fasm-blocks -isysroot $IOS_SDK_PATH" ).split() ) env.Append(ASFLAGS=["-arch", "x86_64"]) @@ -122,7 +122,7 @@ def configure(env): "-fobjc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing" " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits" " -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies" - " -isysroot $IPHONESDK".split() + " -isysroot $IOS_SDK_PATH".split() ) ) env.Append(ASFLAGS=["-arch", "arm64"]) @@ -135,18 +135,18 @@ def configure(env): else: env.Append(CCFLAGS=["-fno-exceptions"]) - # Temp fix for ABS/MAX/MIN macros in iPhone SDK blocking compilation + # Temp fix for ABS/MAX/MIN macros in iOS SDK blocking compilation env.Append(CCFLAGS=["-Wno-ambiguous-macro"]) env.Prepend( CPPPATH=[ - "$IPHONESDK/usr/include", - "$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers", + "$IOS_SDK_PATH/usr/include", + "$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", ] ) - env.Prepend(CPPPATH=["#platform/iphone"]) - env.Append(CPPDEFINES=["IPHONE_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) + env.Prepend(CPPPATH=["#platform/ios"]) + env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) if env["vulkan"]: env.Append(CPPDEFINES=["VULKAN_ENABLED"]) diff --git a/platform/iphone/device_metrics.h b/platform/ios/device_metrics.h index b9fb9b2fd9..b9fb9b2fd9 100644 --- a/platform/iphone/device_metrics.h +++ b/platform/ios/device_metrics.h diff --git a/platform/iphone/device_metrics.m b/platform/ios/device_metrics.m index ec4dd8130d..ec4dd8130d 100644 --- a/platform/iphone/device_metrics.m +++ b/platform/ios/device_metrics.m diff --git a/platform/iphone/display_layer.h b/platform/ios/display_layer.h index a17c75dba1..a17c75dba1 100644 --- a/platform/iphone/display_layer.h +++ b/platform/ios/display_layer.h diff --git a/platform/iphone/display_layer.mm b/platform/ios/display_layer.mm index 92e81448ac..7c83494768 100644 --- a/platform/iphone/display_layer.mm +++ b/platform/ios/display_layer.mm @@ -32,9 +32,9 @@ #include "core/config/project_settings.h" #include "core/os/keyboard.h" -#include "display_server_iphone.h" +#include "display_server_ios.h" #include "main/main.h" -#include "os_iphone.h" +#include "os_ios.h" #include "servers/audio_server.h" #import <AudioToolbox/AudioServices.h> diff --git a/platform/iphone/display_server_iphone.h b/platform/ios/display_server_ios.h index 7af222e3f8..bbb2dd3ab3 100644 --- a/platform/iphone/display_server_iphone.h +++ b/platform/ios/display_server_ios.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* display_server_iphone.h */ +/* display_server_ios.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef display_server_iphone_h -#define display_server_iphone_h +#ifndef DISPLAY_SERVER_IOS_H +#define DISPLAY_SERVER_IOS_H #include "core/input/input.h" #include "servers/display_server.h" @@ -38,7 +38,7 @@ #include "drivers/vulkan/rendering_device_vulkan.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" -#include "vulkan_context_iphone.h" +#include "vulkan_context_ios.h" #import <QuartzCore/CAMetalLayer.h> #ifdef USE_VOLK @@ -48,13 +48,13 @@ #endif #endif -class DisplayServerIPhone : public DisplayServer { - GDCLASS(DisplayServerIPhone, DisplayServer) +class DisplayServerIOS : public DisplayServer { + GDCLASS(DisplayServerIOS, DisplayServer) _THREAD_SAFE_CLASS_ #if defined(VULKAN_ENABLED) - VulkanContextIPhone *context_vulkan = nullptr; + VulkanContextIOS *context_vulkan = nullptr; RenderingDeviceVulkan *rendering_device_vulkan = nullptr; #endif @@ -73,15 +73,15 @@ class DisplayServerIPhone : public DisplayServer { void perform_event(const Ref<InputEvent> &p_event); - DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); - ~DisplayServerIPhone(); + DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + ~DisplayServerIOS(); public: String rendering_driver; - static DisplayServerIPhone *get_singleton(); + static DisplayServerIOS *get_singleton(); - static void register_iphone_driver(); + static void register_ios_driver(); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static Vector<String> get_rendering_drivers_func(); @@ -199,7 +199,7 @@ public: virtual bool screen_is_touchscreen(int p_screen) const override; - virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override; + virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) override; virtual void virtual_keyboard_hide() override; void virtual_keyboard_set_height(int height); @@ -214,4 +214,4 @@ public: void resize_window(CGSize size); }; -#endif /* display_server_iphone_h */ +#endif // DISPLAY_SERVER_IOS_H diff --git a/platform/iphone/display_server_iphone.mm b/platform/ios/display_server_ios.mm index 28ffc9595e..6ce7e676a2 100644 --- a/platform/iphone/display_server_iphone.mm +++ b/platform/ios/display_server_ios.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* display_server_iphone.mm */ +/* display_server_ios.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "display_server_iphone.h" +#include "display_server_ios.h" #import "app_delegate.h" #include "core/config/project_settings.h" @@ -37,20 +37,20 @@ #import "godot_view.h" #include "ios.h" #import "keyboard_input_view.h" -#include "os_iphone.h" +#include "os_ios.h" #include "tts_ios.h" #import "view_controller.h" #import <Foundation/Foundation.h> #import <sys/utsname.h> -static const float kDisplayServerIPhoneAcceleration = 1; +static const float kDisplayServerIOSAcceleration = 1.f; -DisplayServerIPhone *DisplayServerIPhone::get_singleton() { - return (DisplayServerIPhone *)DisplayServer::get_singleton(); +DisplayServerIOS *DisplayServerIOS::get_singleton() { + return (DisplayServerIOS *)DisplayServer::get_singleton(); } -DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { +DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { rendering_driver = p_rendering_driver; // Init TTS @@ -101,7 +101,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo rendering_device_vulkan = nullptr; if (rendering_driver == "vulkan") { - context_vulkan = memnew(VulkanContextIPhone); + context_vulkan = memnew(VulkanContextIOS); if (context_vulkan->initialize() != OK) { memdelete(context_vulkan); context_vulkan = nullptr; @@ -128,7 +128,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo } #endif - bool keep_screen_on = bool(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true)); + bool keep_screen_on = bool(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); screen_set_keep_on(keep_screen_on); Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); @@ -136,7 +136,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo r_error = OK; } -DisplayServerIPhone::~DisplayServerIPhone() { +DisplayServerIOS::~DisplayServerIOS() { #if defined(VULKAN_ENABLED) if (rendering_device_vulkan) { rendering_device_vulkan->finalize(); @@ -152,11 +152,11 @@ DisplayServerIPhone::~DisplayServerIPhone() { #endif } -DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); +DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); } -Vector<String> DisplayServerIPhone::get_rendering_drivers_func() { +Vector<String> DisplayServerIOS::get_rendering_drivers_func() { Vector<String> drivers; #if defined(VULKAN_ENABLED) @@ -169,57 +169,57 @@ Vector<String> DisplayServerIPhone::get_rendering_drivers_func() { return drivers; } -void DisplayServerIPhone::register_iphone_driver() { - register_create_function("iphone", create_func, get_rendering_drivers_func); +void DisplayServerIOS::register_ios_driver() { + register_create_function("iOS", create_func, get_rendering_drivers_func); } // MARK: Events -void DisplayServerIPhone::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerIOS::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { window_resize_callback = p_callable; } -void DisplayServerIPhone::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerIOS::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { window_event_callback = p_callable; } -void DisplayServerIPhone::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerIOS::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { input_event_callback = p_callable; } -void DisplayServerIPhone::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerIOS::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { input_text_callback = p_callable; } -void DisplayServerIPhone::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerIOS::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { // Probably not supported for iOS } -void DisplayServerIPhone::process_events() { +void DisplayServerIOS::process_events() { Input::get_singleton()->flush_buffered_events(); } -void DisplayServerIPhone::_dispatch_input_events(const Ref<InputEvent> &p_event) { - DisplayServerIPhone::get_singleton()->send_input_event(p_event); +void DisplayServerIOS::_dispatch_input_events(const Ref<InputEvent> &p_event) { + DisplayServerIOS::get_singleton()->send_input_event(p_event); } -void DisplayServerIPhone::send_input_event(const Ref<InputEvent> &p_event) const { +void DisplayServerIOS::send_input_event(const Ref<InputEvent> &p_event) const { _window_callback(input_event_callback, p_event); } -void DisplayServerIPhone::send_input_text(const String &p_text) const { +void DisplayServerIOS::send_input_text(const String &p_text) const { _window_callback(input_text_callback, p_text); } -void DisplayServerIPhone::send_window_event(DisplayServer::WindowEvent p_event) const { +void DisplayServerIOS::send_window_event(DisplayServer::WindowEvent p_event) const { _window_callback(window_event_callback, int(p_event)); } -void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Variant &p_arg) const { +void DisplayServerIOS::_window_callback(const Callable &p_callable, const Variant &p_arg) const { if (!p_callable.is_null()) { const Variant *argp = &p_arg; Variant ret; Callable::CallError ce; - p_callable.call((const Variant **)&argp, 1, ret, ce); + p_callable.callp((const Variant **)&argp, 1, ret, ce); } } @@ -227,7 +227,7 @@ void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Var // MARK: Touches -void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) { +void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) { if (!GLOBAL_DEF("debug/disable_touch", false)) { Ref<InputEventScreenTouch> ev; ev.instantiate(); @@ -239,7 +239,7 @@ void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_presse } } -void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) { +void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) { if (!GLOBAL_DEF("debug/disable_touch", false)) { Ref<InputEventScreenDrag> ev; ev.instantiate(); @@ -250,17 +250,17 @@ void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int } } -void DisplayServerIPhone::perform_event(const Ref<InputEvent> &p_event) { +void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) { Input::get_singleton()->parse_input_event(p_event); } -void DisplayServerIPhone::touches_cancelled(int p_idx) { +void DisplayServerIOS::touches_cancelled(int p_idx) { touch_press(p_idx, -1, -1, false, false); } // MARK: Keyboard -void DisplayServerIPhone::key(Key p_key, bool p_pressed) { +void DisplayServerIOS::key(Key p_key, bool p_pressed) { Ref<InputEventKey> ev; ev.instantiate(); ev->set_echo(false); @@ -273,31 +273,31 @@ void DisplayServerIPhone::key(Key p_key, bool p_pressed) { // MARK: Motion -void DisplayServerIPhone::update_gravity(float p_x, float p_y, float p_z) { +void DisplayServerIOS::update_gravity(float p_x, float p_y, float p_z) { Input::get_singleton()->set_gravity(Vector3(p_x, p_y, p_z)); } -void DisplayServerIPhone::update_accelerometer(float p_x, float p_y, float p_z) { +void DisplayServerIOS::update_accelerometer(float p_x, float p_y, float p_z) { // Found out the Z should not be negated! Pass as is! Vector3 v_accelerometer = Vector3( - p_x / kDisplayServerIPhoneAcceleration, - p_y / kDisplayServerIPhoneAcceleration, - p_z / kDisplayServerIPhoneAcceleration); + p_x / kDisplayServerIOSAcceleration, + p_y / kDisplayServerIOSAcceleration, + p_z / kDisplayServerIOSAcceleration); Input::get_singleton()->set_accelerometer(v_accelerometer); } -void DisplayServerIPhone::update_magnetometer(float p_x, float p_y, float p_z) { +void DisplayServerIOS::update_magnetometer(float p_x, float p_y, float p_z) { Input::get_singleton()->set_magnetometer(Vector3(p_x, p_y, p_z)); } -void DisplayServerIPhone::update_gyroscope(float p_x, float p_y, float p_z) { +void DisplayServerIOS::update_gyroscope(float p_x, float p_y, float p_z) { Input::get_singleton()->set_gyroscope(Vector3(p_x, p_y, p_z)); } // MARK: - -bool DisplayServerIPhone::has_feature(Feature p_feature) const { +bool DisplayServerIOS::has_feature(Feature p_feature) const { switch (p_feature) { // case FEATURE_CURSOR_SHAPE: // case FEATURE_CUSTOM_CURSOR_SHAPE: @@ -322,46 +322,46 @@ bool DisplayServerIPhone::has_feature(Feature p_feature) const { } } -String DisplayServerIPhone::get_name() const { - return "iPhone"; +String DisplayServerIOS::get_name() const { + return "iOS"; } -bool DisplayServerIPhone::tts_is_speaking() const { +bool DisplayServerIOS::tts_is_speaking() const { ERR_FAIL_COND_V(!tts, false); return [tts isSpeaking]; } -bool DisplayServerIPhone::tts_is_paused() const { +bool DisplayServerIOS::tts_is_paused() const { ERR_FAIL_COND_V(!tts, false); return [tts isPaused]; } -Array DisplayServerIPhone::tts_get_voices() const { +Array DisplayServerIOS::tts_get_voices() const { ERR_FAIL_COND_V(!tts, Array()); return [tts getVoices]; } -void DisplayServerIPhone::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) { +void DisplayServerIOS::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) { ERR_FAIL_COND(!tts); [tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt]; } -void DisplayServerIPhone::tts_pause() { +void DisplayServerIOS::tts_pause() { ERR_FAIL_COND(!tts); [tts pauseSpeaking]; } -void DisplayServerIPhone::tts_resume() { +void DisplayServerIOS::tts_resume() { ERR_FAIL_COND(!tts); [tts resumeSpeaking]; } -void DisplayServerIPhone::tts_stop() { +void DisplayServerIOS::tts_stop() { ERR_FAIL_COND(!tts); [tts stopSpeaking]; } -Rect2i DisplayServerIPhone::get_display_safe_area() const { +Rect2i DisplayServerIOS::get_display_safe_area() const { if (@available(iOS 11, *)) { UIEdgeInsets insets = UIEdgeInsetsZero; UIView *view = AppDelegate.viewController.godotView; @@ -377,15 +377,15 @@ Rect2i DisplayServerIPhone::get_display_safe_area() const { } } -int DisplayServerIPhone::get_screen_count() const { +int DisplayServerIOS::get_screen_count() const { return 1; } -Point2i DisplayServerIPhone::screen_get_position(int p_screen) const { +Point2i DisplayServerIOS::screen_get_position(int p_screen) const { return Size2i(); } -Size2i DisplayServerIPhone::screen_get_size(int p_screen) const { +Size2i DisplayServerIOS::screen_get_size(int p_screen) const { CALayer *layer = AppDelegate.viewController.godotView.renderingLayer; if (!layer) { @@ -395,11 +395,11 @@ Size2i DisplayServerIPhone::screen_get_size(int p_screen) const { return Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_scale(p_screen); } -Rect2i DisplayServerIPhone::screen_get_usable_rect(int p_screen) const { +Rect2i DisplayServerIOS::screen_get_usable_rect(int p_screen) const { return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); } -int DisplayServerIPhone::screen_get_dpi(int p_screen) const { +int DisplayServerIOS::screen_get_dpi(int p_screen) const { struct utsname systemInfo; uname(&systemInfo); @@ -436,25 +436,25 @@ int DisplayServerIPhone::screen_get_dpi(int p_screen) const { } } -float DisplayServerIPhone::screen_get_refresh_rate(int p_screen) const { +float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const { return [UIScreen mainScreen].maximumFramesPerSecond; } -float DisplayServerIPhone::screen_get_scale(int p_screen) const { +float DisplayServerIOS::screen_get_scale(int p_screen) const { return [UIScreen mainScreen].nativeScale; } -Vector<DisplayServer::WindowID> DisplayServerIPhone::get_window_list() const { +Vector<DisplayServer::WindowID> DisplayServerIOS::get_window_list() const { Vector<DisplayServer::WindowID> list; list.push_back(MAIN_WINDOW_ID); return list; } -DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const Point2i &p_position) const { +DisplayServer::WindowID DisplayServerIOS::get_window_at_screen_position(const Point2i &p_position) const { return MAIN_WINDOW_ID; } -int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { +int64_t DisplayServerIOS::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); switch (p_handle_type) { case DISPLAY_HANDLE: { @@ -472,160 +472,192 @@ int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, } } -void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { +void DisplayServerIOS::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { window_attached_instance_id = p_instance; } -ObjectID DisplayServerIPhone::window_get_attached_instance_id(WindowID p_window) const { +ObjectID DisplayServerIOS::window_get_attached_instance_id(WindowID p_window) const { return window_attached_instance_id; } -void DisplayServerIPhone::window_set_title(const String &p_title, WindowID p_window) { +void DisplayServerIOS::window_set_title(const String &p_title, WindowID p_window) { // Probably not supported for iOS } -int DisplayServerIPhone::window_get_current_screen(WindowID p_window) const { +int DisplayServerIOS::window_get_current_screen(WindowID p_window) const { return SCREEN_OF_MAIN_WINDOW; } -void DisplayServerIPhone::window_set_current_screen(int p_screen, WindowID p_window) { +void DisplayServerIOS::window_set_current_screen(int p_screen, WindowID p_window) { // Probably not supported for iOS } -Point2i DisplayServerIPhone::window_get_position(WindowID p_window) const { +Point2i DisplayServerIOS::window_get_position(WindowID p_window) const { return Point2i(); } -void DisplayServerIPhone::window_set_position(const Point2i &p_position, WindowID p_window) { +void DisplayServerIOS::window_set_position(const Point2i &p_position, WindowID p_window) { // Probably not supported for single window iOS app } -void DisplayServerIPhone::window_set_transient(WindowID p_window, WindowID p_parent) { +void DisplayServerIOS::window_set_transient(WindowID p_window, WindowID p_parent) { // Probably not supported for iOS } -void DisplayServerIPhone::window_set_max_size(const Size2i p_size, WindowID p_window) { +void DisplayServerIOS::window_set_max_size(const Size2i p_size, WindowID p_window) { // Probably not supported for iOS } -Size2i DisplayServerIPhone::window_get_max_size(WindowID p_window) const { +Size2i DisplayServerIOS::window_get_max_size(WindowID p_window) const { return Size2i(); } -void DisplayServerIPhone::window_set_min_size(const Size2i p_size, WindowID p_window) { +void DisplayServerIOS::window_set_min_size(const Size2i p_size, WindowID p_window) { // Probably not supported for iOS } -Size2i DisplayServerIPhone::window_get_min_size(WindowID p_window) const { +Size2i DisplayServerIOS::window_get_min_size(WindowID p_window) const { return Size2i(); } -void DisplayServerIPhone::window_set_size(const Size2i p_size, WindowID p_window) { +void DisplayServerIOS::window_set_size(const Size2i p_size, WindowID p_window) { // Probably not supported for iOS } -Size2i DisplayServerIPhone::window_get_size(WindowID p_window) const { +Size2i DisplayServerIOS::window_get_size(WindowID p_window) const { CGRect screenBounds = [UIScreen mainScreen].bounds; return Size2i(screenBounds.size.width, screenBounds.size.height) * screen_get_max_scale(); } -Size2i DisplayServerIPhone::window_get_real_size(WindowID p_window) const { +Size2i DisplayServerIOS::window_get_real_size(WindowID p_window) const { return window_get_size(p_window); } -void DisplayServerIPhone::window_set_mode(WindowMode p_mode, WindowID p_window) { +void DisplayServerIOS::window_set_mode(WindowMode p_mode, WindowID p_window) { // Probably not supported for iOS } -DisplayServer::WindowMode DisplayServerIPhone::window_get_mode(WindowID p_window) const { +DisplayServer::WindowMode DisplayServerIOS::window_get_mode(WindowID p_window) const { return WindowMode::WINDOW_MODE_FULLSCREEN; } -bool DisplayServerIPhone::window_is_maximize_allowed(WindowID p_window) const { +bool DisplayServerIOS::window_is_maximize_allowed(WindowID p_window) const { return false; } -void DisplayServerIPhone::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { +void DisplayServerIOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { // Probably not supported for iOS } -bool DisplayServerIPhone::window_get_flag(WindowFlags p_flag, WindowID p_window) const { +bool DisplayServerIOS::window_get_flag(WindowFlags p_flag, WindowID p_window) const { return false; } -void DisplayServerIPhone::window_request_attention(WindowID p_window) { +void DisplayServerIOS::window_request_attention(WindowID p_window) { // Probably not supported for iOS } -void DisplayServerIPhone::window_move_to_foreground(WindowID p_window) { +void DisplayServerIOS::window_move_to_foreground(WindowID p_window) { // Probably not supported for iOS } -float DisplayServerIPhone::screen_get_max_scale() const { +float DisplayServerIOS::screen_get_max_scale() const { return screen_get_scale(SCREEN_OF_MAIN_WINDOW); } -void DisplayServerIPhone::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { +void DisplayServerIOS::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { screen_orientation = p_orientation; } -DisplayServer::ScreenOrientation DisplayServerIPhone::screen_get_orientation(int p_screen) const { +DisplayServer::ScreenOrientation DisplayServerIOS::screen_get_orientation(int p_screen) const { return screen_orientation; } -bool DisplayServerIPhone::window_can_draw(WindowID p_window) const { +bool DisplayServerIOS::window_can_draw(WindowID p_window) const { return true; } -bool DisplayServerIPhone::can_any_window_draw() const { +bool DisplayServerIOS::can_any_window_draw() const { return true; } -bool DisplayServerIPhone::screen_is_touchscreen(int p_screen) const { +bool DisplayServerIOS::screen_is_touchscreen(int p_screen) const { return true; } -void DisplayServerIPhone::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) { +void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) { NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()]; + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + AppDelegate.viewController.keyboardView.textContentType = nil; + switch (p_type) { + case KEYBOARD_TYPE_DEFAULT: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + } break; + case KEYBOARD_TYPE_MULTILINE: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + } break; + case KEYBOARD_TYPE_NUMBER: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeNumberPad; + } break; + case KEYBOARD_TYPE_NUMBER_DECIMAL: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDecimalPad; + } break; + case KEYBOARD_TYPE_PHONE: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypePhonePad; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeTelephoneNumber; + } break; + case KEYBOARD_TYPE_EMAIL_ADDRESS: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeEmailAddress; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeEmailAddress; + } break; + case KEYBOARD_TYPE_PASSWORD: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypePassword; + } break; + case KEYBOARD_TYPE_URL: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeWebSearch; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeURL; + } break; + } + [AppDelegate.viewController.keyboardView becomeFirstResponderWithString:existingString - multiline:p_multiline cursorStart:p_cursor_start cursorEnd:p_cursor_end]; } -void DisplayServerIPhone::virtual_keyboard_hide() { +void DisplayServerIOS::virtual_keyboard_hide() { [AppDelegate.viewController.keyboardView resignFirstResponder]; } -void DisplayServerIPhone::virtual_keyboard_set_height(int height) { +void DisplayServerIOS::virtual_keyboard_set_height(int height) { virtual_keyboard_height = height * screen_get_max_scale(); } -int DisplayServerIPhone::virtual_keyboard_get_height() const { +int DisplayServerIOS::virtual_keyboard_get_height() const { return virtual_keyboard_height; } -void DisplayServerIPhone::clipboard_set(const String &p_text) { +void DisplayServerIOS::clipboard_set(const String &p_text) { [UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8()]; } -String DisplayServerIPhone::clipboard_get() const { +String DisplayServerIOS::clipboard_get() const { NSString *text = [UIPasteboard generalPasteboard].string; return String::utf8([text UTF8String]); } -void DisplayServerIPhone::screen_set_keep_on(bool p_enable) { +void DisplayServerIOS::screen_set_keep_on(bool p_enable) { [UIApplication sharedApplication].idleTimerDisabled = p_enable; } -bool DisplayServerIPhone::screen_is_kept_on() const { +bool DisplayServerIOS::screen_is_kept_on() const { return [UIApplication sharedApplication].idleTimerDisabled; } -void DisplayServerIPhone::resize_window(CGSize viewSize) { +void DisplayServerIOS::resize_window(CGSize viewSize) { Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale(); #if defined(VULKAN_ENABLED) @@ -638,14 +670,14 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) { _window_callback(window_resize_callback, resize_rect); } -void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { +void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) context_vulkan->set_vsync_mode(p_window, p_vsync_mode); #endif } -DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const { +DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) return context_vulkan->get_vsync_mode(p_window); diff --git a/platform/iphone/export/export.cpp b/platform/ios/export/export.cpp index 3b02e661c1..6024db2f2c 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/ios/export/export.cpp @@ -30,9 +30,10 @@ #include "export.h" +#include "editor/export/editor_export.h" #include "export_plugin.h" -void register_iphone_exporter() { +void register_ios_exporter() { Ref<EditorExportPlatformIOS> platform; platform.instantiate(); diff --git a/platform/osx/export/export.h b/platform/ios/export/export.h index b386337a09..756a1356ea 100644 --- a/platform/osx/export/export.h +++ b/platform/ios/export/export.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OSX_EXPORT_H -#define OSX_EXPORT_H +#ifndef IOS_EXPORT_H +#define IOS_EXPORT_H -void register_osx_exporter(); +void register_ios_exporter(); -#endif // OSX_EXPORT_H +#endif // IOS_EXPORT_H diff --git a/platform/iphone/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 3b92bd19be..2ac44ccf8b 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -30,9 +30,10 @@ #include "export_plugin.h" +#include "core/string/translation.h" #include "editor/editor_node.h" -void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { +void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); // Vulkan and OpenGL ES 3.0 both mandate ETC2 support. r_features->push_back("etc2"); @@ -43,7 +44,7 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> } } -Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() { +Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() const { Vector<ExportArchitecture> archs; archs.push_back(ExportArchitecture("arm64", true)); return archs; @@ -418,7 +419,7 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ } // !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero... - // should apply the same fix in our OSX export. + // should apply the same fix in our macOS export. CharString cs = strnew.utf8(); pfile.resize(cs.size() - 1); for (int i = 0; i < cs.size() - 1; i++) { @@ -1155,7 +1156,7 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir return OK; } -Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) { +Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const { Vector<ExportArchitecture> all_archs = _get_supported_architectures(); Vector<String> enabled_archs; for (int i = 0; i < all_archs.size(); ++i) { @@ -1394,7 +1395,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p if (src_pkg_name.is_empty()) { String err; - src_pkg_name = find_export_template("iphone.zip", &err); + src_pkg_name = find_export_template("ios.zip", &err); if (src_pkg_name.is_empty()) { add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found.")); return ERR_FILE_NOT_FOUND; @@ -1444,7 +1445,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return ERR_SKIP; } - String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".xcframework"; + String library_to_use = "libgodot.ios." + String(p_debug ? "debug" : "release") + ".xcframework"; print_line("Static framework: " + library_to_use); String pkg_name; @@ -1502,7 +1503,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p int ret = unzGoToFirstFile(src_pkg_zip); Vector<uint8_t> project_file_data; while (ret == UNZ_OK) { -#if defined(OSX_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(X11_ENABLED) bool is_execute = false; #endif @@ -1527,17 +1528,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p //write - file = file.replace_first("iphone/", ""); - if (files_to_parse.has(file)) { _fix_config_file(p_preset, data, config_data, p_debug); - } else if (file.begins_with("libgodot.iphone")) { + } else if (file.begins_with("libgodot.ios")) { if (!file.begins_with(library_to_use) || file.ends_with(String("/empty"))) { ret = unzGoToNextFile(src_pkg_zip); continue; //ignore! } found_library = true; -#if defined(OSX_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(X11_ENABLED) is_execute = true; #endif file = file.replace(library_to_use, binary_name + ".xcframework"); @@ -1580,7 +1579,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p f->store_buffer(data.ptr(), data.size()); } -#if defined(OSX_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(X11_ENABLED) if (is_execute) { // we need execute rights on this file chmod(file.utf8().get_data(), 0755); @@ -1725,7 +1724,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p f->store_buffer(project_file_data.ptr(), project_file_data.size()); } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED { if (ep.step("Code-signing dylibs", 2)) { return ERR_SKIP; @@ -1790,7 +1789,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset // Look for export templates (first official, and if defined custom templates). - bool dvalid = exists_export_template("iphone.zip", &err); + bool dvalid = exists_export_template("ios.zip", &err); bool rvalid = dvalid; // Both in the same ZIP. if (p_preset->get("custom_template/debug") != "") { @@ -1838,7 +1837,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset } EditorExportPlatformIOS::EditorExportPlatformIOS() { - logo = ImageTexture::create_from_image(memnew(Image(_iphone_logo))); + logo = ImageTexture::create_from_image(memnew(Image(_ios_logo))); plugins_changed.set(); check_for_changes_thread.start(_check_for_changes_poll_thread, this); } diff --git a/platform/iphone/export/export_plugin.h b/platform/ios/export/export_plugin.h index 1db7418e3f..07e30c1d00 100644 --- a/platform/iphone/export/export_plugin.h +++ b/platform/ios/export/export_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IPHONE_EXPORT_PLUGIN_H -#define IPHONE_EXPORT_PLUGIN_H +#ifndef IOS_EXPORT_PLUGIN_H +#define IOS_EXPORT_PLUGIN_H #include "core/config/project_settings.h" #include "core/io/file_access.h" @@ -40,10 +40,10 @@ #include "core/os/os.h" #include "core/templates/safe_refcount.h" #include "core/version.h" -#include "editor/editor_export.h" #include "editor/editor_settings.h" +#include "editor/export/editor_export_platform.h" #include "main/splash.gen.h" -#include "platform/iphone/logo.gen.h" +#include "platform/ios/logo.gen.h" #include "string.h" #include "godot_plugin_config.h" @@ -106,8 +106,8 @@ class EditorExportPlatformIOS : public EditorExportPlatform { Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir); Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir); - Vector<ExportArchitecture> _get_supported_architectures(); - Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset); + Vector<ExportArchitecture> _get_supported_architectures() const; + Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const; void _add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets); Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); @@ -173,7 +173,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { } protected: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; public: @@ -199,7 +199,7 @@ public: virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; - virtual void get_platform_features(List<String> *r_features) override { + virtual void get_platform_features(List<String> *r_features) const override { r_features->push_back("mobile"); r_features->push_back("ios"); } @@ -290,4 +290,4 @@ public: } }; -#endif +#endif // IOS_EXPORT_PLUGIN_H diff --git a/platform/iphone/export/godot_plugin_config.cpp b/platform/ios/export/godot_plugin_config.cpp index 9118b95337..9118b95337 100644 --- a/platform/iphone/export/godot_plugin_config.cpp +++ b/platform/ios/export/godot_plugin_config.cpp diff --git a/platform/iphone/export/godot_plugin_config.h b/platform/ios/export/godot_plugin_config.h index 9ef8aa8c6d..5ca8b05b42 100644 --- a/platform/iphone/export/godot_plugin_config.h +++ b/platform/ios/export/godot_plugin_config.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IPHONE_GODOT_PLUGIN_CONFIG_H -#define IPHONE_GODOT_PLUGIN_CONFIG_H +#ifndef IOS_GODOT_PLUGIN_CONFIG_H +#define IOS_GODOT_PLUGIN_CONFIG_H #include "core/error/error_list.h" #include "core/io/config_file.h" @@ -129,4 +129,4 @@ struct PluginConfigIOS { static PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, const String &path); }; -#endif // GODOT_PLUGIN_CONFIG_H +#endif // IOS_GODOT_PLUGIN_CONFIG_H diff --git a/platform/iphone/godot_app_delegate.h b/platform/ios/godot_app_delegate.h index 703a906bda..703a906bda 100644 --- a/platform/iphone/godot_app_delegate.h +++ b/platform/ios/godot_app_delegate.h diff --git a/platform/iphone/godot_app_delegate.m b/platform/ios/godot_app_delegate.m index 84347f9a30..84347f9a30 100644 --- a/platform/iphone/godot_app_delegate.m +++ b/platform/ios/godot_app_delegate.m diff --git a/platform/iphone/godot_iphone.mm b/platform/ios/godot_ios.mm index 59fdfa9dcd..5f3e786b8a 100644 --- a/platform/iphone/godot_iphone.mm +++ b/platform/ios/godot_ios.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_iphone.mm */ +/* godot_ios.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,17 +30,17 @@ #include "core/string/ustring.h" #include "main/main.h" -#include "os_iphone.h" +#include "os_ios.h" #include <stdio.h> #include <string.h> #include <unistd.h> -static OSIPhone *os = nullptr; +static OS_IOS *os = nullptr; int add_path(int, char **); int add_cmdline(int, char **); -int iphone_main(int, char **, String); +int ios_main(int, char **, String); int add_path(int p_argc, char **p_args) { NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"]; @@ -74,7 +74,7 @@ int add_cmdline(int p_argc, char **p_args) { return p_argc; } -int iphone_main(int argc, char **argv, String data_dir, String cache_dir) { +int ios_main(int argc, char **argv, String data_dir, String cache_dir) { size_t len = strlen(argv[0]); while (len--) { @@ -91,11 +91,11 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) { chdir(path); } - printf("godot_iphone %s\n", argv[0]); + printf("godot_ios %s\n", argv[0]); char cwd[512]; getcwd(cwd, sizeof(cwd)); printf("cwd %s\n", cwd); - os = new OSIPhone(data_dir, cache_dir); + os = new OS_IOS(data_dir, cache_dir); // We must override main when testing is enabled TEST_MAIN_OVERRIDE @@ -124,8 +124,8 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) { return 0; } -void iphone_finish() { - printf("iphone_finish\n"); +void ios_finish() { + printf("ios_finish\n"); Main::cleanup(); delete os; } diff --git a/platform/iphone/godot_view.h b/platform/ios/godot_view.h index fcb97fa63a..fcb97fa63a 100644 --- a/platform/iphone/godot_view.h +++ b/platform/ios/godot_view.h diff --git a/platform/iphone/godot_view.mm b/platform/ios/godot_view.mm index e48dd2e507..9ed219508c 100644 --- a/platform/iphone/godot_view.mm +++ b/platform/ios/godot_view.mm @@ -33,7 +33,7 @@ #include "core/os/keyboard.h" #include "core/string/ustring.h" #import "display_layer.h" -#include "display_server_iphone.h" +#include "display_server_ios.h" #import "godot_view_gesture_recognizer.h" #import "godot_view_renderer.h" @@ -281,8 +281,8 @@ static const float earth_gravity = 9.80665; self.renderingLayer.frame = self.bounds; [self.renderingLayer layoutDisplayLayer]; - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->resize_window(self.bounds.size); + if (DisplayServerIOS::get_singleton()) { + DisplayServerIOS::get_singleton()->resize_window(self.bounds.size); } } @@ -348,7 +348,7 @@ static const float earth_gravity = 9.80665; int tid = [self getTouchIDForTouch:touch]; ERR_FAIL_COND(tid == -1); CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); } } } @@ -362,7 +362,7 @@ static const float earth_gravity = 9.80665; ERR_FAIL_COND(tid == -1); CGPoint touchPoint = [touch locationInView:self]; CGPoint prev_point = [touch previousLocationInView:self]; - DisplayServerIPhone::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor); + DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor); } } } @@ -376,7 +376,7 @@ static const float earth_gravity = 9.80665; ERR_FAIL_COND(tid == -1); [self removeTouch:touch]; CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); } } } @@ -388,7 +388,7 @@ static const float earth_gravity = 9.80665; UITouch *touch = [tlist objectAtIndex:i]; int tid = [self getTouchIDForTouch:touch]; ERR_FAIL_COND(tid == -1); - DisplayServerIPhone::get_singleton()->touches_cancelled(tid); + DisplayServerIOS::get_singleton()->touches_cancelled(tid); } } [self clearTouches]; @@ -452,28 +452,28 @@ static const float earth_gravity = 9.80665; switch (interfaceOrientation) { case UIInterfaceOrientationLandscapeLeft: { - DisplayServerIPhone::get_singleton()->update_gravity(-gravity.y, gravity.x, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.y + gravity.y), (acceleration.x + gravity.x), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.y, magnetic.x, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.y, rotation.x, rotation.z); + DisplayServerIOS::get_singleton()->update_gravity(-gravity.y, gravity.x, gravity.z); + DisplayServerIOS::get_singleton()->update_accelerometer(-(acceleration.y + gravity.y), (acceleration.x + gravity.x), acceleration.z + gravity.z); + DisplayServerIOS::get_singleton()->update_magnetometer(-magnetic.y, magnetic.x, magnetic.z); + DisplayServerIOS::get_singleton()->update_gyroscope(-rotation.y, rotation.x, rotation.z); } break; case UIInterfaceOrientationLandscapeRight: { - DisplayServerIPhone::get_singleton()->update_gravity(gravity.y, -gravity.x, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer((acceleration.y + gravity.y), -(acceleration.x + gravity.x), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.y, -magnetic.x, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.y, -rotation.x, rotation.z); + DisplayServerIOS::get_singleton()->update_gravity(gravity.y, -gravity.x, gravity.z); + DisplayServerIOS::get_singleton()->update_accelerometer((acceleration.y + gravity.y), -(acceleration.x + gravity.x), acceleration.z + gravity.z); + DisplayServerIOS::get_singleton()->update_magnetometer(magnetic.y, -magnetic.x, magnetic.z); + DisplayServerIOS::get_singleton()->update_gyroscope(rotation.y, -rotation.x, rotation.z); } break; case UIInterfaceOrientationPortraitUpsideDown: { - DisplayServerIPhone::get_singleton()->update_gravity(-gravity.x, gravity.y, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.x + gravity.x), (acceleration.y + gravity.y), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.x, magnetic.y, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.x, rotation.y, rotation.z); + DisplayServerIOS::get_singleton()->update_gravity(-gravity.x, gravity.y, gravity.z); + DisplayServerIOS::get_singleton()->update_accelerometer(-(acceleration.x + gravity.x), (acceleration.y + gravity.y), acceleration.z + gravity.z); + DisplayServerIOS::get_singleton()->update_magnetometer(-magnetic.x, magnetic.y, magnetic.z); + DisplayServerIOS::get_singleton()->update_gyroscope(-rotation.x, rotation.y, rotation.z); } break; default: { // assume portrait - DisplayServerIPhone::get_singleton()->update_gravity(gravity.x, gravity.y, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z); + DisplayServerIOS::get_singleton()->update_gravity(gravity.x, gravity.y, gravity.z); + DisplayServerIOS::get_singleton()->update_accelerometer(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z); + DisplayServerIOS::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z); + DisplayServerIOS::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z); } break; } } diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/ios/godot_view_gesture_recognizer.h index 9fd8a6b222..9fd8a6b222 100644 --- a/platform/iphone/godot_view_gesture_recognizer.h +++ b/platform/ios/godot_view_gesture_recognizer.h diff --git a/platform/iphone/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm index 49a92add5e..49a92add5e 100644 --- a/platform/iphone/godot_view_gesture_recognizer.mm +++ b/platform/ios/godot_view_gesture_recognizer.mm diff --git a/platform/iphone/godot_view_renderer.h b/platform/ios/godot_view_renderer.h index b3ee23ae4f..b3ee23ae4f 100644 --- a/platform/iphone/godot_view_renderer.h +++ b/platform/ios/godot_view_renderer.h diff --git a/platform/iphone/godot_view_renderer.mm b/platform/ios/godot_view_renderer.mm index 32477ae41c..140410fbef 100644 --- a/platform/iphone/godot_view_renderer.mm +++ b/platform/ios/godot_view_renderer.mm @@ -32,9 +32,9 @@ #include "core/config/project_settings.h" #include "core/os/keyboard.h" -#import "display_server_iphone.h" +#import "display_server_ios.h" #include "main/main.h" -#include "os_iphone.h" +#include "os_ios.h" #include "servers/audio_server.h" #import <AudioToolbox/AudioServices.h> @@ -69,7 +69,7 @@ if (!self.hasStartedMain) { self.hasStartedMain = YES; - OSIPhone::get_singleton()->start(); + OS_IOS::get_singleton()->start(); return YES; } @@ -108,11 +108,11 @@ } - (void)renderOnView:(UIView *)view { - if (!OSIPhone::get_singleton()) { + if (!OS_IOS::get_singleton()) { return; } - OSIPhone::get_singleton()->iterate(); + OS_IOS::get_singleton()->iterate(); } @end diff --git a/platform/iphone/ios.h b/platform/ios/ios.h index 0607d7b395..0b3842b233 100644 --- a/platform/iphone/ios.h +++ b/platform/ios/ios.h @@ -58,4 +58,4 @@ public: iOS(); }; -#endif +#endif // IOS_H diff --git a/platform/iphone/ios.mm b/platform/ios/ios.mm index 79baae028a..79baae028a 100644 --- a/platform/iphone/ios.mm +++ b/platform/ios/ios.mm diff --git a/platform/iphone/joypad_iphone.h b/platform/ios/joypad_ios.h index 37e272a2c9..66c4b090bc 100644 --- a/platform/iphone/joypad_iphone.h +++ b/platform/ios/joypad_ios.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad_iphone.h */ +/* joypad_ios.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #import <GameController/GameController.h> -@interface JoypadIPhoneObserver : NSObject +@interface JoypadIOSObserver : NSObject - (void)startObserving; - (void)startProcessing; @@ -38,13 +38,13 @@ @end -class JoypadIPhone { +class JoypadIOS { private: - JoypadIPhoneObserver *observer; + JoypadIOSObserver *observer; public: - JoypadIPhone(); - ~JoypadIPhone(); + JoypadIOS(); + ~JoypadIOS(); void start_processing(); }; diff --git a/platform/iphone/joypad_iphone.mm b/platform/ios/joypad_ios.mm index 9c2feeaaca..e147cb2527 100644 --- a/platform/iphone/joypad_iphone.mm +++ b/platform/ios/joypad_ios.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad_iphone.mm */ +/* joypad_ios.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#import "joypad_iphone.h" +#import "joypad_ios.h" #include "core/config/project_settings.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" @@ -36,27 +36,27 @@ #import "godot_view.h" -#include "os_iphone.h" +#include "os_ios.h" -JoypadIPhone::JoypadIPhone() { - observer = [[JoypadIPhoneObserver alloc] init]; +JoypadIOS::JoypadIOS() { + observer = [[JoypadIOSObserver alloc] init]; [observer startObserving]; } -JoypadIPhone::~JoypadIPhone() { +JoypadIOS::~JoypadIOS() { if (observer) { [observer finishObserving]; observer = nil; } } -void JoypadIPhone::start_processing() { +void JoypadIOS::start_processing() { if (observer) { [observer startProcessing]; } } -@interface JoypadIPhoneObserver () +@interface JoypadIOSObserver () @property(assign, nonatomic) BOOL isObserving; @property(assign, nonatomic) BOOL isProcessing; @@ -65,7 +65,7 @@ void JoypadIPhone::start_processing() { @end -@implementation JoypadIPhoneObserver +@implementation JoypadIOSObserver - (instancetype)init { self = [super init]; diff --git a/platform/iphone/keyboard_input_view.h b/platform/ios/keyboard_input_view.h index 33fa5d571a..fc34e6a11b 100644 --- a/platform/iphone/keyboard_input_view.h +++ b/platform/ios/keyboard_input_view.h @@ -32,6 +32,6 @@ @interface GodotKeyboardInputView : UITextView -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; +- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; @end diff --git a/platform/iphone/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm index f2a7b22483..f031a1de22 100644 --- a/platform/iphone/keyboard_input_view.mm +++ b/platform/ios/keyboard_input_view.mm @@ -31,8 +31,8 @@ #import "keyboard_input_view.h" #include "core/os/keyboard.h" -#include "display_server_iphone.h" -#include "os_iphone.h" +#include "display_server_ios.h" +#include "os_ios.h" @interface GodotKeyboardInputView () <UITextViewDelegate> @@ -84,7 +84,7 @@ return YES; } -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end { +- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end { self.text = existingString; self.previousText = existingString; @@ -115,8 +115,8 @@ - (void)deleteText:(NSInteger)charactersToDelete { for (int i = 0; i < charactersToDelete; i++) { - DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, true); - DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, false); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, true); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, false); } } @@ -138,8 +138,8 @@ break; } - DisplayServerIPhone::get_singleton()->key((Key)character, true); - DisplayServerIPhone::get_singleton()->key((Key)character, false); + DisplayServerIOS::get_singleton()->key((Key)character, true); + DisplayServerIOS::get_singleton()->key((Key)character, false); } } diff --git a/platform/iphone/logo.png b/platform/ios/logo.png Binary files differindex 966d8aa70a..966d8aa70a 100644 --- a/platform/iphone/logo.png +++ b/platform/ios/logo.png diff --git a/platform/iphone/main.m b/platform/ios/main.m index acfa7ab731..acfa7ab731 100644 --- a/platform/iphone/main.m +++ b/platform/ios/main.m diff --git a/platform/iphone/os_iphone.h b/platform/ios/os_ios.h index d03403bbb4..3b88f53b6a 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/ios/os_ios.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* os_iphone.h */ +/* os_ios.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,24 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef IPHONE_ENABLED +#ifdef IOS_ENABLED -#ifndef OS_IPHONE_H -#define OS_IPHONE_H +#ifndef OS_IOS_H +#define OS_IOS_H #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/unix/os_unix.h" #include "ios.h" -#include "joypad_iphone.h" +#include "joypad_ios.h" #include "servers/audio_server.h" #include "servers/rendering/renderer_compositor.h" #if defined(VULKAN_ENABLED) #include "drivers/vulkan/rendering_device_vulkan.h" -#include "platform/iphone/vulkan_context_iphone.h" +#include "platform/ios/vulkan_context_ios.h" #endif -class OSIPhone : public OS_Unix { +class OS_IOS : public OS_Unix { private: static HashMap<String, void *> dynamic_symbol_lookup_table; friend void register_dynamic_symbol(char *name, void *address); @@ -54,7 +54,7 @@ private: iOS *ios = nullptr; - JoypadIPhone *joypad_iphone = nullptr; + JoypadIOS *joypad_ios = nullptr; MainLoop *main_loop = nullptr; @@ -79,10 +79,10 @@ private: void deinitialize_modules(); public: - static OSIPhone *get_singleton(); + static OS_IOS *get_singleton(); - OSIPhone(String p_data_dir, String p_cache_dir); - ~OSIPhone(); + OS_IOS(String p_data_dir, String p_cache_dir); + ~OS_IOS(); void initialize_modules(); @@ -92,6 +92,9 @@ public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; + virtual Vector<String> get_system_fonts() const override; + virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override; + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override; virtual Error close_dynamic_library(void *p_library_handle) override; virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override; @@ -119,6 +122,6 @@ public: void on_focus_in(); }; -#endif // OS_IPHONE_H +#endif // OS_IOS_H -#endif // IPHONE_ENABLED +#endif // OS_IOS_H diff --git a/platform/iphone/os_iphone.mm b/platform/ios/os_ios.mm index 95b06b728e..b9d186f355 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/ios/os_ios.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* os_iphone.mm */ +/* os_ios.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,22 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef IPHONE_ENABLED +#ifdef IOS_ENABLED -#include "os_iphone.h" +#include "os_ios.h" #import "app_delegate.h" #include "core/config/project_settings.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" #include "core/io/file_access_pack.h" -#include "display_server_iphone.h" +#include "display_server_ios.h" #include "drivers/unix/syslog_logger.h" #import "godot_view.h" #include "main/main.h" #import "view_controller.h" #import <AudioToolbox/AudioServices.h> +#import <CoreText/CoreText.h> #import <UIKit/UIKit.h> #import <dlfcn.h> #include <sys/sysctl.h> @@ -65,7 +66,7 @@ typedef void (*init_callback)(); static init_callback *ios_init_callbacks = nullptr; static int ios_init_callbacks_count = 0; static int ios_init_callbacks_capacity = 0; -HashMap<String, void *> OSIPhone::dynamic_symbol_lookup_table; +HashMap<String, void *> OS_IOS::dynamic_symbol_lookup_table; void add_ios_init_callback(init_callback cb) { if (ios_init_callbacks_count == ios_init_callbacks_capacity) { @@ -82,14 +83,14 @@ void add_ios_init_callback(init_callback cb) { } void register_dynamic_symbol(char *name, void *address) { - OSIPhone::dynamic_symbol_lookup_table[String(name)] = address; + OS_IOS::dynamic_symbol_lookup_table[String(name)] = address; } -OSIPhone *OSIPhone::get_singleton() { - return (OSIPhone *)OS::get_singleton(); +OS_IOS *OS_IOS::get_singleton() { + return (OS_IOS *)OS::get_singleton(); } -OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) { +OS_IOS::OS_IOS(String p_data_dir, String p_cache_dir) { for (int i = 0; i < ios_init_callbacks_count; ++i) { ios_init_callbacks[i](); } @@ -116,37 +117,37 @@ OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) { AudioDriverManager::add_driver(&audio_driver); - DisplayServerIPhone::register_iphone_driver(); + DisplayServerIOS::register_ios_driver(); } -OSIPhone::~OSIPhone() {} +OS_IOS::~OS_IOS() {} -void OSIPhone::alert(const String &p_alert, const String &p_title) { +void OS_IOS::alert(const String &p_alert, const String &p_title) { const CharString utf8_alert = p_alert.utf8(); const CharString utf8_title = p_title.utf8(); iOS::alert(utf8_alert.get_data(), utf8_title.get_data()); } -void OSIPhone::initialize_core() { +void OS_IOS::initialize_core() { OS_Unix::initialize_core(); set_user_data_dir(user_data_dir); } -void OSIPhone::initialize() { +void OS_IOS::initialize() { initialize_core(); } -void OSIPhone::initialize_modules() { +void OS_IOS::initialize_modules() { ios = memnew(iOS); Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios)); - joypad_iphone = memnew(JoypadIPhone); + joypad_ios = memnew(JoypadIOS); } -void OSIPhone::deinitialize_modules() { - if (joypad_iphone) { - memdelete(joypad_iphone); +void OS_IOS::deinitialize_modules() { + if (joypad_ios) { + memdelete(joypad_ios); } if (ios) { @@ -154,7 +155,7 @@ void OSIPhone::deinitialize_modules() { } } -void OSIPhone::set_main_loop(MainLoop *p_main_loop) { +void OS_IOS::set_main_loop(MainLoop *p_main_loop) { main_loop = p_main_loop; if (main_loop) { @@ -162,11 +163,11 @@ void OSIPhone::set_main_loop(MainLoop *p_main_loop) { } } -MainLoop *OSIPhone::get_main_loop() const { +MainLoop *OS_IOS::get_main_loop() const { return main_loop; } -void OSIPhone::delete_main_loop() { +void OS_IOS::delete_main_loop() { if (main_loop) { main_loop->finalize(); memdelete(main_loop); @@ -175,7 +176,7 @@ void OSIPhone::delete_main_loop() { main_loop = nullptr; } -bool OSIPhone::iterate() { +bool OS_IOS::iterate() { if (!main_loop) { return true; } @@ -187,15 +188,15 @@ bool OSIPhone::iterate() { return Main::iteration(); } -void OSIPhone::start() { +void OS_IOS::start() { Main::start(); - if (joypad_iphone) { - joypad_iphone->start_processing(); + if (joypad_ios) { + joypad_ios->start_processing(); } } -void OSIPhone::finalize() { +void OS_IOS::finalize() { deinitialize_modules(); // Already gets called @@ -204,7 +205,7 @@ void OSIPhone::finalize() { // MARK: Dynamic Libraries -Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { +Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { if (p_path.length() == 0) { p_library_handle = RTLD_SELF; @@ -217,16 +218,16 @@ Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handl return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path); } -Error OSIPhone::close_dynamic_library(void *p_library_handle) { +Error OS_IOS::close_dynamic_library(void *p_library_handle) { if (p_library_handle == RTLD_SELF) { return OK; } return OS_Unix::close_dynamic_library(p_library_handle); } -Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { +Error OS_IOS::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { if (p_library_handle == RTLD_SELF) { - void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name); + void **ptr = OS_IOS::dynamic_symbol_lookup_table.getptr(p_name); if (ptr) { p_symbol_handle = *ptr; return OK; @@ -235,11 +236,11 @@ Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional); } -String OSIPhone::get_name() const { +String OS_IOS::get_name() const { return "iOS"; } -String OSIPhone::get_model_name() const { +String OS_IOS::get_model_name() const { String model = ios->get_model(); if (model != "") { return model; @@ -248,7 +249,7 @@ String OSIPhone::get_model_name() const { return OS_Unix::get_model_name(); } -Error OSIPhone::shell_open(String p_uri) { +Error OS_IOS::shell_open(String p_uri) { NSString *urlPath = [[NSString alloc] initWithUTF8String:p_uri.utf8().get_data()]; NSURL *url = [NSURL URLWithString:urlPath]; @@ -263,21 +264,21 @@ Error OSIPhone::shell_open(String p_uri) { return OK; } -void OSIPhone::set_user_data_dir(String p_dir) { +void OS_IOS::set_user_data_dir(String p_dir) { Ref<DirAccess> da = DirAccess::open(p_dir); user_data_dir = da->get_current_dir(); printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data()); } -String OSIPhone::get_user_data_dir() const { +String OS_IOS::get_user_data_dir() const { return user_data_dir; } -String OSIPhone::get_cache_path() const { +String OS_IOS::get_cache_path() const { return cache_dir; } -String OSIPhone::get_locale() const { +String OS_IOS::get_locale() const { NSString *preferedLanguage = [NSLocale preferredLanguages].firstObject; if (preferedLanguage) { @@ -288,12 +289,12 @@ String OSIPhone::get_locale() const { return String::utf8([localeIdentifier UTF8String]).replace("-", "_"); } -String OSIPhone::get_unique_id() const { +String OS_IOS::get_unique_id() const { NSString *uuid = [UIDevice currentDevice].identifierForVendor.UUIDString; return String::utf8([uuid UTF8String]); } -String OSIPhone::get_processor_name() const { +String OS_IOS::get_processor_name() const { char buffer[256]; size_t buffer_len = 256; if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) { @@ -302,7 +303,81 @@ String OSIPhone::get_processor_name() const { ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string.")); } -void OSIPhone::vibrate_handheld(int p_duration_ms) { +Vector<String> OS_IOS::get_system_fonts() const { + HashSet<String> font_names; + CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames(); + if (fonts) { + for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) { + CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i); + if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) { + NSString *ns_name = (__bridge NSString *)cf_name; + font_names.insert(String::utf8([ns_name UTF8String])); + } + } + CFRelease(fonts); + } + + Vector<String> ret; + for (const String &E : font_names) { + ret.push_back(E); + } + return ret; +} + +String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { + String ret; + + String font_name = p_font_name; + if (font_name.to_lower() == "sans-serif") { + font_name = "Helvetica"; + } else if (font_name.to_lower() == "serif") { + font_name = "Times"; + } else if (font_name.to_lower() == "monospace") { + font_name = "Courier"; + } else if (font_name.to_lower() == "fantasy") { + font_name = "Papyrus"; + } else if (font_name.to_lower() == "cursive") { + font_name = "Apple Chancery"; + }; + + CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8); + + CTFontSymbolicTraits traits = 0; + if (p_bold) { + traits |= kCTFontBoldTrait; + } + if (p_italic) { + traits |= kCTFontItalicTrait; + } + + CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits); + CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); + CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits); + + CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name); + CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict); + + CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes); + if (font) { + CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute); + if (url) { + NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]]; + ret = String::utf8([font_path UTF8String]); + CFRelease(url); + } + CFRelease(font); + } + + CFRelease(attributes); + CFRelease(traits_dict); + CFRelease(sym_traits); + CFRelease(name); + + return ret; +} + +void OS_IOS::vibrate_handheld(int p_duration_ms) { if (ios->supports_haptic_engine()) { ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f); } else { @@ -311,16 +386,16 @@ void OSIPhone::vibrate_handheld(int p_duration_ms) { } } -bool OSIPhone::_check_internal_feature_support(const String &p_feature) { +bool OS_IOS::_check_internal_feature_support(const String &p_feature) { return p_feature == "mobile"; } -void OSIPhone::on_focus_out() { +void OS_IOS::on_focus_out() { if (is_focused) { is_focused = false; - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + if (DisplayServerIOS::get_singleton()) { + DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); } [AppDelegate.viewController.godotView stopRendering]; @@ -329,12 +404,12 @@ void OSIPhone::on_focus_out() { } } -void OSIPhone::on_focus_in() { +void OS_IOS::on_focus_in() { if (!is_focused) { is_focused = true; - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); + if (DisplayServerIOS::get_singleton()) { + DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); } [AppDelegate.viewController.godotView startRendering]; @@ -343,4 +418,4 @@ void OSIPhone::on_focus_in() { } } -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED diff --git a/platform/iphone/platform_config.h b/platform/ios/platform_config.h index fed77d8932..fed77d8932 100644 --- a/platform/iphone/platform_config.h +++ b/platform/ios/platform_config.h diff --git a/platform/iphone/tts_ios.h b/platform/ios/tts_ios.h index 064316b0b2..064316b0b2 100644 --- a/platform/iphone/tts_ios.h +++ b/platform/ios/tts_ios.h diff --git a/platform/iphone/tts_ios.mm b/platform/ios/tts_ios.mm index a079d02add..a079d02add 100644 --- a/platform/iphone/tts_ios.mm +++ b/platform/ios/tts_ios.mm diff --git a/platform/iphone/view_controller.h b/platform/ios/view_controller.h index c8b37a4d11..c8b37a4d11 100644 --- a/platform/iphone/view_controller.h +++ b/platform/ios/view_controller.h diff --git a/platform/iphone/view_controller.mm b/platform/ios/view_controller.mm index 4f4ef4f046..43669d3f94 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/ios/view_controller.mm @@ -30,11 +30,11 @@ #import "view_controller.h" #include "core/config/project_settings.h" -#include "display_server_iphone.h" +#include "display_server_ios.h" #import "godot_view.h" #import "godot_view_renderer.h" #import "keyboard_input_view.h" -#include "os_iphone.h" +#include "os_ios.h" #import <AVFoundation/AVFoundation.h> #import <GameController/GameController.h> @@ -168,11 +168,11 @@ } - (BOOL)shouldAutorotate { - if (!DisplayServerIPhone::get_singleton()) { + if (!DisplayServerIOS::get_singleton()) { return NO; } - switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { + switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { case DisplayServer::SCREEN_SENSOR: case DisplayServer::SCREEN_SENSOR_LANDSCAPE: case DisplayServer::SCREEN_SENSOR_PORTRAIT: @@ -183,11 +183,11 @@ } - (UIInterfaceOrientationMask)supportedInterfaceOrientations { - if (!DisplayServerIPhone::get_singleton()) { + if (!DisplayServerIOS::get_singleton()) { return UIInterfaceOrientationMaskAll; } - switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { + switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { case DisplayServer::SCREEN_PORTRAIT: return UIInterfaceOrientationMaskPortrait; case DisplayServer::SCREEN_REVERSE_LANDSCAPE: @@ -226,14 +226,14 @@ CGRect rawFrame = [value CGRectValue]; CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil]; - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height); + if (DisplayServerIOS::get_singleton()) { + DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height); } } - (void)keyboardHidden:(NSNotification *)notification { - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(0); + if (DisplayServerIOS::get_singleton()) { + DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(0); } } diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/ios/vulkan_context_ios.h index 7576525755..e9c09e087a 100644 --- a/platform/iphone/vulkan_context_iphone.h +++ b/platform/ios/vulkan_context_ios.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* vulkan_context_iphone.h */ +/* vulkan_context_ios.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VULKAN_CONTEXT_IPHONE_H -#define VULKAN_CONTEXT_IPHONE_H +#ifndef VULKAN_CONTEXT_IOS_H +#define VULKAN_CONTEXT_IOS_H #include "drivers/vulkan/vulkan_context.h" #import <UIKit/UIKit.h> -class VulkanContextIPhone : public VulkanContext { +class VulkanContextIOS : public VulkanContext { virtual const char *_get_platform_surface_extension() const; public: Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height); - VulkanContextIPhone(); - ~VulkanContextIPhone(); + VulkanContextIOS(); + ~VulkanContextIOS(); }; -#endif // VULKAN_CONTEXT_IPHONE_H +#endif // VULKAN_CONTEXT_IOS_H diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/ios/vulkan_context_ios.mm index 17cb0f6009..09cd369aa5 100644 --- a/platform/iphone/vulkan_context_iphone.mm +++ b/platform/ios/vulkan_context_ios.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* vulkan_context_iphone.mm */ +/* vulkan_context_ios.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "vulkan_context_iphone.h" +#include "vulkan_context_ios.h" #ifdef USE_VOLK #include <volk.h> #else #include <vulkan/vulkan.h> #endif -const char *VulkanContextIPhone::_get_platform_surface_extension() const { +const char *VulkanContextIOS::_get_platform_surface_extension() const { return VK_MVK_IOS_SURFACE_EXTENSION_NAME; } -Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) { +Error VulkanContextIOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) { VkIOSSurfaceCreateInfoMVK createInfo; createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; createInfo.pNext = nullptr; @@ -54,6 +54,6 @@ Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, Di return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height); } -VulkanContextIPhone::VulkanContextIPhone() {} +VulkanContextIOS::VulkanContextIOS() {} -VulkanContextIPhone::~VulkanContextIPhone() {} +VulkanContextIOS::~VulkanContextIOS() {} diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h index b7b0b3ac96..807e2f936b 100644 --- a/platform/javascript/audio_driver_javascript.h +++ b/platform/javascript/audio_driver_javascript.h @@ -158,4 +158,4 @@ public: }; #endif -#endif +#endif // AUDIO_DRIVER_JAVASCRIPT_H diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 4edd6c793a..48f637fcfe 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -83,7 +83,7 @@ void DisplayServerJavaScript::drop_files_js_callback(char **p_filev, int p_filec Variant *vp = &v; Variant ret; Callable::CallError ce; - ds->drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + ds->drop_files_callback.callp((const Variant **)&vp, 1, ret, ce); } // JavaScript quit request callback. @@ -94,7 +94,7 @@ void DisplayServerJavaScript::request_quit_callback() { Variant *eventp = &event; Variant ret; Callable::CallError ce; - ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce); + ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce); } } @@ -586,7 +586,7 @@ void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_c Variant *eventp = &event; Variant ret; Callable::CallError ce; - ds->input_text_callback.call((const Variant **)&eventp, 1, ret, ce); + ds->input_text_callback.callp((const Variant **)&eventp, 1, ret, ce); // Insert key right to reach position. Input *input = Input::get_singleton(); Ref<InputEventKey> k; @@ -604,8 +604,8 @@ void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_c } } -void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { - godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_multiline, p_cursor_start, p_cursor_end); +void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_type, p_cursor_start, p_cursor_end); } void DisplayServerJavaScript::virtual_keyboard_hide() { @@ -691,7 +691,7 @@ void DisplayServerJavaScript::send_window_event_callback(int p_notification) { Variant *eventp = &event; Variant ret; Callable::CallError ce; - ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce); + ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce); } } @@ -734,7 +734,7 @@ void DisplayServerJavaScript::_dispatch_input_event(const Ref<InputEvent> &p_eve Variant *evp = &ev; Variant ret; Callable::CallError ce; - cb.call((const Variant **)&evp, 1, ret, ce); + cb.callp((const Variant **)&evp, 1, ret, ce); } } diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 79b0fbb652..fb7f5d02a8 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -157,7 +157,7 @@ public: virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; + virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; virtual void virtual_keyboard_hide() override; // windows diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 825c1b6638..ea236f62f7 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/editor_settings.h" #include "export_plugin.h" void register_javascript_exporter() { diff --git a/platform/javascript/export/export.h b/platform/javascript/export/export.h index 41cc66cfb8..29c335ed0e 100644 --- a/platform/javascript/export/export.h +++ b/platform/javascript/export/export.h @@ -33,4 +33,4 @@ void register_javascript_exporter(); -#endif +#endif // JAVASCRIPT_EXPORT_H diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index e2ae45627e..b99f88d067 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -31,6 +31,7 @@ #include "export_plugin.h" #include "core/config/project_settings.h" +#include "editor/editor_settings.h" Error EditorExportPlatformJavaScript::_extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa) { Ref<FileAccess> io_fa; @@ -302,7 +303,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> & return OK; } -void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { +void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { if (p_preset->get("vram_texture_compression/for_desktop")) { r_features->push_back("s3tc"); } diff --git a/platform/javascript/export/export_plugin.h b/platform/javascript/export/export_plugin.h index 1aaec5454d..fbaa3615cb 100644 --- a/platform/javascript/export/export_plugin.h +++ b/platform/javascript/export/export_plugin.h @@ -36,8 +36,8 @@ #include "core/io/stream_peer_ssl.h" #include "core/io/tcp_server.h" #include "core/io/zip_io.h" -#include "editor/editor_export.h" #include "editor/editor_node.h" +#include "editor/export/editor_export_platform.h" #include "main/splash.gen.h" #include "platform/javascript/logo.gen.h" #include "platform/javascript/run_icon.gen.h" @@ -110,7 +110,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform { static void _server_thread_poll(void *data); public: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; @@ -130,7 +130,7 @@ public: virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags) override; virtual Ref<Texture2D> get_run_icon() const override; - virtual void get_platform_features(List<String> *r_features) override { + virtual void get_platform_features(List<String> *r_features) const override { r_features->push_back("web"); r_features->push_back(get_os_name().to_lower()); } @@ -144,4 +144,4 @@ public: ~EditorExportPlatformJavaScript(); }; -#endif +#endif // JAVASCRIPT_EXPORT_PLUGIN_H diff --git a/platform/javascript/export/export_server.h b/platform/javascript/export/export_server.h index a831b76076..ddbe3cca30 100644 --- a/platform/javascript/export/export_server.h +++ b/platform/javascript/export/export_server.h @@ -35,7 +35,6 @@ #include "core/io/stream_peer_ssl.h" #include "core/io/tcp_server.h" #include "core/io/zip_io.h" -#include "editor/editor_export.h" #include "editor/editor_paths.h" class EditorHTTPServer : public RefCounted { @@ -248,4 +247,4 @@ public: } }; -#endif +#endif // JAVASCRIPT_EXPORT_SERVER_H diff --git a/platform/javascript/godot_audio.h b/platform/javascript/godot_audio.h index 012f8daeb7..3855b7301e 100644 --- a/platform/javascript/godot_audio.h +++ b/platform/javascript/godot_audio.h @@ -63,4 +63,4 @@ extern void godot_audio_script_start(float *p_in_buf, int p_in_size, float *p_ou } #endif -#endif /* GODOT_AUDIO_H */ +#endif // GODOT_AUDIO_H diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h index 1a383c9799..a323f2d157 100644 --- a/platform/javascript/godot_js.h +++ b/platform/javascript/godot_js.h @@ -58,6 +58,7 @@ extern void godot_js_input_mouse_move_cb(void (*p_callback)(double p_x, double p extern void godot_js_input_mouse_wheel_cb(int (*p_callback)(double p_delta_x, double p_delta_y)); extern void godot_js_input_touch_cb(void (*p_callback)(int p_type, int p_count), uint32_t *r_identifiers, double *r_coords); extern void godot_js_input_key_cb(void (*p_callback)(int p_type, int p_repeat, int p_modifiers), char r_code[32], char r_key[32]); +extern void godot_js_input_vibrate_handheld(int p_duration_ms); // Input gamepad extern void godot_js_input_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid)); @@ -120,11 +121,11 @@ extern void godot_js_display_notification_cb(void (*p_callback)(int p_notificati extern int godot_js_display_vk_available(); extern int godot_js_display_tts_available(); extern void godot_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor)); -extern void godot_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end); +extern void godot_js_display_vk_show(const char *p_text, int p_type, int p_start, int p_end); extern void godot_js_display_vk_hide(); #ifdef __cplusplus } #endif -#endif /* GODOT_JS_H */ +#endif // GODOT_JS_H diff --git a/platform/javascript/godot_webgl2.h b/platform/javascript/godot_webgl2.h index 7c357ff66d..968b70f84b 100644 --- a/platform/javascript/godot_webgl2.h +++ b/platform/javascript/godot_webgl2.h @@ -34,4 +34,4 @@ #include "GLES3/gl3.h" #include "webgl/webgl2.h" -#endif +#endif // GODOT_WEBGL2_H diff --git a/platform/javascript/http_client_javascript.h b/platform/javascript/http_client_javascript.h index 096aa6a153..fcd225ffc9 100644 --- a/platform/javascript/http_client_javascript.h +++ b/platform/javascript/http_client_javascript.h @@ -105,4 +105,5 @@ public: HTTPClientJavaScript(); ~HTTPClientJavaScript(); }; + #endif // HTTP_CLIENT_JAVASCRIPT_H diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp index 8dc7aba5f8..204e92b82b 100644 --- a/platform/javascript/javascript_singleton.cpp +++ b/platform/javascript/javascript_singleton.cpp @@ -259,7 +259,7 @@ void JavaScriptObjectImpl::_callback(void *p_ref, int p_args_id, int p_argc) { const Variant *argv[1] = { &arg }; Callable::CallError err; Variant ret; - obj->_callable.call(argv, 1, ret, err); + obj->_callable.callp(argv, 1, ret, err); // Set return value godot_js_wrapper_ex exchange; diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js index 2e5e1ed0d1..9c4b6c2012 100644 --- a/platform/javascript/js/engine/config.js +++ b/platform/javascript/js/engine/config.js @@ -334,6 +334,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- locale = navigator.languages ? navigator.languages[0] : navigator.language; locale = locale.split('.')[0]; } + locale = locale.replace('-', '_'); const onExit = this.onExit; // Godot configuration. diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 5997631bf8..c7729a8c5b 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -73,7 +73,7 @@ const GodotDisplayVK = { GodotDisplayVK.textarea = create('textarea'); GodotDisplayVK.updateSize(); }, - show: function (text, multiline, start, end) { + show: function (text, type, start, end) { if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) { return; } @@ -81,7 +81,46 @@ const GodotDisplayVK = { GodotDisplayVK.hide(); } GodotDisplayVK.updateSize(); - const elem = multiline ? GodotDisplayVK.textarea : GodotDisplayVK.textinput; + + let elem = GodotDisplayVK.textinput; + switch (type) { + case 0: // KEYBOARD_TYPE_DEFAULT + elem.type = 'text'; + elem.inputmode = ''; + break; + case 1: // KEYBOARD_TYPE_MULTILINE + elem = GodotDisplayVK.textarea; + break; + case 2: // KEYBOARD_TYPE_NUMBER + elem.type = 'text'; + elem.inputmode = 'numeric'; + break; + case 3: // KEYBOARD_TYPE_NUMBER_DECIMAL + elem.type = 'text'; + elem.inputmode = 'decimal'; + break; + case 4: // KEYBOARD_TYPE_PHONE + elem.type = 'tel'; + elem.inputmode = ''; + break; + case 5: // KEYBOARD_TYPE_EMAIL_ADDRESS + elem.type = 'email'; + elem.inputmode = ''; + break; + case 6: // KEYBOARD_TYPE_PASSWORD + elem.type = 'password'; + elem.inputmode = ''; + break; + case 7: // KEYBOARD_TYPE_URL + elem.type = 'url'; + elem.inputmode = ''; + break; + default: + elem.type = 'text'; + elem.inputmode = ''; + break; + } + elem.readonly = false; elem.disabled = false; elem.value = text; @@ -694,11 +733,11 @@ const GodotDisplay = { * Virtual Keyboard */ godot_js_display_vk_show__sig: 'viiii', - godot_js_display_vk_show: function (p_text, p_multiline, p_start, p_end) { + godot_js_display_vk_show: function (p_text, p_type, p_start, p_end) { const text = GodotRuntime.parseString(p_text); const start = p_start > 0 ? p_start : 0; const end = p_end > 0 ? p_end : start; - GodotDisplayVK.show(text, p_multiline, start, end); + GodotDisplayVK.show(text, p_type, start, end); }, godot_js_display_vk_hide__sig: 'v', diff --git a/platform/javascript/js/libs/library_godot_input.js b/platform/javascript/js/libs/library_godot_input.js index 1e64c260f8..51571d64a2 100644 --- a/platform/javascript/js/libs/library_godot_input.js +++ b/platform/javascript/js/libs/library_godot_input.js @@ -534,6 +534,15 @@ const GodotInput = { GodotRuntime.free(ptr); }, false); }, + + godot_js_input_vibrate_handheld__sig: 'vi', + godot_js_input_vibrate_handheld: function (p_duration_ms) { + if (typeof navigator.vibrate !== 'function') { + GodotRuntime.print('This browser does not support vibration.'); + } else { + navigator.vibrate(p_duration_ms); + } + }, }; autoAddDeps(GodotInput, '$GodotInput'); diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 1686353229..dc81b8b4b6 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -177,6 +177,10 @@ String OS_JavaScript::get_name() const { return "HTML5"; } +void OS_JavaScript::vibrate_handheld(int p_duration_ms) { + godot_js_input_vibrate_handheld(p_duration_ms); +} + String OS_JavaScript::get_user_data_dir() const { return "/userfs"; } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 0c672111cc..35e13c94fc 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -90,6 +90,8 @@ public: // Implemented in javascript_main.cpp loop callback instead. void add_frame_delay(bool p_can_draw) override {} + void vibrate_handheld(int p_duration_ms) override; + String get_cache_path() const override; String get_config_path() const override; String get_data_path() const override; @@ -107,4 +109,4 @@ public: OS_JavaScript(); }; -#endif +#endif // OS_JAVASCRIPT_H diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 09a432eae2..35c41556ee 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -12,7 +12,7 @@ common_linuxbsd = [ "freedesktop_screensaver.cpp", ] -if "x11" in env and env["x11"]: +if env["x11"]: common_linuxbsd += [ "gl_manager_x11.cpp", "detect_prime_x11.cpp", @@ -20,15 +20,21 @@ if "x11" in env and env["x11"]: "key_mapping_x11.cpp", ] -if "speechd" in env and env["speechd"]: + if env["vulkan"]: + common_linuxbsd.append("vulkan_context_x11.cpp") + +if env["speechd"]: common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"]) -if "vulkan" in env and env["vulkan"]: - common_linuxbsd.append("vulkan_context_x11.cpp") +if env["fontconfig"]: + common_linuxbsd.append("fontconfig-so_wrap.c") -if "udev" in env and env["udev"]: +if env["udev"]: common_linuxbsd.append("libudev-so_wrap.c") +if env["dbus"]: + common_linuxbsd.append("dbus-so_wrap.c") + prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd) if env["debug_symbols"] and env["separate_debug_symbols"]: diff --git a/platform/linuxbsd/crash_handler_linuxbsd.h b/platform/linuxbsd/crash_handler_linuxbsd.h index 2e44476c3f..1b77352cca 100644 --- a/platform/linuxbsd/crash_handler_linuxbsd.h +++ b/platform/linuxbsd/crash_handler_linuxbsd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CRASH_HANDLER_X11_H -#define CRASH_HANDLER_X11_H +#ifndef CRASH_HANDLER_LINUXBSD_H +#define CRASH_HANDLER_LINUXBSD_H class CrashHandler { bool disabled; @@ -44,4 +44,4 @@ public: ~CrashHandler(); }; -#endif // CRASH_HANDLER_X11_H +#endif // CRASH_HANDLER_LINUXBSD_H diff --git a/platform/linuxbsd/dbus-so_wrap.c b/platform/linuxbsd/dbus-so_wrap.c new file mode 100644 index 0000000000..0876bc88b0 --- /dev/null +++ b/platform/linuxbsd/dbus-so_wrap.c @@ -0,0 +1,2641 @@ +// This file is generated. Do not edit! +// see https://github.com/hpvb/dynload-wrapper for details +// generated by ./generate-wrapper.py 0.3 on 2022-07-29 07:23:21 +// flags: ./generate-wrapper.py --include /usr/include/dbus-1.0/dbus/dbus.h --sys-include <dbus/dbus.h> --soname libdbus-1.so --init-name dbus --output-header dbus-so_wrap.h --output-implementation dbus-so_wrap.c +// +#include <stdint.h> + +#define dbus_error_init dbus_error_init_dylibloader_orig_dbus +#define dbus_error_free dbus_error_free_dylibloader_orig_dbus +#define dbus_set_error dbus_set_error_dylibloader_orig_dbus +#define dbus_set_error_const dbus_set_error_const_dylibloader_orig_dbus +#define dbus_move_error dbus_move_error_dylibloader_orig_dbus +#define dbus_error_has_name dbus_error_has_name_dylibloader_orig_dbus +#define dbus_error_is_set dbus_error_is_set_dylibloader_orig_dbus +#define dbus_parse_address dbus_parse_address_dylibloader_orig_dbus +#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_orig_dbus +#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_orig_dbus +#define dbus_address_entries_free dbus_address_entries_free_dylibloader_orig_dbus +#define dbus_address_escape_value dbus_address_escape_value_dylibloader_orig_dbus +#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_orig_dbus +#define dbus_malloc dbus_malloc_dylibloader_orig_dbus +#define dbus_malloc0 dbus_malloc0_dylibloader_orig_dbus +#define dbus_realloc dbus_realloc_dylibloader_orig_dbus +#define dbus_free dbus_free_dylibloader_orig_dbus +#define dbus_free_string_array dbus_free_string_array_dylibloader_orig_dbus +#define dbus_shutdown dbus_shutdown_dylibloader_orig_dbus +#define dbus_message_new dbus_message_new_dylibloader_orig_dbus +#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_orig_dbus +#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_orig_dbus +#define dbus_message_new_signal dbus_message_new_signal_dylibloader_orig_dbus +#define dbus_message_new_error dbus_message_new_error_dylibloader_orig_dbus +#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_orig_dbus +#define dbus_message_copy dbus_message_copy_dylibloader_orig_dbus +#define dbus_message_ref dbus_message_ref_dylibloader_orig_dbus +#define dbus_message_unref dbus_message_unref_dylibloader_orig_dbus +#define dbus_message_get_type dbus_message_get_type_dylibloader_orig_dbus +#define dbus_message_set_path dbus_message_set_path_dylibloader_orig_dbus +#define dbus_message_get_path dbus_message_get_path_dylibloader_orig_dbus +#define dbus_message_has_path dbus_message_has_path_dylibloader_orig_dbus +#define dbus_message_set_interface dbus_message_set_interface_dylibloader_orig_dbus +#define dbus_message_get_interface dbus_message_get_interface_dylibloader_orig_dbus +#define dbus_message_has_interface dbus_message_has_interface_dylibloader_orig_dbus +#define dbus_message_set_member dbus_message_set_member_dylibloader_orig_dbus +#define dbus_message_get_member dbus_message_get_member_dylibloader_orig_dbus +#define dbus_message_has_member dbus_message_has_member_dylibloader_orig_dbus +#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_orig_dbus +#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_orig_dbus +#define dbus_message_set_destination dbus_message_set_destination_dylibloader_orig_dbus +#define dbus_message_get_destination dbus_message_get_destination_dylibloader_orig_dbus +#define dbus_message_set_sender dbus_message_set_sender_dylibloader_orig_dbus +#define dbus_message_get_sender dbus_message_get_sender_dylibloader_orig_dbus +#define dbus_message_get_signature dbus_message_get_signature_dylibloader_orig_dbus +#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_orig_dbus +#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_orig_dbus +#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_orig_dbus +#define dbus_message_is_signal dbus_message_is_signal_dylibloader_orig_dbus +#define dbus_message_is_error dbus_message_is_error_dylibloader_orig_dbus +#define dbus_message_has_destination dbus_message_has_destination_dylibloader_orig_dbus +#define dbus_message_has_sender dbus_message_has_sender_dylibloader_orig_dbus +#define dbus_message_has_signature dbus_message_has_signature_dylibloader_orig_dbus +#define dbus_message_get_serial dbus_message_get_serial_dylibloader_orig_dbus +#define dbus_message_set_serial dbus_message_set_serial_dylibloader_orig_dbus +#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_orig_dbus +#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_orig_dbus +#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_orig_dbus +#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_orig_dbus +#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_orig_dbus +#define dbus_message_append_args dbus_message_append_args_dylibloader_orig_dbus +#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_orig_dbus +#define dbus_message_get_args dbus_message_get_args_dylibloader_orig_dbus +#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_orig_dbus +#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_orig_dbus +#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_orig_dbus +#define dbus_message_iter_init dbus_message_iter_init_dylibloader_orig_dbus +#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_orig_dbus +#define dbus_message_iter_next dbus_message_iter_next_dylibloader_orig_dbus +#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_orig_dbus +#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_orig_dbus +#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_orig_dbus +#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_orig_dbus +#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_orig_dbus +#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_orig_dbus +#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_orig_dbus +#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_orig_dbus +#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_orig_dbus +#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_orig_dbus +#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_orig_dbus +#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_orig_dbus +#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_orig_dbus +#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_orig_dbus +#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_orig_dbus +#define dbus_message_lock dbus_message_lock_dylibloader_orig_dbus +#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_orig_dbus +#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_orig_dbus +#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_orig_dbus +#define dbus_message_set_data dbus_message_set_data_dylibloader_orig_dbus +#define dbus_message_get_data dbus_message_get_data_dylibloader_orig_dbus +#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_orig_dbus +#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_orig_dbus +#define dbus_message_marshal dbus_message_marshal_dylibloader_orig_dbus +#define dbus_message_demarshal dbus_message_demarshal_dylibloader_orig_dbus +#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_orig_dbus +#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_orig_dbus +#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_orig_dbus +#define dbus_connection_open dbus_connection_open_dylibloader_orig_dbus +#define dbus_connection_open_private dbus_connection_open_private_dylibloader_orig_dbus +#define dbus_connection_ref dbus_connection_ref_dylibloader_orig_dbus +#define dbus_connection_unref dbus_connection_unref_dylibloader_orig_dbus +#define dbus_connection_close dbus_connection_close_dylibloader_orig_dbus +#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_orig_dbus +#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_orig_dbus +#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_orig_dbus +#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_orig_dbus +#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_orig_dbus +#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_orig_dbus +#define dbus_connection_flush dbus_connection_flush_dylibloader_orig_dbus +#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_orig_dbus +#define dbus_connection_read_write dbus_connection_read_write_dylibloader_orig_dbus +#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_orig_dbus +#define dbus_connection_return_message dbus_connection_return_message_dylibloader_orig_dbus +#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_orig_dbus +#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_orig_dbus +#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_orig_dbus +#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_orig_dbus +#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_orig_dbus +#define dbus_connection_send dbus_connection_send_dylibloader_orig_dbus +#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_orig_dbus +#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_orig_dbus +#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_orig_dbus +#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_orig_dbus +#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_orig_dbus +#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_orig_dbus +#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_orig_dbus +#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_orig_dbus +#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_orig_dbus +#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_orig_dbus +#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_orig_dbus +#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_orig_dbus +#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_orig_dbus +#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_orig_dbus +#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_orig_dbus +#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_orig_dbus +#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_orig_dbus +#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_orig_dbus +#define dbus_connection_set_data dbus_connection_set_data_dylibloader_orig_dbus +#define dbus_connection_get_data dbus_connection_get_data_dylibloader_orig_dbus +#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_orig_dbus +#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_orig_dbus +#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_orig_dbus +#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_orig_dbus +#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_orig_dbus +#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_orig_dbus +#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_orig_dbus +#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_orig_dbus +#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_orig_dbus +#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_orig_dbus +#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_orig_dbus +#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_orig_dbus +#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_orig_dbus +#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_orig_dbus +#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_orig_dbus +#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_orig_dbus +#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_orig_dbus +#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_orig_dbus +#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_orig_dbus +#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_orig_dbus +#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_orig_dbus +#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_orig_dbus +#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_orig_dbus +#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_orig_dbus +#define dbus_watch_get_data dbus_watch_get_data_dylibloader_orig_dbus +#define dbus_watch_set_data dbus_watch_set_data_dylibloader_orig_dbus +#define dbus_watch_handle dbus_watch_handle_dylibloader_orig_dbus +#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_orig_dbus +#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_orig_dbus +#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_orig_dbus +#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_orig_dbus +#define dbus_timeout_handle dbus_timeout_handle_dylibloader_orig_dbus +#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_orig_dbus +#define dbus_bus_get dbus_bus_get_dylibloader_orig_dbus +#define dbus_bus_get_private dbus_bus_get_private_dylibloader_orig_dbus +#define dbus_bus_register dbus_bus_register_dylibloader_orig_dbus +#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_orig_dbus +#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_orig_dbus +#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_orig_dbus +#define dbus_bus_get_id dbus_bus_get_id_dylibloader_orig_dbus +#define dbus_bus_request_name dbus_bus_request_name_dylibloader_orig_dbus +#define dbus_bus_release_name dbus_bus_release_name_dylibloader_orig_dbus +#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_orig_dbus +#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_orig_dbus +#define dbus_bus_add_match dbus_bus_add_match_dylibloader_orig_dbus +#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_orig_dbus +#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_orig_dbus +#define dbus_get_version dbus_get_version_dylibloader_orig_dbus +#define dbus_setenv dbus_setenv_dylibloader_orig_dbus +#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_orig_dbus +#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_orig_dbus +#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_orig_dbus +#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_orig_dbus +#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_orig_dbus +#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_orig_dbus +#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_orig_dbus +#define dbus_pending_call_block dbus_pending_call_block_dylibloader_orig_dbus +#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_orig_dbus +#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_orig_dbus +#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_orig_dbus +#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_orig_dbus +#define dbus_server_listen dbus_server_listen_dylibloader_orig_dbus +#define dbus_server_ref dbus_server_ref_dylibloader_orig_dbus +#define dbus_server_unref dbus_server_unref_dylibloader_orig_dbus +#define dbus_server_disconnect dbus_server_disconnect_dylibloader_orig_dbus +#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_orig_dbus +#define dbus_server_get_address dbus_server_get_address_dylibloader_orig_dbus +#define dbus_server_get_id dbus_server_get_id_dylibloader_orig_dbus +#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_orig_dbus +#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_orig_dbus +#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_orig_dbus +#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_orig_dbus +#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_orig_dbus +#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_orig_dbus +#define dbus_server_set_data dbus_server_set_data_dylibloader_orig_dbus +#define dbus_server_get_data dbus_server_get_data_dylibloader_orig_dbus +#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_orig_dbus +#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_orig_dbus +#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_orig_dbus +#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_orig_dbus +#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_orig_dbus +#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_orig_dbus +#define dbus_signature_validate dbus_signature_validate_dylibloader_orig_dbus +#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_orig_dbus +#define dbus_type_is_valid dbus_type_is_valid_dylibloader_orig_dbus +#define dbus_type_is_basic dbus_type_is_basic_dylibloader_orig_dbus +#define dbus_type_is_container dbus_type_is_container_dylibloader_orig_dbus +#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_orig_dbus +#define dbus_validate_path dbus_validate_path_dylibloader_orig_dbus +#define dbus_validate_interface dbus_validate_interface_dylibloader_orig_dbus +#define dbus_validate_member dbus_validate_member_dylibloader_orig_dbus +#define dbus_validate_error_name dbus_validate_error_name_dylibloader_orig_dbus +#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_orig_dbus +#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_orig_dbus +#define dbus_threads_init dbus_threads_init_dylibloader_orig_dbus +#define dbus_threads_init_default dbus_threads_init_default_dylibloader_orig_dbus +#include <dbus/dbus.h> +#undef dbus_error_init +#undef dbus_error_free +#undef dbus_set_error +#undef dbus_set_error_const +#undef dbus_move_error +#undef dbus_error_has_name +#undef dbus_error_is_set +#undef dbus_parse_address +#undef dbus_address_entry_get_value +#undef dbus_address_entry_get_method +#undef dbus_address_entries_free +#undef dbus_address_escape_value +#undef dbus_address_unescape_value +#undef dbus_malloc +#undef dbus_malloc0 +#undef dbus_realloc +#undef dbus_free +#undef dbus_free_string_array +#undef dbus_shutdown +#undef dbus_message_new +#undef dbus_message_new_method_call +#undef dbus_message_new_method_return +#undef dbus_message_new_signal +#undef dbus_message_new_error +#undef dbus_message_new_error_printf +#undef dbus_message_copy +#undef dbus_message_ref +#undef dbus_message_unref +#undef dbus_message_get_type +#undef dbus_message_set_path +#undef dbus_message_get_path +#undef dbus_message_has_path +#undef dbus_message_set_interface +#undef dbus_message_get_interface +#undef dbus_message_has_interface +#undef dbus_message_set_member +#undef dbus_message_get_member +#undef dbus_message_has_member +#undef dbus_message_set_error_name +#undef dbus_message_get_error_name +#undef dbus_message_set_destination +#undef dbus_message_get_destination +#undef dbus_message_set_sender +#undef dbus_message_get_sender +#undef dbus_message_get_signature +#undef dbus_message_set_no_reply +#undef dbus_message_get_no_reply +#undef dbus_message_is_method_call +#undef dbus_message_is_signal +#undef dbus_message_is_error +#undef dbus_message_has_destination +#undef dbus_message_has_sender +#undef dbus_message_has_signature +#undef dbus_message_get_serial +#undef dbus_message_set_serial +#undef dbus_message_set_reply_serial +#undef dbus_message_get_reply_serial +#undef dbus_message_set_auto_start +#undef dbus_message_get_auto_start +#undef dbus_message_get_path_decomposed +#undef dbus_message_append_args +#undef dbus_message_append_args_valist +#undef dbus_message_get_args +#undef dbus_message_get_args_valist +#undef dbus_message_contains_unix_fds +#undef dbus_message_iter_init_closed +#undef dbus_message_iter_init +#undef dbus_message_iter_has_next +#undef dbus_message_iter_next +#undef dbus_message_iter_get_signature +#undef dbus_message_iter_get_arg_type +#undef dbus_message_iter_get_element_type +#undef dbus_message_iter_recurse +#undef dbus_message_iter_get_basic +#undef dbus_message_iter_get_element_count +#undef dbus_message_iter_get_array_len +#undef dbus_message_iter_get_fixed_array +#undef dbus_message_iter_init_append +#undef dbus_message_iter_append_basic +#undef dbus_message_iter_append_fixed_array +#undef dbus_message_iter_open_container +#undef dbus_message_iter_close_container +#undef dbus_message_iter_abandon_container +#undef dbus_message_iter_abandon_container_if_open +#undef dbus_message_lock +#undef dbus_set_error_from_message +#undef dbus_message_allocate_data_slot +#undef dbus_message_free_data_slot +#undef dbus_message_set_data +#undef dbus_message_get_data +#undef dbus_message_type_from_string +#undef dbus_message_type_to_string +#undef dbus_message_marshal +#undef dbus_message_demarshal +#undef dbus_message_demarshal_bytes_needed +#undef dbus_message_set_allow_interactive_authorization +#undef dbus_message_get_allow_interactive_authorization +#undef dbus_connection_open +#undef dbus_connection_open_private +#undef dbus_connection_ref +#undef dbus_connection_unref +#undef dbus_connection_close +#undef dbus_connection_get_is_connected +#undef dbus_connection_get_is_authenticated +#undef dbus_connection_get_is_anonymous +#undef dbus_connection_get_server_id +#undef dbus_connection_can_send_type +#undef dbus_connection_set_exit_on_disconnect +#undef dbus_connection_flush +#undef dbus_connection_read_write_dispatch +#undef dbus_connection_read_write +#undef dbus_connection_borrow_message +#undef dbus_connection_return_message +#undef dbus_connection_steal_borrowed_message +#undef dbus_connection_pop_message +#undef dbus_connection_get_dispatch_status +#undef dbus_connection_dispatch +#undef dbus_connection_has_messages_to_send +#undef dbus_connection_send +#undef dbus_connection_send_with_reply +#undef dbus_connection_send_with_reply_and_block +#undef dbus_connection_set_watch_functions +#undef dbus_connection_set_timeout_functions +#undef dbus_connection_set_wakeup_main_function +#undef dbus_connection_set_dispatch_status_function +#undef dbus_connection_get_unix_user +#undef dbus_connection_get_unix_process_id +#undef dbus_connection_get_adt_audit_session_data +#undef dbus_connection_set_unix_user_function +#undef dbus_connection_get_windows_user +#undef dbus_connection_set_windows_user_function +#undef dbus_connection_set_allow_anonymous +#undef dbus_connection_set_route_peer_messages +#undef dbus_connection_add_filter +#undef dbus_connection_remove_filter +#undef dbus_connection_allocate_data_slot +#undef dbus_connection_free_data_slot +#undef dbus_connection_set_data +#undef dbus_connection_get_data +#undef dbus_connection_set_change_sigpipe +#undef dbus_connection_set_max_message_size +#undef dbus_connection_get_max_message_size +#undef dbus_connection_set_max_received_size +#undef dbus_connection_get_max_received_size +#undef dbus_connection_set_max_message_unix_fds +#undef dbus_connection_get_max_message_unix_fds +#undef dbus_connection_set_max_received_unix_fds +#undef dbus_connection_get_max_received_unix_fds +#undef dbus_connection_get_outgoing_size +#undef dbus_connection_get_outgoing_unix_fds +#undef dbus_connection_preallocate_send +#undef dbus_connection_free_preallocated_send +#undef dbus_connection_send_preallocated +#undef dbus_connection_try_register_object_path +#undef dbus_connection_register_object_path +#undef dbus_connection_try_register_fallback +#undef dbus_connection_register_fallback +#undef dbus_connection_unregister_object_path +#undef dbus_connection_get_object_path_data +#undef dbus_connection_list_registered +#undef dbus_connection_get_unix_fd +#undef dbus_connection_get_socket +#undef dbus_watch_get_fd +#undef dbus_watch_get_unix_fd +#undef dbus_watch_get_socket +#undef dbus_watch_get_flags +#undef dbus_watch_get_data +#undef dbus_watch_set_data +#undef dbus_watch_handle +#undef dbus_watch_get_enabled +#undef dbus_timeout_get_interval +#undef dbus_timeout_get_data +#undef dbus_timeout_set_data +#undef dbus_timeout_handle +#undef dbus_timeout_get_enabled +#undef dbus_bus_get +#undef dbus_bus_get_private +#undef dbus_bus_register +#undef dbus_bus_set_unique_name +#undef dbus_bus_get_unique_name +#undef dbus_bus_get_unix_user +#undef dbus_bus_get_id +#undef dbus_bus_request_name +#undef dbus_bus_release_name +#undef dbus_bus_name_has_owner +#undef dbus_bus_start_service_by_name +#undef dbus_bus_add_match +#undef dbus_bus_remove_match +#undef dbus_get_local_machine_id +#undef dbus_get_version +#undef dbus_setenv +#undef dbus_try_get_local_machine_id +#undef dbus_pending_call_ref +#undef dbus_pending_call_unref +#undef dbus_pending_call_set_notify +#undef dbus_pending_call_cancel +#undef dbus_pending_call_get_completed +#undef dbus_pending_call_steal_reply +#undef dbus_pending_call_block +#undef dbus_pending_call_allocate_data_slot +#undef dbus_pending_call_free_data_slot +#undef dbus_pending_call_set_data +#undef dbus_pending_call_get_data +#undef dbus_server_listen +#undef dbus_server_ref +#undef dbus_server_unref +#undef dbus_server_disconnect +#undef dbus_server_get_is_connected +#undef dbus_server_get_address +#undef dbus_server_get_id +#undef dbus_server_set_new_connection_function +#undef dbus_server_set_watch_functions +#undef dbus_server_set_timeout_functions +#undef dbus_server_set_auth_mechanisms +#undef dbus_server_allocate_data_slot +#undef dbus_server_free_data_slot +#undef dbus_server_set_data +#undef dbus_server_get_data +#undef dbus_signature_iter_init +#undef dbus_signature_iter_get_current_type +#undef dbus_signature_iter_get_signature +#undef dbus_signature_iter_get_element_type +#undef dbus_signature_iter_next +#undef dbus_signature_iter_recurse +#undef dbus_signature_validate +#undef dbus_signature_validate_single +#undef dbus_type_is_valid +#undef dbus_type_is_basic +#undef dbus_type_is_container +#undef dbus_type_is_fixed +#undef dbus_validate_path +#undef dbus_validate_interface +#undef dbus_validate_member +#undef dbus_validate_error_name +#undef dbus_validate_bus_name +#undef dbus_validate_utf8 +#undef dbus_threads_init +#undef dbus_threads_init_default +#include <dlfcn.h> +#include <stdio.h> +void (*dbus_error_init_dylibloader_wrapper_dbus)( DBusError*); +void (*dbus_error_free_dylibloader_wrapper_dbus)( DBusError*); +void (*dbus_set_error_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*,...); +void (*dbus_set_error_const_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*); +void (*dbus_move_error_dylibloader_wrapper_dbus)( DBusError*, DBusError*); +dbus_bool_t (*dbus_error_has_name_dylibloader_wrapper_dbus)(const DBusError*,const char*); +dbus_bool_t (*dbus_error_is_set_dylibloader_wrapper_dbus)(const DBusError*); +dbus_bool_t (*dbus_parse_address_dylibloader_wrapper_dbus)(const char*, DBusAddressEntry***, int*, DBusError*); +const char* (*dbus_address_entry_get_value_dylibloader_wrapper_dbus)( DBusAddressEntry*,const char*); +const char* (*dbus_address_entry_get_method_dylibloader_wrapper_dbus)( DBusAddressEntry*); +void (*dbus_address_entries_free_dylibloader_wrapper_dbus)( DBusAddressEntry**); +char* (*dbus_address_escape_value_dylibloader_wrapper_dbus)(const char*); +char* (*dbus_address_unescape_value_dylibloader_wrapper_dbus)(const char*, DBusError*); +void* (*dbus_malloc_dylibloader_wrapper_dbus)( size_t); +void* (*dbus_malloc0_dylibloader_wrapper_dbus)( size_t); +void* (*dbus_realloc_dylibloader_wrapper_dbus)( void*, size_t); +void (*dbus_free_dylibloader_wrapper_dbus)( void*); +void (*dbus_free_string_array_dylibloader_wrapper_dbus)( char**); +void (*dbus_shutdown_dylibloader_wrapper_dbus)( void); +DBusMessage* (*dbus_message_new_dylibloader_wrapper_dbus)( int); +DBusMessage* (*dbus_message_new_method_call_dylibloader_wrapper_dbus)(const char*,const char*,const char*,const char*); +DBusMessage* (*dbus_message_new_method_return_dylibloader_wrapper_dbus)( DBusMessage*); +DBusMessage* (*dbus_message_new_signal_dylibloader_wrapper_dbus)(const char*,const char*,const char*); +DBusMessage* (*dbus_message_new_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +DBusMessage* (*dbus_message_new_error_printf_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*,...); +DBusMessage* (*dbus_message_copy_dylibloader_wrapper_dbus)(const DBusMessage*); +DBusMessage* (*dbus_message_ref_dylibloader_wrapper_dbus)( DBusMessage*); +void (*dbus_message_unref_dylibloader_wrapper_dbus)( DBusMessage*); +int (*dbus_message_get_type_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_set_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_path_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_has_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_set_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_interface_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_has_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_set_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_member_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_has_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_set_error_name_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_error_name_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_set_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_destination_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_set_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +const char* (*dbus_message_get_sender_dylibloader_wrapper_dbus)( DBusMessage*); +const char* (*dbus_message_get_signature_dylibloader_wrapper_dbus)( DBusMessage*); +void (*dbus_message_set_no_reply_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +dbus_bool_t (*dbus_message_get_no_reply_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_is_method_call_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +dbus_bool_t (*dbus_message_is_signal_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +dbus_bool_t (*dbus_message_is_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_has_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_has_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_bool_t (*dbus_message_has_signature_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +dbus_uint32_t (*dbus_message_get_serial_dylibloader_wrapper_dbus)( DBusMessage*); +void (*dbus_message_set_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t); +dbus_bool_t (*dbus_message_set_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t); +dbus_uint32_t (*dbus_message_get_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*); +void (*dbus_message_set_auto_start_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +dbus_bool_t (*dbus_message_get_auto_start_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_message_get_path_decomposed_dylibloader_wrapper_dbus)( DBusMessage*, char***); +dbus_bool_t (*dbus_message_append_args_dylibloader_wrapper_dbus)( DBusMessage*, int,...); +dbus_bool_t (*dbus_message_append_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, int, va_list); +dbus_bool_t (*dbus_message_get_args_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int,...); +dbus_bool_t (*dbus_message_get_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int, va_list); +dbus_bool_t (*dbus_message_contains_unix_fds_dylibloader_wrapper_dbus)( DBusMessage*); +void (*dbus_message_iter_init_closed_dylibloader_wrapper_dbus)( DBusMessageIter*); +dbus_bool_t (*dbus_message_iter_init_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*); +dbus_bool_t (*dbus_message_iter_has_next_dylibloader_wrapper_dbus)( DBusMessageIter*); +dbus_bool_t (*dbus_message_iter_next_dylibloader_wrapper_dbus)( DBusMessageIter*); +char* (*dbus_message_iter_get_signature_dylibloader_wrapper_dbus)( DBusMessageIter*); +int (*dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus)( DBusMessageIter*); +int (*dbus_message_iter_get_element_type_dylibloader_wrapper_dbus)( DBusMessageIter*); +void (*dbus_message_iter_recurse_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +void (*dbus_message_iter_get_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, void*); +int (*dbus_message_iter_get_element_count_dylibloader_wrapper_dbus)( DBusMessageIter*); +int (*dbus_message_iter_get_array_len_dylibloader_wrapper_dbus)( DBusMessageIter*); +void (*dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, void*, int*); +void (*dbus_message_iter_init_append_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*); +dbus_bool_t (*dbus_message_iter_append_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*); +dbus_bool_t (*dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*, int); +dbus_bool_t (*dbus_message_iter_open_container_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const char*, DBusMessageIter*); +dbus_bool_t (*dbus_message_iter_close_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +void (*dbus_message_iter_abandon_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +void (*dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +void (*dbus_message_lock_dylibloader_wrapper_dbus)( DBusMessage*); +dbus_bool_t (*dbus_set_error_from_message_dylibloader_wrapper_dbus)( DBusError*, DBusMessage*); +dbus_bool_t (*dbus_message_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +void (*dbus_message_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +dbus_bool_t (*dbus_message_set_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t, void*, DBusFreeFunction); +void* (*dbus_message_get_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t); +int (*dbus_message_type_from_string_dylibloader_wrapper_dbus)(const char*); +const char* (*dbus_message_type_to_string_dylibloader_wrapper_dbus)( int); +dbus_bool_t (*dbus_message_marshal_dylibloader_wrapper_dbus)( DBusMessage*, char**, int*); +DBusMessage* (*dbus_message_demarshal_dylibloader_wrapper_dbus)(const char*, int, DBusError*); +int (*dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus)(const char*, int); +void (*dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +dbus_bool_t (*dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*); +DBusConnection* (*dbus_connection_open_dylibloader_wrapper_dbus)(const char*, DBusError*); +DBusConnection* (*dbus_connection_open_private_dylibloader_wrapper_dbus)(const char*, DBusError*); +DBusConnection* (*dbus_connection_ref_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_unref_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_close_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_get_is_connected_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus)( DBusConnection*); +char* (*dbus_connection_get_server_id_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_can_send_type_dylibloader_wrapper_dbus)( DBusConnection*, int); +void (*dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +void (*dbus_connection_flush_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus)( DBusConnection*, int); +dbus_bool_t (*dbus_connection_read_write_dylibloader_wrapper_dbus)( DBusConnection*, int); +DBusMessage* (*dbus_connection_borrow_message_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_return_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*); +void (*dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*); +DBusMessage* (*dbus_connection_pop_message_dylibloader_wrapper_dbus)( DBusConnection*); +DBusDispatchStatus (*dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus)( DBusConnection*); +DBusDispatchStatus (*dbus_connection_dispatch_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus)( DBusConnection*); +dbus_bool_t (*dbus_connection_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, dbus_uint32_t*); +dbus_bool_t (*dbus_connection_send_with_reply_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, DBusPendingCall**, int); +DBusMessage* (*dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, int, DBusError*); +dbus_bool_t (*dbus_connection_set_watch_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction); +void (*dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusWakeupMainFunction, void*, DBusFreeFunction); +void (*dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusDispatchStatusFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_connection_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*); +dbus_bool_t (*dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*); +dbus_bool_t (*dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus)( DBusConnection*, void**, dbus_int32_t*); +void (*dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowUnixUserFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_connection_get_windows_user_dylibloader_wrapper_dbus)( DBusConnection*, char**); +void (*dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowWindowsUserFunction, void*, DBusFreeFunction); +void (*dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +void (*dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +dbus_bool_t (*dbus_connection_add_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*, DBusFreeFunction); +void (*dbus_connection_remove_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*); +dbus_bool_t (*dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +void (*dbus_connection_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +dbus_bool_t (*dbus_connection_set_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t, void*, DBusFreeFunction); +void* (*dbus_connection_get_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t); +void (*dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus)( dbus_bool_t); +void (*dbus_connection_set_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*, long); +long (*dbus_connection_get_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_set_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*, long); +long (*dbus_connection_get_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long); +long (*dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long); +long (*dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +long (*dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus)( DBusConnection*); +long (*dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +DBusPreallocatedSend* (*dbus_connection_preallocate_send_dylibloader_wrapper_dbus)( DBusConnection*); +void (*dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*); +void (*dbus_connection_send_preallocated_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*, DBusMessage*, dbus_uint32_t*); +dbus_bool_t (*dbus_connection_try_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*); +dbus_bool_t (*dbus_connection_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*); +dbus_bool_t (*dbus_connection_try_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*); +dbus_bool_t (*dbus_connection_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*); +dbus_bool_t (*dbus_connection_unregister_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*); +dbus_bool_t (*dbus_connection_get_object_path_data_dylibloader_wrapper_dbus)( DBusConnection*,const char*, void**); +dbus_bool_t (*dbus_connection_list_registered_dylibloader_wrapper_dbus)( DBusConnection*,const char*, char***); +dbus_bool_t (*dbus_connection_get_unix_fd_dylibloader_wrapper_dbus)( DBusConnection*, int*); +dbus_bool_t (*dbus_connection_get_socket_dylibloader_wrapper_dbus)( DBusConnection*, int*); +int (*dbus_watch_get_fd_dylibloader_wrapper_dbus)( DBusWatch*); +int (*dbus_watch_get_unix_fd_dylibloader_wrapper_dbus)( DBusWatch*); +int (*dbus_watch_get_socket_dylibloader_wrapper_dbus)( DBusWatch*); +unsigned int (*dbus_watch_get_flags_dylibloader_wrapper_dbus)( DBusWatch*); +void* (*dbus_watch_get_data_dylibloader_wrapper_dbus)( DBusWatch*); +void (*dbus_watch_set_data_dylibloader_wrapper_dbus)( DBusWatch*, void*, DBusFreeFunction); +dbus_bool_t (*dbus_watch_handle_dylibloader_wrapper_dbus)( DBusWatch*, unsigned int); +dbus_bool_t (*dbus_watch_get_enabled_dylibloader_wrapper_dbus)( DBusWatch*); +int (*dbus_timeout_get_interval_dylibloader_wrapper_dbus)( DBusTimeout*); +void* (*dbus_timeout_get_data_dylibloader_wrapper_dbus)( DBusTimeout*); +void (*dbus_timeout_set_data_dylibloader_wrapper_dbus)( DBusTimeout*, void*, DBusFreeFunction); +dbus_bool_t (*dbus_timeout_handle_dylibloader_wrapper_dbus)( DBusTimeout*); +dbus_bool_t (*dbus_timeout_get_enabled_dylibloader_wrapper_dbus)( DBusTimeout*); +DBusConnection* (*dbus_bus_get_dylibloader_wrapper_dbus)( DBusBusType, DBusError*); +DBusConnection* (*dbus_bus_get_private_dylibloader_wrapper_dbus)( DBusBusType, DBusError*); +dbus_bool_t (*dbus_bus_register_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*); +dbus_bool_t (*dbus_bus_set_unique_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*); +const char* (*dbus_bus_get_unique_name_dylibloader_wrapper_dbus)( DBusConnection*); +unsigned long (*dbus_bus_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +char* (*dbus_bus_get_id_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*); +int (*dbus_bus_request_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, unsigned int, DBusError*); +int (*dbus_bus_release_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +dbus_bool_t (*dbus_bus_name_has_owner_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +dbus_bool_t (*dbus_bus_start_service_by_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, dbus_uint32_t, dbus_uint32_t*, DBusError*); +void (*dbus_bus_add_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +void (*dbus_bus_remove_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +char* (*dbus_get_local_machine_id_dylibloader_wrapper_dbus)( void); +void (*dbus_get_version_dylibloader_wrapper_dbus)( int*, int*, int*); +dbus_bool_t (*dbus_setenv_dylibloader_wrapper_dbus)(const char*,const char*); +char* (*dbus_try_get_local_machine_id_dylibloader_wrapper_dbus)( DBusError*); +DBusPendingCall* (*dbus_pending_call_ref_dylibloader_wrapper_dbus)( DBusPendingCall*); +void (*dbus_pending_call_unref_dylibloader_wrapper_dbus)( DBusPendingCall*); +dbus_bool_t (*dbus_pending_call_set_notify_dylibloader_wrapper_dbus)( DBusPendingCall*, DBusPendingCallNotifyFunction, void*, DBusFreeFunction); +void (*dbus_pending_call_cancel_dylibloader_wrapper_dbus)( DBusPendingCall*); +dbus_bool_t (*dbus_pending_call_get_completed_dylibloader_wrapper_dbus)( DBusPendingCall*); +DBusMessage* (*dbus_pending_call_steal_reply_dylibloader_wrapper_dbus)( DBusPendingCall*); +void (*dbus_pending_call_block_dylibloader_wrapper_dbus)( DBusPendingCall*); +dbus_bool_t (*dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +void (*dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +dbus_bool_t (*dbus_pending_call_set_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t, void*, DBusFreeFunction); +void* (*dbus_pending_call_get_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t); +DBusServer* (*dbus_server_listen_dylibloader_wrapper_dbus)(const char*, DBusError*); +DBusServer* (*dbus_server_ref_dylibloader_wrapper_dbus)( DBusServer*); +void (*dbus_server_unref_dylibloader_wrapper_dbus)( DBusServer*); +void (*dbus_server_disconnect_dylibloader_wrapper_dbus)( DBusServer*); +dbus_bool_t (*dbus_server_get_is_connected_dylibloader_wrapper_dbus)( DBusServer*); +char* (*dbus_server_get_address_dylibloader_wrapper_dbus)( DBusServer*); +char* (*dbus_server_get_id_dylibloader_wrapper_dbus)( DBusServer*); +void (*dbus_server_set_new_connection_function_dylibloader_wrapper_dbus)( DBusServer*, DBusNewConnectionFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_server_set_watch_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_server_set_timeout_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction); +dbus_bool_t (*dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus)( DBusServer*,const char**); +dbus_bool_t (*dbus_server_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +void (*dbus_server_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +dbus_bool_t (*dbus_server_set_data_dylibloader_wrapper_dbus)( DBusServer*, int, void*, DBusFreeFunction); +void* (*dbus_server_get_data_dylibloader_wrapper_dbus)( DBusServer*, int); +void (*dbus_signature_iter_init_dylibloader_wrapper_dbus)( DBusSignatureIter*,const char*); +int (*dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +char* (*dbus_signature_iter_get_signature_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +int (*dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +dbus_bool_t (*dbus_signature_iter_next_dylibloader_wrapper_dbus)( DBusSignatureIter*); +void (*dbus_signature_iter_recurse_dylibloader_wrapper_dbus)(const DBusSignatureIter*, DBusSignatureIter*); +dbus_bool_t (*dbus_signature_validate_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_signature_validate_single_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_type_is_valid_dylibloader_wrapper_dbus)( int); +dbus_bool_t (*dbus_type_is_basic_dylibloader_wrapper_dbus)( int); +dbus_bool_t (*dbus_type_is_container_dylibloader_wrapper_dbus)( int); +dbus_bool_t (*dbus_type_is_fixed_dylibloader_wrapper_dbus)( int); +dbus_bool_t (*dbus_validate_path_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_validate_interface_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_validate_member_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_validate_error_name_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_validate_bus_name_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_validate_utf8_dylibloader_wrapper_dbus)(const char*, DBusError*); +dbus_bool_t (*dbus_threads_init_dylibloader_wrapper_dbus)(const DBusThreadFunctions*); +dbus_bool_t (*dbus_threads_init_default_dylibloader_wrapper_dbus)( void); +int initialize_dbus(int verbose) { + void *handle; + char *error; + handle = dlopen("libdbus-1.so", RTLD_LAZY); + if (!handle) { + if (verbose) { + fprintf(stderr, "%s\n", dlerror()); + } + return(1); + } + dlerror(); +// dbus_error_init + *(void **) (&dbus_error_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_init"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_error_free + *(void **) (&dbus_error_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_free"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_set_error + *(void **) (&dbus_set_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_set_error_const + *(void **) (&dbus_set_error_const_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error_const"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_move_error + *(void **) (&dbus_move_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_move_error"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_error_has_name + *(void **) (&dbus_error_has_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_has_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_error_is_set + *(void **) (&dbus_error_is_set_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_is_set"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_parse_address + *(void **) (&dbus_parse_address_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_parse_address"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_address_entry_get_value + *(void **) (&dbus_address_entry_get_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entry_get_value"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_address_entry_get_method + *(void **) (&dbus_address_entry_get_method_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entry_get_method"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_address_entries_free + *(void **) (&dbus_address_entries_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entries_free"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_address_escape_value + *(void **) (&dbus_address_escape_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_escape_value"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_address_unescape_value + *(void **) (&dbus_address_unescape_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_unescape_value"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_malloc + *(void **) (&dbus_malloc_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_malloc"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_malloc0 + *(void **) (&dbus_malloc0_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_malloc0"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_realloc + *(void **) (&dbus_realloc_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_realloc"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_free + *(void **) (&dbus_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_free"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_free_string_array + *(void **) (&dbus_free_string_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_free_string_array"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_shutdown + *(void **) (&dbus_shutdown_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_shutdown"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new + *(void **) (&dbus_message_new_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new_method_call + *(void **) (&dbus_message_new_method_call_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_method_call"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new_method_return + *(void **) (&dbus_message_new_method_return_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_method_return"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new_signal + *(void **) (&dbus_message_new_signal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_signal"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new_error + *(void **) (&dbus_message_new_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_error"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_new_error_printf + *(void **) (&dbus_message_new_error_printf_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_error_printf"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_copy + *(void **) (&dbus_message_copy_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_copy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_ref + *(void **) (&dbus_message_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_ref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_unref + *(void **) (&dbus_message_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_unref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_type + *(void **) (&dbus_message_get_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_path + *(void **) (&dbus_message_set_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_path + *(void **) (&dbus_message_get_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_path + *(void **) (&dbus_message_has_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_interface + *(void **) (&dbus_message_set_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_interface"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_interface + *(void **) (&dbus_message_get_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_interface"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_interface + *(void **) (&dbus_message_has_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_interface"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_member + *(void **) (&dbus_message_set_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_member"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_member + *(void **) (&dbus_message_get_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_member"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_member + *(void **) (&dbus_message_has_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_member"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_error_name + *(void **) (&dbus_message_set_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_error_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_error_name + *(void **) (&dbus_message_get_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_error_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_destination + *(void **) (&dbus_message_set_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_destination"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_destination + *(void **) (&dbus_message_get_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_destination"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_sender + *(void **) (&dbus_message_set_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_sender"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_sender + *(void **) (&dbus_message_get_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_sender"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_signature + *(void **) (&dbus_message_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_signature"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_no_reply + *(void **) (&dbus_message_set_no_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_no_reply"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_no_reply + *(void **) (&dbus_message_get_no_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_no_reply"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_is_method_call + *(void **) (&dbus_message_is_method_call_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_method_call"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_is_signal + *(void **) (&dbus_message_is_signal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_signal"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_is_error + *(void **) (&dbus_message_is_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_error"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_destination + *(void **) (&dbus_message_has_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_destination"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_sender + *(void **) (&dbus_message_has_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_sender"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_has_signature + *(void **) (&dbus_message_has_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_signature"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_serial + *(void **) (&dbus_message_get_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_serial"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_serial + *(void **) (&dbus_message_set_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_serial"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_reply_serial + *(void **) (&dbus_message_set_reply_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_reply_serial"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_reply_serial + *(void **) (&dbus_message_get_reply_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_reply_serial"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_auto_start + *(void **) (&dbus_message_set_auto_start_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_auto_start"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_auto_start + *(void **) (&dbus_message_get_auto_start_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_auto_start"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_path_decomposed + *(void **) (&dbus_message_get_path_decomposed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_path_decomposed"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_append_args + *(void **) (&dbus_message_append_args_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_append_args"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_append_args_valist + *(void **) (&dbus_message_append_args_valist_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_append_args_valist"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_args + *(void **) (&dbus_message_get_args_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_args"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_args_valist + *(void **) (&dbus_message_get_args_valist_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_args_valist"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_contains_unix_fds + *(void **) (&dbus_message_contains_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_contains_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_init_closed + *(void **) (&dbus_message_iter_init_closed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init_closed"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_init + *(void **) (&dbus_message_iter_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_has_next + *(void **) (&dbus_message_iter_has_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_has_next"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_next + *(void **) (&dbus_message_iter_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_next"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_signature + *(void **) (&dbus_message_iter_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_signature"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_arg_type + *(void **) (&dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_arg_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_element_type + *(void **) (&dbus_message_iter_get_element_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_element_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_recurse + *(void **) (&dbus_message_iter_recurse_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_recurse"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_basic + *(void **) (&dbus_message_iter_get_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_basic"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_element_count + *(void **) (&dbus_message_iter_get_element_count_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_element_count"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_array_len + *(void **) (&dbus_message_iter_get_array_len_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_array_len"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_get_fixed_array + *(void **) (&dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_fixed_array"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_init_append + *(void **) (&dbus_message_iter_init_append_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init_append"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_append_basic + *(void **) (&dbus_message_iter_append_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_append_basic"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_append_fixed_array + *(void **) (&dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_append_fixed_array"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_open_container + *(void **) (&dbus_message_iter_open_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_open_container"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_close_container + *(void **) (&dbus_message_iter_close_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_close_container"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_abandon_container + *(void **) (&dbus_message_iter_abandon_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_abandon_container"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_iter_abandon_container_if_open + *(void **) (&dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_abandon_container_if_open"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_lock + *(void **) (&dbus_message_lock_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_lock"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_set_error_from_message + *(void **) (&dbus_set_error_from_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error_from_message"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_allocate_data_slot + *(void **) (&dbus_message_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_allocate_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_free_data_slot + *(void **) (&dbus_message_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_free_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_data + *(void **) (&dbus_message_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_data + *(void **) (&dbus_message_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_type_from_string + *(void **) (&dbus_message_type_from_string_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_type_from_string"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_type_to_string + *(void **) (&dbus_message_type_to_string_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_type_to_string"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_marshal + *(void **) (&dbus_message_marshal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_marshal"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_demarshal + *(void **) (&dbus_message_demarshal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_demarshal"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_demarshal_bytes_needed + *(void **) (&dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_demarshal_bytes_needed"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_set_allow_interactive_authorization + *(void **) (&dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_allow_interactive_authorization"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_message_get_allow_interactive_authorization + *(void **) (&dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_allow_interactive_authorization"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_open + *(void **) (&dbus_connection_open_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_open"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_open_private + *(void **) (&dbus_connection_open_private_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_open_private"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_ref + *(void **) (&dbus_connection_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_ref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_unref + *(void **) (&dbus_connection_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_unref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_close + *(void **) (&dbus_connection_close_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_close"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_is_connected + *(void **) (&dbus_connection_get_is_connected_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_connected"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_is_authenticated + *(void **) (&dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_authenticated"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_is_anonymous + *(void **) (&dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_anonymous"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_server_id + *(void **) (&dbus_connection_get_server_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_server_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_can_send_type + *(void **) (&dbus_connection_can_send_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_can_send_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_exit_on_disconnect + *(void **) (&dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_exit_on_disconnect"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_flush + *(void **) (&dbus_connection_flush_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_flush"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_read_write_dispatch + *(void **) (&dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_read_write_dispatch"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_read_write + *(void **) (&dbus_connection_read_write_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_read_write"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_borrow_message + *(void **) (&dbus_connection_borrow_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_borrow_message"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_return_message + *(void **) (&dbus_connection_return_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_return_message"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_steal_borrowed_message + *(void **) (&dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_steal_borrowed_message"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_pop_message + *(void **) (&dbus_connection_pop_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_pop_message"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_dispatch_status + *(void **) (&dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_dispatch_status"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_dispatch + *(void **) (&dbus_connection_dispatch_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_dispatch"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_has_messages_to_send + *(void **) (&dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_has_messages_to_send"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_send + *(void **) (&dbus_connection_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_send_with_reply + *(void **) (&dbus_connection_send_with_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_with_reply"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_send_with_reply_and_block + *(void **) (&dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_with_reply_and_block"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_watch_functions + *(void **) (&dbus_connection_set_watch_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_watch_functions"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_timeout_functions + *(void **) (&dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_timeout_functions"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_wakeup_main_function + *(void **) (&dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_wakeup_main_function"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_dispatch_status_function + *(void **) (&dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_dispatch_status_function"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_unix_user + *(void **) (&dbus_connection_get_unix_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_user"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_unix_process_id + *(void **) (&dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_process_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_adt_audit_session_data + *(void **) (&dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_adt_audit_session_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_unix_user_function + *(void **) (&dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_unix_user_function"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_windows_user + *(void **) (&dbus_connection_get_windows_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_windows_user"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_windows_user_function + *(void **) (&dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_windows_user_function"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_allow_anonymous + *(void **) (&dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_allow_anonymous"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_route_peer_messages + *(void **) (&dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_route_peer_messages"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_add_filter + *(void **) (&dbus_connection_add_filter_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_add_filter"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_remove_filter + *(void **) (&dbus_connection_remove_filter_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_remove_filter"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_allocate_data_slot + *(void **) (&dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_allocate_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_free_data_slot + *(void **) (&dbus_connection_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_free_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_data + *(void **) (&dbus_connection_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_data + *(void **) (&dbus_connection_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_change_sigpipe + *(void **) (&dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_change_sigpipe"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_max_message_size + *(void **) (&dbus_connection_set_max_message_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_message_size"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_max_message_size + *(void **) (&dbus_connection_get_max_message_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_message_size"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_max_received_size + *(void **) (&dbus_connection_set_max_received_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_received_size"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_max_received_size + *(void **) (&dbus_connection_get_max_received_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_received_size"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_max_message_unix_fds + *(void **) (&dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_message_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_max_message_unix_fds + *(void **) (&dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_message_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_set_max_received_unix_fds + *(void **) (&dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_received_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_max_received_unix_fds + *(void **) (&dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_received_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_outgoing_size + *(void **) (&dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_outgoing_size"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_outgoing_unix_fds + *(void **) (&dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_outgoing_unix_fds"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_preallocate_send + *(void **) (&dbus_connection_preallocate_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_preallocate_send"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_free_preallocated_send + *(void **) (&dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_free_preallocated_send"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_send_preallocated + *(void **) (&dbus_connection_send_preallocated_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_preallocated"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_try_register_object_path + *(void **) (&dbus_connection_try_register_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_try_register_object_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_register_object_path + *(void **) (&dbus_connection_register_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_register_object_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_try_register_fallback + *(void **) (&dbus_connection_try_register_fallback_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_try_register_fallback"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_register_fallback + *(void **) (&dbus_connection_register_fallback_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_register_fallback"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_unregister_object_path + *(void **) (&dbus_connection_unregister_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_unregister_object_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_object_path_data + *(void **) (&dbus_connection_get_object_path_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_object_path_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_list_registered + *(void **) (&dbus_connection_list_registered_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_list_registered"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_unix_fd + *(void **) (&dbus_connection_get_unix_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_fd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_connection_get_socket + *(void **) (&dbus_connection_get_socket_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_socket"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_fd + *(void **) (&dbus_watch_get_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_fd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_unix_fd + *(void **) (&dbus_watch_get_unix_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_unix_fd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_socket + *(void **) (&dbus_watch_get_socket_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_socket"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_flags + *(void **) (&dbus_watch_get_flags_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_flags"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_data + *(void **) (&dbus_watch_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_set_data + *(void **) (&dbus_watch_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_handle + *(void **) (&dbus_watch_handle_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_handle"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_watch_get_enabled + *(void **) (&dbus_watch_get_enabled_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_enabled"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_timeout_get_interval + *(void **) (&dbus_timeout_get_interval_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_interval"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_timeout_get_data + *(void **) (&dbus_timeout_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_timeout_set_data + *(void **) (&dbus_timeout_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_timeout_handle + *(void **) (&dbus_timeout_handle_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_handle"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_timeout_get_enabled + *(void **) (&dbus_timeout_get_enabled_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_enabled"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_get + *(void **) (&dbus_bus_get_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_get_private + *(void **) (&dbus_bus_get_private_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_private"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_register + *(void **) (&dbus_bus_register_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_register"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_set_unique_name + *(void **) (&dbus_bus_set_unique_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_set_unique_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_get_unique_name + *(void **) (&dbus_bus_get_unique_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_unique_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_get_unix_user + *(void **) (&dbus_bus_get_unix_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_unix_user"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_get_id + *(void **) (&dbus_bus_get_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_request_name + *(void **) (&dbus_bus_request_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_request_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_release_name + *(void **) (&dbus_bus_release_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_release_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_name_has_owner + *(void **) (&dbus_bus_name_has_owner_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_name_has_owner"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_start_service_by_name + *(void **) (&dbus_bus_start_service_by_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_start_service_by_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_add_match + *(void **) (&dbus_bus_add_match_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_add_match"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_bus_remove_match + *(void **) (&dbus_bus_remove_match_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_remove_match"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_get_local_machine_id + *(void **) (&dbus_get_local_machine_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_get_local_machine_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_get_version + *(void **) (&dbus_get_version_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_get_version"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_setenv + *(void **) (&dbus_setenv_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_setenv"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_try_get_local_machine_id + *(void **) (&dbus_try_get_local_machine_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_try_get_local_machine_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_ref + *(void **) (&dbus_pending_call_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_ref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_unref + *(void **) (&dbus_pending_call_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_unref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_set_notify + *(void **) (&dbus_pending_call_set_notify_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_set_notify"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_cancel + *(void **) (&dbus_pending_call_cancel_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_cancel"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_get_completed + *(void **) (&dbus_pending_call_get_completed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_get_completed"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_steal_reply + *(void **) (&dbus_pending_call_steal_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_steal_reply"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_block + *(void **) (&dbus_pending_call_block_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_block"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_allocate_data_slot + *(void **) (&dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_allocate_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_free_data_slot + *(void **) (&dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_free_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_set_data + *(void **) (&dbus_pending_call_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_pending_call_get_data + *(void **) (&dbus_pending_call_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_listen + *(void **) (&dbus_server_listen_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_listen"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_ref + *(void **) (&dbus_server_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_ref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_unref + *(void **) (&dbus_server_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_unref"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_disconnect + *(void **) (&dbus_server_disconnect_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_disconnect"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_get_is_connected + *(void **) (&dbus_server_get_is_connected_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_is_connected"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_get_address + *(void **) (&dbus_server_get_address_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_address"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_get_id + *(void **) (&dbus_server_get_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_id"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_set_new_connection_function + *(void **) (&dbus_server_set_new_connection_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_new_connection_function"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_set_watch_functions + *(void **) (&dbus_server_set_watch_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_watch_functions"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_set_timeout_functions + *(void **) (&dbus_server_set_timeout_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_timeout_functions"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_set_auth_mechanisms + *(void **) (&dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_auth_mechanisms"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_allocate_data_slot + *(void **) (&dbus_server_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_allocate_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_free_data_slot + *(void **) (&dbus_server_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_free_data_slot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_set_data + *(void **) (&dbus_server_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_server_get_data + *(void **) (&dbus_server_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_data"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_init + *(void **) (&dbus_signature_iter_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_init"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_get_current_type + *(void **) (&dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_current_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_get_signature + *(void **) (&dbus_signature_iter_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_signature"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_get_element_type + *(void **) (&dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_element_type"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_next + *(void **) (&dbus_signature_iter_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_next"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_iter_recurse + *(void **) (&dbus_signature_iter_recurse_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_recurse"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_validate + *(void **) (&dbus_signature_validate_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_validate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_signature_validate_single + *(void **) (&dbus_signature_validate_single_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_validate_single"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_type_is_valid + *(void **) (&dbus_type_is_valid_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_valid"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_type_is_basic + *(void **) (&dbus_type_is_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_basic"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_type_is_container + *(void **) (&dbus_type_is_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_container"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_type_is_fixed + *(void **) (&dbus_type_is_fixed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_fixed"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_path + *(void **) (&dbus_validate_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_path"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_interface + *(void **) (&dbus_validate_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_interface"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_member + *(void **) (&dbus_validate_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_member"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_error_name + *(void **) (&dbus_validate_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_error_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_bus_name + *(void **) (&dbus_validate_bus_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_bus_name"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_validate_utf8 + *(void **) (&dbus_validate_utf8_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_utf8"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_threads_init + *(void **) (&dbus_threads_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_threads_init"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// dbus_threads_init_default + *(void **) (&dbus_threads_init_default_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_threads_init_default"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +return 0; +} diff --git a/platform/linuxbsd/dbus-so_wrap.h b/platform/linuxbsd/dbus-so_wrap.h new file mode 100644 index 0000000000..52e1dd300c --- /dev/null +++ b/platform/linuxbsd/dbus-so_wrap.h @@ -0,0 +1,970 @@ +#ifndef DYLIBLOAD_WRAPPER_DBUS +#define DYLIBLOAD_WRAPPER_DBUS +// This file is generated. Do not edit! +// see https://github.com/hpvb/dynload-wrapper for details +// generated by ./generate-wrapper.py 0.3 on 2022-07-29 07:23:21 +// flags: ./generate-wrapper.py --include /usr/include/dbus-1.0/dbus/dbus.h --sys-include <dbus/dbus.h> --soname libdbus-1.so --init-name dbus --output-header dbus-so_wrap.h --output-implementation dbus-so_wrap.c +// +#include <stdint.h> + +#define dbus_error_init dbus_error_init_dylibloader_orig_dbus +#define dbus_error_free dbus_error_free_dylibloader_orig_dbus +#define dbus_set_error dbus_set_error_dylibloader_orig_dbus +#define dbus_set_error_const dbus_set_error_const_dylibloader_orig_dbus +#define dbus_move_error dbus_move_error_dylibloader_orig_dbus +#define dbus_error_has_name dbus_error_has_name_dylibloader_orig_dbus +#define dbus_error_is_set dbus_error_is_set_dylibloader_orig_dbus +#define dbus_parse_address dbus_parse_address_dylibloader_orig_dbus +#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_orig_dbus +#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_orig_dbus +#define dbus_address_entries_free dbus_address_entries_free_dylibloader_orig_dbus +#define dbus_address_escape_value dbus_address_escape_value_dylibloader_orig_dbus +#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_orig_dbus +#define dbus_malloc dbus_malloc_dylibloader_orig_dbus +#define dbus_malloc0 dbus_malloc0_dylibloader_orig_dbus +#define dbus_realloc dbus_realloc_dylibloader_orig_dbus +#define dbus_free dbus_free_dylibloader_orig_dbus +#define dbus_free_string_array dbus_free_string_array_dylibloader_orig_dbus +#define dbus_shutdown dbus_shutdown_dylibloader_orig_dbus +#define dbus_message_new dbus_message_new_dylibloader_orig_dbus +#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_orig_dbus +#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_orig_dbus +#define dbus_message_new_signal dbus_message_new_signal_dylibloader_orig_dbus +#define dbus_message_new_error dbus_message_new_error_dylibloader_orig_dbus +#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_orig_dbus +#define dbus_message_copy dbus_message_copy_dylibloader_orig_dbus +#define dbus_message_ref dbus_message_ref_dylibloader_orig_dbus +#define dbus_message_unref dbus_message_unref_dylibloader_orig_dbus +#define dbus_message_get_type dbus_message_get_type_dylibloader_orig_dbus +#define dbus_message_set_path dbus_message_set_path_dylibloader_orig_dbus +#define dbus_message_get_path dbus_message_get_path_dylibloader_orig_dbus +#define dbus_message_has_path dbus_message_has_path_dylibloader_orig_dbus +#define dbus_message_set_interface dbus_message_set_interface_dylibloader_orig_dbus +#define dbus_message_get_interface dbus_message_get_interface_dylibloader_orig_dbus +#define dbus_message_has_interface dbus_message_has_interface_dylibloader_orig_dbus +#define dbus_message_set_member dbus_message_set_member_dylibloader_orig_dbus +#define dbus_message_get_member dbus_message_get_member_dylibloader_orig_dbus +#define dbus_message_has_member dbus_message_has_member_dylibloader_orig_dbus +#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_orig_dbus +#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_orig_dbus +#define dbus_message_set_destination dbus_message_set_destination_dylibloader_orig_dbus +#define dbus_message_get_destination dbus_message_get_destination_dylibloader_orig_dbus +#define dbus_message_set_sender dbus_message_set_sender_dylibloader_orig_dbus +#define dbus_message_get_sender dbus_message_get_sender_dylibloader_orig_dbus +#define dbus_message_get_signature dbus_message_get_signature_dylibloader_orig_dbus +#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_orig_dbus +#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_orig_dbus +#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_orig_dbus +#define dbus_message_is_signal dbus_message_is_signal_dylibloader_orig_dbus +#define dbus_message_is_error dbus_message_is_error_dylibloader_orig_dbus +#define dbus_message_has_destination dbus_message_has_destination_dylibloader_orig_dbus +#define dbus_message_has_sender dbus_message_has_sender_dylibloader_orig_dbus +#define dbus_message_has_signature dbus_message_has_signature_dylibloader_orig_dbus +#define dbus_message_get_serial dbus_message_get_serial_dylibloader_orig_dbus +#define dbus_message_set_serial dbus_message_set_serial_dylibloader_orig_dbus +#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_orig_dbus +#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_orig_dbus +#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_orig_dbus +#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_orig_dbus +#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_orig_dbus +#define dbus_message_append_args dbus_message_append_args_dylibloader_orig_dbus +#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_orig_dbus +#define dbus_message_get_args dbus_message_get_args_dylibloader_orig_dbus +#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_orig_dbus +#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_orig_dbus +#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_orig_dbus +#define dbus_message_iter_init dbus_message_iter_init_dylibloader_orig_dbus +#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_orig_dbus +#define dbus_message_iter_next dbus_message_iter_next_dylibloader_orig_dbus +#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_orig_dbus +#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_orig_dbus +#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_orig_dbus +#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_orig_dbus +#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_orig_dbus +#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_orig_dbus +#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_orig_dbus +#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_orig_dbus +#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_orig_dbus +#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_orig_dbus +#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_orig_dbus +#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_orig_dbus +#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_orig_dbus +#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_orig_dbus +#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_orig_dbus +#define dbus_message_lock dbus_message_lock_dylibloader_orig_dbus +#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_orig_dbus +#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_orig_dbus +#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_orig_dbus +#define dbus_message_set_data dbus_message_set_data_dylibloader_orig_dbus +#define dbus_message_get_data dbus_message_get_data_dylibloader_orig_dbus +#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_orig_dbus +#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_orig_dbus +#define dbus_message_marshal dbus_message_marshal_dylibloader_orig_dbus +#define dbus_message_demarshal dbus_message_demarshal_dylibloader_orig_dbus +#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_orig_dbus +#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_orig_dbus +#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_orig_dbus +#define dbus_connection_open dbus_connection_open_dylibloader_orig_dbus +#define dbus_connection_open_private dbus_connection_open_private_dylibloader_orig_dbus +#define dbus_connection_ref dbus_connection_ref_dylibloader_orig_dbus +#define dbus_connection_unref dbus_connection_unref_dylibloader_orig_dbus +#define dbus_connection_close dbus_connection_close_dylibloader_orig_dbus +#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_orig_dbus +#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_orig_dbus +#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_orig_dbus +#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_orig_dbus +#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_orig_dbus +#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_orig_dbus +#define dbus_connection_flush dbus_connection_flush_dylibloader_orig_dbus +#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_orig_dbus +#define dbus_connection_read_write dbus_connection_read_write_dylibloader_orig_dbus +#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_orig_dbus +#define dbus_connection_return_message dbus_connection_return_message_dylibloader_orig_dbus +#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_orig_dbus +#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_orig_dbus +#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_orig_dbus +#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_orig_dbus +#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_orig_dbus +#define dbus_connection_send dbus_connection_send_dylibloader_orig_dbus +#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_orig_dbus +#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_orig_dbus +#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_orig_dbus +#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_orig_dbus +#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_orig_dbus +#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_orig_dbus +#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_orig_dbus +#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_orig_dbus +#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_orig_dbus +#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_orig_dbus +#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_orig_dbus +#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_orig_dbus +#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_orig_dbus +#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_orig_dbus +#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_orig_dbus +#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_orig_dbus +#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_orig_dbus +#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_orig_dbus +#define dbus_connection_set_data dbus_connection_set_data_dylibloader_orig_dbus +#define dbus_connection_get_data dbus_connection_get_data_dylibloader_orig_dbus +#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_orig_dbus +#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_orig_dbus +#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_orig_dbus +#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_orig_dbus +#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_orig_dbus +#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_orig_dbus +#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_orig_dbus +#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_orig_dbus +#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_orig_dbus +#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_orig_dbus +#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_orig_dbus +#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_orig_dbus +#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_orig_dbus +#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_orig_dbus +#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_orig_dbus +#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_orig_dbus +#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_orig_dbus +#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_orig_dbus +#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_orig_dbus +#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_orig_dbus +#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_orig_dbus +#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_orig_dbus +#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_orig_dbus +#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_orig_dbus +#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_orig_dbus +#define dbus_watch_get_data dbus_watch_get_data_dylibloader_orig_dbus +#define dbus_watch_set_data dbus_watch_set_data_dylibloader_orig_dbus +#define dbus_watch_handle dbus_watch_handle_dylibloader_orig_dbus +#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_orig_dbus +#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_orig_dbus +#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_orig_dbus +#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_orig_dbus +#define dbus_timeout_handle dbus_timeout_handle_dylibloader_orig_dbus +#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_orig_dbus +#define dbus_bus_get dbus_bus_get_dylibloader_orig_dbus +#define dbus_bus_get_private dbus_bus_get_private_dylibloader_orig_dbus +#define dbus_bus_register dbus_bus_register_dylibloader_orig_dbus +#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_orig_dbus +#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_orig_dbus +#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_orig_dbus +#define dbus_bus_get_id dbus_bus_get_id_dylibloader_orig_dbus +#define dbus_bus_request_name dbus_bus_request_name_dylibloader_orig_dbus +#define dbus_bus_release_name dbus_bus_release_name_dylibloader_orig_dbus +#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_orig_dbus +#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_orig_dbus +#define dbus_bus_add_match dbus_bus_add_match_dylibloader_orig_dbus +#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_orig_dbus +#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_orig_dbus +#define dbus_get_version dbus_get_version_dylibloader_orig_dbus +#define dbus_setenv dbus_setenv_dylibloader_orig_dbus +#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_orig_dbus +#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_orig_dbus +#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_orig_dbus +#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_orig_dbus +#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_orig_dbus +#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_orig_dbus +#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_orig_dbus +#define dbus_pending_call_block dbus_pending_call_block_dylibloader_orig_dbus +#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_orig_dbus +#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_orig_dbus +#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_orig_dbus +#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_orig_dbus +#define dbus_server_listen dbus_server_listen_dylibloader_orig_dbus +#define dbus_server_ref dbus_server_ref_dylibloader_orig_dbus +#define dbus_server_unref dbus_server_unref_dylibloader_orig_dbus +#define dbus_server_disconnect dbus_server_disconnect_dylibloader_orig_dbus +#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_orig_dbus +#define dbus_server_get_address dbus_server_get_address_dylibloader_orig_dbus +#define dbus_server_get_id dbus_server_get_id_dylibloader_orig_dbus +#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_orig_dbus +#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_orig_dbus +#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_orig_dbus +#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_orig_dbus +#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_orig_dbus +#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_orig_dbus +#define dbus_server_set_data dbus_server_set_data_dylibloader_orig_dbus +#define dbus_server_get_data dbus_server_get_data_dylibloader_orig_dbus +#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_orig_dbus +#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_orig_dbus +#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_orig_dbus +#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_orig_dbus +#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_orig_dbus +#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_orig_dbus +#define dbus_signature_validate dbus_signature_validate_dylibloader_orig_dbus +#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_orig_dbus +#define dbus_type_is_valid dbus_type_is_valid_dylibloader_orig_dbus +#define dbus_type_is_basic dbus_type_is_basic_dylibloader_orig_dbus +#define dbus_type_is_container dbus_type_is_container_dylibloader_orig_dbus +#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_orig_dbus +#define dbus_validate_path dbus_validate_path_dylibloader_orig_dbus +#define dbus_validate_interface dbus_validate_interface_dylibloader_orig_dbus +#define dbus_validate_member dbus_validate_member_dylibloader_orig_dbus +#define dbus_validate_error_name dbus_validate_error_name_dylibloader_orig_dbus +#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_orig_dbus +#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_orig_dbus +#define dbus_threads_init dbus_threads_init_dylibloader_orig_dbus +#define dbus_threads_init_default dbus_threads_init_default_dylibloader_orig_dbus +#include <dbus/dbus.h> +#undef dbus_error_init +#undef dbus_error_free +#undef dbus_set_error +#undef dbus_set_error_const +#undef dbus_move_error +#undef dbus_error_has_name +#undef dbus_error_is_set +#undef dbus_parse_address +#undef dbus_address_entry_get_value +#undef dbus_address_entry_get_method +#undef dbus_address_entries_free +#undef dbus_address_escape_value +#undef dbus_address_unescape_value +#undef dbus_malloc +#undef dbus_malloc0 +#undef dbus_realloc +#undef dbus_free +#undef dbus_free_string_array +#undef dbus_shutdown +#undef dbus_message_new +#undef dbus_message_new_method_call +#undef dbus_message_new_method_return +#undef dbus_message_new_signal +#undef dbus_message_new_error +#undef dbus_message_new_error_printf +#undef dbus_message_copy +#undef dbus_message_ref +#undef dbus_message_unref +#undef dbus_message_get_type +#undef dbus_message_set_path +#undef dbus_message_get_path +#undef dbus_message_has_path +#undef dbus_message_set_interface +#undef dbus_message_get_interface +#undef dbus_message_has_interface +#undef dbus_message_set_member +#undef dbus_message_get_member +#undef dbus_message_has_member +#undef dbus_message_set_error_name +#undef dbus_message_get_error_name +#undef dbus_message_set_destination +#undef dbus_message_get_destination +#undef dbus_message_set_sender +#undef dbus_message_get_sender +#undef dbus_message_get_signature +#undef dbus_message_set_no_reply +#undef dbus_message_get_no_reply +#undef dbus_message_is_method_call +#undef dbus_message_is_signal +#undef dbus_message_is_error +#undef dbus_message_has_destination +#undef dbus_message_has_sender +#undef dbus_message_has_signature +#undef dbus_message_get_serial +#undef dbus_message_set_serial +#undef dbus_message_set_reply_serial +#undef dbus_message_get_reply_serial +#undef dbus_message_set_auto_start +#undef dbus_message_get_auto_start +#undef dbus_message_get_path_decomposed +#undef dbus_message_append_args +#undef dbus_message_append_args_valist +#undef dbus_message_get_args +#undef dbus_message_get_args_valist +#undef dbus_message_contains_unix_fds +#undef dbus_message_iter_init_closed +#undef dbus_message_iter_init +#undef dbus_message_iter_has_next +#undef dbus_message_iter_next +#undef dbus_message_iter_get_signature +#undef dbus_message_iter_get_arg_type +#undef dbus_message_iter_get_element_type +#undef dbus_message_iter_recurse +#undef dbus_message_iter_get_basic +#undef dbus_message_iter_get_element_count +#undef dbus_message_iter_get_array_len +#undef dbus_message_iter_get_fixed_array +#undef dbus_message_iter_init_append +#undef dbus_message_iter_append_basic +#undef dbus_message_iter_append_fixed_array +#undef dbus_message_iter_open_container +#undef dbus_message_iter_close_container +#undef dbus_message_iter_abandon_container +#undef dbus_message_iter_abandon_container_if_open +#undef dbus_message_lock +#undef dbus_set_error_from_message +#undef dbus_message_allocate_data_slot +#undef dbus_message_free_data_slot +#undef dbus_message_set_data +#undef dbus_message_get_data +#undef dbus_message_type_from_string +#undef dbus_message_type_to_string +#undef dbus_message_marshal +#undef dbus_message_demarshal +#undef dbus_message_demarshal_bytes_needed +#undef dbus_message_set_allow_interactive_authorization +#undef dbus_message_get_allow_interactive_authorization +#undef dbus_connection_open +#undef dbus_connection_open_private +#undef dbus_connection_ref +#undef dbus_connection_unref +#undef dbus_connection_close +#undef dbus_connection_get_is_connected +#undef dbus_connection_get_is_authenticated +#undef dbus_connection_get_is_anonymous +#undef dbus_connection_get_server_id +#undef dbus_connection_can_send_type +#undef dbus_connection_set_exit_on_disconnect +#undef dbus_connection_flush +#undef dbus_connection_read_write_dispatch +#undef dbus_connection_read_write +#undef dbus_connection_borrow_message +#undef dbus_connection_return_message +#undef dbus_connection_steal_borrowed_message +#undef dbus_connection_pop_message +#undef dbus_connection_get_dispatch_status +#undef dbus_connection_dispatch +#undef dbus_connection_has_messages_to_send +#undef dbus_connection_send +#undef dbus_connection_send_with_reply +#undef dbus_connection_send_with_reply_and_block +#undef dbus_connection_set_watch_functions +#undef dbus_connection_set_timeout_functions +#undef dbus_connection_set_wakeup_main_function +#undef dbus_connection_set_dispatch_status_function +#undef dbus_connection_get_unix_user +#undef dbus_connection_get_unix_process_id +#undef dbus_connection_get_adt_audit_session_data +#undef dbus_connection_set_unix_user_function +#undef dbus_connection_get_windows_user +#undef dbus_connection_set_windows_user_function +#undef dbus_connection_set_allow_anonymous +#undef dbus_connection_set_route_peer_messages +#undef dbus_connection_add_filter +#undef dbus_connection_remove_filter +#undef dbus_connection_allocate_data_slot +#undef dbus_connection_free_data_slot +#undef dbus_connection_set_data +#undef dbus_connection_get_data +#undef dbus_connection_set_change_sigpipe +#undef dbus_connection_set_max_message_size +#undef dbus_connection_get_max_message_size +#undef dbus_connection_set_max_received_size +#undef dbus_connection_get_max_received_size +#undef dbus_connection_set_max_message_unix_fds +#undef dbus_connection_get_max_message_unix_fds +#undef dbus_connection_set_max_received_unix_fds +#undef dbus_connection_get_max_received_unix_fds +#undef dbus_connection_get_outgoing_size +#undef dbus_connection_get_outgoing_unix_fds +#undef dbus_connection_preallocate_send +#undef dbus_connection_free_preallocated_send +#undef dbus_connection_send_preallocated +#undef dbus_connection_try_register_object_path +#undef dbus_connection_register_object_path +#undef dbus_connection_try_register_fallback +#undef dbus_connection_register_fallback +#undef dbus_connection_unregister_object_path +#undef dbus_connection_get_object_path_data +#undef dbus_connection_list_registered +#undef dbus_connection_get_unix_fd +#undef dbus_connection_get_socket +#undef dbus_watch_get_fd +#undef dbus_watch_get_unix_fd +#undef dbus_watch_get_socket +#undef dbus_watch_get_flags +#undef dbus_watch_get_data +#undef dbus_watch_set_data +#undef dbus_watch_handle +#undef dbus_watch_get_enabled +#undef dbus_timeout_get_interval +#undef dbus_timeout_get_data +#undef dbus_timeout_set_data +#undef dbus_timeout_handle +#undef dbus_timeout_get_enabled +#undef dbus_bus_get +#undef dbus_bus_get_private +#undef dbus_bus_register +#undef dbus_bus_set_unique_name +#undef dbus_bus_get_unique_name +#undef dbus_bus_get_unix_user +#undef dbus_bus_get_id +#undef dbus_bus_request_name +#undef dbus_bus_release_name +#undef dbus_bus_name_has_owner +#undef dbus_bus_start_service_by_name +#undef dbus_bus_add_match +#undef dbus_bus_remove_match +#undef dbus_get_local_machine_id +#undef dbus_get_version +#undef dbus_setenv +#undef dbus_try_get_local_machine_id +#undef dbus_pending_call_ref +#undef dbus_pending_call_unref +#undef dbus_pending_call_set_notify +#undef dbus_pending_call_cancel +#undef dbus_pending_call_get_completed +#undef dbus_pending_call_steal_reply +#undef dbus_pending_call_block +#undef dbus_pending_call_allocate_data_slot +#undef dbus_pending_call_free_data_slot +#undef dbus_pending_call_set_data +#undef dbus_pending_call_get_data +#undef dbus_server_listen +#undef dbus_server_ref +#undef dbus_server_unref +#undef dbus_server_disconnect +#undef dbus_server_get_is_connected +#undef dbus_server_get_address +#undef dbus_server_get_id +#undef dbus_server_set_new_connection_function +#undef dbus_server_set_watch_functions +#undef dbus_server_set_timeout_functions +#undef dbus_server_set_auth_mechanisms +#undef dbus_server_allocate_data_slot +#undef dbus_server_free_data_slot +#undef dbus_server_set_data +#undef dbus_server_get_data +#undef dbus_signature_iter_init +#undef dbus_signature_iter_get_current_type +#undef dbus_signature_iter_get_signature +#undef dbus_signature_iter_get_element_type +#undef dbus_signature_iter_next +#undef dbus_signature_iter_recurse +#undef dbus_signature_validate +#undef dbus_signature_validate_single +#undef dbus_type_is_valid +#undef dbus_type_is_basic +#undef dbus_type_is_container +#undef dbus_type_is_fixed +#undef dbus_validate_path +#undef dbus_validate_interface +#undef dbus_validate_member +#undef dbus_validate_error_name +#undef dbus_validate_bus_name +#undef dbus_validate_utf8 +#undef dbus_threads_init +#undef dbus_threads_init_default +#ifdef __cplusplus +extern "C" { +#endif +#define dbus_error_init dbus_error_init_dylibloader_wrapper_dbus +#define dbus_error_free dbus_error_free_dylibloader_wrapper_dbus +#define dbus_set_error dbus_set_error_dylibloader_wrapper_dbus +#define dbus_set_error_const dbus_set_error_const_dylibloader_wrapper_dbus +#define dbus_move_error dbus_move_error_dylibloader_wrapper_dbus +#define dbus_error_has_name dbus_error_has_name_dylibloader_wrapper_dbus +#define dbus_error_is_set dbus_error_is_set_dylibloader_wrapper_dbus +#define dbus_parse_address dbus_parse_address_dylibloader_wrapper_dbus +#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_wrapper_dbus +#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_wrapper_dbus +#define dbus_address_entries_free dbus_address_entries_free_dylibloader_wrapper_dbus +#define dbus_address_escape_value dbus_address_escape_value_dylibloader_wrapper_dbus +#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_wrapper_dbus +#define dbus_malloc dbus_malloc_dylibloader_wrapper_dbus +#define dbus_malloc0 dbus_malloc0_dylibloader_wrapper_dbus +#define dbus_realloc dbus_realloc_dylibloader_wrapper_dbus +#define dbus_free dbus_free_dylibloader_wrapper_dbus +#define dbus_free_string_array dbus_free_string_array_dylibloader_wrapper_dbus +#define dbus_shutdown dbus_shutdown_dylibloader_wrapper_dbus +#define dbus_message_new dbus_message_new_dylibloader_wrapper_dbus +#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_wrapper_dbus +#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_wrapper_dbus +#define dbus_message_new_signal dbus_message_new_signal_dylibloader_wrapper_dbus +#define dbus_message_new_error dbus_message_new_error_dylibloader_wrapper_dbus +#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_wrapper_dbus +#define dbus_message_copy dbus_message_copy_dylibloader_wrapper_dbus +#define dbus_message_ref dbus_message_ref_dylibloader_wrapper_dbus +#define dbus_message_unref dbus_message_unref_dylibloader_wrapper_dbus +#define dbus_message_get_type dbus_message_get_type_dylibloader_wrapper_dbus +#define dbus_message_set_path dbus_message_set_path_dylibloader_wrapper_dbus +#define dbus_message_get_path dbus_message_get_path_dylibloader_wrapper_dbus +#define dbus_message_has_path dbus_message_has_path_dylibloader_wrapper_dbus +#define dbus_message_set_interface dbus_message_set_interface_dylibloader_wrapper_dbus +#define dbus_message_get_interface dbus_message_get_interface_dylibloader_wrapper_dbus +#define dbus_message_has_interface dbus_message_has_interface_dylibloader_wrapper_dbus +#define dbus_message_set_member dbus_message_set_member_dylibloader_wrapper_dbus +#define dbus_message_get_member dbus_message_get_member_dylibloader_wrapper_dbus +#define dbus_message_has_member dbus_message_has_member_dylibloader_wrapper_dbus +#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_wrapper_dbus +#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_wrapper_dbus +#define dbus_message_set_destination dbus_message_set_destination_dylibloader_wrapper_dbus +#define dbus_message_get_destination dbus_message_get_destination_dylibloader_wrapper_dbus +#define dbus_message_set_sender dbus_message_set_sender_dylibloader_wrapper_dbus +#define dbus_message_get_sender dbus_message_get_sender_dylibloader_wrapper_dbus +#define dbus_message_get_signature dbus_message_get_signature_dylibloader_wrapper_dbus +#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_wrapper_dbus +#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_wrapper_dbus +#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_wrapper_dbus +#define dbus_message_is_signal dbus_message_is_signal_dylibloader_wrapper_dbus +#define dbus_message_is_error dbus_message_is_error_dylibloader_wrapper_dbus +#define dbus_message_has_destination dbus_message_has_destination_dylibloader_wrapper_dbus +#define dbus_message_has_sender dbus_message_has_sender_dylibloader_wrapper_dbus +#define dbus_message_has_signature dbus_message_has_signature_dylibloader_wrapper_dbus +#define dbus_message_get_serial dbus_message_get_serial_dylibloader_wrapper_dbus +#define dbus_message_set_serial dbus_message_set_serial_dylibloader_wrapper_dbus +#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_wrapper_dbus +#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_wrapper_dbus +#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_wrapper_dbus +#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_wrapper_dbus +#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_wrapper_dbus +#define dbus_message_append_args dbus_message_append_args_dylibloader_wrapper_dbus +#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_wrapper_dbus +#define dbus_message_get_args dbus_message_get_args_dylibloader_wrapper_dbus +#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_wrapper_dbus +#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_wrapper_dbus +#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_wrapper_dbus +#define dbus_message_iter_init dbus_message_iter_init_dylibloader_wrapper_dbus +#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_wrapper_dbus +#define dbus_message_iter_next dbus_message_iter_next_dylibloader_wrapper_dbus +#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_wrapper_dbus +#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus +#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_wrapper_dbus +#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_wrapper_dbus +#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_wrapper_dbus +#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_wrapper_dbus +#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_wrapper_dbus +#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus +#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_wrapper_dbus +#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_wrapper_dbus +#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus +#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_wrapper_dbus +#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_wrapper_dbus +#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_wrapper_dbus +#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus +#define dbus_message_lock dbus_message_lock_dylibloader_wrapper_dbus +#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_wrapper_dbus +#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_wrapper_dbus +#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_wrapper_dbus +#define dbus_message_set_data dbus_message_set_data_dylibloader_wrapper_dbus +#define dbus_message_get_data dbus_message_get_data_dylibloader_wrapper_dbus +#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_wrapper_dbus +#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_wrapper_dbus +#define dbus_message_marshal dbus_message_marshal_dylibloader_wrapper_dbus +#define dbus_message_demarshal dbus_message_demarshal_dylibloader_wrapper_dbus +#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus +#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus +#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus +#define dbus_connection_open dbus_connection_open_dylibloader_wrapper_dbus +#define dbus_connection_open_private dbus_connection_open_private_dylibloader_wrapper_dbus +#define dbus_connection_ref dbus_connection_ref_dylibloader_wrapper_dbus +#define dbus_connection_unref dbus_connection_unref_dylibloader_wrapper_dbus +#define dbus_connection_close dbus_connection_close_dylibloader_wrapper_dbus +#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_wrapper_dbus +#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus +#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus +#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_wrapper_dbus +#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_wrapper_dbus +#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus +#define dbus_connection_flush dbus_connection_flush_dylibloader_wrapper_dbus +#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus +#define dbus_connection_read_write dbus_connection_read_write_dylibloader_wrapper_dbus +#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_wrapper_dbus +#define dbus_connection_return_message dbus_connection_return_message_dylibloader_wrapper_dbus +#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus +#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_wrapper_dbus +#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus +#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_wrapper_dbus +#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus +#define dbus_connection_send dbus_connection_send_dylibloader_wrapper_dbus +#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_wrapper_dbus +#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus +#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_wrapper_dbus +#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus +#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus +#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus +#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_wrapper_dbus +#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus +#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus +#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus +#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_wrapper_dbus +#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus +#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus +#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus +#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_wrapper_dbus +#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_wrapper_dbus +#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus +#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_wrapper_dbus +#define dbus_connection_set_data dbus_connection_set_data_dylibloader_wrapper_dbus +#define dbus_connection_get_data dbus_connection_get_data_dylibloader_wrapper_dbus +#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus +#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_wrapper_dbus +#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_wrapper_dbus +#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_wrapper_dbus +#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_wrapper_dbus +#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus +#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus +#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus +#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus +#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus +#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus +#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_wrapper_dbus +#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus +#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_wrapper_dbus +#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_wrapper_dbus +#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_wrapper_dbus +#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_wrapper_dbus +#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_wrapper_dbus +#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_wrapper_dbus +#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_wrapper_dbus +#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_wrapper_dbus +#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_wrapper_dbus +#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_wrapper_dbus +#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_wrapper_dbus +#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_wrapper_dbus +#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_wrapper_dbus +#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_wrapper_dbus +#define dbus_watch_get_data dbus_watch_get_data_dylibloader_wrapper_dbus +#define dbus_watch_set_data dbus_watch_set_data_dylibloader_wrapper_dbus +#define dbus_watch_handle dbus_watch_handle_dylibloader_wrapper_dbus +#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_wrapper_dbus +#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_wrapper_dbus +#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_wrapper_dbus +#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_wrapper_dbus +#define dbus_timeout_handle dbus_timeout_handle_dylibloader_wrapper_dbus +#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_wrapper_dbus +#define dbus_bus_get dbus_bus_get_dylibloader_wrapper_dbus +#define dbus_bus_get_private dbus_bus_get_private_dylibloader_wrapper_dbus +#define dbus_bus_register dbus_bus_register_dylibloader_wrapper_dbus +#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_wrapper_dbus +#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_wrapper_dbus +#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_wrapper_dbus +#define dbus_bus_get_id dbus_bus_get_id_dylibloader_wrapper_dbus +#define dbus_bus_request_name dbus_bus_request_name_dylibloader_wrapper_dbus +#define dbus_bus_release_name dbus_bus_release_name_dylibloader_wrapper_dbus +#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_wrapper_dbus +#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_wrapper_dbus +#define dbus_bus_add_match dbus_bus_add_match_dylibloader_wrapper_dbus +#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_wrapper_dbus +#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_wrapper_dbus +#define dbus_get_version dbus_get_version_dylibloader_wrapper_dbus +#define dbus_setenv dbus_setenv_dylibloader_wrapper_dbus +#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_wrapper_dbus +#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_wrapper_dbus +#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_wrapper_dbus +#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_wrapper_dbus +#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_wrapper_dbus +#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_wrapper_dbus +#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_wrapper_dbus +#define dbus_pending_call_block dbus_pending_call_block_dylibloader_wrapper_dbus +#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus +#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus +#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_wrapper_dbus +#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_wrapper_dbus +#define dbus_server_listen dbus_server_listen_dylibloader_wrapper_dbus +#define dbus_server_ref dbus_server_ref_dylibloader_wrapper_dbus +#define dbus_server_unref dbus_server_unref_dylibloader_wrapper_dbus +#define dbus_server_disconnect dbus_server_disconnect_dylibloader_wrapper_dbus +#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_wrapper_dbus +#define dbus_server_get_address dbus_server_get_address_dylibloader_wrapper_dbus +#define dbus_server_get_id dbus_server_get_id_dylibloader_wrapper_dbus +#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_wrapper_dbus +#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_wrapper_dbus +#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_wrapper_dbus +#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus +#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_wrapper_dbus +#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_wrapper_dbus +#define dbus_server_set_data dbus_server_set_data_dylibloader_wrapper_dbus +#define dbus_server_get_data dbus_server_get_data_dylibloader_wrapper_dbus +#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_wrapper_dbus +#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus +#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_wrapper_dbus +#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus +#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_wrapper_dbus +#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_wrapper_dbus +#define dbus_signature_validate dbus_signature_validate_dylibloader_wrapper_dbus +#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_wrapper_dbus +#define dbus_type_is_valid dbus_type_is_valid_dylibloader_wrapper_dbus +#define dbus_type_is_basic dbus_type_is_basic_dylibloader_wrapper_dbus +#define dbus_type_is_container dbus_type_is_container_dylibloader_wrapper_dbus +#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_wrapper_dbus +#define dbus_validate_path dbus_validate_path_dylibloader_wrapper_dbus +#define dbus_validate_interface dbus_validate_interface_dylibloader_wrapper_dbus +#define dbus_validate_member dbus_validate_member_dylibloader_wrapper_dbus +#define dbus_validate_error_name dbus_validate_error_name_dylibloader_wrapper_dbus +#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_wrapper_dbus +#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_wrapper_dbus +#define dbus_threads_init dbus_threads_init_dylibloader_wrapper_dbus +#define dbus_threads_init_default dbus_threads_init_default_dylibloader_wrapper_dbus +extern void (*dbus_error_init_dylibloader_wrapper_dbus)( DBusError*); +extern void (*dbus_error_free_dylibloader_wrapper_dbus)( DBusError*); +extern void (*dbus_set_error_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*,...); +extern void (*dbus_set_error_const_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*); +extern void (*dbus_move_error_dylibloader_wrapper_dbus)( DBusError*, DBusError*); +extern dbus_bool_t (*dbus_error_has_name_dylibloader_wrapper_dbus)(const DBusError*,const char*); +extern dbus_bool_t (*dbus_error_is_set_dylibloader_wrapper_dbus)(const DBusError*); +extern dbus_bool_t (*dbus_parse_address_dylibloader_wrapper_dbus)(const char*, DBusAddressEntry***, int*, DBusError*); +extern const char* (*dbus_address_entry_get_value_dylibloader_wrapper_dbus)( DBusAddressEntry*,const char*); +extern const char* (*dbus_address_entry_get_method_dylibloader_wrapper_dbus)( DBusAddressEntry*); +extern void (*dbus_address_entries_free_dylibloader_wrapper_dbus)( DBusAddressEntry**); +extern char* (*dbus_address_escape_value_dylibloader_wrapper_dbus)(const char*); +extern char* (*dbus_address_unescape_value_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern void* (*dbus_malloc_dylibloader_wrapper_dbus)( size_t); +extern void* (*dbus_malloc0_dylibloader_wrapper_dbus)( size_t); +extern void* (*dbus_realloc_dylibloader_wrapper_dbus)( void*, size_t); +extern void (*dbus_free_dylibloader_wrapper_dbus)( void*); +extern void (*dbus_free_string_array_dylibloader_wrapper_dbus)( char**); +extern void (*dbus_shutdown_dylibloader_wrapper_dbus)( void); +extern DBusMessage* (*dbus_message_new_dylibloader_wrapper_dbus)( int); +extern DBusMessage* (*dbus_message_new_method_call_dylibloader_wrapper_dbus)(const char*,const char*,const char*,const char*); +extern DBusMessage* (*dbus_message_new_method_return_dylibloader_wrapper_dbus)( DBusMessage*); +extern DBusMessage* (*dbus_message_new_signal_dylibloader_wrapper_dbus)(const char*,const char*,const char*); +extern DBusMessage* (*dbus_message_new_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +extern DBusMessage* (*dbus_message_new_error_printf_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*,...); +extern DBusMessage* (*dbus_message_copy_dylibloader_wrapper_dbus)(const DBusMessage*); +extern DBusMessage* (*dbus_message_ref_dylibloader_wrapper_dbus)( DBusMessage*); +extern void (*dbus_message_unref_dylibloader_wrapper_dbus)( DBusMessage*); +extern int (*dbus_message_get_type_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_set_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_path_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_has_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_set_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_interface_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_has_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_set_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_member_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_has_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_set_error_name_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_error_name_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_set_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_destination_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_set_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern const char* (*dbus_message_get_sender_dylibloader_wrapper_dbus)( DBusMessage*); +extern const char* (*dbus_message_get_signature_dylibloader_wrapper_dbus)( DBusMessage*); +extern void (*dbus_message_set_no_reply_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +extern dbus_bool_t (*dbus_message_get_no_reply_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_is_method_call_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +extern dbus_bool_t (*dbus_message_is_signal_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*); +extern dbus_bool_t (*dbus_message_is_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_has_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_has_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_bool_t (*dbus_message_has_signature_dylibloader_wrapper_dbus)( DBusMessage*,const char*); +extern dbus_uint32_t (*dbus_message_get_serial_dylibloader_wrapper_dbus)( DBusMessage*); +extern void (*dbus_message_set_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t); +extern dbus_bool_t (*dbus_message_set_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t); +extern dbus_uint32_t (*dbus_message_get_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*); +extern void (*dbus_message_set_auto_start_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +extern dbus_bool_t (*dbus_message_get_auto_start_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_message_get_path_decomposed_dylibloader_wrapper_dbus)( DBusMessage*, char***); +extern dbus_bool_t (*dbus_message_append_args_dylibloader_wrapper_dbus)( DBusMessage*, int,...); +extern dbus_bool_t (*dbus_message_append_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, int, va_list); +extern dbus_bool_t (*dbus_message_get_args_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int,...); +extern dbus_bool_t (*dbus_message_get_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int, va_list); +extern dbus_bool_t (*dbus_message_contains_unix_fds_dylibloader_wrapper_dbus)( DBusMessage*); +extern void (*dbus_message_iter_init_closed_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern dbus_bool_t (*dbus_message_iter_init_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*); +extern dbus_bool_t (*dbus_message_iter_has_next_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern dbus_bool_t (*dbus_message_iter_next_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern char* (*dbus_message_iter_get_signature_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern int (*dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern int (*dbus_message_iter_get_element_type_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern void (*dbus_message_iter_recurse_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +extern void (*dbus_message_iter_get_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, void*); +extern int (*dbus_message_iter_get_element_count_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern int (*dbus_message_iter_get_array_len_dylibloader_wrapper_dbus)( DBusMessageIter*); +extern void (*dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, void*, int*); +extern void (*dbus_message_iter_init_append_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*); +extern dbus_bool_t (*dbus_message_iter_append_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*); +extern dbus_bool_t (*dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*, int); +extern dbus_bool_t (*dbus_message_iter_open_container_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const char*, DBusMessageIter*); +extern dbus_bool_t (*dbus_message_iter_close_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +extern void (*dbus_message_iter_abandon_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +extern void (*dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*); +extern void (*dbus_message_lock_dylibloader_wrapper_dbus)( DBusMessage*); +extern dbus_bool_t (*dbus_set_error_from_message_dylibloader_wrapper_dbus)( DBusError*, DBusMessage*); +extern dbus_bool_t (*dbus_message_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern void (*dbus_message_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern dbus_bool_t (*dbus_message_set_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t, void*, DBusFreeFunction); +extern void* (*dbus_message_get_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t); +extern int (*dbus_message_type_from_string_dylibloader_wrapper_dbus)(const char*); +extern const char* (*dbus_message_type_to_string_dylibloader_wrapper_dbus)( int); +extern dbus_bool_t (*dbus_message_marshal_dylibloader_wrapper_dbus)( DBusMessage*, char**, int*); +extern DBusMessage* (*dbus_message_demarshal_dylibloader_wrapper_dbus)(const char*, int, DBusError*); +extern int (*dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus)(const char*, int); +extern void (*dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t); +extern dbus_bool_t (*dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*); +extern DBusConnection* (*dbus_connection_open_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern DBusConnection* (*dbus_connection_open_private_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern DBusConnection* (*dbus_connection_ref_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_unref_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_close_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_get_is_connected_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus)( DBusConnection*); +extern char* (*dbus_connection_get_server_id_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_can_send_type_dylibloader_wrapper_dbus)( DBusConnection*, int); +extern void (*dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +extern void (*dbus_connection_flush_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus)( DBusConnection*, int); +extern dbus_bool_t (*dbus_connection_read_write_dylibloader_wrapper_dbus)( DBusConnection*, int); +extern DBusMessage* (*dbus_connection_borrow_message_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_return_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*); +extern void (*dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*); +extern DBusMessage* (*dbus_connection_pop_message_dylibloader_wrapper_dbus)( DBusConnection*); +extern DBusDispatchStatus (*dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus)( DBusConnection*); +extern DBusDispatchStatus (*dbus_connection_dispatch_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus)( DBusConnection*); +extern dbus_bool_t (*dbus_connection_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, dbus_uint32_t*); +extern dbus_bool_t (*dbus_connection_send_with_reply_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, DBusPendingCall**, int); +extern DBusMessage* (*dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, int, DBusError*); +extern dbus_bool_t (*dbus_connection_set_watch_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction); +extern void (*dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusWakeupMainFunction, void*, DBusFreeFunction); +extern void (*dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusDispatchStatusFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_connection_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*); +extern dbus_bool_t (*dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*); +extern dbus_bool_t (*dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus)( DBusConnection*, void**, dbus_int32_t*); +extern void (*dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowUnixUserFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_connection_get_windows_user_dylibloader_wrapper_dbus)( DBusConnection*, char**); +extern void (*dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowWindowsUserFunction, void*, DBusFreeFunction); +extern void (*dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +extern void (*dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t); +extern dbus_bool_t (*dbus_connection_add_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*, DBusFreeFunction); +extern void (*dbus_connection_remove_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*); +extern dbus_bool_t (*dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern void (*dbus_connection_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern dbus_bool_t (*dbus_connection_set_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t, void*, DBusFreeFunction); +extern void* (*dbus_connection_get_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t); +extern void (*dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus)( dbus_bool_t); +extern void (*dbus_connection_set_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*, long); +extern long (*dbus_connection_get_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_set_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*, long); +extern long (*dbus_connection_get_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long); +extern long (*dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long); +extern long (*dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +extern long (*dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus)( DBusConnection*); +extern long (*dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*); +extern DBusPreallocatedSend* (*dbus_connection_preallocate_send_dylibloader_wrapper_dbus)( DBusConnection*); +extern void (*dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*); +extern void (*dbus_connection_send_preallocated_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*, DBusMessage*, dbus_uint32_t*); +extern dbus_bool_t (*dbus_connection_try_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*); +extern dbus_bool_t (*dbus_connection_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*); +extern dbus_bool_t (*dbus_connection_try_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*); +extern dbus_bool_t (*dbus_connection_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*); +extern dbus_bool_t (*dbus_connection_unregister_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*); +extern dbus_bool_t (*dbus_connection_get_object_path_data_dylibloader_wrapper_dbus)( DBusConnection*,const char*, void**); +extern dbus_bool_t (*dbus_connection_list_registered_dylibloader_wrapper_dbus)( DBusConnection*,const char*, char***); +extern dbus_bool_t (*dbus_connection_get_unix_fd_dylibloader_wrapper_dbus)( DBusConnection*, int*); +extern dbus_bool_t (*dbus_connection_get_socket_dylibloader_wrapper_dbus)( DBusConnection*, int*); +extern int (*dbus_watch_get_fd_dylibloader_wrapper_dbus)( DBusWatch*); +extern int (*dbus_watch_get_unix_fd_dylibloader_wrapper_dbus)( DBusWatch*); +extern int (*dbus_watch_get_socket_dylibloader_wrapper_dbus)( DBusWatch*); +extern unsigned int (*dbus_watch_get_flags_dylibloader_wrapper_dbus)( DBusWatch*); +extern void* (*dbus_watch_get_data_dylibloader_wrapper_dbus)( DBusWatch*); +extern void (*dbus_watch_set_data_dylibloader_wrapper_dbus)( DBusWatch*, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_watch_handle_dylibloader_wrapper_dbus)( DBusWatch*, unsigned int); +extern dbus_bool_t (*dbus_watch_get_enabled_dylibloader_wrapper_dbus)( DBusWatch*); +extern int (*dbus_timeout_get_interval_dylibloader_wrapper_dbus)( DBusTimeout*); +extern void* (*dbus_timeout_get_data_dylibloader_wrapper_dbus)( DBusTimeout*); +extern void (*dbus_timeout_set_data_dylibloader_wrapper_dbus)( DBusTimeout*, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_timeout_handle_dylibloader_wrapper_dbus)( DBusTimeout*); +extern dbus_bool_t (*dbus_timeout_get_enabled_dylibloader_wrapper_dbus)( DBusTimeout*); +extern DBusConnection* (*dbus_bus_get_dylibloader_wrapper_dbus)( DBusBusType, DBusError*); +extern DBusConnection* (*dbus_bus_get_private_dylibloader_wrapper_dbus)( DBusBusType, DBusError*); +extern dbus_bool_t (*dbus_bus_register_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*); +extern dbus_bool_t (*dbus_bus_set_unique_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*); +extern const char* (*dbus_bus_get_unique_name_dylibloader_wrapper_dbus)( DBusConnection*); +extern unsigned long (*dbus_bus_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +extern char* (*dbus_bus_get_id_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*); +extern int (*dbus_bus_request_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, unsigned int, DBusError*); +extern int (*dbus_bus_release_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +extern dbus_bool_t (*dbus_bus_name_has_owner_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +extern dbus_bool_t (*dbus_bus_start_service_by_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, dbus_uint32_t, dbus_uint32_t*, DBusError*); +extern void (*dbus_bus_add_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +extern void (*dbus_bus_remove_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*); +extern char* (*dbus_get_local_machine_id_dylibloader_wrapper_dbus)( void); +extern void (*dbus_get_version_dylibloader_wrapper_dbus)( int*, int*, int*); +extern dbus_bool_t (*dbus_setenv_dylibloader_wrapper_dbus)(const char*,const char*); +extern char* (*dbus_try_get_local_machine_id_dylibloader_wrapper_dbus)( DBusError*); +extern DBusPendingCall* (*dbus_pending_call_ref_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern void (*dbus_pending_call_unref_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern dbus_bool_t (*dbus_pending_call_set_notify_dylibloader_wrapper_dbus)( DBusPendingCall*, DBusPendingCallNotifyFunction, void*, DBusFreeFunction); +extern void (*dbus_pending_call_cancel_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern dbus_bool_t (*dbus_pending_call_get_completed_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern DBusMessage* (*dbus_pending_call_steal_reply_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern void (*dbus_pending_call_block_dylibloader_wrapper_dbus)( DBusPendingCall*); +extern dbus_bool_t (*dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern void (*dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern dbus_bool_t (*dbus_pending_call_set_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t, void*, DBusFreeFunction); +extern void* (*dbus_pending_call_get_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t); +extern DBusServer* (*dbus_server_listen_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern DBusServer* (*dbus_server_ref_dylibloader_wrapper_dbus)( DBusServer*); +extern void (*dbus_server_unref_dylibloader_wrapper_dbus)( DBusServer*); +extern void (*dbus_server_disconnect_dylibloader_wrapper_dbus)( DBusServer*); +extern dbus_bool_t (*dbus_server_get_is_connected_dylibloader_wrapper_dbus)( DBusServer*); +extern char* (*dbus_server_get_address_dylibloader_wrapper_dbus)( DBusServer*); +extern char* (*dbus_server_get_id_dylibloader_wrapper_dbus)( DBusServer*); +extern void (*dbus_server_set_new_connection_function_dylibloader_wrapper_dbus)( DBusServer*, DBusNewConnectionFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_server_set_watch_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_server_set_timeout_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction); +extern dbus_bool_t (*dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus)( DBusServer*,const char**); +extern dbus_bool_t (*dbus_server_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern void (*dbus_server_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*); +extern dbus_bool_t (*dbus_server_set_data_dylibloader_wrapper_dbus)( DBusServer*, int, void*, DBusFreeFunction); +extern void* (*dbus_server_get_data_dylibloader_wrapper_dbus)( DBusServer*, int); +extern void (*dbus_signature_iter_init_dylibloader_wrapper_dbus)( DBusSignatureIter*,const char*); +extern int (*dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +extern char* (*dbus_signature_iter_get_signature_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +extern int (*dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*); +extern dbus_bool_t (*dbus_signature_iter_next_dylibloader_wrapper_dbus)( DBusSignatureIter*); +extern void (*dbus_signature_iter_recurse_dylibloader_wrapper_dbus)(const DBusSignatureIter*, DBusSignatureIter*); +extern dbus_bool_t (*dbus_signature_validate_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_signature_validate_single_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_type_is_valid_dylibloader_wrapper_dbus)( int); +extern dbus_bool_t (*dbus_type_is_basic_dylibloader_wrapper_dbus)( int); +extern dbus_bool_t (*dbus_type_is_container_dylibloader_wrapper_dbus)( int); +extern dbus_bool_t (*dbus_type_is_fixed_dylibloader_wrapper_dbus)( int); +extern dbus_bool_t (*dbus_validate_path_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_validate_interface_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_validate_member_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_validate_error_name_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_validate_bus_name_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_validate_utf8_dylibloader_wrapper_dbus)(const char*, DBusError*); +extern dbus_bool_t (*dbus_threads_init_dylibloader_wrapper_dbus)(const DBusThreadFunctions*); +extern dbus_bool_t (*dbus_threads_init_default_dylibloader_wrapper_dbus)( void); +int initialize_dbus(int verbose); +#ifdef __cplusplus +} +#endif +#endif diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 19cf341c85..00e2b9e6eb 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -1,6 +1,7 @@ import os import platform import sys +from methods import get_compiler_version, using_gcc def is_active(): @@ -15,47 +16,11 @@ def can_build(): if os.name != "posix" or sys.platform == "darwin": return False - # Check the minimal dependencies - x11_error = os.system("pkg-config --version > /dev/null") - if x11_error: + pkgconf_error = os.system("pkg-config --version > /dev/null") + if pkgconf_error: print("Error: pkg-config not found. Aborting.") return False - x11_error = os.system("pkg-config x11 --modversion > /dev/null") - if x11_error: - print("Error: X11 libraries not found. Aborting.") - return False - - x11_error = os.system("pkg-config xcursor --modversion > /dev/null") - if x11_error: - print("Error: Xcursor library not found. Aborting.") - return False - - x11_error = os.system("pkg-config xinerama --modversion > /dev/null") - if x11_error: - print("Error: Xinerama library not found. Aborting.") - return False - - x11_error = os.system("pkg-config xext --modversion > /dev/null") - if x11_error: - print("Error: Xext library not found. Aborting.") - return False - - x11_error = os.system("pkg-config xrandr --modversion > /dev/null") - if x11_error: - print("Error: XrandR library not found. Aborting.") - return False - - x11_error = os.system("pkg-config xrender --modversion > /dev/null") - if x11_error: - print("Error: XRender library not found. Aborting.") - return False - - x11_error = os.system("pkg-config xi --modversion > /dev/null") - if x11_error: - print("Error: Xi library not found. Aborting.") - return False - return True @@ -63,9 +28,9 @@ def get_opts(): from SCons.Variables import BoolVariable, EnumVariable return [ + EnumVariable("linker", "Linker program", "default", ("default", "bfd", "gold", "lld", "mold")), BoolVariable("use_llvm", "Use the LLVM compiler", False), - BoolVariable("use_lld", "Use the LLD linker", False), - BoolVariable("use_thinlto", "Use ThinLTO", False), + BoolVariable("use_thinlto", "Use ThinLTO (LLVM only, requires linker=lld, implies use_lto=yes)", False), BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True), BoolVariable("use_coverage", "Test Godot coverage", False), BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False), @@ -76,6 +41,7 @@ def get_opts(): BoolVariable("pulseaudio", "Detect and use PulseAudio", True), BoolVariable("dbus", "Detect and use D-Bus to handle screensaver", True), BoolVariable("speechd", "Detect and use Speech Dispatcher for Text-to-Speech support", True), + BoolVariable("fontconfig", "Detect and use fontconfig for system fonts support", True), BoolVariable("udev", "Use udev for gamepad connection callbacks", True), BoolVariable("x11", "Enable X11 display", True), BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), @@ -147,15 +113,32 @@ def configure(env): env["CXX"] = "clang++" env.extra_suffix = ".llvm" + env.extra_suffix - if env["use_lld"]: - if env["use_llvm"]: - env.Append(LINKFLAGS=["-fuse-ld=lld"]) - if env["use_thinlto"]: - # A convenience so you don't need to write use_lto too when using SCons - env["use_lto"] = True + if env["linker"] != "default": + print("Using linker program: " + env["linker"]) + if env["linker"] == "mold" and using_gcc(env): # GCC < 12.1 doesn't support -fuse-ld=mold. + cc_version = get_compiler_version(env) + cc_semver = (int(cc_version["major"]), int(cc_version["minor"])) + if cc_semver < (12, 1): + found_wrapper = False + for path in ["/usr/libexec", "/usr/local/libexec", "/usr/lib", "/usr/local/lib"]: + if os.path.isfile(path + "/mold/ld"): + env.Append(LINKFLAGS=["-B" + path + "/mold"]) + found_wrapper = True + break + if not found_wrapper: + print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.") + sys.exit(255) + else: + env.Append(LINKFLAGS=["-fuse-ld=mold"]) else: - print("Using LLD with GCC is not supported yet. Try compiling with 'use_llvm=yes'.") + env.Append(LINKFLAGS=["-fuse-ld=%s" % env["linker"]]) + + if env["use_thinlto"]: + if not env["use_llvm"] or env["linker"] != "lld": + print("ThinLTO is only compatible with LLVM and the LLD linker, use `use_llvm=yes linker=lld`.") sys.exit(255) + else: + env["use_lto"] = True # ThinLTO implies LTO if env["use_coverage"]: env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"]) @@ -200,33 +183,32 @@ def configure(env): env.Append(LINKFLAGS=["-fsanitize=memory"]) if env["use_lto"]: - if not env["use_llvm"] and env.GetOption("num_jobs") > 1: + if env["use_thinlto"]: + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif not env["use_llvm"] and env.GetOption("num_jobs") > 1: env.Append(CCFLAGS=["-flto"]) env.Append(LINKFLAGS=["-flto=" + str(env.GetOption("num_jobs"))]) else: - if env["use_lld"] and env["use_thinlto"]: - env.Append(CCFLAGS=["-flto=thin"]) - env.Append(LINKFLAGS=["-flto=thin"]) - else: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) if not env["use_llvm"]: env["RANLIB"] = "gcc-ranlib" env["AR"] = "gcc-ar" env.Append(CCFLAGS=["-pipe"]) - env.Append(LINKFLAGS=["-pipe"]) ## Dependencies - 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") + if env["x11"]: + 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") if env["touch"]: env.Append(CPPDEFINES=["TOUCH_ENABLED"]) @@ -317,6 +299,14 @@ def configure(env): ## Flags + if env["fontconfig"]: + if os.system("pkg-config --exists fontconfig") == 0: # 0 means found + env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) + env.ParseConfig("pkg-config fontconfig --cflags") # Only cflags, we dlopen the library. + else: + env["fontconfig"] = False + print("Warning: fontconfig libraries not found. Disabling the system fonts support.") + if os.system("pkg-config --exists alsa") == 0: # 0 means found env["alsa"] = True env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) @@ -335,8 +325,9 @@ def configure(env): if env["dbus"]: if os.system("pkg-config --exists dbus-1") == 0: # 0 means found env.Append(CPPDEFINES=["DBUS_ENABLED"]) - env.ParseConfig("pkg-config dbus-1 --cflags --libs") + env.ParseConfig("pkg-config dbus-1 --cflags") # Only cflags, we dlopen the library. else: + env["dbus"] = False print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.") if env["speechd"]: @@ -382,8 +373,9 @@ def configure(env): # No pkgconfig file so far, hardcode expected lib name. env.Append(LIBS=["glslang", "SPIRV"]) - env.Append(CPPDEFINES=["GLES3_ENABLED"]) - env.ParseConfig("pkg-config gl --cflags --libs") + if env["opengl3"]: + env.Append(CPPDEFINES=["GLES3_ENABLED"]) + env.ParseConfig("pkg-config gl --cflags --libs") env.Append(LIBS=["pthread"]) diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp index 42b7f68a5e..fb833ab5e6 100644 --- a/platform/linuxbsd/detect_prime_x11.cpp +++ b/platform/linuxbsd/detect_prime_x11.cpp @@ -177,6 +177,11 @@ int detect_prime() { } else { // In child, exit() here will not quit the engine. + // Prevent false leak reports as we will not be properly + // cleaning up these processes, and fork() makes a copy + // of all globals. + CoreGlobals::leak_reporting_enabled = false; + char string[201]; close(fdset[0]); diff --git a/platform/linuxbsd/detect_prime_x11.h b/platform/linuxbsd/detect_prime_x11.h index e60f9ebfdf..21ebaead32 100644 --- a/platform/linuxbsd/detect_prime_x11.h +++ b/platform/linuxbsd/detect_prime_x11.h @@ -34,4 +34,5 @@ int detect_prime(); #endif -#endif + +#endif // DETECT_PRIME_X11_H diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index b0f87484b9..8efbd2e3c5 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -275,7 +275,7 @@ bool DisplayServerX11::_refresh_device_info() { xi.pen_pressure_range[dev->deviceid] = Vector2(pressure_min, pressure_max); xi.pen_tilt_x_range[dev->deviceid] = Vector2(tilt_x_min, tilt_x_max); xi.pen_tilt_y_range[dev->deviceid] = Vector2(tilt_y_min, tilt_y_max); - xi.pen_inverted_devices[dev->deviceid] = (bool)strstr(dev->name, "eraser"); + xi.pen_inverted_devices[dev->deviceid] = String(dev->name).findn("eraser") > 0; } XIFreeDeviceInfo(info); @@ -1489,8 +1489,8 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window XMoveResizeWindow(x11_display, wd.x11_window, position.x, position.y, size.x, size.y); } else { if (p_screen != window_get_current_screen(p_window)) { - Point2i position = screen_get_position(p_screen); - XMoveWindow(x11_display, wd.x11_window, position.x, position.y); + Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); + window_set_position(ofs + screen_get_position(p_screen), p_window); } } } @@ -3147,7 +3147,7 @@ void DisplayServerX11::_window_changed(XEvent *event) { Variant *rectp = ▭ Variant ret; Callable::CallError ce; - wd.rect_changed_callback.call((const Variant **)&rectp, 1, ret, ce); + wd.rect_changed_callback.callp((const Variant **)&rectp, 1, ret, ce); } } @@ -3168,7 +3168,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) { if (windows.has(E->get())) { Callable callable = windows[E->get()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } return; @@ -3181,7 +3181,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) { if (windows.has(event_from_window->get_window_id())) { Callable callable = windows[event_from_window->get_window_id()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } else { @@ -3189,7 +3189,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) { for (KeyValue<WindowID, WindowData> &E : windows) { Callable callable = E.value.input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } @@ -3201,7 +3201,7 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev Variant *eventp = &event; Variant ret; Callable::CallError ce; - wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce); } } @@ -4068,7 +4068,7 @@ void DisplayServerX11::process_events() { Variant *vp = &v; Variant ret; Callable::CallError ce; - windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + windows[window_id].drop_files_callback.callp((const Variant **)&vp, 1, ret, ce); } //Reply that all is well. @@ -4991,7 +4991,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode #ifdef DBUS_ENABLED screensaver = memnew(FreeDesktopScreenSaver); - screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true)); + screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); #endif r_error = OK; diff --git a/platform/linuxbsd/export/export.cpp b/platform/linuxbsd/export/export.cpp index 4240e9adc0..990351d13f 100644 --- a/platform/linuxbsd/export/export.cpp +++ b/platform/linuxbsd/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/export/editor_export.h" #include "export_plugin.h" void register_linuxbsd_exporter() { @@ -37,8 +38,6 @@ void register_linuxbsd_exporter() { platform.instantiate(); platform->set_logo(ImageTexture::create_from_image(memnew(Image(_linuxbsd_logo)))); platform->set_name("Linux/X11"); - platform->set_extension("x86_32"); - platform->set_extension("x86_64", "binary_format/64_bits"); platform->set_os_name("Linux"); platform->set_chmod_flags(0755); diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 4e14920e79..4d45d3ba12 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -79,31 +79,21 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> return err; } -void EditorExportPlatformLinuxBSD::set_extension(const String &p_extension, const String &p_feature_key) { - extensions[p_feature_key] = p_extension; -} - String EditorExportPlatformLinuxBSD::get_template_file_name(const String &p_target, const String &p_arch) const { - return "linux_x11_" + p_arch + "_" + p_target; + return "linux_" + p_target + "." + p_arch; } List<String> EditorExportPlatformLinuxBSD::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const { List<String> list; - for (const KeyValue<String, String> &E : extensions) { - if (p_preset->get(E.key)) { - list.push_back(extensions[E.key]); - return list; - } - } - - if (extensions.has("default")) { - list.push_back(extensions["default"]); - return list; - } - + list.push_back(p_preset->get("binary_format/architecture")); return list; } +void EditorExportPlatformLinuxBSD::get_export_options(List<ExportOption> *r_options) { + EditorExportPlatformPC::get_export_options(r_options); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm64,arm32,rv64,ppc64,ppc32"), "x86_64")); +} + Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index e04bcc20f9..4d6737498b 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -32,21 +32,21 @@ #define LINUXBSD_EXPORT_PLUGIN_H #include "core/io/file_access.h" -#include "editor/editor_export.h" #include "editor/editor_settings.h" +#include "editor/export/editor_export_platform_pc.h" #include "platform/linuxbsd/logo.gen.h" #include "scene/resources/texture.h" class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { - HashMap<String, String> extensions; Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); public: void set_extension(const String &p_extension, const String &p_feature_key = "default"); virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; + virtual void get_export_options(List<ExportOption> *r_options) override; virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; }; -#endif +#endif // LINUXBSD_EXPORT_PLUGIN_H diff --git a/platform/linuxbsd/fontconfig-so_wrap.c b/platform/linuxbsd/fontconfig-so_wrap.c new file mode 100644 index 0000000000..1a915faf98 --- /dev/null +++ b/platform/linuxbsd/fontconfig-so_wrap.c @@ -0,0 +1,2091 @@ +// This file is generated. Do not edit! +// see https://github.com/hpvb/dynload-wrapper for details +// generated by ./generate-wrapper.py 0.3 on 2022-07-29 05:40:07 +// flags: ./generate-wrapper.py --include /usr/include/fontconfig/fontconfig.h --sys-include <fontconfig/fontconfig.h> --soname libfontconfig.so --init-name fontconfig --output-header fontconfig-so_wrap.h --output-implementation fontconfig-so_wrap.c --omit-prefix FcCharSet +// +#include <stdint.h> + +#define FcBlanksCreate FcBlanksCreate_dylibloader_orig_fontconfig +#define FcBlanksDestroy FcBlanksDestroy_dylibloader_orig_fontconfig +#define FcBlanksAdd FcBlanksAdd_dylibloader_orig_fontconfig +#define FcBlanksIsMember FcBlanksIsMember_dylibloader_orig_fontconfig +#define FcCacheDir FcCacheDir_dylibloader_orig_fontconfig +#define FcCacheCopySet FcCacheCopySet_dylibloader_orig_fontconfig +#define FcCacheSubdir FcCacheSubdir_dylibloader_orig_fontconfig +#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_orig_fontconfig +#define FcCacheNumFont FcCacheNumFont_dylibloader_orig_fontconfig +#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_orig_fontconfig +#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig +#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig +#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig +#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig +#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig +#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig +#define FcConfigCreate FcConfigCreate_dylibloader_orig_fontconfig +#define FcConfigReference FcConfigReference_dylibloader_orig_fontconfig +#define FcConfigDestroy FcConfigDestroy_dylibloader_orig_fontconfig +#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_orig_fontconfig +#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_orig_fontconfig +#define FcConfigUptoDate FcConfigUptoDate_dylibloader_orig_fontconfig +#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_orig_fontconfig +#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_orig_fontconfig +#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_orig_fontconfig +#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_orig_fontconfig +#define FcConfigGetCache FcConfigGetCache_dylibloader_orig_fontconfig +#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_orig_fontconfig +#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_orig_fontconfig +#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_orig_fontconfig +#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_orig_fontconfig +#define FcConfigGetFonts FcConfigGetFonts_dylibloader_orig_fontconfig +#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_orig_fontconfig +#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_orig_fontconfig +#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_orig_fontconfig +#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_orig_fontconfig +#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig +#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig +#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig +#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig +#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig +#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig +#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_orig_fontconfig +#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_orig_fontconfig +#define FcFileIsDir FcFileIsDir_dylibloader_orig_fontconfig +#define FcFileScan FcFileScan_dylibloader_orig_fontconfig +#define FcDirScan FcDirScan_dylibloader_orig_fontconfig +#define FcDirSave FcDirSave_dylibloader_orig_fontconfig +#define FcDirCacheLoad FcDirCacheLoad_dylibloader_orig_fontconfig +#define FcDirCacheRescan FcDirCacheRescan_dylibloader_orig_fontconfig +#define FcDirCacheRead FcDirCacheRead_dylibloader_orig_fontconfig +#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig +#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig +#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig +#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig +#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig +#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig +#define FcInitLoadConfig FcInitLoadConfig_dylibloader_orig_fontconfig +#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_orig_fontconfig +#define FcInit FcInit_dylibloader_orig_fontconfig +#define FcFini FcFini_dylibloader_orig_fontconfig +#define FcGetVersion FcGetVersion_dylibloader_orig_fontconfig +#define FcInitReinitialize FcInitReinitialize_dylibloader_orig_fontconfig +#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_orig_fontconfig +#define FcGetLangs FcGetLangs_dylibloader_orig_fontconfig +#define FcLangNormalize FcLangNormalize_dylibloader_orig_fontconfig +#define FcLangGetCharSet FcLangGetCharSet_dylibloader_orig_fontconfig +#define FcLangSetCreate FcLangSetCreate_dylibloader_orig_fontconfig +#define FcLangSetDestroy FcLangSetDestroy_dylibloader_orig_fontconfig +#define FcLangSetCopy FcLangSetCopy_dylibloader_orig_fontconfig +#define FcLangSetAdd FcLangSetAdd_dylibloader_orig_fontconfig +#define FcLangSetDel FcLangSetDel_dylibloader_orig_fontconfig +#define FcLangSetHasLang FcLangSetHasLang_dylibloader_orig_fontconfig +#define FcLangSetCompare FcLangSetCompare_dylibloader_orig_fontconfig +#define FcLangSetContains FcLangSetContains_dylibloader_orig_fontconfig +#define FcLangSetEqual FcLangSetEqual_dylibloader_orig_fontconfig +#define FcLangSetHash FcLangSetHash_dylibloader_orig_fontconfig +#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_orig_fontconfig +#define FcLangSetUnion FcLangSetUnion_dylibloader_orig_fontconfig +#define FcLangSetSubtract FcLangSetSubtract_dylibloader_orig_fontconfig +#define FcObjectSetCreate FcObjectSetCreate_dylibloader_orig_fontconfig +#define FcObjectSetAdd FcObjectSetAdd_dylibloader_orig_fontconfig +#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_orig_fontconfig +#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_orig_fontconfig +#define FcObjectSetBuild FcObjectSetBuild_dylibloader_orig_fontconfig +#define FcFontSetList FcFontSetList_dylibloader_orig_fontconfig +#define FcFontList FcFontList_dylibloader_orig_fontconfig +#define FcAtomicCreate FcAtomicCreate_dylibloader_orig_fontconfig +#define FcAtomicLock FcAtomicLock_dylibloader_orig_fontconfig +#define FcAtomicNewFile FcAtomicNewFile_dylibloader_orig_fontconfig +#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_orig_fontconfig +#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_orig_fontconfig +#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_orig_fontconfig +#define FcAtomicUnlock FcAtomicUnlock_dylibloader_orig_fontconfig +#define FcAtomicDestroy FcAtomicDestroy_dylibloader_orig_fontconfig +#define FcFontSetMatch FcFontSetMatch_dylibloader_orig_fontconfig +#define FcFontMatch FcFontMatch_dylibloader_orig_fontconfig +#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_orig_fontconfig +#define FcFontSetSort FcFontSetSort_dylibloader_orig_fontconfig +#define FcFontSort FcFontSort_dylibloader_orig_fontconfig +#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_orig_fontconfig +#define FcMatrixCopy FcMatrixCopy_dylibloader_orig_fontconfig +#define FcMatrixEqual FcMatrixEqual_dylibloader_orig_fontconfig +#define FcMatrixMultiply FcMatrixMultiply_dylibloader_orig_fontconfig +#define FcMatrixRotate FcMatrixRotate_dylibloader_orig_fontconfig +#define FcMatrixScale FcMatrixScale_dylibloader_orig_fontconfig +#define FcMatrixShear FcMatrixShear_dylibloader_orig_fontconfig +#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_orig_fontconfig +#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_orig_fontconfig +#define FcNameGetObjectType FcNameGetObjectType_dylibloader_orig_fontconfig +#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_orig_fontconfig +#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_orig_fontconfig +#define FcNameGetConstant FcNameGetConstant_dylibloader_orig_fontconfig +#define FcNameConstant FcNameConstant_dylibloader_orig_fontconfig +#define FcNameParse FcNameParse_dylibloader_orig_fontconfig +#define FcNameUnparse FcNameUnparse_dylibloader_orig_fontconfig +#define FcPatternCreate FcPatternCreate_dylibloader_orig_fontconfig +#define FcPatternDuplicate FcPatternDuplicate_dylibloader_orig_fontconfig +#define FcPatternReference FcPatternReference_dylibloader_orig_fontconfig +#define FcPatternFilter FcPatternFilter_dylibloader_orig_fontconfig +#define FcValueDestroy FcValueDestroy_dylibloader_orig_fontconfig +#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig +#define FcValueSave FcValueSave_dylibloader_orig_fontconfig +#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig +#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig +#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig +#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig +#define FcPatternAdd FcPatternAdd_dylibloader_orig_fontconfig +#define FcPatternAddWeak FcPatternAddWeak_dylibloader_orig_fontconfig +#define FcPatternGet FcPatternGet_dylibloader_orig_fontconfig +#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_orig_fontconfig +#define FcPatternDel FcPatternDel_dylibloader_orig_fontconfig +#define FcPatternRemove FcPatternRemove_dylibloader_orig_fontconfig +#define FcPatternAddInteger FcPatternAddInteger_dylibloader_orig_fontconfig +#define FcPatternAddDouble FcPatternAddDouble_dylibloader_orig_fontconfig +#define FcPatternAddString FcPatternAddString_dylibloader_orig_fontconfig +#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_orig_fontconfig +#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_orig_fontconfig +#define FcPatternAddBool FcPatternAddBool_dylibloader_orig_fontconfig +#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_orig_fontconfig +#define FcPatternAddRange FcPatternAddRange_dylibloader_orig_fontconfig +#define FcPatternGetInteger FcPatternGetInteger_dylibloader_orig_fontconfig +#define FcPatternGetDouble FcPatternGetDouble_dylibloader_orig_fontconfig +#define FcPatternGetString FcPatternGetString_dylibloader_orig_fontconfig +#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_orig_fontconfig +#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_orig_fontconfig +#define FcPatternGetBool FcPatternGetBool_dylibloader_orig_fontconfig +#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_orig_fontconfig +#define FcPatternGetRange FcPatternGetRange_dylibloader_orig_fontconfig +#define FcPatternVaBuild FcPatternVaBuild_dylibloader_orig_fontconfig +#define FcPatternBuild FcPatternBuild_dylibloader_orig_fontconfig +#define FcPatternFormat FcPatternFormat_dylibloader_orig_fontconfig +#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_orig_fontconfig +#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_orig_fontconfig +#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig +#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig +#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig +#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig +#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig +#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig +#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig +#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig +#define FcStrFree FcStrFree_dylibloader_orig_fontconfig +#define FcStrDowncase FcStrDowncase_dylibloader_orig_fontconfig +#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_orig_fontconfig +#define FcStrCmp FcStrCmp_dylibloader_orig_fontconfig +#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_orig_fontconfig +#define FcStrStr FcStrStr_dylibloader_orig_fontconfig +#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_orig_fontconfig +#define FcUtf8Len FcUtf8Len_dylibloader_orig_fontconfig +#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_orig_fontconfig +#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_orig_fontconfig +#define FcUtf16Len FcUtf16Len_dylibloader_orig_fontconfig +#define FcStrDirname FcStrDirname_dylibloader_orig_fontconfig +#define FcStrBasename FcStrBasename_dylibloader_orig_fontconfig +#define FcStrSetCreate FcStrSetCreate_dylibloader_orig_fontconfig +#define FcStrSetMember FcStrSetMember_dylibloader_orig_fontconfig +#define FcStrSetEqual FcStrSetEqual_dylibloader_orig_fontconfig +#define FcStrSetAdd FcStrSetAdd_dylibloader_orig_fontconfig +#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_orig_fontconfig +#define FcStrSetDel FcStrSetDel_dylibloader_orig_fontconfig +#define FcStrSetDestroy FcStrSetDestroy_dylibloader_orig_fontconfig +#define FcStrListCreate FcStrListCreate_dylibloader_orig_fontconfig +#define FcStrListFirst FcStrListFirst_dylibloader_orig_fontconfig +#define FcStrListNext FcStrListNext_dylibloader_orig_fontconfig +#define FcStrListDone FcStrListDone_dylibloader_orig_fontconfig +#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_orig_fontconfig +#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_orig_fontconfig +#include <fontconfig/fontconfig.h> +#undef FcBlanksCreate +#undef FcBlanksDestroy +#undef FcBlanksAdd +#undef FcBlanksIsMember +#undef FcCacheDir +#undef FcCacheCopySet +#undef FcCacheSubdir +#undef FcCacheNumSubdir +#undef FcCacheNumFont +#undef FcDirCacheUnlink +#undef FcDirCacheValid +#undef FcDirCacheClean +#undef FcCacheCreateTagFile +#undef FcConfigHome +#undef FcConfigEnableHome +#undef FcConfigFilename +#undef FcConfigCreate +#undef FcConfigReference +#undef FcConfigDestroy +#undef FcConfigSetCurrent +#undef FcConfigGetCurrent +#undef FcConfigUptoDate +#undef FcConfigBuildFonts +#undef FcConfigGetFontDirs +#undef FcConfigGetConfigDirs +#undef FcConfigGetConfigFiles +#undef FcConfigGetCache +#undef FcConfigGetBlanks +#undef FcConfigGetCacheDirs +#undef FcConfigGetRescanInterval +#undef FcConfigSetRescanInterval +#undef FcConfigGetFonts +#undef FcConfigAppFontAddFile +#undef FcConfigAppFontAddDir +#undef FcConfigAppFontClear +#undef FcConfigSubstituteWithPat +#undef FcConfigSubstitute +#undef FcConfigGetSysRoot +#undef FcConfigSetSysRoot +#undef FcValuePrint +#undef FcPatternPrint +#undef FcFontSetPrint +#undef FcGetDefaultLangs +#undef FcDefaultSubstitute +#undef FcFileIsDir +#undef FcFileScan +#undef FcDirScan +#undef FcDirSave +#undef FcDirCacheLoad +#undef FcDirCacheRescan +#undef FcDirCacheRead +#undef FcDirCacheLoadFile +#undef FcDirCacheUnload +#undef FcFreeTypeQuery +#undef FcFontSetCreate +#undef FcFontSetDestroy +#undef FcFontSetAdd +#undef FcInitLoadConfig +#undef FcInitLoadConfigAndFonts +#undef FcInit +#undef FcFini +#undef FcGetVersion +#undef FcInitReinitialize +#undef FcInitBringUptoDate +#undef FcGetLangs +#undef FcLangNormalize +#undef FcLangGetCharSet +#undef FcLangSetCreate +#undef FcLangSetDestroy +#undef FcLangSetCopy +#undef FcLangSetAdd +#undef FcLangSetDel +#undef FcLangSetHasLang +#undef FcLangSetCompare +#undef FcLangSetContains +#undef FcLangSetEqual +#undef FcLangSetHash +#undef FcLangSetGetLangs +#undef FcLangSetUnion +#undef FcLangSetSubtract +#undef FcObjectSetCreate +#undef FcObjectSetAdd +#undef FcObjectSetDestroy +#undef FcObjectSetVaBuild +#undef FcObjectSetBuild +#undef FcFontSetList +#undef FcFontList +#undef FcAtomicCreate +#undef FcAtomicLock +#undef FcAtomicNewFile +#undef FcAtomicOrigFile +#undef FcAtomicReplaceOrig +#undef FcAtomicDeleteNew +#undef FcAtomicUnlock +#undef FcAtomicDestroy +#undef FcFontSetMatch +#undef FcFontMatch +#undef FcFontRenderPrepare +#undef FcFontSetSort +#undef FcFontSort +#undef FcFontSetSortDestroy +#undef FcMatrixCopy +#undef FcMatrixEqual +#undef FcMatrixMultiply +#undef FcMatrixRotate +#undef FcMatrixScale +#undef FcMatrixShear +#undef FcNameRegisterObjectTypes +#undef FcNameUnregisterObjectTypes +#undef FcNameGetObjectType +#undef FcNameRegisterConstants +#undef FcNameUnregisterConstants +#undef FcNameGetConstant +#undef FcNameConstant +#undef FcNameParse +#undef FcNameUnparse +#undef FcPatternCreate +#undef FcPatternDuplicate +#undef FcPatternReference +#undef FcPatternFilter +#undef FcValueDestroy +#undef FcValueEqual +#undef FcValueSave +#undef FcPatternDestroy +#undef FcPatternEqual +#undef FcPatternEqualSubset +#undef FcPatternHash +#undef FcPatternAdd +#undef FcPatternAddWeak +#undef FcPatternGet +#undef FcPatternGetWithBinding +#undef FcPatternDel +#undef FcPatternRemove +#undef FcPatternAddInteger +#undef FcPatternAddDouble +#undef FcPatternAddString +#undef FcPatternAddMatrix +#undef FcPatternAddCharSet +#undef FcPatternAddBool +#undef FcPatternAddLangSet +#undef FcPatternAddRange +#undef FcPatternGetInteger +#undef FcPatternGetDouble +#undef FcPatternGetString +#undef FcPatternGetMatrix +#undef FcPatternGetCharSet +#undef FcPatternGetBool +#undef FcPatternGetLangSet +#undef FcPatternGetRange +#undef FcPatternVaBuild +#undef FcPatternBuild +#undef FcPatternFormat +#undef FcRangeCreateDouble +#undef FcRangeCreateInteger +#undef FcRangeDestroy +#undef FcRangeCopy +#undef FcRangeGetDouble +#undef FcWeightFromOpenType +#undef FcWeightToOpenType +#undef FcStrCopy +#undef FcStrCopyFilename +#undef FcStrPlus +#undef FcStrFree +#undef FcStrDowncase +#undef FcStrCmpIgnoreCase +#undef FcStrCmp +#undef FcStrStrIgnoreCase +#undef FcStrStr +#undef FcUtf8ToUcs4 +#undef FcUtf8Len +#undef FcUcs4ToUtf8 +#undef FcUtf16ToUcs4 +#undef FcUtf16Len +#undef FcStrDirname +#undef FcStrBasename +#undef FcStrSetCreate +#undef FcStrSetMember +#undef FcStrSetEqual +#undef FcStrSetAdd +#undef FcStrSetAddFilename +#undef FcStrSetDel +#undef FcStrSetDestroy +#undef FcStrListCreate +#undef FcStrListFirst +#undef FcStrListNext +#undef FcStrListDone +#undef FcConfigParseAndLoad +#undef FcConfigParseAndLoadFromMemory +#include <dlfcn.h> +#include <stdio.h> +FcBlanks* (*FcBlanksCreate_dylibloader_wrapper_fontconfig)( void); +void (*FcBlanksDestroy_dylibloader_wrapper_fontconfig)( FcBlanks*); +FcBool (*FcBlanksAdd_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32); +FcBool (*FcBlanksIsMember_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32); +const FcChar8* (*FcCacheDir_dylibloader_wrapper_fontconfig)(const FcCache*); +FcFontSet* (*FcCacheCopySet_dylibloader_wrapper_fontconfig)(const FcCache*); +const FcChar8* (*FcCacheSubdir_dylibloader_wrapper_fontconfig)(const FcCache*, int); +int (*FcCacheNumSubdir_dylibloader_wrapper_fontconfig)(const FcCache*); +int (*FcCacheNumFont_dylibloader_wrapper_fontconfig)(const FcCache*); +FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*); +FcBool (*FcDirCacheValid_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcBool (*FcDirCacheClean_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool); +void (*FcCacheCreateTagFile_dylibloader_wrapper_fontconfig)(const FcConfig*); +FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool); +FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcConfig* (*FcConfigCreate_dylibloader_wrapper_fontconfig)( void); +FcConfig* (*FcConfigReference_dylibloader_wrapper_fontconfig)( FcConfig*); +void (*FcConfigDestroy_dylibloader_wrapper_fontconfig)( FcConfig*); +FcBool (*FcConfigSetCurrent_dylibloader_wrapper_fontconfig)( FcConfig*); +FcConfig* (*FcConfigGetCurrent_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcConfigUptoDate_dylibloader_wrapper_fontconfig)( FcConfig*); +FcBool (*FcConfigBuildFonts_dylibloader_wrapper_fontconfig)( FcConfig*); +FcStrList* (*FcConfigGetFontDirs_dylibloader_wrapper_fontconfig)( FcConfig*); +FcStrList* (*FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig)( FcConfig*); +FcStrList* (*FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig)( FcConfig*); +FcChar8* (*FcConfigGetCache_dylibloader_wrapper_fontconfig)( FcConfig*); +FcBlanks* (*FcConfigGetBlanks_dylibloader_wrapper_fontconfig)( FcConfig*); +FcStrList* (*FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig)(const FcConfig*); +int (*FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*); +FcBool (*FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*, int); +FcFontSet* (*FcConfigGetFonts_dylibloader_wrapper_fontconfig)( FcConfig*, FcSetName); +FcBool (*FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +FcBool (*FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +void (*FcConfigAppFontClear_dylibloader_wrapper_fontconfig)( FcConfig*); +FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*, FcMatchKind); +FcBool (*FcConfigSubstitute_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcMatchKind); +const FcChar8* (*FcConfigGetSysRoot_dylibloader_wrapper_fontconfig)(const FcConfig*); +void (*FcConfigSetSysRoot_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue); +void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*); +void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*); +FcStrSet* (*FcGetDefaultLangs_dylibloader_wrapper_fontconfig)( void); +void (*FcDefaultSubstitute_dylibloader_wrapper_fontconfig)( FcPattern*); +FcBool (*FcFileIsDir_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcBool (*FcFileScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool); +FcBool (*FcDirScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool); +FcBool (*FcDirSave_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*,const FcChar8*); +FcCache* (*FcDirCacheLoad_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*, FcChar8**); +FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*); +FcCache* (*FcDirCacheRead_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool, FcConfig*); +FcCache* (*FcDirCacheLoadFile_dylibloader_wrapper_fontconfig)(const FcChar8*,struct stat*); +void (*FcDirCacheUnload_dylibloader_wrapper_fontconfig)( FcCache*); +FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, int, FcBlanks*, int*); +FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void); +void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*); +FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*); +FcConfig* (*FcInitLoadConfig_dylibloader_wrapper_fontconfig)( void); +FcConfig* (*FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcInit_dylibloader_wrapper_fontconfig)( void); +void (*FcFini_dylibloader_wrapper_fontconfig)( void); +int (*FcGetVersion_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcInitReinitialize_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcInitBringUptoDate_dylibloader_wrapper_fontconfig)( void); +FcStrSet* (*FcGetLangs_dylibloader_wrapper_fontconfig)( void); +FcChar8* (*FcLangNormalize_dylibloader_wrapper_fontconfig)(const FcChar8*); +const FcCharSet* (*FcLangGetCharSet_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcLangSet* (*FcLangSetCreate_dylibloader_wrapper_fontconfig)( void); +void (*FcLangSetDestroy_dylibloader_wrapper_fontconfig)( FcLangSet*); +FcLangSet* (*FcLangSetCopy_dylibloader_wrapper_fontconfig)(const FcLangSet*); +FcBool (*FcLangSetAdd_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*); +FcBool (*FcLangSetDel_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*); +FcLangResult (*FcLangSetHasLang_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcChar8*); +FcLangResult (*FcLangSetCompare_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +FcBool (*FcLangSetContains_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +FcBool (*FcLangSetEqual_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +FcChar32 (*FcLangSetHash_dylibloader_wrapper_fontconfig)(const FcLangSet*); +FcStrSet* (*FcLangSetGetLangs_dylibloader_wrapper_fontconfig)(const FcLangSet*); +FcLangSet* (*FcLangSetUnion_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +FcLangSet* (*FcLangSetSubtract_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +FcObjectSet* (*FcObjectSetCreate_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcObjectSetAdd_dylibloader_wrapper_fontconfig)( FcObjectSet*,const char*); +void (*FcObjectSetDestroy_dylibloader_wrapper_fontconfig)( FcObjectSet*); +FcObjectSet* (*FcObjectSetVaBuild_dylibloader_wrapper_fontconfig)(const char*, va_list); +FcObjectSet* (*FcObjectSetBuild_dylibloader_wrapper_fontconfig)(const char*,...); +FcFontSet* (*FcFontSetList_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcObjectSet*); +FcFontSet* (*FcFontList_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcObjectSet*); +FcAtomic* (*FcAtomicCreate_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcBool (*FcAtomicLock_dylibloader_wrapper_fontconfig)( FcAtomic*); +FcChar8* (*FcAtomicNewFile_dylibloader_wrapper_fontconfig)( FcAtomic*); +FcChar8* (*FcAtomicOrigFile_dylibloader_wrapper_fontconfig)( FcAtomic*); +FcBool (*FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig)( FcAtomic*); +void (*FcAtomicDeleteNew_dylibloader_wrapper_fontconfig)( FcAtomic*); +void (*FcAtomicUnlock_dylibloader_wrapper_fontconfig)( FcAtomic*); +void (*FcAtomicDestroy_dylibloader_wrapper_fontconfig)( FcAtomic*); +FcPattern* (*FcFontSetMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcResult*); +FcPattern* (*FcFontMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcResult*); +FcPattern* (*FcFontRenderPrepare_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*); +FcFontSet* (*FcFontSetSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcBool, FcCharSet**, FcResult*); +FcFontSet* (*FcFontSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcBool, FcCharSet**, FcResult*); +void (*FcFontSetSortDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*); +FcMatrix* (*FcMatrixCopy_dylibloader_wrapper_fontconfig)(const FcMatrix*); +FcBool (*FcMatrixEqual_dylibloader_wrapper_fontconfig)(const FcMatrix*,const FcMatrix*); +void (*FcMatrixMultiply_dylibloader_wrapper_fontconfig)( FcMatrix*,const FcMatrix*,const FcMatrix*); +void (*FcMatrixRotate_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +void (*FcMatrixScale_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +void (*FcMatrixShear_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +FcBool (*FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int); +FcBool (*FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int); +const FcObjectType* (*FcNameGetObjectType_dylibloader_wrapper_fontconfig)(const char*); +FcBool (*FcNameRegisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int); +FcBool (*FcNameUnregisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int); +const FcConstant* (*FcNameGetConstant_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcBool (*FcNameConstant_dylibloader_wrapper_fontconfig)(const FcChar8*, int*); +FcPattern* (*FcNameParse_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcChar8* (*FcNameUnparse_dylibloader_wrapper_fontconfig)( FcPattern*); +FcPattern* (*FcPatternCreate_dylibloader_wrapper_fontconfig)( void); +FcPattern* (*FcPatternDuplicate_dylibloader_wrapper_fontconfig)(const FcPattern*); +void (*FcPatternReference_dylibloader_wrapper_fontconfig)( FcPattern*); +FcPattern* (*FcPatternFilter_dylibloader_wrapper_fontconfig)( FcPattern*,const FcObjectSet*); +void (*FcValueDestroy_dylibloader_wrapper_fontconfig)( FcValue); +FcBool (*FcValueEqual_dylibloader_wrapper_fontconfig)( FcValue, FcValue); +FcValue (*FcValueSave_dylibloader_wrapper_fontconfig)( FcValue); +void (*FcPatternDestroy_dylibloader_wrapper_fontconfig)( FcPattern*); +FcBool (*FcPatternEqual_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*); +FcBool (*FcPatternEqualSubset_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*,const FcObjectSet*); +FcChar32 (*FcPatternHash_dylibloader_wrapper_fontconfig)(const FcPattern*); +FcBool (*FcPatternAdd_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool); +FcBool (*FcPatternAddWeak_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool); +FcResult (*FcPatternGet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*); +FcResult (*FcPatternGetWithBinding_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*, FcValueBinding*); +FcBool (*FcPatternDel_dylibloader_wrapper_fontconfig)( FcPattern*,const char*); +FcBool (*FcPatternRemove_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int); +FcBool (*FcPatternAddInteger_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int); +FcBool (*FcPatternAddDouble_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, double); +FcBool (*FcPatternAddString_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcChar8*); +FcBool (*FcPatternAddMatrix_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcMatrix*); +FcBool (*FcPatternAddCharSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcCharSet*); +FcBool (*FcPatternAddBool_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcBool); +FcBool (*FcPatternAddLangSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcLangSet*); +FcBool (*FcPatternAddRange_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcRange*); +FcResult (*FcPatternGetInteger_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, int*); +FcResult (*FcPatternGetDouble_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, double*); +FcResult (*FcPatternGetString_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcChar8**); +FcResult (*FcPatternGetMatrix_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcMatrix**); +FcResult (*FcPatternGetCharSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcCharSet**); +FcResult (*FcPatternGetBool_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcBool*); +FcResult (*FcPatternGetLangSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcLangSet**); +FcResult (*FcPatternGetRange_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcRange**); +FcPattern* (*FcPatternVaBuild_dylibloader_wrapper_fontconfig)( FcPattern*, va_list); +FcPattern* (*FcPatternBuild_dylibloader_wrapper_fontconfig)( FcPattern*,...); +FcChar8* (*FcPatternFormat_dylibloader_wrapper_fontconfig)( FcPattern*,const FcChar8*); +FcRange* (*FcRangeCreateDouble_dylibloader_wrapper_fontconfig)( double, double); +FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( FcChar32, FcChar32); +void (*FcRangeDestroy_dylibloader_wrapper_fontconfig)( FcRange*); +FcRange* (*FcRangeCopy_dylibloader_wrapper_fontconfig)(const FcRange*); +FcBool (*FcRangeGetDouble_dylibloader_wrapper_fontconfig)(const FcRange*, double*, double*); +int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int); +int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int); +FcChar8* (*FcStrCopy_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcChar8* (*FcStrCopyFilename_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcChar8* (*FcStrPlus_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +void (*FcStrFree_dylibloader_wrapper_fontconfig)( FcChar8*); +FcChar8* (*FcStrDowncase_dylibloader_wrapper_fontconfig)(const FcChar8*); +int (*FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +int (*FcStrCmp_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +const FcChar8* (*FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +const FcChar8* (*FcStrStr_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +int (*FcUtf8ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcChar32*, int); +FcBool (*FcUtf8Len_dylibloader_wrapper_fontconfig)(const FcChar8*, int, int*, int*); +int (*FcUcs4ToUtf8_dylibloader_wrapper_fontconfig)( FcChar32, FcChar8 [6]); +int (*FcUtf16ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, FcChar32*, int); +FcBool (*FcUtf16Len_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, int, int*, int*); +FcChar8* (*FcStrDirname_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcChar8* (*FcStrBasename_dylibloader_wrapper_fontconfig)(const FcChar8*); +FcStrSet* (*FcStrSetCreate_dylibloader_wrapper_fontconfig)( void); +FcBool (*FcStrSetMember_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +FcBool (*FcStrSetEqual_dylibloader_wrapper_fontconfig)( FcStrSet*, FcStrSet*); +FcBool (*FcStrSetAdd_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +FcBool (*FcStrSetAddFilename_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +FcBool (*FcStrSetDel_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +void (*FcStrSetDestroy_dylibloader_wrapper_fontconfig)( FcStrSet*); +FcStrList* (*FcStrListCreate_dylibloader_wrapper_fontconfig)( FcStrSet*); +void (*FcStrListFirst_dylibloader_wrapper_fontconfig)( FcStrList*); +FcChar8* (*FcStrListNext_dylibloader_wrapper_fontconfig)( FcStrList*); +void (*FcStrListDone_dylibloader_wrapper_fontconfig)( FcStrList*); +FcBool (*FcConfigParseAndLoad_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool); +FcBool (*FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool); +int initialize_fontconfig(int verbose) { + void *handle; + char *error; + handle = dlopen("libfontconfig.so", RTLD_LAZY); + if (!handle) { + if (verbose) { + fprintf(stderr, "%s\n", dlerror()); + } + return(1); + } + dlerror(); +// FcBlanksCreate + *(void **) (&FcBlanksCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcBlanksDestroy + *(void **) (&FcBlanksDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcBlanksAdd + *(void **) (&FcBlanksAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcBlanksIsMember + *(void **) (&FcBlanksIsMember_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksIsMember"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheDir + *(void **) (&FcCacheDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheDir"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheCopySet + *(void **) (&FcCacheCopySet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheCopySet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheSubdir + *(void **) (&FcCacheSubdir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheSubdir"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheNumSubdir + *(void **) (&FcCacheNumSubdir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheNumSubdir"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheNumFont + *(void **) (&FcCacheNumFont_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheNumFont"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheUnlink + *(void **) (&FcDirCacheUnlink_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheUnlink"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheValid + *(void **) (&FcDirCacheValid_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheValid"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheClean + *(void **) (&FcDirCacheClean_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheClean"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcCacheCreateTagFile + *(void **) (&FcCacheCreateTagFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheCreateTagFile"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigHome + *(void **) (&FcConfigHome_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigHome"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigEnableHome + *(void **) (&FcConfigEnableHome_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigEnableHome"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigFilename + *(void **) (&FcConfigFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigFilename"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigCreate + *(void **) (&FcConfigCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigReference + *(void **) (&FcConfigReference_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigReference"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigDestroy + *(void **) (&FcConfigDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigSetCurrent + *(void **) (&FcConfigSetCurrent_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetCurrent"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetCurrent + *(void **) (&FcConfigGetCurrent_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCurrent"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigUptoDate + *(void **) (&FcConfigUptoDate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigUptoDate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigBuildFonts + *(void **) (&FcConfigBuildFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigBuildFonts"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetFontDirs + *(void **) (&FcConfigGetFontDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetFontDirs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetConfigDirs + *(void **) (&FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetConfigDirs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetConfigFiles + *(void **) (&FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetConfigFiles"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetCache + *(void **) (&FcConfigGetCache_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCache"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetBlanks + *(void **) (&FcConfigGetBlanks_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetBlanks"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetCacheDirs + *(void **) (&FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCacheDirs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetRescanInterval + *(void **) (&FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetRescanInterval"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigSetRescanInterval + *(void **) (&FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetRescanInterval"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetFonts + *(void **) (&FcConfigGetFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetFonts"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigAppFontAddFile + *(void **) (&FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontAddFile"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigAppFontAddDir + *(void **) (&FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontAddDir"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigAppFontClear + *(void **) (&FcConfigAppFontClear_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontClear"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigSubstituteWithPat + *(void **) (&FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSubstituteWithPat"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigSubstitute + *(void **) (&FcConfigSubstitute_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSubstitute"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigGetSysRoot + *(void **) (&FcConfigGetSysRoot_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetSysRoot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigSetSysRoot + *(void **) (&FcConfigSetSysRoot_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetSysRoot"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcValuePrint + *(void **) (&FcValuePrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValuePrint"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternPrint + *(void **) (&FcPatternPrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternPrint"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetPrint + *(void **) (&FcFontSetPrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetPrint"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcGetDefaultLangs + *(void **) (&FcGetDefaultLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetDefaultLangs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDefaultSubstitute + *(void **) (&FcDefaultSubstitute_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDefaultSubstitute"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFileIsDir + *(void **) (&FcFileIsDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFileIsDir"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFileScan + *(void **) (&FcFileScan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFileScan"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirScan + *(void **) (&FcDirScan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirScan"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirSave + *(void **) (&FcDirSave_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirSave"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheLoad + *(void **) (&FcDirCacheLoad_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheLoad"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheRescan + *(void **) (&FcDirCacheRescan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheRescan"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheRead + *(void **) (&FcDirCacheRead_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheRead"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheLoadFile + *(void **) (&FcDirCacheLoadFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheLoadFile"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcDirCacheUnload + *(void **) (&FcDirCacheUnload_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheUnload"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFreeTypeQuery + *(void **) (&FcFreeTypeQuery_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFreeTypeQuery"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetCreate + *(void **) (&FcFontSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetDestroy + *(void **) (&FcFontSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetAdd + *(void **) (&FcFontSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcInitLoadConfig + *(void **) (&FcInitLoadConfig_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitLoadConfig"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcInitLoadConfigAndFonts + *(void **) (&FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitLoadConfigAndFonts"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcInit + *(void **) (&FcInit_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInit"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFini + *(void **) (&FcFini_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFini"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcGetVersion + *(void **) (&FcGetVersion_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetVersion"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcInitReinitialize + *(void **) (&FcInitReinitialize_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitReinitialize"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcInitBringUptoDate + *(void **) (&FcInitBringUptoDate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitBringUptoDate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcGetLangs + *(void **) (&FcGetLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetLangs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangNormalize + *(void **) (&FcLangNormalize_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangNormalize"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangGetCharSet + *(void **) (&FcLangGetCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangGetCharSet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetCreate + *(void **) (&FcLangSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetDestroy + *(void **) (&FcLangSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetCopy + *(void **) (&FcLangSetCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCopy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetAdd + *(void **) (&FcLangSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetDel + *(void **) (&FcLangSetDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetDel"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetHasLang + *(void **) (&FcLangSetHasLang_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetHasLang"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetCompare + *(void **) (&FcLangSetCompare_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCompare"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetContains + *(void **) (&FcLangSetContains_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetContains"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetEqual + *(void **) (&FcLangSetEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetEqual"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetHash + *(void **) (&FcLangSetHash_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetHash"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetGetLangs + *(void **) (&FcLangSetGetLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetGetLangs"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetUnion + *(void **) (&FcLangSetUnion_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetUnion"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcLangSetSubtract + *(void **) (&FcLangSetSubtract_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetSubtract"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcObjectSetCreate + *(void **) (&FcObjectSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcObjectSetAdd + *(void **) (&FcObjectSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcObjectSetDestroy + *(void **) (&FcObjectSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcObjectSetVaBuild + *(void **) (&FcObjectSetVaBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetVaBuild"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcObjectSetBuild + *(void **) (&FcObjectSetBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetBuild"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetList + *(void **) (&FcFontSetList_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetList"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontList + *(void **) (&FcFontList_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontList"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicCreate + *(void **) (&FcAtomicCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicLock + *(void **) (&FcAtomicLock_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicLock"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicNewFile + *(void **) (&FcAtomicNewFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicNewFile"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicOrigFile + *(void **) (&FcAtomicOrigFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicOrigFile"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicReplaceOrig + *(void **) (&FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicReplaceOrig"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicDeleteNew + *(void **) (&FcAtomicDeleteNew_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicDeleteNew"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicUnlock + *(void **) (&FcAtomicUnlock_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicUnlock"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcAtomicDestroy + *(void **) (&FcAtomicDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetMatch + *(void **) (&FcFontSetMatch_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetMatch"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontMatch + *(void **) (&FcFontMatch_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontMatch"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontRenderPrepare + *(void **) (&FcFontRenderPrepare_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontRenderPrepare"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetSort + *(void **) (&FcFontSetSort_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetSort"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSort + *(void **) (&FcFontSort_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSort"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcFontSetSortDestroy + *(void **) (&FcFontSetSortDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetSortDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixCopy + *(void **) (&FcMatrixCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixCopy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixEqual + *(void **) (&FcMatrixEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixEqual"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixMultiply + *(void **) (&FcMatrixMultiply_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixMultiply"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixRotate + *(void **) (&FcMatrixRotate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixRotate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixScale + *(void **) (&FcMatrixScale_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixScale"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcMatrixShear + *(void **) (&FcMatrixShear_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixShear"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameRegisterObjectTypes + *(void **) (&FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameRegisterObjectTypes"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameUnregisterObjectTypes + *(void **) (&FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnregisterObjectTypes"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameGetObjectType + *(void **) (&FcNameGetObjectType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameGetObjectType"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameRegisterConstants + *(void **) (&FcNameRegisterConstants_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameRegisterConstants"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameUnregisterConstants + *(void **) (&FcNameUnregisterConstants_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnregisterConstants"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameGetConstant + *(void **) (&FcNameGetConstant_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameGetConstant"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameConstant + *(void **) (&FcNameConstant_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameConstant"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameParse + *(void **) (&FcNameParse_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameParse"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcNameUnparse + *(void **) (&FcNameUnparse_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnparse"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternCreate + *(void **) (&FcPatternCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternDuplicate + *(void **) (&FcPatternDuplicate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDuplicate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternReference + *(void **) (&FcPatternReference_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternReference"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternFilter + *(void **) (&FcPatternFilter_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternFilter"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcValueDestroy + *(void **) (&FcValueDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcValueEqual + *(void **) (&FcValueEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueEqual"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcValueSave + *(void **) (&FcValueSave_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueSave"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternDestroy + *(void **) (&FcPatternDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternEqual + *(void **) (&FcPatternEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternEqual"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternEqualSubset + *(void **) (&FcPatternEqualSubset_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternEqualSubset"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternHash + *(void **) (&FcPatternHash_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternHash"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAdd + *(void **) (&FcPatternAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddWeak + *(void **) (&FcPatternAddWeak_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddWeak"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGet + *(void **) (&FcPatternGet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetWithBinding + *(void **) (&FcPatternGetWithBinding_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetWithBinding"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternDel + *(void **) (&FcPatternDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDel"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternRemove + *(void **) (&FcPatternRemove_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternRemove"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddInteger + *(void **) (&FcPatternAddInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddInteger"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddDouble + *(void **) (&FcPatternAddDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddDouble"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddString + *(void **) (&FcPatternAddString_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddString"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddMatrix + *(void **) (&FcPatternAddMatrix_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddMatrix"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddCharSet + *(void **) (&FcPatternAddCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddCharSet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddBool + *(void **) (&FcPatternAddBool_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddBool"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddLangSet + *(void **) (&FcPatternAddLangSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddLangSet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternAddRange + *(void **) (&FcPatternAddRange_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddRange"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetInteger + *(void **) (&FcPatternGetInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetInteger"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetDouble + *(void **) (&FcPatternGetDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetDouble"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetString + *(void **) (&FcPatternGetString_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetString"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetMatrix + *(void **) (&FcPatternGetMatrix_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetMatrix"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetCharSet + *(void **) (&FcPatternGetCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetCharSet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetBool + *(void **) (&FcPatternGetBool_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetBool"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetLangSet + *(void **) (&FcPatternGetLangSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetLangSet"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternGetRange + *(void **) (&FcPatternGetRange_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetRange"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternVaBuild + *(void **) (&FcPatternVaBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternVaBuild"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternBuild + *(void **) (&FcPatternBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternBuild"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcPatternFormat + *(void **) (&FcPatternFormat_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternFormat"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcRangeCreateDouble + *(void **) (&FcRangeCreateDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCreateDouble"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcRangeCreateInteger + *(void **) (&FcRangeCreateInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCreateInteger"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcRangeDestroy + *(void **) (&FcRangeDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcRangeCopy + *(void **) (&FcRangeCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCopy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcRangeGetDouble + *(void **) (&FcRangeGetDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeGetDouble"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcWeightFromOpenType + *(void **) (&FcWeightFromOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightFromOpenType"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcWeightToOpenType + *(void **) (&FcWeightToOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightToOpenType"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrCopy + *(void **) (&FcStrCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCopy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrCopyFilename + *(void **) (&FcStrCopyFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCopyFilename"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrPlus + *(void **) (&FcStrPlus_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrPlus"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrFree + *(void **) (&FcStrFree_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrFree"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrDowncase + *(void **) (&FcStrDowncase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrDowncase"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrCmpIgnoreCase + *(void **) (&FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCmpIgnoreCase"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrCmp + *(void **) (&FcStrCmp_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCmp"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrStrIgnoreCase + *(void **) (&FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrStrIgnoreCase"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrStr + *(void **) (&FcStrStr_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrStr"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcUtf8ToUcs4 + *(void **) (&FcUtf8ToUcs4_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf8ToUcs4"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcUtf8Len + *(void **) (&FcUtf8Len_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf8Len"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcUcs4ToUtf8 + *(void **) (&FcUcs4ToUtf8_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUcs4ToUtf8"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcUtf16ToUcs4 + *(void **) (&FcUtf16ToUcs4_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf16ToUcs4"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcUtf16Len + *(void **) (&FcUtf16Len_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf16Len"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrDirname + *(void **) (&FcStrDirname_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrDirname"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrBasename + *(void **) (&FcStrBasename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrBasename"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetCreate + *(void **) (&FcStrSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetMember + *(void **) (&FcStrSetMember_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetMember"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetEqual + *(void **) (&FcStrSetEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetEqual"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetAdd + *(void **) (&FcStrSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetAdd"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetAddFilename + *(void **) (&FcStrSetAddFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetAddFilename"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetDel + *(void **) (&FcStrSetDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetDel"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrSetDestroy + *(void **) (&FcStrSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetDestroy"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrListCreate + *(void **) (&FcStrListCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListCreate"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrListFirst + *(void **) (&FcStrListFirst_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListFirst"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrListNext + *(void **) (&FcStrListNext_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListNext"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcStrListDone + *(void **) (&FcStrListDone_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListDone"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigParseAndLoad + *(void **) (&FcConfigParseAndLoad_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigParseAndLoad"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +// FcConfigParseAndLoadFromMemory + *(void **) (&FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigParseAndLoadFromMemory"); + if (verbose) { + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "%s\n", error); + } + } +return 0; +} diff --git a/platform/linuxbsd/fontconfig-so_wrap.h b/platform/linuxbsd/fontconfig-so_wrap.h new file mode 100644 index 0000000000..f0794cce8b --- /dev/null +++ b/platform/linuxbsd/fontconfig-so_wrap.h @@ -0,0 +1,770 @@ +#ifndef DYLIBLOAD_WRAPPER_FONTCONFIG +#define DYLIBLOAD_WRAPPER_FONTCONFIG +// This file is generated. Do not edit! +// see https://github.com/hpvb/dynload-wrapper for details +// generated by ./generate-wrapper.py 0.3 on 2022-07-29 05:40:07 +// flags: ./generate-wrapper.py --include /usr/include/fontconfig/fontconfig.h --sys-include <fontconfig/fontconfig.h> --soname libfontconfig.so --init-name fontconfig --output-header fontconfig-so_wrap.h --output-implementation fontconfig-so_wrap.c --omit-prefix FcCharSet +// +#include <stdint.h> + +#define FcBlanksCreate FcBlanksCreate_dylibloader_orig_fontconfig +#define FcBlanksDestroy FcBlanksDestroy_dylibloader_orig_fontconfig +#define FcBlanksAdd FcBlanksAdd_dylibloader_orig_fontconfig +#define FcBlanksIsMember FcBlanksIsMember_dylibloader_orig_fontconfig +#define FcCacheDir FcCacheDir_dylibloader_orig_fontconfig +#define FcCacheCopySet FcCacheCopySet_dylibloader_orig_fontconfig +#define FcCacheSubdir FcCacheSubdir_dylibloader_orig_fontconfig +#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_orig_fontconfig +#define FcCacheNumFont FcCacheNumFont_dylibloader_orig_fontconfig +#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_orig_fontconfig +#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig +#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig +#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig +#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig +#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig +#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig +#define FcConfigCreate FcConfigCreate_dylibloader_orig_fontconfig +#define FcConfigReference FcConfigReference_dylibloader_orig_fontconfig +#define FcConfigDestroy FcConfigDestroy_dylibloader_orig_fontconfig +#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_orig_fontconfig +#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_orig_fontconfig +#define FcConfigUptoDate FcConfigUptoDate_dylibloader_orig_fontconfig +#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_orig_fontconfig +#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_orig_fontconfig +#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_orig_fontconfig +#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_orig_fontconfig +#define FcConfigGetCache FcConfigGetCache_dylibloader_orig_fontconfig +#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_orig_fontconfig +#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_orig_fontconfig +#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_orig_fontconfig +#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_orig_fontconfig +#define FcConfigGetFonts FcConfigGetFonts_dylibloader_orig_fontconfig +#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_orig_fontconfig +#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_orig_fontconfig +#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_orig_fontconfig +#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_orig_fontconfig +#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig +#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig +#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig +#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig +#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig +#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig +#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_orig_fontconfig +#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_orig_fontconfig +#define FcFileIsDir FcFileIsDir_dylibloader_orig_fontconfig +#define FcFileScan FcFileScan_dylibloader_orig_fontconfig +#define FcDirScan FcDirScan_dylibloader_orig_fontconfig +#define FcDirSave FcDirSave_dylibloader_orig_fontconfig +#define FcDirCacheLoad FcDirCacheLoad_dylibloader_orig_fontconfig +#define FcDirCacheRescan FcDirCacheRescan_dylibloader_orig_fontconfig +#define FcDirCacheRead FcDirCacheRead_dylibloader_orig_fontconfig +#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig +#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig +#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig +#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig +#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig +#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig +#define FcInitLoadConfig FcInitLoadConfig_dylibloader_orig_fontconfig +#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_orig_fontconfig +#define FcInit FcInit_dylibloader_orig_fontconfig +#define FcFini FcFini_dylibloader_orig_fontconfig +#define FcGetVersion FcGetVersion_dylibloader_orig_fontconfig +#define FcInitReinitialize FcInitReinitialize_dylibloader_orig_fontconfig +#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_orig_fontconfig +#define FcGetLangs FcGetLangs_dylibloader_orig_fontconfig +#define FcLangNormalize FcLangNormalize_dylibloader_orig_fontconfig +#define FcLangGetCharSet FcLangGetCharSet_dylibloader_orig_fontconfig +#define FcLangSetCreate FcLangSetCreate_dylibloader_orig_fontconfig +#define FcLangSetDestroy FcLangSetDestroy_dylibloader_orig_fontconfig +#define FcLangSetCopy FcLangSetCopy_dylibloader_orig_fontconfig +#define FcLangSetAdd FcLangSetAdd_dylibloader_orig_fontconfig +#define FcLangSetDel FcLangSetDel_dylibloader_orig_fontconfig +#define FcLangSetHasLang FcLangSetHasLang_dylibloader_orig_fontconfig +#define FcLangSetCompare FcLangSetCompare_dylibloader_orig_fontconfig +#define FcLangSetContains FcLangSetContains_dylibloader_orig_fontconfig +#define FcLangSetEqual FcLangSetEqual_dylibloader_orig_fontconfig +#define FcLangSetHash FcLangSetHash_dylibloader_orig_fontconfig +#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_orig_fontconfig +#define FcLangSetUnion FcLangSetUnion_dylibloader_orig_fontconfig +#define FcLangSetSubtract FcLangSetSubtract_dylibloader_orig_fontconfig +#define FcObjectSetCreate FcObjectSetCreate_dylibloader_orig_fontconfig +#define FcObjectSetAdd FcObjectSetAdd_dylibloader_orig_fontconfig +#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_orig_fontconfig +#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_orig_fontconfig +#define FcObjectSetBuild FcObjectSetBuild_dylibloader_orig_fontconfig +#define FcFontSetList FcFontSetList_dylibloader_orig_fontconfig +#define FcFontList FcFontList_dylibloader_orig_fontconfig +#define FcAtomicCreate FcAtomicCreate_dylibloader_orig_fontconfig +#define FcAtomicLock FcAtomicLock_dylibloader_orig_fontconfig +#define FcAtomicNewFile FcAtomicNewFile_dylibloader_orig_fontconfig +#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_orig_fontconfig +#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_orig_fontconfig +#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_orig_fontconfig +#define FcAtomicUnlock FcAtomicUnlock_dylibloader_orig_fontconfig +#define FcAtomicDestroy FcAtomicDestroy_dylibloader_orig_fontconfig +#define FcFontSetMatch FcFontSetMatch_dylibloader_orig_fontconfig +#define FcFontMatch FcFontMatch_dylibloader_orig_fontconfig +#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_orig_fontconfig +#define FcFontSetSort FcFontSetSort_dylibloader_orig_fontconfig +#define FcFontSort FcFontSort_dylibloader_orig_fontconfig +#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_orig_fontconfig +#define FcMatrixCopy FcMatrixCopy_dylibloader_orig_fontconfig +#define FcMatrixEqual FcMatrixEqual_dylibloader_orig_fontconfig +#define FcMatrixMultiply FcMatrixMultiply_dylibloader_orig_fontconfig +#define FcMatrixRotate FcMatrixRotate_dylibloader_orig_fontconfig +#define FcMatrixScale FcMatrixScale_dylibloader_orig_fontconfig +#define FcMatrixShear FcMatrixShear_dylibloader_orig_fontconfig +#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_orig_fontconfig +#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_orig_fontconfig +#define FcNameGetObjectType FcNameGetObjectType_dylibloader_orig_fontconfig +#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_orig_fontconfig +#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_orig_fontconfig +#define FcNameGetConstant FcNameGetConstant_dylibloader_orig_fontconfig +#define FcNameConstant FcNameConstant_dylibloader_orig_fontconfig +#define FcNameParse FcNameParse_dylibloader_orig_fontconfig +#define FcNameUnparse FcNameUnparse_dylibloader_orig_fontconfig +#define FcPatternCreate FcPatternCreate_dylibloader_orig_fontconfig +#define FcPatternDuplicate FcPatternDuplicate_dylibloader_orig_fontconfig +#define FcPatternReference FcPatternReference_dylibloader_orig_fontconfig +#define FcPatternFilter FcPatternFilter_dylibloader_orig_fontconfig +#define FcValueDestroy FcValueDestroy_dylibloader_orig_fontconfig +#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig +#define FcValueSave FcValueSave_dylibloader_orig_fontconfig +#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig +#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig +#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig +#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig +#define FcPatternAdd FcPatternAdd_dylibloader_orig_fontconfig +#define FcPatternAddWeak FcPatternAddWeak_dylibloader_orig_fontconfig +#define FcPatternGet FcPatternGet_dylibloader_orig_fontconfig +#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_orig_fontconfig +#define FcPatternDel FcPatternDel_dylibloader_orig_fontconfig +#define FcPatternRemove FcPatternRemove_dylibloader_orig_fontconfig +#define FcPatternAddInteger FcPatternAddInteger_dylibloader_orig_fontconfig +#define FcPatternAddDouble FcPatternAddDouble_dylibloader_orig_fontconfig +#define FcPatternAddString FcPatternAddString_dylibloader_orig_fontconfig +#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_orig_fontconfig +#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_orig_fontconfig +#define FcPatternAddBool FcPatternAddBool_dylibloader_orig_fontconfig +#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_orig_fontconfig +#define FcPatternAddRange FcPatternAddRange_dylibloader_orig_fontconfig +#define FcPatternGetInteger FcPatternGetInteger_dylibloader_orig_fontconfig +#define FcPatternGetDouble FcPatternGetDouble_dylibloader_orig_fontconfig +#define FcPatternGetString FcPatternGetString_dylibloader_orig_fontconfig +#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_orig_fontconfig +#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_orig_fontconfig +#define FcPatternGetBool FcPatternGetBool_dylibloader_orig_fontconfig +#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_orig_fontconfig +#define FcPatternGetRange FcPatternGetRange_dylibloader_orig_fontconfig +#define FcPatternVaBuild FcPatternVaBuild_dylibloader_orig_fontconfig +#define FcPatternBuild FcPatternBuild_dylibloader_orig_fontconfig +#define FcPatternFormat FcPatternFormat_dylibloader_orig_fontconfig +#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_orig_fontconfig +#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_orig_fontconfig +#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig +#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig +#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig +#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig +#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig +#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig +#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig +#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig +#define FcStrFree FcStrFree_dylibloader_orig_fontconfig +#define FcStrDowncase FcStrDowncase_dylibloader_orig_fontconfig +#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_orig_fontconfig +#define FcStrCmp FcStrCmp_dylibloader_orig_fontconfig +#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_orig_fontconfig +#define FcStrStr FcStrStr_dylibloader_orig_fontconfig +#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_orig_fontconfig +#define FcUtf8Len FcUtf8Len_dylibloader_orig_fontconfig +#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_orig_fontconfig +#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_orig_fontconfig +#define FcUtf16Len FcUtf16Len_dylibloader_orig_fontconfig +#define FcStrDirname FcStrDirname_dylibloader_orig_fontconfig +#define FcStrBasename FcStrBasename_dylibloader_orig_fontconfig +#define FcStrSetCreate FcStrSetCreate_dylibloader_orig_fontconfig +#define FcStrSetMember FcStrSetMember_dylibloader_orig_fontconfig +#define FcStrSetEqual FcStrSetEqual_dylibloader_orig_fontconfig +#define FcStrSetAdd FcStrSetAdd_dylibloader_orig_fontconfig +#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_orig_fontconfig +#define FcStrSetDel FcStrSetDel_dylibloader_orig_fontconfig +#define FcStrSetDestroy FcStrSetDestroy_dylibloader_orig_fontconfig +#define FcStrListCreate FcStrListCreate_dylibloader_orig_fontconfig +#define FcStrListFirst FcStrListFirst_dylibloader_orig_fontconfig +#define FcStrListNext FcStrListNext_dylibloader_orig_fontconfig +#define FcStrListDone FcStrListDone_dylibloader_orig_fontconfig +#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_orig_fontconfig +#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_orig_fontconfig +#include <fontconfig/fontconfig.h> +#undef FcBlanksCreate +#undef FcBlanksDestroy +#undef FcBlanksAdd +#undef FcBlanksIsMember +#undef FcCacheDir +#undef FcCacheCopySet +#undef FcCacheSubdir +#undef FcCacheNumSubdir +#undef FcCacheNumFont +#undef FcDirCacheUnlink +#undef FcDirCacheValid +#undef FcDirCacheClean +#undef FcCacheCreateTagFile +#undef FcConfigHome +#undef FcConfigEnableHome +#undef FcConfigFilename +#undef FcConfigCreate +#undef FcConfigReference +#undef FcConfigDestroy +#undef FcConfigSetCurrent +#undef FcConfigGetCurrent +#undef FcConfigUptoDate +#undef FcConfigBuildFonts +#undef FcConfigGetFontDirs +#undef FcConfigGetConfigDirs +#undef FcConfigGetConfigFiles +#undef FcConfigGetCache +#undef FcConfigGetBlanks +#undef FcConfigGetCacheDirs +#undef FcConfigGetRescanInterval +#undef FcConfigSetRescanInterval +#undef FcConfigGetFonts +#undef FcConfigAppFontAddFile +#undef FcConfigAppFontAddDir +#undef FcConfigAppFontClear +#undef FcConfigSubstituteWithPat +#undef FcConfigSubstitute +#undef FcConfigGetSysRoot +#undef FcConfigSetSysRoot +#undef FcValuePrint +#undef FcPatternPrint +#undef FcFontSetPrint +#undef FcGetDefaultLangs +#undef FcDefaultSubstitute +#undef FcFileIsDir +#undef FcFileScan +#undef FcDirScan +#undef FcDirSave +#undef FcDirCacheLoad +#undef FcDirCacheRescan +#undef FcDirCacheRead +#undef FcDirCacheLoadFile +#undef FcDirCacheUnload +#undef FcFreeTypeQuery +#undef FcFontSetCreate +#undef FcFontSetDestroy +#undef FcFontSetAdd +#undef FcInitLoadConfig +#undef FcInitLoadConfigAndFonts +#undef FcInit +#undef FcFini +#undef FcGetVersion +#undef FcInitReinitialize +#undef FcInitBringUptoDate +#undef FcGetLangs +#undef FcLangNormalize +#undef FcLangGetCharSet +#undef FcLangSetCreate +#undef FcLangSetDestroy +#undef FcLangSetCopy +#undef FcLangSetAdd +#undef FcLangSetDel +#undef FcLangSetHasLang +#undef FcLangSetCompare +#undef FcLangSetContains +#undef FcLangSetEqual +#undef FcLangSetHash +#undef FcLangSetGetLangs +#undef FcLangSetUnion +#undef FcLangSetSubtract +#undef FcObjectSetCreate +#undef FcObjectSetAdd +#undef FcObjectSetDestroy +#undef FcObjectSetVaBuild +#undef FcObjectSetBuild +#undef FcFontSetList +#undef FcFontList +#undef FcAtomicCreate +#undef FcAtomicLock +#undef FcAtomicNewFile +#undef FcAtomicOrigFile +#undef FcAtomicReplaceOrig +#undef FcAtomicDeleteNew +#undef FcAtomicUnlock +#undef FcAtomicDestroy +#undef FcFontSetMatch +#undef FcFontMatch +#undef FcFontRenderPrepare +#undef FcFontSetSort +#undef FcFontSort +#undef FcFontSetSortDestroy +#undef FcMatrixCopy +#undef FcMatrixEqual +#undef FcMatrixMultiply +#undef FcMatrixRotate +#undef FcMatrixScale +#undef FcMatrixShear +#undef FcNameRegisterObjectTypes +#undef FcNameUnregisterObjectTypes +#undef FcNameGetObjectType +#undef FcNameRegisterConstants +#undef FcNameUnregisterConstants +#undef FcNameGetConstant +#undef FcNameConstant +#undef FcNameParse +#undef FcNameUnparse +#undef FcPatternCreate +#undef FcPatternDuplicate +#undef FcPatternReference +#undef FcPatternFilter +#undef FcValueDestroy +#undef FcValueEqual +#undef FcValueSave +#undef FcPatternDestroy +#undef FcPatternEqual +#undef FcPatternEqualSubset +#undef FcPatternHash +#undef FcPatternAdd +#undef FcPatternAddWeak +#undef FcPatternGet +#undef FcPatternGetWithBinding +#undef FcPatternDel +#undef FcPatternRemove +#undef FcPatternAddInteger +#undef FcPatternAddDouble +#undef FcPatternAddString +#undef FcPatternAddMatrix +#undef FcPatternAddCharSet +#undef FcPatternAddBool +#undef FcPatternAddLangSet +#undef FcPatternAddRange +#undef FcPatternGetInteger +#undef FcPatternGetDouble +#undef FcPatternGetString +#undef FcPatternGetMatrix +#undef FcPatternGetCharSet +#undef FcPatternGetBool +#undef FcPatternGetLangSet +#undef FcPatternGetRange +#undef FcPatternVaBuild +#undef FcPatternBuild +#undef FcPatternFormat +#undef FcRangeCreateDouble +#undef FcRangeCreateInteger +#undef FcRangeDestroy +#undef FcRangeCopy +#undef FcRangeGetDouble +#undef FcWeightFromOpenType +#undef FcWeightToOpenType +#undef FcStrCopy +#undef FcStrCopyFilename +#undef FcStrPlus +#undef FcStrFree +#undef FcStrDowncase +#undef FcStrCmpIgnoreCase +#undef FcStrCmp +#undef FcStrStrIgnoreCase +#undef FcStrStr +#undef FcUtf8ToUcs4 +#undef FcUtf8Len +#undef FcUcs4ToUtf8 +#undef FcUtf16ToUcs4 +#undef FcUtf16Len +#undef FcStrDirname +#undef FcStrBasename +#undef FcStrSetCreate +#undef FcStrSetMember +#undef FcStrSetEqual +#undef FcStrSetAdd +#undef FcStrSetAddFilename +#undef FcStrSetDel +#undef FcStrSetDestroy +#undef FcStrListCreate +#undef FcStrListFirst +#undef FcStrListNext +#undef FcStrListDone +#undef FcConfigParseAndLoad +#undef FcConfigParseAndLoadFromMemory +#ifdef __cplusplus +extern "C" { +#endif +#define FcBlanksCreate FcBlanksCreate_dylibloader_wrapper_fontconfig +#define FcBlanksDestroy FcBlanksDestroy_dylibloader_wrapper_fontconfig +#define FcBlanksAdd FcBlanksAdd_dylibloader_wrapper_fontconfig +#define FcBlanksIsMember FcBlanksIsMember_dylibloader_wrapper_fontconfig +#define FcCacheDir FcCacheDir_dylibloader_wrapper_fontconfig +#define FcCacheCopySet FcCacheCopySet_dylibloader_wrapper_fontconfig +#define FcCacheSubdir FcCacheSubdir_dylibloader_wrapper_fontconfig +#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_wrapper_fontconfig +#define FcCacheNumFont FcCacheNumFont_dylibloader_wrapper_fontconfig +#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_wrapper_fontconfig +#define FcDirCacheValid FcDirCacheValid_dylibloader_wrapper_fontconfig +#define FcDirCacheClean FcDirCacheClean_dylibloader_wrapper_fontconfig +#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_wrapper_fontconfig +#define FcConfigHome FcConfigHome_dylibloader_wrapper_fontconfig +#define FcConfigEnableHome FcConfigEnableHome_dylibloader_wrapper_fontconfig +#define FcConfigFilename FcConfigFilename_dylibloader_wrapper_fontconfig +#define FcConfigCreate FcConfigCreate_dylibloader_wrapper_fontconfig +#define FcConfigReference FcConfigReference_dylibloader_wrapper_fontconfig +#define FcConfigDestroy FcConfigDestroy_dylibloader_wrapper_fontconfig +#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_wrapper_fontconfig +#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_wrapper_fontconfig +#define FcConfigUptoDate FcConfigUptoDate_dylibloader_wrapper_fontconfig +#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_wrapper_fontconfig +#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_wrapper_fontconfig +#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig +#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig +#define FcConfigGetCache FcConfigGetCache_dylibloader_wrapper_fontconfig +#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_wrapper_fontconfig +#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig +#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig +#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig +#define FcConfigGetFonts FcConfigGetFonts_dylibloader_wrapper_fontconfig +#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig +#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig +#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_wrapper_fontconfig +#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig +#define FcConfigSubstitute FcConfigSubstitute_dylibloader_wrapper_fontconfig +#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_wrapper_fontconfig +#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_wrapper_fontconfig +#define FcValuePrint FcValuePrint_dylibloader_wrapper_fontconfig +#define FcPatternPrint FcPatternPrint_dylibloader_wrapper_fontconfig +#define FcFontSetPrint FcFontSetPrint_dylibloader_wrapper_fontconfig +#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_wrapper_fontconfig +#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_wrapper_fontconfig +#define FcFileIsDir FcFileIsDir_dylibloader_wrapper_fontconfig +#define FcFileScan FcFileScan_dylibloader_wrapper_fontconfig +#define FcDirScan FcDirScan_dylibloader_wrapper_fontconfig +#define FcDirSave FcDirSave_dylibloader_wrapper_fontconfig +#define FcDirCacheLoad FcDirCacheLoad_dylibloader_wrapper_fontconfig +#define FcDirCacheRescan FcDirCacheRescan_dylibloader_wrapper_fontconfig +#define FcDirCacheRead FcDirCacheRead_dylibloader_wrapper_fontconfig +#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_wrapper_fontconfig +#define FcDirCacheUnload FcDirCacheUnload_dylibloader_wrapper_fontconfig +#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_wrapper_fontconfig +#define FcFontSetCreate FcFontSetCreate_dylibloader_wrapper_fontconfig +#define FcFontSetDestroy FcFontSetDestroy_dylibloader_wrapper_fontconfig +#define FcFontSetAdd FcFontSetAdd_dylibloader_wrapper_fontconfig +#define FcInitLoadConfig FcInitLoadConfig_dylibloader_wrapper_fontconfig +#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig +#define FcInit FcInit_dylibloader_wrapper_fontconfig +#define FcFini FcFini_dylibloader_wrapper_fontconfig +#define FcGetVersion FcGetVersion_dylibloader_wrapper_fontconfig +#define FcInitReinitialize FcInitReinitialize_dylibloader_wrapper_fontconfig +#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_wrapper_fontconfig +#define FcGetLangs FcGetLangs_dylibloader_wrapper_fontconfig +#define FcLangNormalize FcLangNormalize_dylibloader_wrapper_fontconfig +#define FcLangGetCharSet FcLangGetCharSet_dylibloader_wrapper_fontconfig +#define FcLangSetCreate FcLangSetCreate_dylibloader_wrapper_fontconfig +#define FcLangSetDestroy FcLangSetDestroy_dylibloader_wrapper_fontconfig +#define FcLangSetCopy FcLangSetCopy_dylibloader_wrapper_fontconfig +#define FcLangSetAdd FcLangSetAdd_dylibloader_wrapper_fontconfig +#define FcLangSetDel FcLangSetDel_dylibloader_wrapper_fontconfig +#define FcLangSetHasLang FcLangSetHasLang_dylibloader_wrapper_fontconfig +#define FcLangSetCompare FcLangSetCompare_dylibloader_wrapper_fontconfig +#define FcLangSetContains FcLangSetContains_dylibloader_wrapper_fontconfig +#define FcLangSetEqual FcLangSetEqual_dylibloader_wrapper_fontconfig +#define FcLangSetHash FcLangSetHash_dylibloader_wrapper_fontconfig +#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_wrapper_fontconfig +#define FcLangSetUnion FcLangSetUnion_dylibloader_wrapper_fontconfig +#define FcLangSetSubtract FcLangSetSubtract_dylibloader_wrapper_fontconfig +#define FcObjectSetCreate FcObjectSetCreate_dylibloader_wrapper_fontconfig +#define FcObjectSetAdd FcObjectSetAdd_dylibloader_wrapper_fontconfig +#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_wrapper_fontconfig +#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_wrapper_fontconfig +#define FcObjectSetBuild FcObjectSetBuild_dylibloader_wrapper_fontconfig +#define FcFontSetList FcFontSetList_dylibloader_wrapper_fontconfig +#define FcFontList FcFontList_dylibloader_wrapper_fontconfig +#define FcAtomicCreate FcAtomicCreate_dylibloader_wrapper_fontconfig +#define FcAtomicLock FcAtomicLock_dylibloader_wrapper_fontconfig +#define FcAtomicNewFile FcAtomicNewFile_dylibloader_wrapper_fontconfig +#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_wrapper_fontconfig +#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig +#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_wrapper_fontconfig +#define FcAtomicUnlock FcAtomicUnlock_dylibloader_wrapper_fontconfig +#define FcAtomicDestroy FcAtomicDestroy_dylibloader_wrapper_fontconfig +#define FcFontSetMatch FcFontSetMatch_dylibloader_wrapper_fontconfig +#define FcFontMatch FcFontMatch_dylibloader_wrapper_fontconfig +#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_wrapper_fontconfig +#define FcFontSetSort FcFontSetSort_dylibloader_wrapper_fontconfig +#define FcFontSort FcFontSort_dylibloader_wrapper_fontconfig +#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_wrapper_fontconfig +#define FcMatrixCopy FcMatrixCopy_dylibloader_wrapper_fontconfig +#define FcMatrixEqual FcMatrixEqual_dylibloader_wrapper_fontconfig +#define FcMatrixMultiply FcMatrixMultiply_dylibloader_wrapper_fontconfig +#define FcMatrixRotate FcMatrixRotate_dylibloader_wrapper_fontconfig +#define FcMatrixScale FcMatrixScale_dylibloader_wrapper_fontconfig +#define FcMatrixShear FcMatrixShear_dylibloader_wrapper_fontconfig +#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig +#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig +#define FcNameGetObjectType FcNameGetObjectType_dylibloader_wrapper_fontconfig +#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_wrapper_fontconfig +#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_wrapper_fontconfig +#define FcNameGetConstant FcNameGetConstant_dylibloader_wrapper_fontconfig +#define FcNameConstant FcNameConstant_dylibloader_wrapper_fontconfig +#define FcNameParse FcNameParse_dylibloader_wrapper_fontconfig +#define FcNameUnparse FcNameUnparse_dylibloader_wrapper_fontconfig +#define FcPatternCreate FcPatternCreate_dylibloader_wrapper_fontconfig +#define FcPatternDuplicate FcPatternDuplicate_dylibloader_wrapper_fontconfig +#define FcPatternReference FcPatternReference_dylibloader_wrapper_fontconfig +#define FcPatternFilter FcPatternFilter_dylibloader_wrapper_fontconfig +#define FcValueDestroy FcValueDestroy_dylibloader_wrapper_fontconfig +#define FcValueEqual FcValueEqual_dylibloader_wrapper_fontconfig +#define FcValueSave FcValueSave_dylibloader_wrapper_fontconfig +#define FcPatternDestroy FcPatternDestroy_dylibloader_wrapper_fontconfig +#define FcPatternEqual FcPatternEqual_dylibloader_wrapper_fontconfig +#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_wrapper_fontconfig +#define FcPatternHash FcPatternHash_dylibloader_wrapper_fontconfig +#define FcPatternAdd FcPatternAdd_dylibloader_wrapper_fontconfig +#define FcPatternAddWeak FcPatternAddWeak_dylibloader_wrapper_fontconfig +#define FcPatternGet FcPatternGet_dylibloader_wrapper_fontconfig +#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_wrapper_fontconfig +#define FcPatternDel FcPatternDel_dylibloader_wrapper_fontconfig +#define FcPatternRemove FcPatternRemove_dylibloader_wrapper_fontconfig +#define FcPatternAddInteger FcPatternAddInteger_dylibloader_wrapper_fontconfig +#define FcPatternAddDouble FcPatternAddDouble_dylibloader_wrapper_fontconfig +#define FcPatternAddString FcPatternAddString_dylibloader_wrapper_fontconfig +#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_wrapper_fontconfig +#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_wrapper_fontconfig +#define FcPatternAddBool FcPatternAddBool_dylibloader_wrapper_fontconfig +#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_wrapper_fontconfig +#define FcPatternAddRange FcPatternAddRange_dylibloader_wrapper_fontconfig +#define FcPatternGetInteger FcPatternGetInteger_dylibloader_wrapper_fontconfig +#define FcPatternGetDouble FcPatternGetDouble_dylibloader_wrapper_fontconfig +#define FcPatternGetString FcPatternGetString_dylibloader_wrapper_fontconfig +#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_wrapper_fontconfig +#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_wrapper_fontconfig +#define FcPatternGetBool FcPatternGetBool_dylibloader_wrapper_fontconfig +#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_wrapper_fontconfig +#define FcPatternGetRange FcPatternGetRange_dylibloader_wrapper_fontconfig +#define FcPatternVaBuild FcPatternVaBuild_dylibloader_wrapper_fontconfig +#define FcPatternBuild FcPatternBuild_dylibloader_wrapper_fontconfig +#define FcPatternFormat FcPatternFormat_dylibloader_wrapper_fontconfig +#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_wrapper_fontconfig +#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_wrapper_fontconfig +#define FcRangeDestroy FcRangeDestroy_dylibloader_wrapper_fontconfig +#define FcRangeCopy FcRangeCopy_dylibloader_wrapper_fontconfig +#define FcRangeGetDouble FcRangeGetDouble_dylibloader_wrapper_fontconfig +#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_wrapper_fontconfig +#define FcWeightToOpenType FcWeightToOpenType_dylibloader_wrapper_fontconfig +#define FcStrCopy FcStrCopy_dylibloader_wrapper_fontconfig +#define FcStrCopyFilename FcStrCopyFilename_dylibloader_wrapper_fontconfig +#define FcStrPlus FcStrPlus_dylibloader_wrapper_fontconfig +#define FcStrFree FcStrFree_dylibloader_wrapper_fontconfig +#define FcStrDowncase FcStrDowncase_dylibloader_wrapper_fontconfig +#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig +#define FcStrCmp FcStrCmp_dylibloader_wrapper_fontconfig +#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig +#define FcStrStr FcStrStr_dylibloader_wrapper_fontconfig +#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_wrapper_fontconfig +#define FcUtf8Len FcUtf8Len_dylibloader_wrapper_fontconfig +#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_wrapper_fontconfig +#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_wrapper_fontconfig +#define FcUtf16Len FcUtf16Len_dylibloader_wrapper_fontconfig +#define FcStrDirname FcStrDirname_dylibloader_wrapper_fontconfig +#define FcStrBasename FcStrBasename_dylibloader_wrapper_fontconfig +#define FcStrSetCreate FcStrSetCreate_dylibloader_wrapper_fontconfig +#define FcStrSetMember FcStrSetMember_dylibloader_wrapper_fontconfig +#define FcStrSetEqual FcStrSetEqual_dylibloader_wrapper_fontconfig +#define FcStrSetAdd FcStrSetAdd_dylibloader_wrapper_fontconfig +#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_wrapper_fontconfig +#define FcStrSetDel FcStrSetDel_dylibloader_wrapper_fontconfig +#define FcStrSetDestroy FcStrSetDestroy_dylibloader_wrapper_fontconfig +#define FcStrListCreate FcStrListCreate_dylibloader_wrapper_fontconfig +#define FcStrListFirst FcStrListFirst_dylibloader_wrapper_fontconfig +#define FcStrListNext FcStrListNext_dylibloader_wrapper_fontconfig +#define FcStrListDone FcStrListDone_dylibloader_wrapper_fontconfig +#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_wrapper_fontconfig +#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig +extern FcBlanks* (*FcBlanksCreate_dylibloader_wrapper_fontconfig)( void); +extern void (*FcBlanksDestroy_dylibloader_wrapper_fontconfig)( FcBlanks*); +extern FcBool (*FcBlanksAdd_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32); +extern FcBool (*FcBlanksIsMember_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32); +extern const FcChar8* (*FcCacheDir_dylibloader_wrapper_fontconfig)(const FcCache*); +extern FcFontSet* (*FcCacheCopySet_dylibloader_wrapper_fontconfig)(const FcCache*); +extern const FcChar8* (*FcCacheSubdir_dylibloader_wrapper_fontconfig)(const FcCache*, int); +extern int (*FcCacheNumSubdir_dylibloader_wrapper_fontconfig)(const FcCache*); +extern int (*FcCacheNumFont_dylibloader_wrapper_fontconfig)(const FcCache*); +extern FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*); +extern FcBool (*FcDirCacheValid_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcBool (*FcDirCacheClean_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool); +extern void (*FcCacheCreateTagFile_dylibloader_wrapper_fontconfig)(const FcConfig*); +extern FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool); +extern FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcConfig* (*FcConfigCreate_dylibloader_wrapper_fontconfig)( void); +extern FcConfig* (*FcConfigReference_dylibloader_wrapper_fontconfig)( FcConfig*); +extern void (*FcConfigDestroy_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcBool (*FcConfigSetCurrent_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcConfig* (*FcConfigGetCurrent_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcConfigUptoDate_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcBool (*FcConfigBuildFonts_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcStrList* (*FcConfigGetFontDirs_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcStrList* (*FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcStrList* (*FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcChar8* (*FcConfigGetCache_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcBlanks* (*FcConfigGetBlanks_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcStrList* (*FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig)(const FcConfig*); +extern int (*FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcBool (*FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*, int); +extern FcFontSet* (*FcConfigGetFonts_dylibloader_wrapper_fontconfig)( FcConfig*, FcSetName); +extern FcBool (*FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +extern FcBool (*FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +extern void (*FcConfigAppFontClear_dylibloader_wrapper_fontconfig)( FcConfig*); +extern FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*, FcMatchKind); +extern FcBool (*FcConfigSubstitute_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcMatchKind); +extern const FcChar8* (*FcConfigGetSysRoot_dylibloader_wrapper_fontconfig)(const FcConfig*); +extern void (*FcConfigSetSysRoot_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*); +extern void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue); +extern void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*); +extern void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*); +extern FcStrSet* (*FcGetDefaultLangs_dylibloader_wrapper_fontconfig)( void); +extern void (*FcDefaultSubstitute_dylibloader_wrapper_fontconfig)( FcPattern*); +extern FcBool (*FcFileIsDir_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcBool (*FcFileScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool); +extern FcBool (*FcDirScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool); +extern FcBool (*FcDirSave_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*,const FcChar8*); +extern FcCache* (*FcDirCacheLoad_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*, FcChar8**); +extern FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*); +extern FcCache* (*FcDirCacheRead_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool, FcConfig*); +extern FcCache* (*FcDirCacheLoadFile_dylibloader_wrapper_fontconfig)(const FcChar8*,struct stat*); +extern void (*FcDirCacheUnload_dylibloader_wrapper_fontconfig)( FcCache*); +extern FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, int, FcBlanks*, int*); +extern FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void); +extern void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*); +extern FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*); +extern FcConfig* (*FcInitLoadConfig_dylibloader_wrapper_fontconfig)( void); +extern FcConfig* (*FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcInit_dylibloader_wrapper_fontconfig)( void); +extern void (*FcFini_dylibloader_wrapper_fontconfig)( void); +extern int (*FcGetVersion_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcInitReinitialize_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcInitBringUptoDate_dylibloader_wrapper_fontconfig)( void); +extern FcStrSet* (*FcGetLangs_dylibloader_wrapper_fontconfig)( void); +extern FcChar8* (*FcLangNormalize_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern const FcCharSet* (*FcLangGetCharSet_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcLangSet* (*FcLangSetCreate_dylibloader_wrapper_fontconfig)( void); +extern void (*FcLangSetDestroy_dylibloader_wrapper_fontconfig)( FcLangSet*); +extern FcLangSet* (*FcLangSetCopy_dylibloader_wrapper_fontconfig)(const FcLangSet*); +extern FcBool (*FcLangSetAdd_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*); +extern FcBool (*FcLangSetDel_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*); +extern FcLangResult (*FcLangSetHasLang_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcChar8*); +extern FcLangResult (*FcLangSetCompare_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +extern FcBool (*FcLangSetContains_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +extern FcBool (*FcLangSetEqual_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +extern FcChar32 (*FcLangSetHash_dylibloader_wrapper_fontconfig)(const FcLangSet*); +extern FcStrSet* (*FcLangSetGetLangs_dylibloader_wrapper_fontconfig)(const FcLangSet*); +extern FcLangSet* (*FcLangSetUnion_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +extern FcLangSet* (*FcLangSetSubtract_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*); +extern FcObjectSet* (*FcObjectSetCreate_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcObjectSetAdd_dylibloader_wrapper_fontconfig)( FcObjectSet*,const char*); +extern void (*FcObjectSetDestroy_dylibloader_wrapper_fontconfig)( FcObjectSet*); +extern FcObjectSet* (*FcObjectSetVaBuild_dylibloader_wrapper_fontconfig)(const char*, va_list); +extern FcObjectSet* (*FcObjectSetBuild_dylibloader_wrapper_fontconfig)(const char*,...); +extern FcFontSet* (*FcFontSetList_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcObjectSet*); +extern FcFontSet* (*FcFontList_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcObjectSet*); +extern FcAtomic* (*FcAtomicCreate_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcBool (*FcAtomicLock_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern FcChar8* (*FcAtomicNewFile_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern FcChar8* (*FcAtomicOrigFile_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern FcBool (*FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern void (*FcAtomicDeleteNew_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern void (*FcAtomicUnlock_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern void (*FcAtomicDestroy_dylibloader_wrapper_fontconfig)( FcAtomic*); +extern FcPattern* (*FcFontSetMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcResult*); +extern FcPattern* (*FcFontMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcResult*); +extern FcPattern* (*FcFontRenderPrepare_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*); +extern FcFontSet* (*FcFontSetSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcBool, FcCharSet**, FcResult*); +extern FcFontSet* (*FcFontSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcBool, FcCharSet**, FcResult*); +extern void (*FcFontSetSortDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*); +extern FcMatrix* (*FcMatrixCopy_dylibloader_wrapper_fontconfig)(const FcMatrix*); +extern FcBool (*FcMatrixEqual_dylibloader_wrapper_fontconfig)(const FcMatrix*,const FcMatrix*); +extern void (*FcMatrixMultiply_dylibloader_wrapper_fontconfig)( FcMatrix*,const FcMatrix*,const FcMatrix*); +extern void (*FcMatrixRotate_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +extern void (*FcMatrixScale_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +extern void (*FcMatrixShear_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double); +extern FcBool (*FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int); +extern FcBool (*FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int); +extern const FcObjectType* (*FcNameGetObjectType_dylibloader_wrapper_fontconfig)(const char*); +extern FcBool (*FcNameRegisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int); +extern FcBool (*FcNameUnregisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int); +extern const FcConstant* (*FcNameGetConstant_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcBool (*FcNameConstant_dylibloader_wrapper_fontconfig)(const FcChar8*, int*); +extern FcPattern* (*FcNameParse_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcChar8* (*FcNameUnparse_dylibloader_wrapper_fontconfig)( FcPattern*); +extern FcPattern* (*FcPatternCreate_dylibloader_wrapper_fontconfig)( void); +extern FcPattern* (*FcPatternDuplicate_dylibloader_wrapper_fontconfig)(const FcPattern*); +extern void (*FcPatternReference_dylibloader_wrapper_fontconfig)( FcPattern*); +extern FcPattern* (*FcPatternFilter_dylibloader_wrapper_fontconfig)( FcPattern*,const FcObjectSet*); +extern void (*FcValueDestroy_dylibloader_wrapper_fontconfig)( FcValue); +extern FcBool (*FcValueEqual_dylibloader_wrapper_fontconfig)( FcValue, FcValue); +extern FcValue (*FcValueSave_dylibloader_wrapper_fontconfig)( FcValue); +extern void (*FcPatternDestroy_dylibloader_wrapper_fontconfig)( FcPattern*); +extern FcBool (*FcPatternEqual_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*); +extern FcBool (*FcPatternEqualSubset_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*,const FcObjectSet*); +extern FcChar32 (*FcPatternHash_dylibloader_wrapper_fontconfig)(const FcPattern*); +extern FcBool (*FcPatternAdd_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool); +extern FcBool (*FcPatternAddWeak_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool); +extern FcResult (*FcPatternGet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*); +extern FcResult (*FcPatternGetWithBinding_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*, FcValueBinding*); +extern FcBool (*FcPatternDel_dylibloader_wrapper_fontconfig)( FcPattern*,const char*); +extern FcBool (*FcPatternRemove_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int); +extern FcBool (*FcPatternAddInteger_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int); +extern FcBool (*FcPatternAddDouble_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, double); +extern FcBool (*FcPatternAddString_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcChar8*); +extern FcBool (*FcPatternAddMatrix_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcMatrix*); +extern FcBool (*FcPatternAddCharSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcCharSet*); +extern FcBool (*FcPatternAddBool_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcBool); +extern FcBool (*FcPatternAddLangSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcLangSet*); +extern FcBool (*FcPatternAddRange_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcRange*); +extern FcResult (*FcPatternGetInteger_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, int*); +extern FcResult (*FcPatternGetDouble_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, double*); +extern FcResult (*FcPatternGetString_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcChar8**); +extern FcResult (*FcPatternGetMatrix_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcMatrix**); +extern FcResult (*FcPatternGetCharSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcCharSet**); +extern FcResult (*FcPatternGetBool_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcBool*); +extern FcResult (*FcPatternGetLangSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcLangSet**); +extern FcResult (*FcPatternGetRange_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcRange**); +extern FcPattern* (*FcPatternVaBuild_dylibloader_wrapper_fontconfig)( FcPattern*, va_list); +extern FcPattern* (*FcPatternBuild_dylibloader_wrapper_fontconfig)( FcPattern*,...); +extern FcChar8* (*FcPatternFormat_dylibloader_wrapper_fontconfig)( FcPattern*,const FcChar8*); +extern FcRange* (*FcRangeCreateDouble_dylibloader_wrapper_fontconfig)( double, double); +extern FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( FcChar32, FcChar32); +extern void (*FcRangeDestroy_dylibloader_wrapper_fontconfig)( FcRange*); +extern FcRange* (*FcRangeCopy_dylibloader_wrapper_fontconfig)(const FcRange*); +extern FcBool (*FcRangeGetDouble_dylibloader_wrapper_fontconfig)(const FcRange*, double*, double*); +extern int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int); +extern int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int); +extern FcChar8* (*FcStrCopy_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcChar8* (*FcStrCopyFilename_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcChar8* (*FcStrPlus_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +extern void (*FcStrFree_dylibloader_wrapper_fontconfig)( FcChar8*); +extern FcChar8* (*FcStrDowncase_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern int (*FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +extern int (*FcStrCmp_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +extern const FcChar8* (*FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +extern const FcChar8* (*FcStrStr_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*); +extern int (*FcUtf8ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcChar32*, int); +extern FcBool (*FcUtf8Len_dylibloader_wrapper_fontconfig)(const FcChar8*, int, int*, int*); +extern int (*FcUcs4ToUtf8_dylibloader_wrapper_fontconfig)( FcChar32, FcChar8 [6]); +extern int (*FcUtf16ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, FcChar32*, int); +extern FcBool (*FcUtf16Len_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, int, int*, int*); +extern FcChar8* (*FcStrDirname_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcChar8* (*FcStrBasename_dylibloader_wrapper_fontconfig)(const FcChar8*); +extern FcStrSet* (*FcStrSetCreate_dylibloader_wrapper_fontconfig)( void); +extern FcBool (*FcStrSetMember_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +extern FcBool (*FcStrSetEqual_dylibloader_wrapper_fontconfig)( FcStrSet*, FcStrSet*); +extern FcBool (*FcStrSetAdd_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +extern FcBool (*FcStrSetAddFilename_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +extern FcBool (*FcStrSetDel_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*); +extern void (*FcStrSetDestroy_dylibloader_wrapper_fontconfig)( FcStrSet*); +extern FcStrList* (*FcStrListCreate_dylibloader_wrapper_fontconfig)( FcStrSet*); +extern void (*FcStrListFirst_dylibloader_wrapper_fontconfig)( FcStrList*); +extern FcChar8* (*FcStrListNext_dylibloader_wrapper_fontconfig)( FcStrList*); +extern void (*FcStrListDone_dylibloader_wrapper_fontconfig)( FcStrList*); +extern FcBool (*FcConfigParseAndLoad_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool); +extern FcBool (*FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool); +int initialize_fontconfig(int verbose); +#ifdef __cplusplus +} +#endif +#endif diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp index 1e93334e40..fa3f7fbfea 100644 --- a/platform/linuxbsd/freedesktop_screensaver.cpp +++ b/platform/linuxbsd/freedesktop_screensaver.cpp @@ -34,7 +34,7 @@ #include "core/config/project_settings.h" -#include <dbus/dbus.h> +#include "dbus-so_wrap.h" #define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver" #define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver" @@ -126,4 +126,13 @@ void FreeDesktopScreenSaver::uninhibit() { dbus_connection_unref(bus); } +FreeDesktopScreenSaver::FreeDesktopScreenSaver() { +#ifdef DEBUG_ENABLED + int dylibloader_verbose = 1; +#else + int dylibloader_verbose = 0; +#endif + unsupported = (initialize_dbus(dylibloader_verbose) != 0); +} + #endif // DBUS_ENABLED diff --git a/platform/linuxbsd/freedesktop_screensaver.h b/platform/linuxbsd/freedesktop_screensaver.h index b2303791bd..1a8b010cd5 100644 --- a/platform/linuxbsd/freedesktop_screensaver.h +++ b/platform/linuxbsd/freedesktop_screensaver.h @@ -28,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef FREEDESKTOP_SCREENSAVER_H +#define FREEDESKTOP_SCREENSAVER_H + #ifdef DBUS_ENABLED -#include <dbus/dbus.h> #include <stdint.h> class FreeDesktopScreenSaver { @@ -39,9 +41,11 @@ private: bool unsupported = false; public: - FreeDesktopScreenSaver() {} + FreeDesktopScreenSaver(); void inhibit(); void uninhibit(); }; #endif // DBUS_ENABLED + +#endif // FREEDESKTOP_SCREENSAVER_H diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index b73d4dc626..e306c1054b 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -52,6 +52,10 @@ #include <sys/types.h> #include <unistd.h> +#ifdef FONTCONFIG_ENABLED +#include "fontconfig-so_wrap.h" +#endif + void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) { const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" }; @@ -327,6 +331,98 @@ uint64_t OS_LinuxBSD::get_embedded_pck_offset() const { return off; } +Vector<String> OS_LinuxBSD::get_system_fonts() const { +#ifdef FONTCONFIG_ENABLED + if (!font_config_initialized) { + ERR_FAIL_V_MSG(Vector<String>(), "Unable to load fontconfig, system font support is disabled."); + } + HashSet<String> font_names; + Vector<String> ret; + + FcConfig *config = FcInitLoadConfigAndFonts(); + ERR_FAIL_COND_V(!config, ret); + + FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, nullptr); + ERR_FAIL_COND_V(!object_set, ret); + + static const char *allowed_formats[] = { "TrueType", "CFF" }; + for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) { + FcPattern *pattern = FcPatternCreate(); + ERR_CONTINUE(!pattern); + + FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); + FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i])); + + FcFontSet *font_set = FcFontList(config, pattern, object_set); + if (font_set) { + for (int j = 0; j < font_set->nfont; j++) { + char *family_name = nullptr; + if (FcPatternGetString(font_set->fonts[j], FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) { + if (family_name) { + font_names.insert(String::utf8(family_name)); + } + } + } + FcFontSetDestroy(font_set); + } + FcPatternDestroy(pattern); + } + FcObjectSetDestroy(object_set); + + for (const String &E : font_names) { + ret.push_back(E); + } + return ret; +#else + ERR_FAIL_V_MSG(Vector<String>(), "Godot was compiled without fontconfig, system font support is disabled."); +#endif +} + +String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { +#ifdef FONTCONFIG_ENABLED + if (!font_config_initialized) { + ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled."); + } + + String ret; + + FcConfig *config = FcInitLoadConfigAndFonts(); + ERR_FAIL_COND_V(!config, ret); + + FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, FC_FILE, nullptr); + ERR_FAIL_COND_V(!object_set, ret); + + FcPattern *pattern = FcPatternCreate(); + if (pattern) { + FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); + FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data())); + FcPatternAddInteger(pattern, FC_WEIGHT, p_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL); + FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN); + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcResult result; + FcPattern *match = FcFontMatch(0, pattern, &result); + if (match) { + char *file_name = nullptr; + if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) { + if (file_name) { + ret = String::utf8(file_name); + } + } + + FcPatternDestroy(match); + } + FcPatternDestroy(pattern); + } + FcObjectSetDestroy(object_set); + return ret; +#else + ERR_FAIL_V_MSG(String(), "Godot was compiled without fontconfig, system font support is disabled."); +#endif +} + String OS_LinuxBSD::get_config_path() const { if (has_environment("XDG_CONFIG_HOME")) { if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) { @@ -644,4 +740,13 @@ OS_LinuxBSD::OS_LinuxBSD() { #ifdef X11_ENABLED DisplayServerX11::register_x11_driver(); #endif + +#ifdef FONTCONFIG_ENABLED +#ifdef DEBUG_ENABLED + int dylibloader_verbose = 1; +#else + int dylibloader_verbose = 0; +#endif + font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0); +#endif // FONTCONFIG_ENABLED } diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index 3f97b86eae..cc4e91e885 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -45,6 +45,10 @@ class OS_LinuxBSD : public OS_Unix { bool force_quit; +#ifdef FONTCONFIG_ENABLED + bool font_config_initialized = false; +#endif + #ifdef JOYDEV_ENABLED JoypadLinux *joypad = nullptr; #endif @@ -80,6 +84,9 @@ public: virtual uint64_t get_embedded_pck_offset() const override; + virtual Vector<String> get_system_fonts() const override; + virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override; + virtual String get_config_path() const override; virtual String get_data_path() const override; virtual String get_cache_path() const override; @@ -105,4 +112,4 @@ public: OS_LinuxBSD(); }; -#endif +#endif // OS_LINUXBSD_H diff --git a/platform/linuxbsd/vulkan_context_x11.h b/platform/linuxbsd/vulkan_context_x11.h index a89afa2eff..0c4a6cd278 100644 --- a/platform/linuxbsd/vulkan_context_x11.h +++ b/platform/linuxbsd/vulkan_context_x11.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VULKAN_DEVICE_X11_H -#define VULKAN_DEVICE_X11_H +#ifndef VULKAN_CONTEXT_X11_H +#define VULKAN_CONTEXT_X11_H #include "drivers/vulkan/vulkan_context.h" #include <X11/Xlib.h> @@ -44,4 +44,4 @@ public: ~VulkanContextX11(); }; -#endif // VULKAN_DEVICE_X11_H +#endif // VULKAN_CONTEXT_X11_H diff --git a/platform/macos/SCsub b/platform/macos/SCsub new file mode 100644 index 0000000000..d0856c709a --- /dev/null +++ b/platform/macos/SCsub @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +Import("env") + +from platform_methods import run_in_subprocess +import platform_macos_builders + +files = [ + "os_macos.mm", + "godot_application.mm", + "godot_application_delegate.mm", + "crash_handler_macos.mm", + "macos_terminal_logger.mm", + "display_server_macos.mm", + "godot_content_view.mm", + "godot_window_delegate.mm", + "godot_window.mm", + "key_mapping_macos.mm", + "godot_main_macos.mm", + "dir_access_macos.mm", + "tts_macos.mm", + "joypad_macos.cpp", + "vulkan_context_macos.mm", + "gl_manager_macos_legacy.mm", +] + +prog = env.add_program("#bin/godot", files) + +if env["debug_symbols"] and env["separate_debug_symbols"]: + env.AddPostAction(prog, run_in_subprocess(platform_macos_builders.make_debug_macos)) diff --git a/platform/osx/crash_handler_osx.h b/platform/macos/crash_handler_macos.h index 72938e5e0a..c9b0e77dc4 100644 --- a/platform/osx/crash_handler_osx.h +++ b/platform/macos/crash_handler_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_osx.h */ +/* crash_handler_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CRASH_HANDLER_OSX_H -#define CRASH_HANDLER_OSX_H +#ifndef CRASH_HANDLER_MACOS_H +#define CRASH_HANDLER_MACOS_H class CrashHandler { bool disabled; @@ -44,4 +44,4 @@ public: ~CrashHandler(); }; -#endif // CRASH_HANDLER_OSX_H +#endif // CRASH_HANDLER_MACOS_H diff --git a/platform/osx/crash_handler_osx.mm b/platform/macos/crash_handler_macos.mm index a798ba3b46..74bd012f0c 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/macos/crash_handler_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_osx.mm */ +/* crash_handler_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "crash_handler_osx.h" +#include "crash_handler_macos.h" #include "core/config/project_settings.h" #include "core/os/os.h" diff --git a/platform/osx/detect.py b/platform/macos/detect.py index 47765cff71..20e7afa772 100644 --- a/platform/osx/detect.py +++ b/platform/macos/detect.py @@ -8,7 +8,7 @@ def is_active(): def get_name(): - return "OSX" + return "macOS" def can_build(): @@ -98,7 +98,7 @@ def configure(env): ## Architecture - # Mac OS X no longer runs on 32-bit since 10.7 which is unsupported since 2014 + # macOS no longer runs on 32-bit since 10.7 which is unsupported since 2014 # As such, we only support 64-bit env["bits"] = "64" @@ -134,7 +134,7 @@ def configure(env): env["CC"] = "clang" env["CXX"] = "clang++" - detect_darwin_sdk_path("osx", env) + detect_darwin_sdk_path("macos", env) env.Append(CCFLAGS=["-isysroot", "$MACOS_SDK_PATH"]) env.Append(LINKFLAGS=["-isysroot", "$MACOS_SDK_PATH"]) @@ -191,8 +191,10 @@ def configure(env): ## Flags - env.Prepend(CPPPATH=["#platform/osx"]) - env.Append(CPPDEFINES=["OSX_ENABLED", "UNIX_ENABLED", "APPLE_STYLE_KEYS", "COREAUDIO_ENABLED", "COREMIDI_ENABLED"]) + env.Prepend(CPPPATH=["#platform/macos"]) + env.Append( + CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED", "APPLE_STYLE_KEYS", "COREAUDIO_ENABLED", "COREMIDI_ENABLED"] + ) env.Append( LINKFLAGS=[ "-framework", diff --git a/platform/osx/dir_access_osx.h b/platform/macos/dir_access_macos.h index 3c66c81d4f..920e69ef3e 100644 --- a/platform/osx/dir_access_osx.h +++ b/platform/macos/dir_access_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* dir_access_osx.h */ +/* dir_access_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DIR_ACCESS_OSX_H -#define DIR_ACCESS_OSX_H +#ifndef DIR_ACCESS_MACOS_H +#define DIR_ACCESS_MACOS_H #if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) @@ -41,15 +41,16 @@ #include "core/io/dir_access.h" #include "drivers/unix/dir_access_unix.h" -class DirAccessOSX : public DirAccessUnix { +class DirAccessMacOS : public DirAccessUnix { protected: - virtual String fix_unicode_name(const char *p_name) const; + virtual String fix_unicode_name(const char *p_name) const override; - virtual int get_drive_count(); - virtual String get_drive(int p_drive); + virtual int get_drive_count() override; + virtual String get_drive(int p_drive) override; - virtual bool is_hidden(const String &p_name); + virtual bool is_hidden(const String &p_name) override; }; -#endif //UNIX ENABLED -#endif +#endif // UNIX ENABLED || LIBC_FILEIO_ENABLED + +#endif // DIR_ACCESS_MACOS_H diff --git a/platform/osx/dir_access_osx.mm b/platform/macos/dir_access_macos.mm index 6bafb9470d..94d937a7dc 100644 --- a/platform/osx/dir_access_osx.mm +++ b/platform/macos/dir_access_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* dir_access_osx.mm */ +/* dir_access_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "dir_access_osx.h" +#include "dir_access_macos.h" #if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) @@ -37,7 +37,7 @@ #import <AppKit/NSWorkspace.h> #import <Foundation/Foundation.h> -String DirAccessOSX::fix_unicode_name(const char *p_name) const { +String DirAccessMacOS::fix_unicode_name(const char *p_name) const { String fname; NSString *nsstr = [[NSString stringWithUTF8String:p_name] precomposedStringWithCanonicalMapping]; @@ -46,14 +46,14 @@ String DirAccessOSX::fix_unicode_name(const char *p_name) const { return fname; } -int DirAccessOSX::get_drive_count() { +int DirAccessMacOS::get_drive_count() { NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil]; NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes]; return [vols count]; } -String DirAccessOSX::get_drive(int p_drive) { +String DirAccessMacOS::get_drive(int p_drive) { NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil]; NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes]; int count = [vols count]; @@ -68,7 +68,7 @@ String DirAccessOSX::get_drive(int p_drive) { return volname; } -bool DirAccessOSX::is_hidden(const String &p_name) { +bool DirAccessMacOS::is_hidden(const String &p_name) { String f = get_current_dir().plus_file(p_name); NSURL *url = [NSURL fileURLWithPath:@(f.utf8().get_data())]; NSNumber *hidden = nil; @@ -78,4 +78,4 @@ bool DirAccessOSX::is_hidden(const String &p_name) { return [hidden boolValue]; } -#endif //posix_enabled +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED diff --git a/platform/osx/display_server_osx.h b/platform/macos/display_server_macos.h index 9575cb29a2..54c479fc81 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/macos/display_server_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* display_server_osx.h */ +/* display_server_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DISPLAY_SERVER_OSX_H -#define DISPLAY_SERVER_OSX_H +#ifndef DISPLAY_SERVER_MACOS_H +#define DISPLAY_SERVER_MACOS_H #define BitMap _QDBitMap // Suppress deprecated QuickDraw definition. @@ -37,12 +37,12 @@ #include "servers/display_server.h" #if defined(GLES3_ENABLED) -#include "gl_manager_osx_legacy.h" +#include "gl_manager_macos_legacy.h" #endif // GLES3_ENABLED #if defined(VULKAN_ENABLED) #include "drivers/vulkan/rendering_device_vulkan.h" -#include "platform/osx/vulkan_context_osx.h" +#include "platform/macos/vulkan_context_macos.h" #endif // VULKAN_ENABLED #import <AppKit/AppKit.h> @@ -50,19 +50,20 @@ #import <ApplicationServices/ApplicationServices.h> #import <CoreVideo/CoreVideo.h> #import <Foundation/Foundation.h> +#import <IOKit/pwr_mgt/IOPMLib.h> #undef BitMap #undef CursorShape -class DisplayServerOSX : public DisplayServer { - GDCLASS(DisplayServerOSX, DisplayServer) +class DisplayServerMacOS : public DisplayServer { + GDCLASS(DisplayServerMacOS, DisplayServer) _THREAD_SAFE_CLASS_ public: struct KeyEvent { WindowID window_id = INVALID_WINDOW_ID; - unsigned int osx_state = false; + unsigned int macos_state = false; bool pressed = false; bool echo = false; bool raw = false; @@ -115,10 +116,10 @@ public: private: #if defined(GLES3_ENABLED) - GLManager_OSX *gl_manager = nullptr; + GLManager_MacOS *gl_manager = nullptr; #endif #if defined(VULKAN_ENABLED) - VulkanContextOSX *context_vulkan = nullptr; + VulkanContextMacOS *context_vulkan = nullptr; RenderingDeviceVulkan *rendering_device_vulkan = nullptr; #endif String rendering_driver; @@ -171,6 +172,8 @@ private: HashMap<WindowID, WindowData> windows; + IOPMAssertionID screen_keep_on_assertion = kIOPMNullAssertionID; + const NSMenu *_get_menu_root(const String &p_menu_root) const; NSMenu *_get_menu_root(const String &p_menu_root); @@ -203,7 +206,7 @@ public: void send_event(NSEvent *p_event); void send_window_event(const WindowData &p_wd, WindowEvent p_event); void release_pressed_events(); - void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) const; + void get_key_modifier_state(unsigned int p_macos_state, Ref<InputEventWithModifiers> r_state) const; void update_mouse_pos(WindowData &p_wd, NSPoint p_location_in_window); void push_to_key_event_buffer(const KeyEvent &p_event); void update_im_text(const Point2i &p_selection, const String &p_text); @@ -299,6 +302,8 @@ public: virtual float screen_get_max_scale() const override; virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual void screen_set_keep_on(bool p_enable) override; + virtual bool screen_is_kept_on() const override; virtual Vector<int> get_window_list() const override; @@ -397,10 +402,10 @@ public: static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static Vector<String> get_rendering_drivers_func(); - static void register_osx_driver(); + static void register_macos_driver(); - DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); - ~DisplayServerOSX(); + DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + ~DisplayServerMacOS(); }; -#endif // DISPLAY_SERVER_OSX_H +#endif // DISPLAY_SERVER_MACOS_H diff --git a/platform/osx/display_server_osx.mm b/platform/macos/display_server_macos.mm index 91d64b50f0..a49485154b 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/macos/display_server_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* display_server_osx.mm */ +/* display_server_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "display_server_osx.h" +#include "display_server_macos.h" #include "godot_content_view.h" #include "godot_menu_item.h" #include "godot_window.h" #include "godot_window_delegate.h" -#include "key_mapping_osx.h" -#include "os_osx.h" +#include "key_mapping_macos.h" +#include "os_macos.h" -#include "tts_osx.h" +#include "tts_macos.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" @@ -60,7 +61,7 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #endif -const NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) const { +const NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) const { const NSMenu *menu = nullptr; if (p_menu_root == "") { // Main menu. @@ -81,7 +82,7 @@ const NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) const return menu; } -NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) { +NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) { NSMenu *menu = nullptr; if (p_menu_root == "") { // Main menu. @@ -105,7 +106,7 @@ NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) { return menu; } -DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) { +DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) { WindowID id; const float scale = screen_get_max_scale(); { @@ -193,7 +194,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V return id; } -void DisplayServerOSX::_update_window_style(WindowData p_wd) { +void DisplayServerMacOS::_update_window_style(WindowData p_wd) { bool borderless_full = false; if (p_wd.borderless) { @@ -222,7 +223,7 @@ void DisplayServerOSX::_update_window_style(WindowData p_wd) { } } -void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) { +void DisplayServerMacOS::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; @@ -267,7 +268,7 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled } } -void DisplayServerOSX::_update_displays_arrangement() { +void DisplayServerMacOS::_update_displays_arrangement() { origin = Point2i(); for (int i = 0; i < get_screen_count(); i++) { @@ -282,20 +283,20 @@ void DisplayServerOSX::_update_displays_arrangement() { displays_arrangement_dirty = false; } -Point2i DisplayServerOSX::_get_screens_origin() const { +Point2i DisplayServerMacOS::_get_screens_origin() const { // Returns the native top-left screen coordinate of the smallest rectangle // that encompasses all screens. Needed in get_screen_position(), // window_get_position, and window_set_position() // to convert between OS X native screen coordinates and the ones expected by Godot. if (displays_arrangement_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_displays_arrangement(); + const_cast<DisplayServerMacOS *>(this)->_update_displays_arrangement(); } return origin; } -Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const { +Point2i DisplayServerMacOS::_get_native_screen_position(int p_screen) const { NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; @@ -306,18 +307,18 @@ Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const { return Point2i(); } -void DisplayServerOSX::_displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); +void DisplayServerMacOS::_displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { ds->displays_arrangement_dirty = true; } } -void DisplayServerOSX::_dispatch_input_events(const Ref<InputEvent> &p_event) { - ((DisplayServerOSX *)(get_singleton()))->_dispatch_input_event(p_event); +void DisplayServerMacOS::_dispatch_input_events(const Ref<InputEvent> &p_event) { + ((DisplayServerMacOS *)(get_singleton()))->_dispatch_input_event(p_event); } -void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { +void DisplayServerMacOS::_dispatch_input_event(const Ref<InputEvent> &p_event) { _THREAD_SAFE_METHOD_ if (!in_dispatch_input_event) { in_dispatch_input_event = true; @@ -334,7 +335,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { if (windows.has(E->get())) { Callable callable = windows[E->get()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } in_dispatch_input_event = false; @@ -348,7 +349,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { if (windows.has(event_from_window->get_window_id())) { Callable callable = windows[event_from_window->get_window_id()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } else { @@ -356,7 +357,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { for (KeyValue<WindowID, WindowData> &E : windows) { Callable callable = E.value.input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } @@ -364,12 +365,12 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { } } -void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) { +void DisplayServerMacOS::_push_input(const Ref<InputEvent> &p_event) { Ref<InputEvent> ev = p_event; Input::get_singleton()->parse_input_event(ev); } -void DisplayServerOSX::_process_key_events() { +void DisplayServerMacOS::_process_key_events() { Ref<InputEventKey> k; for (int i = 0; i < key_event_pos; i++) { const KeyEvent &ke = key_event_buffer[i]; @@ -378,7 +379,7 @@ void DisplayServerOSX::_process_key_events() { k.instantiate(); k->set_window_id(ke.window_id); - get_key_modifier_state(ke.osx_state, k); + get_key_modifier_state(ke.macos_state, k); k->set_pressed(ke.pressed); k->set_echo(ke.echo); k->set_keycode(ke.keycode); @@ -392,7 +393,7 @@ void DisplayServerOSX::_process_key_events() { k.instantiate(); k->set_window_id(ke.window_id); - get_key_modifier_state(ke.osx_state, k); + get_key_modifier_state(ke.macos_state, k); k->set_pressed(ke.pressed); k->set_echo(ke.echo); k->set_keycode(Key::NONE); @@ -405,7 +406,7 @@ void DisplayServerOSX::_process_key_events() { k.instantiate(); k->set_window_id(ke.window_id); - get_key_modifier_state(ke.osx_state, k); + get_key_modifier_state(ke.macos_state, k); k->set_pressed(ke.pressed); k->set_echo(ke.echo); k->set_keycode(ke.keycode); @@ -423,7 +424,7 @@ void DisplayServerOSX::_process_key_events() { key_event_pos = 0; } -void DisplayServerOSX::_update_keyboard_layouts() { +void DisplayServerMacOS::_update_keyboard_layouts() { kbd_layouts.clear(); current_layout = 0; @@ -468,14 +469,14 @@ void DisplayServerOSX::_update_keyboard_layouts() { keyboard_layout_dirty = false; } -void DisplayServerOSX::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); +void DisplayServerMacOS::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { ds->keyboard_layout_dirty = true; } } -NSImage *DisplayServerOSX::_convert_to_nsimg(Ref<Image> &p_image) const { +NSImage *DisplayServerMacOS::_convert_to_nsimg(Ref<Image> &p_image) const { p_image->convert(Image::FORMAT_RGBA8); NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL @@ -509,7 +510,7 @@ NSImage *DisplayServerOSX::_convert_to_nsimg(Ref<Image> &p_image) const { return nsimg; } -NSCursor *DisplayServerOSX::_cursor_from_selector(SEL p_selector, SEL p_fallback) { +NSCursor *DisplayServerMacOS::_cursor_from_selector(SEL p_selector, SEL p_fallback) { if ([NSCursor respondsToSelector:p_selector]) { id object = [NSCursor performSelector:p_selector]; if ([object isKindOfClass:[NSCursor class]]) { @@ -523,11 +524,11 @@ NSCursor *DisplayServerOSX::_cursor_from_selector(SEL p_selector, SEL p_fallback return [NSCursor arrowCursor]; } -NSMenu *DisplayServerOSX::get_dock_menu() const { +NSMenu *DisplayServerMacOS::get_dock_menu() const { return dock_menu; } -void DisplayServerOSX::menu_callback(id p_sender) { +void DisplayServerMacOS::menu_callback(id p_sender) { if (![p_sender representedObject]) { return; } @@ -555,20 +556,20 @@ void DisplayServerOSX::menu_callback(id p_sender) { Variant *tagp = &tag; Variant ret; Callable::CallError ce; - value->callback.call((const Variant **)&tagp, 1, ret, ce); + value->callback.callp((const Variant **)&tagp, 1, ret, ce); } } } -bool DisplayServerOSX::has_window(WindowID p_window) const { +bool DisplayServerMacOS::has_window(WindowID p_window) const { return windows.has(p_window); } -DisplayServerOSX::WindowData &DisplayServerOSX::get_window(WindowID p_window) { +DisplayServerMacOS::WindowData &DisplayServerMacOS::get_window(WindowID p_window) { return windows[p_window]; } -void DisplayServerOSX::send_event(NSEvent *p_event) { +void DisplayServerMacOS::send_event(NSEvent *p_event) { // Special case handling of command-period, which is traditionally a special // shortcut in macOS and doesn't arrive at our regular keyDown handler. if ([p_event type] == NSEventTypeKeyDown) { @@ -577,7 +578,7 @@ void DisplayServerOSX::send_event(NSEvent *p_event) { k.instantiate(); get_key_modifier_state([p_event modifierFlags], k); - k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID); + k->set_window_id(DisplayServerMacOS::INVALID_WINDOW_ID); k->set_pressed(true); k->set_keycode(Key::PERIOD); k->set_physical_keycode(Key::PERIOD); @@ -588,7 +589,7 @@ void DisplayServerOSX::send_event(NSEvent *p_event) { } } -void DisplayServerOSX::send_window_event(const WindowData &wd, WindowEvent p_event) { +void DisplayServerMacOS::send_window_event(const WindowData &wd, WindowEvent p_event) { _THREAD_SAFE_METHOD_ if (!wd.event_callback.is_null()) { @@ -596,25 +597,25 @@ void DisplayServerOSX::send_window_event(const WindowData &wd, WindowEvent p_eve Variant *eventp = &event; Variant ret; Callable::CallError ce; - wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce); } } -void DisplayServerOSX::release_pressed_events() { +void DisplayServerMacOS::release_pressed_events() { _THREAD_SAFE_METHOD_ if (Input::get_singleton()) { Input::get_singleton()->release_pressed_events(); } } -void DisplayServerOSX::get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) const { - r_state->set_shift_pressed((p_osx_state & NSEventModifierFlagShift)); - r_state->set_ctrl_pressed((p_osx_state & NSEventModifierFlagControl)); - r_state->set_alt_pressed((p_osx_state & NSEventModifierFlagOption)); - r_state->set_meta_pressed((p_osx_state & NSEventModifierFlagCommand)); +void DisplayServerMacOS::get_key_modifier_state(unsigned int p_macos_state, Ref<InputEventWithModifiers> r_state) const { + r_state->set_shift_pressed((p_macos_state & NSEventModifierFlagShift)); + r_state->set_ctrl_pressed((p_macos_state & NSEventModifierFlagControl)); + r_state->set_alt_pressed((p_macos_state & NSEventModifierFlagOption)); + r_state->set_meta_pressed((p_macos_state & NSEventModifierFlagCommand)); } -void DisplayServerOSX::update_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_location_in_window) { +void DisplayServerMacOS::update_mouse_pos(DisplayServerMacOS::WindowData &p_wd, NSPoint p_location_in_window) { const NSRect content_rect = [p_wd.window_view frame]; const float scale = screen_get_max_scale(); p_wd.mouse_pos.x = p_location_in_window.x * scale; @@ -622,33 +623,33 @@ void DisplayServerOSX::update_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPo Input::get_singleton()->set_mouse_position(p_wd.mouse_pos); } -void DisplayServerOSX::push_to_key_event_buffer(const DisplayServerOSX::KeyEvent &p_event) { +void DisplayServerMacOS::push_to_key_event_buffer(const DisplayServerMacOS::KeyEvent &p_event) { if (key_event_pos >= key_event_buffer.size()) { key_event_buffer.resize(1 + key_event_pos); } key_event_buffer.write[key_event_pos++] = p_event; } -void DisplayServerOSX::update_im_text(const Point2i &p_selection, const String &p_text) { +void DisplayServerMacOS::update_im_text(const Point2i &p_selection, const String &p_text) { im_selection = p_selection; im_text = p_text; OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); } -void DisplayServerOSX::set_last_focused_window(WindowID p_window) { +void DisplayServerMacOS::set_last_focused_window(WindowID p_window) { last_focused_window = p_window; } -void DisplayServerOSX::set_is_resizing(bool p_is_resizing) { +void DisplayServerMacOS::set_is_resizing(bool p_is_resizing) { is_resizing = p_is_resizing; } -bool DisplayServerOSX::get_is_resizing() const { +bool DisplayServerMacOS::get_is_resizing() const { return is_resizing; } -void DisplayServerOSX::window_update(WindowID p_window) { +void DisplayServerMacOS::window_update(WindowID p_window) { #if defined(GLES3_ENABLED) if (gl_manager) { gl_manager->window_update(p_window); @@ -656,7 +657,7 @@ void DisplayServerOSX::window_update(WindowID p_window) { #endif } -void DisplayServerOSX::window_destroy(WindowID p_window) { +void DisplayServerMacOS::window_destroy(WindowID p_window) { #if defined(GLES3_ENABLED) if (gl_manager) { gl_manager->window_destroy(p_window); @@ -670,7 +671,7 @@ void DisplayServerOSX::window_destroy(WindowID p_window) { windows.erase(p_window); } -void DisplayServerOSX::window_resize(WindowID p_window, int p_width, int p_height) { +void DisplayServerMacOS::window_resize(WindowID p_window, int p_width, int p_height) { #if defined(GLES3_ENABLED) if (gl_manager) { gl_manager->window_resize(p_window, p_width, p_height); @@ -683,7 +684,7 @@ void DisplayServerOSX::window_resize(WindowID p_window, int p_width, int p_heigh #endif } -bool DisplayServerOSX::has_feature(Feature p_feature) const { +bool DisplayServerMacOS::has_feature(Feature p_feature) const { switch (p_feature) { case FEATURE_GLOBAL_MENU: case FEATURE_SUBWINDOWS: @@ -709,16 +710,16 @@ bool DisplayServerOSX::has_feature(Feature p_feature) const { return false; } -String DisplayServerOSX::get_name() const { - return "OSX"; +String DisplayServerMacOS::get_name() const { + return "macOS"; } -void DisplayServerOSX::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -731,17 +732,17 @@ void DisplayServerOSX::global_menu_add_item(const String &p_menu_root, const Str obj->checkable_type = CHECKABLE_TYPE_NONE; obj->max_states = 0; obj->state = 0; - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -754,17 +755,17 @@ void DisplayServerOSX::global_menu_add_check_item(const String &p_menu_root, con obj->checkable_type = CHECKABLE_TYPE_CHECK_BOX; obj->max_states = 0; obj->state = 0; - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -786,17 +787,17 @@ void DisplayServerOSX::global_menu_add_icon_item(const String &p_menu_root, cons obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS); [menu_item setImage:_convert_to_nsimg(obj->img)]; } - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -818,17 +819,17 @@ void DisplayServerOSX::global_menu_add_icon_check_item(const String &p_menu_root obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS); [menu_item setImage:_convert_to_nsimg(obj->img)]; } - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -841,17 +842,17 @@ void DisplayServerOSX::global_menu_add_radio_check_item(const String &p_menu_roo obj->checkable_type = CHECKABLE_TYPE_RADIO_BUTTON; obj->max_states = 0; obj->state = 0; - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -873,17 +874,17 @@ void DisplayServerOSX::global_menu_add_icon_radio_check_item(const String &p_men obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS); [menu_item setImage:_convert_to_nsimg(obj->img)]; } - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +void DisplayServerMacOS::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); if (menu) { - String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); + String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK); NSMenuItem *menu_item; if (p_index != -1) { menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index]; @@ -896,12 +897,12 @@ void DisplayServerOSX::global_menu_add_multistate_item(const String &p_menu_root obj->checkable_type = CHECKABLE_TYPE_NONE; obj->max_states = p_max_states; obj->state = p_default_state; - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)]; + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)]; [menu_item setRepresentedObject:obj]; } } -void DisplayServerOSX::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { +void DisplayServerMacOS::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -926,7 +927,7 @@ void DisplayServerOSX::global_menu_add_submenu_item(const String &p_menu_root, c } } -void DisplayServerOSX::global_menu_add_separator(const String &p_menu_root, int p_index) { +void DisplayServerMacOS::global_menu_add_separator(const String &p_menu_root, int p_index) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -939,7 +940,7 @@ void DisplayServerOSX::global_menu_add_separator(const String &p_menu_root, int } } -int DisplayServerOSX::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { +int DisplayServerMacOS::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -950,7 +951,7 @@ int DisplayServerOSX::global_menu_get_item_index_from_text(const String &p_menu_ return -1; } -int DisplayServerOSX::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const { +int DisplayServerMacOS::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -969,7 +970,7 @@ int DisplayServerOSX::global_menu_get_item_index_from_tag(const String &p_menu_r return -1; } -bool DisplayServerOSX::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const { +bool DisplayServerMacOS::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -982,7 +983,7 @@ bool DisplayServerOSX::global_menu_is_item_checked(const String &p_menu_root, in return false; } -bool DisplayServerOSX::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const { +bool DisplayServerMacOS::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -998,7 +999,7 @@ bool DisplayServerOSX::global_menu_is_item_checkable(const String &p_menu_root, return false; } -bool DisplayServerOSX::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const { +bool DisplayServerMacOS::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1014,7 +1015,7 @@ bool DisplayServerOSX::global_menu_is_item_radio_checkable(const String &p_menu_ return false; } -Callable DisplayServerOSX::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const { +Callable DisplayServerMacOS::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1030,7 +1031,7 @@ Callable DisplayServerOSX::global_menu_get_item_callback(const String &p_menu_ro return Callable(); } -Variant DisplayServerOSX::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const { +Variant DisplayServerMacOS::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1046,7 +1047,7 @@ Variant DisplayServerOSX::global_menu_get_item_tag(const String &p_menu_root, in return Variant(); } -String DisplayServerOSX::global_menu_get_item_text(const String &p_menu_root, int p_idx) const { +String DisplayServerMacOS::global_menu_get_item_text(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1059,7 +1060,7 @@ String DisplayServerOSX::global_menu_get_item_text(const String &p_menu_root, in return String(); } -String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const { +String DisplayServerMacOS::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1079,7 +1080,7 @@ String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root, return String(); } -Key DisplayServerOSX::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const { +Key DisplayServerMacOS::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1110,7 +1111,7 @@ Key DisplayServerOSX::global_menu_get_item_accelerator(const String &p_menu_root return Key::NONE; } -bool DisplayServerOSX::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const { +bool DisplayServerMacOS::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1123,7 +1124,7 @@ bool DisplayServerOSX::global_menu_is_item_disabled(const String &p_menu_root, i return false; } -String DisplayServerOSX::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const { +String DisplayServerMacOS::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1136,7 +1137,7 @@ String DisplayServerOSX::global_menu_get_item_tooltip(const String &p_menu_root, return String(); } -int DisplayServerOSX::global_menu_get_item_state(const String &p_menu_root, int p_idx) const { +int DisplayServerMacOS::global_menu_get_item_state(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1152,7 +1153,7 @@ int DisplayServerOSX::global_menu_get_item_state(const String &p_menu_root, int return 0; } -int DisplayServerOSX::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const { +int DisplayServerMacOS::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1168,7 +1169,7 @@ int DisplayServerOSX::global_menu_get_item_max_states(const String &p_menu_root, return 0; } -Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const { +Ref<Texture2D> DisplayServerMacOS::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1186,7 +1187,7 @@ Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_ return Ref<Texture2D>(); } -void DisplayServerOSX::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { +void DisplayServerMacOS::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1205,7 +1206,7 @@ void DisplayServerOSX::global_menu_set_item_checked(const String &p_menu_root, i } } -void DisplayServerOSX::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { +void DisplayServerMacOS::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1221,7 +1222,7 @@ void DisplayServerOSX::global_menu_set_item_checkable(const String &p_menu_root, } } -void DisplayServerOSX::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { +void DisplayServerMacOS::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1237,7 +1238,7 @@ void DisplayServerOSX::global_menu_set_item_radio_checkable(const String &p_menu } } -void DisplayServerOSX::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) { +void DisplayServerMacOS::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1253,7 +1254,7 @@ void DisplayServerOSX::global_menu_set_item_callback(const String &p_menu_root, } } -void DisplayServerOSX::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) { +void DisplayServerMacOS::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1269,7 +1270,7 @@ void DisplayServerOSX::global_menu_set_item_tag(const String &p_menu_root, int p } } -void DisplayServerOSX::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) { +void DisplayServerMacOS::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1284,7 +1285,7 @@ void DisplayServerOSX::global_menu_set_item_text(const String &p_menu_root, int } } -void DisplayServerOSX::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) { +void DisplayServerMacOS::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1308,7 +1309,7 @@ void DisplayServerOSX::global_menu_set_item_submenu(const String &p_menu_root, i } } -void DisplayServerOSX::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) { +void DisplayServerMacOS::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1318,14 +1319,14 @@ void DisplayServerOSX::global_menu_set_item_accelerator(const String &p_menu_roo } NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; if (menu_item) { - [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_keycode)]; - String keycode = KeyMappingOSX::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK); + [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_keycode)]; + String keycode = KeyMappingMacOS::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK); [menu_item setKeyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]]; } } } -void DisplayServerOSX::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) { +void DisplayServerMacOS::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1340,7 +1341,7 @@ void DisplayServerOSX::global_menu_set_item_disabled(const String &p_menu_root, } } -void DisplayServerOSX::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) { +void DisplayServerMacOS::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1355,7 +1356,7 @@ void DisplayServerOSX::global_menu_set_item_tooltip(const String &p_menu_root, i } } -void DisplayServerOSX::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) { +void DisplayServerMacOS::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1373,7 +1374,7 @@ void DisplayServerOSX::global_menu_set_item_state(const String &p_menu_root, int } } -void DisplayServerOSX::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) { +void DisplayServerMacOS::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1391,7 +1392,7 @@ void DisplayServerOSX::global_menu_set_item_max_states(const String &p_menu_root } } -void DisplayServerOSX::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) { +void DisplayServerMacOS::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1418,7 +1419,7 @@ void DisplayServerOSX::global_menu_set_item_icon(const String &p_menu_root, int } } -int DisplayServerOSX::global_menu_get_item_count(const String &p_menu_root) const { +int DisplayServerMacOS::global_menu_get_item_count(const String &p_menu_root) const { _THREAD_SAFE_METHOD_ const NSMenu *menu = _get_menu_root(p_menu_root); @@ -1429,7 +1430,7 @@ int DisplayServerOSX::global_menu_get_item_count(const String &p_menu_root) cons } } -void DisplayServerOSX::global_menu_remove_item(const String &p_menu_root, int p_idx) { +void DisplayServerMacOS::global_menu_remove_item(const String &p_menu_root, int p_idx) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1441,7 +1442,7 @@ void DisplayServerOSX::global_menu_remove_item(const String &p_menu_root, int p_ } } -void DisplayServerOSX::global_menu_clear(const String &p_menu_root) { +void DisplayServerMacOS::global_menu_clear(const String &p_menu_root) { _THREAD_SAFE_METHOD_ NSMenu *menu = _get_menu_root(p_menu_root); @@ -1455,42 +1456,42 @@ void DisplayServerOSX::global_menu_clear(const String &p_menu_root) { } } -bool DisplayServerOSX::tts_is_speaking() const { +bool DisplayServerMacOS::tts_is_speaking() const { ERR_FAIL_COND_V(!tts, false); return [tts isSpeaking]; } -bool DisplayServerOSX::tts_is_paused() const { +bool DisplayServerMacOS::tts_is_paused() const { ERR_FAIL_COND_V(!tts, false); return [tts isPaused]; } -Array DisplayServerOSX::tts_get_voices() const { +Array DisplayServerMacOS::tts_get_voices() const { ERR_FAIL_COND_V(!tts, Array()); return [tts getVoices]; } -void DisplayServerOSX::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) { +void DisplayServerMacOS::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) { ERR_FAIL_COND(!tts); [tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt]; } -void DisplayServerOSX::tts_pause() { +void DisplayServerMacOS::tts_pause() { ERR_FAIL_COND(!tts); [tts pauseSpeaking]; } -void DisplayServerOSX::tts_resume() { +void DisplayServerMacOS::tts_resume() { ERR_FAIL_COND(!tts); [tts resumeSpeaking]; } -void DisplayServerOSX::tts_stop() { +void DisplayServerMacOS::tts_stop() { ERR_FAIL_COND(!tts); [tts stopSpeaking]; } -Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) { +Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) { _THREAD_SAFE_METHOD_ NSAlert *window = [[NSAlert alloc] init]; @@ -1522,13 +1523,13 @@ Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector Variant *buttonp = &button; Variant ret; Callable::CallError ce; - p_callback.call((const Variant **)&buttonp, 1, ret, ce); + p_callback.callp((const Variant **)&buttonp, 1, ret, ce); } return OK; } -Error DisplayServerOSX::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) { +Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) { _THREAD_SAFE_METHOD_ NSAlert *window = [[NSAlert alloc] init]; @@ -1554,13 +1555,13 @@ Error DisplayServerOSX::dialog_input_text(String p_title, String p_description, Variant *textp = &text; Variant ret; Callable::CallError ce; - p_callback.call((const Variant **)&textp, 1, ret, ce); + p_callback.callp((const Variant **)&textp, 1, ret, ce); } return OK; } -void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { +void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { _THREAD_SAFE_METHOD_ if (p_mode == mouse_mode) { @@ -1615,11 +1616,11 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { } } -DisplayServer::MouseMode DisplayServerOSX::mouse_get_mode() const { +DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode() const { return mouse_mode; } -bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) { +bool DisplayServerMacOS::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) { _THREAD_SAFE_METHOD_ if (ignore_warp) { @@ -1641,7 +1642,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP List<WarpEvent>::Element *F = warp_events.front(); while (F) { if (F->get().timestamp < p_timestamp) { - List<DisplayServerOSX::WarpEvent>::Element *E = F; + List<DisplayServerMacOS::WarpEvent>::Element *E = F; r_delta.x -= E->get().delta.x; r_delta.y -= E->get().delta.y; F = F->next(); @@ -1669,7 +1670,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP // Save warp data. last_warp = [[NSProcessInfo processInfo] systemUptime]; - DisplayServerOSX::WarpEvent ev; + DisplayServerMacOS::WarpEvent ev; ev.timestamp = last_warp; ev.delta = r_delta; warp_events.push_back(ev); @@ -1678,7 +1679,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP return false; } -void DisplayServerOSX::warp_mouse(const Point2i &p_position) { +void DisplayServerMacOS::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ if (mouse_mode != MOUSE_MODE_CAPTURED) { @@ -1705,7 +1706,7 @@ void DisplayServerOSX::warp_mouse(const Point2i &p_position) { } } -Point2i DisplayServerOSX::mouse_get_position() const { +Point2i DisplayServerMacOS::mouse_get_position() const { _THREAD_SAFE_METHOD_ const NSPoint mouse_pos = [NSEvent mouseLocation]; @@ -1724,15 +1725,15 @@ Point2i DisplayServerOSX::mouse_get_position() const { return Vector2i(); } -void DisplayServerOSX::mouse_set_button_state(MouseButton p_state) { +void DisplayServerMacOS::mouse_set_button_state(MouseButton p_state) { last_button_state = p_state; } -MouseButton DisplayServerOSX::mouse_get_button_state() const { +MouseButton DisplayServerMacOS::mouse_get_button_state() const { return last_button_state; } -void DisplayServerOSX::clipboard_set(const String &p_text) { +void DisplayServerMacOS::clipboard_set(const String &p_text) { _THREAD_SAFE_METHOD_ NSString *copiedString = [NSString stringWithUTF8String:p_text.utf8().get_data()]; @@ -1743,7 +1744,7 @@ void DisplayServerOSX::clipboard_set(const String &p_text) { [pasteboard writeObjects:copiedStringArray]; } -String DisplayServerOSX::clipboard_get() const { +String DisplayServerMacOS::clipboard_get() const { _THREAD_SAFE_METHOD_ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; @@ -1764,14 +1765,14 @@ String DisplayServerOSX::clipboard_get() const { return ret; } -int DisplayServerOSX::get_screen_count() const { +int DisplayServerMacOS::get_screen_count() const { _THREAD_SAFE_METHOD_ NSArray *screenArray = [NSScreen screens]; return [screenArray count]; } -Point2i DisplayServerOSX::screen_get_position(int p_screen) const { +Point2i DisplayServerMacOS::screen_get_position(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1785,7 +1786,7 @@ Point2i DisplayServerOSX::screen_get_position(int p_screen) const { return position; } -Size2i DisplayServerOSX::screen_get_size(int p_screen) const { +Size2i DisplayServerMacOS::screen_get_size(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1802,7 +1803,7 @@ Size2i DisplayServerOSX::screen_get_size(int p_screen) const { return Size2i(); } -int DisplayServerOSX::screen_get_dpi(int p_screen) const { +int DisplayServerMacOS::screen_get_dpi(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1826,7 +1827,7 @@ int DisplayServerOSX::screen_get_dpi(int p_screen) const { return 72; } -float DisplayServerOSX::screen_get_scale(int p_screen) const { +float DisplayServerMacOS::screen_get_scale(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1844,14 +1845,14 @@ float DisplayServerOSX::screen_get_scale(int p_screen) const { return 1.f; } -float DisplayServerOSX::screen_get_max_scale() const { +float DisplayServerMacOS::screen_get_max_scale() const { _THREAD_SAFE_METHOD_ // Note: Do not update max display scale on screen configuration change, existing editor windows can't be rescaled on the fly. return display_max_scale; } -Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const { +Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1873,7 +1874,7 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const { return Rect2i(); } -float DisplayServerOSX::screen_get_refresh_rate(int p_screen) const { +float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ if (p_screen == SCREEN_OF_MAIN_WINDOW) { @@ -1891,7 +1892,25 @@ float DisplayServerOSX::screen_get_refresh_rate(int p_screen) const { return SCREEN_REFRESH_RATE_FALLBACK; } -Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const { +bool DisplayServerMacOS::screen_is_kept_on() const { + return (screen_keep_on_assertion); +} + +void DisplayServerMacOS::screen_set_keep_on(bool p_enable) { + if (screen_keep_on_assertion) { + IOPMAssertionRelease(screen_keep_on_assertion); + screen_keep_on_assertion = kIOPMNullAssertionID; + } + + if (p_enable) { + String app_name_string = ProjectSettings::get_singleton()->get("application/config/name"); + NSString *name = [NSString stringWithUTF8String:(app_name_string.is_empty() ? "Godot Engine" : app_name_string.utf8().get_data())]; + NSString *reason = @"Godot Engine running with display/window/energy_saving/keep_screen_on = true"; + IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep, (__bridge CFStringRef)name, (__bridge CFStringRef)reason, (__bridge CFStringRef)reason, nullptr, 0, nullptr, &screen_keep_on_assertion); + } +} + +Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const { _THREAD_SAFE_METHOD_ Vector<int> ret; @@ -1901,7 +1920,7 @@ Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const { return ret; } -DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { +DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { _THREAD_SAFE_METHOD_ WindowID id = _create_window(p_mode, p_vsync_mode, p_rect); @@ -1914,7 +1933,7 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, V return id; } -void DisplayServerOSX::show_window(WindowID p_id) { +void DisplayServerMacOS::show_window(WindowID p_id) { WindowData &wd = windows[p_id]; popup_open(p_id); @@ -1925,7 +1944,7 @@ void DisplayServerOSX::show_window(WindowID p_id) { } } -void DisplayServerOSX::delete_sub_window(WindowID p_id) { +void DisplayServerMacOS::delete_sub_window(WindowID p_id) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_id)); @@ -1937,7 +1956,7 @@ void DisplayServerOSX::delete_sub_window(WindowID p_id) { [wd.window_object close]; } -void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerMacOS::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -1945,7 +1964,7 @@ void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callab wd.rect_changed_callback = p_callable; } -void DisplayServerOSX::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerMacOS::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -1953,7 +1972,7 @@ void DisplayServerOSX::window_set_window_event_callback(const Callable &p_callab wd.event_callback = p_callable; } -void DisplayServerOSX::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerMacOS::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -1961,21 +1980,21 @@ void DisplayServerOSX::window_set_input_event_callback(const Callable &p_callabl wd.input_event_callback = p_callable; } -void DisplayServerOSX::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerMacOS::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; wd.input_text_callback = p_callable; } -void DisplayServerOSX::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { +void DisplayServerMacOS::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; wd.drop_files_callback = p_callable; } -void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window) { +void DisplayServerMacOS::window_set_title(const String &p_title, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -1984,7 +2003,7 @@ 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) { +void DisplayServerMacOS::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -1993,7 +2012,7 @@ void DisplayServerOSX::window_set_mouse_passthrough(const Vector<Vector2> &p_reg wd.mpath = p_region; } -int DisplayServerOSX::window_get_current_screen(WindowID p_window) const { +int DisplayServerMacOS::window_get_current_screen(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), -1); const WindowData &wd = windows[p_window]; @@ -2002,12 +2021,16 @@ int DisplayServerOSX::window_get_current_screen(WindowID p_window) const { return (index == NSNotFound) ? 0 : index; } -void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window) { +void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; + if (window_get_current_screen(p_window) == p_screen) { + return; + } + bool was_fullscreen = false; if (wd.fullscreen) { // Temporary exit fullscreen mode to move window. @@ -2024,7 +2047,7 @@ void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window } } -void DisplayServerOSX::window_set_exclusive(WindowID p_window, bool p_exclusive) { +void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; @@ -2042,7 +2065,7 @@ void DisplayServerOSX::window_set_exclusive(WindowID p_window, bool p_exclusive) } } -Point2i DisplayServerOSX::window_get_position(WindowID p_window) const { +Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Point2i()); @@ -2065,7 +2088,7 @@ Point2i DisplayServerOSX::window_get_position(WindowID p_window) const { return pos; } -void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p_window) { +void DisplayServerMacOS::window_set_position(const Point2i &p_position, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2093,7 +2116,7 @@ void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); } -void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent) { +void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_parent) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(p_window == p_parent); @@ -2132,7 +2155,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent } } -void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) { +void DisplayServerMacOS::window_set_max_size(const Size2i p_size, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2152,7 +2175,7 @@ void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_windo } } -Size2i DisplayServerOSX::window_get_max_size(WindowID p_window) const { +Size2i DisplayServerMacOS::window_get_max_size(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); @@ -2160,7 +2183,7 @@ Size2i DisplayServerOSX::window_get_max_size(WindowID p_window) const { return wd.max_size; } -void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_window) { +void DisplayServerMacOS::window_set_min_size(const Size2i p_size, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2180,7 +2203,7 @@ void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_windo } } -Size2i DisplayServerOSX::window_get_min_size(WindowID p_window) const { +Size2i DisplayServerMacOS::window_get_min_size(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); @@ -2189,7 +2212,7 @@ Size2i DisplayServerOSX::window_get_min_size(WindowID p_window) const { return wd.min_size; } -void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) { +void DisplayServerMacOS::window_set_size(const Size2i p_size, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2213,7 +2236,7 @@ void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) { _update_window_style(wd); } -Size2i DisplayServerOSX::window_get_size(WindowID p_window) const { +Size2i DisplayServerMacOS::window_get_size(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); @@ -2221,7 +2244,7 @@ Size2i DisplayServerOSX::window_get_size(WindowID p_window) const { return wd.size; } -Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const { +Size2i DisplayServerMacOS::window_get_real_size(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); @@ -2230,7 +2253,7 @@ Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const { return Size2i(frame.size.width, frame.size.height) * screen_get_max_scale(); } -void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) { +void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2299,7 +2322,7 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) { } } -DisplayServer::WindowMode DisplayServerOSX::window_get_mode(WindowID p_window) const { +DisplayServer::WindowMode DisplayServerMacOS::window_get_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED); @@ -2321,11 +2344,11 @@ DisplayServer::WindowMode DisplayServerOSX::window_get_mode(WindowID p_window) c return WINDOW_MODE_WINDOWED; } -bool DisplayServerOSX::window_is_maximize_allowed(WindowID p_window) const { +bool DisplayServerMacOS::window_is_maximize_allowed(WindowID p_window) const { return true; } -void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { +void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2400,7 +2423,7 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo } } -bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) const { +bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), false); @@ -2436,12 +2459,12 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co return false; } -void DisplayServerOSX::window_request_attention(WindowID p_window) { +void DisplayServerMacOS::window_request_attention(WindowID p_window) { // It's app global, ignore window id. [NSApp requestUserAttention:NSCriticalRequest]; } -void DisplayServerOSX::window_move_to_foreground(WindowID p_window) { +void DisplayServerMacOS::window_move_to_foreground(WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2455,11 +2478,11 @@ void DisplayServerOSX::window_move_to_foreground(WindowID p_window) { } } -bool DisplayServerOSX::window_can_draw(WindowID p_window) const { +bool DisplayServerMacOS::window_can_draw(WindowID p_window) const { return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED; } -bool DisplayServerOSX::can_any_window_draw() const { +bool DisplayServerMacOS::can_any_window_draw() const { _THREAD_SAFE_METHOD_ for (const KeyValue<WindowID, WindowData> &E : windows) { @@ -2470,7 +2493,7 @@ bool DisplayServerOSX::can_any_window_draw() const { return false; } -void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_window) { +void DisplayServerMacOS::window_set_ime_active(const bool p_active, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2483,7 +2506,7 @@ void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_win } } -void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { +void DisplayServerMacOS::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -2492,7 +2515,7 @@ void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_ wd.im_position = p_pos; } -DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const { +DisplayServer::WindowID DisplayServerMacOS::get_window_at_screen_position(const Point2i &p_position) const { Point2i position = p_position; position.y *= -1; position += _get_screens_origin(); @@ -2507,7 +2530,7 @@ DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Po return INVALID_WINDOW_ID; } -int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { +int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { ERR_FAIL_COND_V(!windows.has(p_window), 0); switch (p_handle_type) { case DISPLAY_HANDLE: { @@ -2525,27 +2548,27 @@ int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, Win } } -void DisplayServerOSX::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { +void DisplayServerMacOS::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); windows[p_window].instance_id = p_instance; } -ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) const { +ObjectID DisplayServerMacOS::window_get_attached_instance_id(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), ObjectID()); return windows[p_window].instance_id; } -void DisplayServerOSX::gl_window_make_current(DisplayServer::WindowID p_window_id) { +void DisplayServerMacOS::gl_window_make_current(DisplayServer::WindowID p_window_id) { #if defined(GLES3_ENABLED) gl_manager->window_make_current(p_window_id); #endif } -void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { +void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(GLES3_ENABLED) if (gl_manager) { @@ -2559,7 +2582,7 @@ void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo #endif } -DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const { +DisplayServer::VSyncMode DisplayServerMacOS::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(GLES3_ENABLED) if (gl_manager) { @@ -2574,15 +2597,15 @@ DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_wind return DisplayServer::VSYNC_ENABLED; } -Point2i DisplayServerOSX::ime_get_selection() const { +Point2i DisplayServerMacOS::ime_get_selection() const { return im_selection; } -String DisplayServerOSX::ime_get_text() const { +String DisplayServerMacOS::ime_get_text() const { return im_text; } -void DisplayServerOSX::cursor_update_shape() { +void DisplayServerMacOS::cursor_update_shape() { _THREAD_SAFE_METHOD_ if (cursors[cursor_shape] != nullptr) { @@ -2646,7 +2669,7 @@ void DisplayServerOSX::cursor_update_shape() { } } -void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) { +void DisplayServerMacOS::cursor_set_shape(CursorShape p_shape) { _THREAD_SAFE_METHOD_ ERR_FAIL_INDEX(p_shape, CURSOR_MAX); @@ -2664,11 +2687,11 @@ void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) { cursor_update_shape(); } -DisplayServerOSX::CursorShape DisplayServerOSX::cursor_get_shape() const { +DisplayServerMacOS::CursorShape DisplayServerMacOS::cursor_get_shape() const { return cursor_shape; } -void DisplayServerOSX::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { _THREAD_SAFE_METHOD_ if (p_cursor.is_valid()) { @@ -2780,20 +2803,20 @@ void DisplayServerOSX::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu } } -bool DisplayServerOSX::get_swap_cancel_ok() { +bool DisplayServerMacOS::get_swap_cancel_ok() { return false; } -int DisplayServerOSX::keyboard_get_layout_count() const { +int DisplayServerMacOS::keyboard_get_layout_count() const { if (keyboard_layout_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts(); + const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts(); } return kbd_layouts.size(); } -void DisplayServerOSX::keyboard_set_current_layout(int p_index) { +void DisplayServerMacOS::keyboard_set_current_layout(int p_index) { if (keyboard_layout_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts(); + const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts(); } ERR_FAIL_INDEX(p_index, kbd_layouts.size()); @@ -2821,44 +2844,44 @@ void DisplayServerOSX::keyboard_set_current_layout(int p_index) { } } -int DisplayServerOSX::keyboard_get_current_layout() const { +int DisplayServerMacOS::keyboard_get_current_layout() const { if (keyboard_layout_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts(); + const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts(); } return current_layout; } -String DisplayServerOSX::keyboard_get_layout_language(int p_index) const { +String DisplayServerMacOS::keyboard_get_layout_language(int p_index) const { if (keyboard_layout_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts(); + const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts(); } ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); return kbd_layouts[p_index].code; } -String DisplayServerOSX::keyboard_get_layout_name(int p_index) const { +String DisplayServerMacOS::keyboard_get_layout_name(int p_index) const { if (keyboard_layout_dirty) { - const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts(); + const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts(); } ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); return kbd_layouts[p_index].name; } -Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const { +Key DisplayServerMacOS::keyboard_get_keycode_from_physical(Key p_keycode) const { if (p_keycode == Key::PAUSE) { return p_keycode; } Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; - unsigned int osx_keycode = KeyMappingOSX::unmap_key((Key)keycode_no_mod); - return (Key)(KeyMappingOSX::remap_key(osx_keycode, 0) | modifiers); + unsigned int macos_keycode = KeyMappingMacOS::unmap_key((Key)keycode_no_mod); + return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0) | modifiers); } -void DisplayServerOSX::process_events() { +void DisplayServerMacOS::process_events() { _THREAD_SAFE_METHOD_ while (true) { @@ -2901,7 +2924,7 @@ void DisplayServerOSX::process_events() { } } -void DisplayServerOSX::force_process_and_drop_events() { +void DisplayServerMacOS::force_process_and_drop_events() { _THREAD_SAFE_METHOD_ drop_events = true; @@ -2909,13 +2932,13 @@ void DisplayServerOSX::force_process_and_drop_events() { drop_events = false; } -void DisplayServerOSX::release_rendering_thread() { +void DisplayServerMacOS::release_rendering_thread() { } -void DisplayServerOSX::make_rendering_thread() { +void DisplayServerMacOS::make_rendering_thread() { } -void DisplayServerOSX::swap_buffers() { +void DisplayServerMacOS::swap_buffers() { #if defined(GLES3_ENABLED) if (gl_manager) { gl_manager->swap_buffers(); @@ -2923,7 +2946,7 @@ void DisplayServerOSX::swap_buffers() { #endif } -void DisplayServerOSX::set_native_icon(const String &p_filename) { +void DisplayServerMacOS::set_native_icon(const String &p_filename) { _THREAD_SAFE_METHOD_ Ref<FileAccess> f = FileAccess::open(p_filename, FileAccess::READ); @@ -2943,7 +2966,7 @@ void DisplayServerOSX::set_native_icon(const String &p_filename) { [NSApp setApplicationIconImage:icon]; } -void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) { +void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) { _THREAD_SAFE_METHOD_ Ref<Image> img = p_icon; @@ -2982,15 +3005,15 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) { [NSApp setApplicationIconImage:nsimg]; } -DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); +DisplayServer *DisplayServerMacOS::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + DisplayServer *ds = memnew(DisplayServerMacOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); if (r_error != OK) { OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.", "Unable to initialize Video driver"); } return ds; } -Vector<String> DisplayServerOSX::get_rendering_drivers_func() { +Vector<String> DisplayServerMacOS::get_rendering_drivers_func() { Vector<String> drivers; #if defined(VULKAN_ENABLED) @@ -3003,11 +3026,11 @@ Vector<String> DisplayServerOSX::get_rendering_drivers_func() { return drivers; } -void DisplayServerOSX::register_osx_driver() { - register_create_function("osx", create_func, get_rendering_drivers_func); +void DisplayServerMacOS::register_macos_driver() { + register_create_function("macos", create_func, get_rendering_drivers_func); } -DisplayServer::WindowID DisplayServerOSX::window_get_active_popup() const { +DisplayServer::WindowID DisplayServerMacOS::window_get_active_popup() const { const List<WindowID>::Element *E = popup_list.back(); if (E) { return E->get(); @@ -3016,7 +3039,7 @@ DisplayServer::WindowID DisplayServerOSX::window_get_active_popup() const { } } -void DisplayServerOSX::window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) { +void DisplayServerMacOS::window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); @@ -3024,7 +3047,7 @@ void DisplayServerOSX::window_set_popup_safe_rect(WindowID p_window, const Rect2 wd.parent_safe_rect = p_rect; } -Rect2i DisplayServerOSX::window_get_popup_safe_rect(WindowID p_window) const { +Rect2i DisplayServerMacOS::window_get_popup_safe_rect(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), Rect2i()); @@ -3032,7 +3055,7 @@ Rect2i DisplayServerOSX::window_get_popup_safe_rect(WindowID p_window) const { return wd.parent_safe_rect; } -void DisplayServerOSX::popup_open(WindowID p_window) { +void DisplayServerMacOS::popup_open(WindowID p_window) { _THREAD_SAFE_METHOD_ WindowData &wd = windows[p_window]; @@ -3050,7 +3073,7 @@ void DisplayServerOSX::popup_open(WindowID p_window) { } } if (C) { - send_window_event(windows[C->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + send_window_event(windows[C->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); } if (was_empty && popup_list.is_empty()) { @@ -3062,7 +3085,7 @@ void DisplayServerOSX::popup_open(WindowID p_window) { } } -void DisplayServerOSX::popup_close(WindowID p_window) { +void DisplayServerMacOS::popup_close(WindowID p_window) { _THREAD_SAFE_METHOD_ bool was_empty = popup_list.is_empty(); @@ -3072,7 +3095,7 @@ void DisplayServerOSX::popup_close(WindowID p_window) { WindowID win_id = E->get(); popup_list.erase(E); - send_window_event(windows[win_id], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + send_window_event(windows[win_id], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); E = F; } if (!was_empty && popup_list.is_empty()) { @@ -3081,7 +3104,7 @@ void DisplayServerOSX::popup_close(WindowID p_window) { } } -bool DisplayServerOSX::mouse_process_popups(bool p_close) { +bool DisplayServerMacOS::mouse_process_popups(bool p_close) { _THREAD_SAFE_METHOD_ bool was_empty = popup_list.is_empty(); @@ -3090,7 +3113,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) { // Close all popups. List<WindowID>::Element *E = popup_list.front(); if (E) { - send_window_event(windows[E->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + send_window_event(windows[E->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); closed = true; } if (!was_empty) { @@ -3122,7 +3145,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) { } } if (C) { - send_window_event(windows[C->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + send_window_event(windows[C->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); closed = true; } if (!was_empty && popup_list.is_empty()) { @@ -3133,7 +3156,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) { return closed; } -DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { +DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); r_error = OK; @@ -3160,7 +3183,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode CGDisplayRegisterReconfigurationCallback(_displays_arrangement_changed, nullptr); // Init TTS - tts = [[TTS_OSX alloc] init]; + tts = [[TTS_MacOS alloc] init]; NSMenuItem *menu_item; NSString *title; @@ -3214,8 +3237,8 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode #if defined(GLES3_ENABLED) if (rendering_driver == "opengl3") { - GLManager_OSX::ContextType opengl_api_type = GLManager_OSX::GLES_3_0_COMPATIBLE; - gl_manager = memnew(GLManager_OSX(opengl_api_type)); + GLManager_MacOS::ContextType opengl_api_type = GLManager_MacOS::GLES_3_0_COMPATIBLE; + gl_manager = memnew(GLManager_MacOS(opengl_api_type)); if (gl_manager->initialize() != OK) { memdelete(gl_manager); gl_manager = nullptr; @@ -3227,7 +3250,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode #endif #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { - context_vulkan = memnew(VulkanContextOSX); + context_vulkan = memnew(VulkanContextMacOS); if (context_vulkan->initialize() != OK) { memdelete(context_vulkan); context_vulkan = nullptr; @@ -3262,9 +3285,16 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode RendererCompositorRD::make_current(); } #endif + + screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); } -DisplayServerOSX::~DisplayServerOSX() { +DisplayServerMacOS::~DisplayServerMacOS() { + if (screen_keep_on_assertion) { + IOPMAssertionRelease(screen_keep_on_assertion); + screen_keep_on_assertion = kIOPMNullAssertionID; + } + // Destroy all windows. for (HashMap<WindowID, WindowData>::Iterator E = windows.begin(); E;) { HashMap<WindowID, WindowData>::Iterator F = E; diff --git a/platform/osx/export/codesign.cpp b/platform/macos/export/codesign.cpp index fd044c00cc..fd044c00cc 100644 --- a/platform/osx/export/codesign.cpp +++ b/platform/macos/export/codesign.cpp diff --git a/platform/osx/export/codesign.h b/platform/macos/export/codesign.h index 3a08c0ea86..fea7b117d0 100644 --- a/platform/osx/export/codesign.h +++ b/platform/macos/export/codesign.h @@ -38,8 +38,8 @@ // - Requirements code generator is not implemented (only hard-coded requirements for the ad-hoc signing is supported). // - RFC5652/CMS blob generation is not implemented, supports ad-hoc signing only. -#ifndef CODESIGN_H -#define CODESIGN_H +#ifndef MACOS_CODESIGN_H +#define MACOS_CODESIGN_H #include "core/crypto/crypto_core.h" #include "core/io/dir_access.h" @@ -365,4 +365,4 @@ public: #endif // MODULE_REGEX_ENABLED -#endif // CODESIGN_H +#endif // MACOS_CODESIGN_H diff --git a/platform/osx/export/export.cpp b/platform/macos/export/export.cpp index bd35b39e9e..ff7457081f 100644 --- a/platform/osx/export/export.cpp +++ b/platform/macos/export/export.cpp @@ -32,11 +32,11 @@ #include "export_plugin.h" -void register_osx_exporter() { +void register_macos_exporter() { EDITOR_DEF("export/macos/force_builtin_codesign", false); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::BOOL, "export/macos/force_builtin_codesign", PROPERTY_HINT_NONE)); - Ref<EditorExportPlatformOSX> platform; + Ref<EditorExportPlatformMacOS> platform; platform.instantiate(); EditorExport::get_singleton()->add_export_platform(platform); diff --git a/platform/iphone/export/export.h b/platform/macos/export/export.h index adb3c23957..260c691209 100644 --- a/platform/iphone/export/export.h +++ b/platform/macos/export/export.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IPHONE_EXPORT_H -#define IPHONE_EXPORT_H +#ifndef MACOS_EXPORT_H +#define MACOS_EXPORT_H -void register_iphone_exporter(); +void register_macos_exporter(); -#endif // IPHONE_EXPORT_H +#endif // MACOS_EXPORT_H diff --git a/platform/osx/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index a22d7e5e3d..bcc2636c07 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -32,12 +32,13 @@ #include "codesign.h" +#include "core/string/translation.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "modules/modules_enabled.gen.h" // For regex. -void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { +void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { if (p_preset->get("texture_format/s3tc")) { r_features->push_back("s3tc"); } @@ -47,11 +48,10 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> if (p_preset->get("texture_format/etc2")) { r_features->push_back("etc2"); } - - r_features->push_back("64"); + r_features->push_back(p_preset->get("binary_format/architecture")); } -bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { +bool EditorExportPlatformMacOS::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { // These options are not supported by built-in codesign, used on non macOS host. if (!OS::get_singleton()->has_feature("macos")) { if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) { @@ -68,7 +68,8 @@ bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_optio return true; } -void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) { +void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options) { + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "universal,x86_64,arm64", PROPERTY_USAGE_STORAGE), "universal")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); @@ -214,7 +215,7 @@ void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source, memcpy(&p_dest.write[ofs], result.ptr(), res_size); } -void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) { +void EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) { Ref<ImageTexture> it = memnew(ImageTexture); Vector<uint8_t> data; @@ -254,7 +255,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_ // Encode PNG icon. it->set_image(copy); String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png"); - ResourceSaver::save(path, it); + ResourceSaver::save(it, path); { Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ); @@ -320,7 +321,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_ p_data = data; } -void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) { +void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) { String str; String strnew; str.parse_utf8((const char *)plist.ptr(), plist.size()); @@ -407,14 +408,14 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset } /** - * If we're running the OSX version of the Godot editor we'll: + * If we're running the macOS version of the Godot editor we'll: * - export our application bundle to a temporary folder * - attempt to code sign it * - and then wrap it up in a DMG */ -Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) { -#ifdef OSX_ENABLED +Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) { +#ifdef MACOS_ENABLED List<String> args; args.push_back("altool"); @@ -468,7 +469,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset return OK; } -Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) { +Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) { bool force_builtin_codesign = EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign"); bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); @@ -476,7 +477,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese print_verbose("using built-in codesign..."); #ifdef MODULE_REGEX_ENABLED -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (p_preset->get("codesign/timestamp") && p_warn) { add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!")); } @@ -566,9 +567,9 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese } } -Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, +Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_should_error_on_non_code) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED static Vector<String> extensions_to_sign; if (extensions_to_sign.is_empty()) { @@ -615,7 +616,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset return OK; } -Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, +Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, const String &p_in_app_path, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, bool p_should_error_on_non_code_sign) { @@ -644,14 +645,14 @@ Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access, return err; } -Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, +Error EditorExportPlatformMacOS::_export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name, Ref<DirAccess> &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path) { Error error{ OK }; - const Vector<String> &osx_plugins{ p_editor_export_plugin->get_osx_plugin_files() }; - for (int i = 0; i < osx_plugins.size(); ++i) { - String src_path{ ProjectSettings::get_singleton()->globalize_path(osx_plugins[i]) }; + const Vector<String> &macos_plugins{ p_editor_export_plugin->get_macos_plugin_files() }; + for (int i = 0; i < macos_plugins.size(); ++i) { + String src_path{ ProjectSettings::get_singleton()->globalize_path(macos_plugins[i]) }; String path_in_app{ p_app_path_name + "/Contents/PlugIns/" + src_path.get_file() }; error = _copy_and_sign_files(dir_access, src_path, path_in_app, p_sign_enabled, p_preset, p_ent_path, false); if (error != OK) { @@ -661,7 +662,7 @@ Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p return error; } -Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) { +Error EditorExportPlatformMacOS::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) { List<String> args; if (FileAccess::exists(p_dmg_path)) { @@ -697,7 +698,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin return OK; } -Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) { +Error EditorExportPlatformMacOS::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE); if (f.is_null()) { add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Script Export"), vformat(TTR("Could not open file \"%s\"."), p_path)); @@ -706,19 +707,30 @@ Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset f->store_line("#!/bin/sh"); f->store_line("echo -ne '\\033c\\033]0;" + p_app_name + "\\a'"); - f->store_line("function realpath() { python -c \"import os,sys; print(os.path.realpath(sys.argv[1]))\" \"$0\"; }"); - f->store_line("base_path=\"$(dirname \"$(realpath \"$0\")\")\""); - f->store_line("\"$base_path/" + p_pkg_name + "\" \"$@\""); + f->store_line(""); + f->store_line("function app_realpath() {"); + f->store_line(" SOURCE=$1"); + f->store_line(" while [ -h \"$SOURCE\" ]; do"); + f->store_line(" DIR=$(dirname \"$SOURCE\")"); + f->store_line(" SOURCE=$(readlink \"$SOURCE\")"); + f->store_line(" [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE"); + f->store_line(" done"); + f->store_line(" echo \"$( cd -P \"$( dirname \"$SOURCE\" )\" >/dev/null 2>&1 && pwd )\""); + f->store_line("}"); + f->store_line(""); + f->store_line("BASE_PATH=\"$(app_realpath \"${BASH_SOURCE[0]}\")\""); + f->store_line("\"$BASE_PATH/" + p_pkg_name + "\" \"$@\""); + f->store_line(""); return OK; } -Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { +Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); String src_pkg_name; - EditorProgress ep("export", "Exporting for OSX", 3, true); + EditorProgress ep("export", "Exporting for macOS", 3, true); if (p_debug) { src_pkg_name = p_preset->get("custom_template/debug"); @@ -728,7 +740,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p if (src_pkg_name.is_empty()) { String err; - src_pkg_name = find_export_template("osx.zip", &err); + src_pkg_name = find_export_template("macos.zip", &err); if (src_pkg_name.is_empty()) { add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found.")); return ERR_FILE_NOT_FOUND; @@ -755,7 +767,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p int ret = unzGoToFirstFile(src_pkg_zip); - String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64"; + String architecture = p_preset->get("binary_format/architecture"); + String binary_to_use = "godot_macos_" + String(p_debug ? "debug" : "release") + "." + architecture; String pkg_name; if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { @@ -984,7 +997,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p unzCloseCurrentFile(src_pkg_zip); // Write. - file = file.replace_first("osx_template.app/", ""); + file = file.replace_first("macos_template.app/", ""); if (((info.external_fa >> 16L) & 0120000) == 0120000) { #ifndef UNIX_ENABLED @@ -1053,19 +1066,19 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } if (data.size() > 0) { - if (file.find("/data.mono.osx.64.release_debug/") != -1) { + if (file.find("/data.mono.macos.release_debug." + architecture + "/") != -1) { if (!p_debug) { ret = unzGoToNextFile(src_pkg_zip); continue; // skip } - file = file.replace("/data.mono.osx.64.release_debug/", "/GodotSharp/"); + file = file.replace("/data.mono.macos.release_debug." + architecture + "/", "/GodotSharp/"); } - if (file.find("/data.mono.osx.64.release/") != -1) { + if (file.find("/data.mono.macos.release." + architecture + "/") != -1) { if (p_debug) { ret = unzGoToNextFile(src_pkg_zip); continue; // skip } - file = file.replace("/data.mono.osx.64.release/", "/GodotSharp/"); + file = file.replace("/data.mono.macos.release." + architecture + "/", "/GodotSharp/"); } if (file.ends_with(".dylib")) { @@ -1299,7 +1312,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p bool ad_hoc = true; if (err == OK) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED String sign_identity = p_preset->get("codesign/identity"); #else String sign_identity = "-"; @@ -1330,7 +1343,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p Vector<Ref<EditorExportPlugin>> export_plugins{ EditorExport::get_singleton()->get_export_plugins() }; for (int i = 0; i < export_plugins.size(); ++i) { - err = _export_osx_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path); + err = _export_macos_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path); if (err != OK) { break; } @@ -1387,7 +1400,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool noto_enabled = p_preset->get("notarization/enable"); if (err == OK && noto_enabled) { if (export_format == "app") { @@ -1420,7 +1433,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p return err; } -void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) { +void EditorExportPlatformMacOS::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) { String dir = p_folder.is_empty() ? p_root_path : p_root_path.plus_file(p_folder); Ref<DirAccess> da = DirAccess::open(dir); @@ -1537,7 +1550,7 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String da->list_dir_end(); } -bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { +bool EditorExportPlatformMacOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { String err; bool valid = false; @@ -1560,7 +1573,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset // Look for export templates (official templates, check only is custom templates are not set). if (!dvalid || !rvalid) { - dvalid = exists_export_template("osx.zip", &err); + dvalid = exists_export_template("macos.zip", &err); rvalid = dvalid; // Both in the same ZIP. } @@ -1576,7 +1589,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset bool sign_enabled = p_preset->get("codesign/enable"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool noto_enabled = p_preset->get("notarization/enable"); bool ad_hoc = ((p_preset->get("codesign/identity") == "") || (p_preset->get("codesign/identity") == "-")); @@ -1665,9 +1678,9 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset return valid; } -EditorExportPlatformOSX::EditorExportPlatformOSX() { - logo = ImageTexture::create_from_image(memnew(Image(_osx_logo))); +EditorExportPlatformMacOS::EditorExportPlatformMacOS() { + logo = ImageTexture::create_from_image(memnew(Image(_macos_logo))); } -EditorExportPlatformOSX::~EditorExportPlatformOSX() { +EditorExportPlatformMacOS::~EditorExportPlatformMacOS() { } diff --git a/platform/osx/export/export_plugin.h b/platform/macos/export/export_plugin.h index ec97d4139f..21bc380d55 100644 --- a/platform/osx/export/export_plugin.h +++ b/platform/macos/export/export_plugin.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OSX_EXPORT_PLUGIN_H -#define OSX_EXPORT_PLUGIN_H +#ifndef MACOS_EXPORT_PLUGIN_H +#define MACOS_EXPORT_PLUGIN_H #include "core/config/project_settings.h" #include "core/io/dir_access.h" @@ -39,14 +39,14 @@ #include "core/io/zip_io.h" #include "core/os/os.h" #include "core/version.h" -#include "editor/editor_export.h" #include "editor/editor_settings.h" -#include "platform/osx/logo.gen.h" +#include "editor/export/editor_export.h" +#include "platform/macos/logo.gen.h" #include <sys/stat.h> -class EditorExportPlatformOSX : public EditorExportPlatform { - GDCLASS(EditorExportPlatformOSX, EditorExportPlatform); +class EditorExportPlatformMacOS : public EditorExportPlatform { + GDCLASS(EditorExportPlatformMacOS, EditorExportPlatform); int version_code = 0; @@ -61,7 +61,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { Error _copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, const String &p_in_app_path, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, bool p_should_error_on_non_code_sign); - Error _export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name, + Error _export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name, Ref<DirAccess> &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path); Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name); @@ -69,7 +69,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); bool use_codesign() const { return true; } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_dmg() const { return true; } #else bool use_dmg() const { return false; } @@ -99,7 +99,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { } protected: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; @@ -121,7 +121,7 @@ public: virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; - virtual void get_platform_features(List<String> *r_features) override { + virtual void get_platform_features(List<String> *r_features) const override { r_features->push_back("pc"); r_features->push_back("s3tc"); r_features->push_back("macos"); @@ -130,8 +130,8 @@ public: virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override { } - EditorExportPlatformOSX(); - ~EditorExportPlatformOSX(); + EditorExportPlatformMacOS(); + ~EditorExportPlatformMacOS(); }; -#endif +#endif // MACOS_EXPORT_PLUGIN_H diff --git a/platform/osx/export/lipo.cpp b/platform/macos/export/lipo.cpp index 82baf18c52..82baf18c52 100644 --- a/platform/osx/export/lipo.cpp +++ b/platform/macos/export/lipo.cpp diff --git a/platform/osx/export/lipo.h b/platform/macos/export/lipo.h index 0e419be17e..516ef99860 100644 --- a/platform/osx/export/lipo.h +++ b/platform/macos/export/lipo.h @@ -30,8 +30,8 @@ // Universal / Universal 2 fat binary file creator and extractor. -#ifndef LIPO_H -#define LIPO_H +#ifndef MACOS_LIPO_H +#define MACOS_LIPO_H #include "core/io/file_access.h" #include "core/object/ref_counted.h" @@ -73,4 +73,4 @@ public: #endif // MODULE_REGEX_ENABLED -#endif // LIPO_H +#endif // MACOS_LIPO_H diff --git a/platform/osx/export/macho.cpp b/platform/macos/export/macho.cpp index e6e67eff06..e6e67eff06 100644 --- a/platform/osx/export/macho.cpp +++ b/platform/macos/export/macho.cpp diff --git a/platform/osx/export/macho.h b/platform/macos/export/macho.h index 6cfc3c44f5..7ef0d9067e 100644 --- a/platform/osx/export/macho.h +++ b/platform/macos/export/macho.h @@ -30,8 +30,8 @@ // Mach-O binary object file format parser and editor. -#ifndef MACHO_H -#define MACHO_H +#ifndef MACOS_MACHO_H +#define MACOS_MACHO_H #include "core/crypto/crypto.h" #include "core/crypto/crypto_core.h" @@ -212,4 +212,4 @@ public: #endif // MODULE_REGEX_ENABLED -#endif // MACHO_H +#endif // MACOS_MACHO_H diff --git a/platform/osx/export/plist.cpp b/platform/macos/export/plist.cpp index 36de9dd34b..36de9dd34b 100644 --- a/platform/osx/export/plist.cpp +++ b/platform/macos/export/plist.cpp diff --git a/platform/osx/export/plist.h b/platform/macos/export/plist.h index ba9eaec196..79cb928d0a 100644 --- a/platform/osx/export/plist.h +++ b/platform/macos/export/plist.h @@ -30,8 +30,8 @@ // Property list file format (application/x-plist) parser, property list ASN-1 serialization. -#ifndef PLIST_H -#define PLIST_H +#ifndef MACOS_PLIST_H +#define MACOS_PLIST_H #include "core/crypto/crypto_core.h" #include "core/io/file_access.h" @@ -113,4 +113,4 @@ public: #endif // MODULE_REGEX_ENABLED -#endif // PLIST_H +#endif // MACOS_PLIST_H diff --git a/platform/osx/gl_manager_osx_legacy.h b/platform/macos/gl_manager_macos_legacy.h index 2d4913a7a6..8752086551 100644 --- a/platform/osx/gl_manager_osx_legacy.h +++ b/platform/macos/gl_manager_macos_legacy.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_manager_osx_legacy.h */ +/* gl_manager_macos_legacy.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GL_MANAGER_OSX_LEGACY_H -#define GL_MANAGER_OSX_LEGACY_H +#ifndef GL_MANAGER_MACOS_LEGACY_H +#define GL_MANAGER_MACOS_LEGACY_H -#if defined(OSX_ENABLED) && defined(GLES3_ENABLED) +#if defined(MACOS_ENABLED) && defined(GLES3_ENABLED) #include "core/error/error_list.h" #include "core/os/os.h" @@ -42,7 +42,7 @@ #import <ApplicationServices/ApplicationServices.h> #import <CoreVideo/CoreVideo.h> -class GLManager_OSX { +class GLManager_MacOS { public: enum ContextType { GLES_3_0_COMPATIBLE, @@ -89,9 +89,10 @@ public: void set_use_vsync(bool p_use); bool is_using_vsync() const; - GLManager_OSX(ContextType p_context_type); - ~GLManager_OSX(); + GLManager_MacOS(ContextType p_context_type); + ~GLManager_MacOS(); }; -#endif // OSX_ENABLED && GLES3_ENABLED -#endif // GL_MANAGER_OSX_LEGACY_H +#endif // MACOS_ENABLED && GLES3_ENABLED + +#endif // GL_MANAGER_MACOS_LEGACY_H diff --git a/platform/osx/gl_manager_osx_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm index c769d7f5c5..e6bb7aaa85 100644 --- a/platform/osx/gl_manager_osx_legacy.mm +++ b/platform/macos/gl_manager_macos_legacy.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_manager_osx_legacy.mm */ +/* gl_manager_macos_legacy.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gl_manager_osx_legacy.h" +#include "gl_manager_macos_legacy.h" -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #ifdef GLES3_ENABLED #include <stdio.h> #include <stdlib.h> -Error GLManager_OSX::create_context(GLWindow &win) { +Error GLManager_MacOS::create_context(GLWindow &win) { NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAClosestPolicy, @@ -62,7 +62,7 @@ Error GLManager_OSX::create_context(GLWindow &win) { return OK; } -Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) { +Error GLManager_MacOS::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) { GLWindow win; win.width = p_width; win.height = p_height; @@ -78,7 +78,7 @@ Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_vie return OK; } -void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) { +void GLManager_MacOS::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) { if (!windows.has(p_window_id)) { return; } @@ -102,7 +102,7 @@ void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_wid [win.context update]; } -int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) { +int GLManager_MacOS::window_get_width(DisplayServer::WindowID p_window_id) { if (!windows.has(p_window_id)) { return 0; } @@ -111,7 +111,7 @@ int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) { return win.width; } -int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) { +int GLManager_MacOS::window_get_height(DisplayServer::WindowID p_window_id) { if (!windows.has(p_window_id)) { return 0; } @@ -120,7 +120,7 @@ int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) { return win.height; } -void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) { +void GLManager_MacOS::window_destroy(DisplayServer::WindowID p_window_id) { if (!windows.has(p_window_id)) { return; } @@ -132,7 +132,7 @@ void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) { windows.erase(p_window_id); } -void GLManager_OSX::release_current() { +void GLManager_MacOS::release_current() { if (current_window == DisplayServer::INVALID_WINDOW_ID) { return; } @@ -140,7 +140,7 @@ void GLManager_OSX::release_current() { [NSOpenGLContext clearCurrentContext]; } -void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) { +void GLManager_MacOS::window_make_current(DisplayServer::WindowID p_window_id) { if (current_window == p_window_id) { return; } @@ -154,7 +154,7 @@ void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) { current_window = p_window_id; } -void GLManager_OSX::make_current() { +void GLManager_MacOS::make_current() { if (current_window == DisplayServer::INVALID_WINDOW_ID) { return; } @@ -166,13 +166,13 @@ void GLManager_OSX::make_current() { [win.context makeCurrentContext]; } -void GLManager_OSX::swap_buffers() { +void GLManager_MacOS::swap_buffers() { for (const KeyValue<DisplayServer::WindowID, GLWindow> &E : windows) { [E.value.context flushBuffer]; } } -void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) { +void GLManager_MacOS::window_update(DisplayServer::WindowID p_window_id) { if (!windows.has(p_window_id)) { return; } @@ -181,7 +181,7 @@ void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) { [win.context update]; } -void GLManager_OSX::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) { +void GLManager_MacOS::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) { if (!windows.has(p_window_id)) { return; } @@ -197,11 +197,11 @@ void GLManager_OSX::window_set_per_pixel_transparency_enabled(DisplayServer::Win [win.context update]; } -Error GLManager_OSX::initialize() { +Error GLManager_MacOS::initialize() { return OK; } -void GLManager_OSX::set_use_vsync(bool p_use) { +void GLManager_MacOS::set_use_vsync(bool p_use) { use_vsync = p_use; CGLContextObj ctx = CGLGetCurrentContext(); @@ -212,17 +212,17 @@ void GLManager_OSX::set_use_vsync(bool p_use) { } } -bool GLManager_OSX::is_using_vsync() const { +bool GLManager_MacOS::is_using_vsync() const { return use_vsync; } -GLManager_OSX::GLManager_OSX(ContextType p_context_type) { +GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) { context_type = p_context_type; } -GLManager_OSX::~GLManager_OSX() { +GLManager_MacOS::~GLManager_MacOS() { release_current(); } #endif // GLES3_ENABLED -#endif // OSX +#endif // MACOS_ENABLED diff --git a/platform/osx/godot_application.h b/platform/macos/godot_application.h index 8d48a659f3..8d48a659f3 100644 --- a/platform/osx/godot_application.h +++ b/platform/macos/godot_application.h diff --git a/platform/osx/godot_application.mm b/platform/macos/godot_application.mm index 13313a025a..3f71c77fd1 100644 --- a/platform/osx/godot_application.mm +++ b/platform/macos/godot_application.mm @@ -30,12 +30,12 @@ #include "godot_application.h" -#include "display_server_osx.h" +#include "display_server_macos.h" @implementation GodotApplication - (void)sendEvent:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { if ([event type] == NSEventTypeLeftMouseDown || [event type] == NSEventTypeRightMouseDown || [event type] == NSEventTypeOtherMouseDown) { if (ds->mouse_process_popups()) { diff --git a/platform/osx/godot_application_delegate.h b/platform/macos/godot_application_delegate.h index f5b67b580f..f5b67b580f 100644 --- a/platform/osx/godot_application_delegate.h +++ b/platform/macos/godot_application_delegate.h diff --git a/platform/osx/godot_application_delegate.mm b/platform/macos/godot_application_delegate.mm index 4d3558b273..bacdcc2bc4 100644 --- a/platform/osx/godot_application_delegate.mm +++ b/platform/macos/godot_application_delegate.mm @@ -30,8 +30,8 @@ #include "godot_application_delegate.h" -#include "display_server_osx.h" -#include "os_osx.h" +#include "display_server_macos.h" +#include "os_macos.h" @implementation GodotApplicationDelegate @@ -78,7 +78,7 @@ } - (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { - OS_OSX *os = (OS_OSX *)OS::get_singleton(); + OS_MacOS *os = (OS_MacOS *)OS::get_singleton(); if (!event || !os) { return; } @@ -114,7 +114,7 @@ } - (void)applicationDidResignActive:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { ds->mouse_process_popups(true); } @@ -130,14 +130,14 @@ } - (void)globalMenuCallback:(id)sender { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { return ds->menu_callback(sender); } } - (NSMenu *)applicationDockMenu:(NSApplication *)sender { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { return ds->get_dock_menu(); } else { @@ -146,15 +146,15 @@ } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { - ds->send_window_event(ds->get_window(DisplayServerOSX::MAIN_WINDOW_ID), DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + ds->send_window_event(ds->get_window(DisplayServerMacOS::MAIN_WINDOW_ID), DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); } return NSTerminateCancel; } - (void)showAbout:(id)sender { - OS_OSX *os = (OS_OSX *)OS::get_singleton(); + OS_MacOS *os = (OS_MacOS *)OS::get_singleton(); if (os && os->get_main_loop()) { os->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT); } diff --git a/platform/osx/godot_content_view.h b/platform/macos/godot_content_view.h index 353305aec1..353305aec1 100644 --- a/platform/osx/godot_content_view.h +++ b/platform/macos/godot_content_view.h diff --git a/platform/osx/godot_content_view.mm b/platform/macos/godot_content_view.mm index 018b90e629..dbed969901 100644 --- a/platform/osx/godot_content_view.mm +++ b/platform/macos/godot_content_view.mm @@ -30,8 +30,8 @@ #include "godot_content_view.h" -#include "display_server_osx.h" -#include "key_mapping_osx.h" +#include "display_server_macos.h" +#include "key_mapping_macos.h" @implementation GodotContentView @@ -56,7 +56,7 @@ return self; } -- (void)setWindowID:(DisplayServerOSX::WindowID)wid { +- (void)setWindowID:(DisplayServerMacOS::WindowID)wid { window_id = wid; } @@ -67,7 +67,7 @@ } - (void)updateLayer { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); ds->window_update(window_id); [super updateLayer]; } @@ -106,12 +106,12 @@ return; } - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (wd.im_active) { ime_input_event_in_progress = true; ds->update_im_text(Point2i(selectedRange.location, selectedRange.length), String::utf8([[marked_text mutableString] UTF8String])); @@ -126,12 +126,12 @@ ime_input_event_in_progress = false; [[marked_text mutableString] setString:@""]; - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (wd.im_active) { ds->update_im_text(Point2i(), String()); } @@ -150,12 +150,12 @@ } - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return NSMakeRect(0, 0, 0, 0); } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); const NSRect content_rect = [wd.window_view frame]; const float scale = ds->screen_get_max_scale(); NSRect point_in_window_rect = NSMakeRect(wd.im_position.x / scale, content_rect.size.height - (wd.im_position.y / scale) - 1, 0, 0); @@ -191,7 +191,7 @@ return; } - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { [self cancelComposition]; return; @@ -210,10 +210,10 @@ continue; } - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; - ke.osx_state = [event modifierFlags]; + ke.macos_state = [event modifierFlags]; ke.pressed = true; ke.echo = false; ke.raw = false; // IME input event. @@ -237,12 +237,12 @@ } - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return NO; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (!wd.drop_files_callback.is_null()) { Vector<String> files; NSPasteboard *pboard = [sender draggingPasteboard]; @@ -267,7 +267,7 @@ Variant *vp = &v; Variant ret; Callable::CallError ce; - wd.drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + wd.drop_files_callback.callp((const Variant **)&vp, 1, ret, ce); } return NO; @@ -276,12 +276,12 @@ // MARK: Focus - (BOOL)canBecomeKeyView { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return YES; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); return !wd.no_focus && !wd.is_popup; } @@ -292,7 +292,7 @@ // MARK: Mouse - (void)cursorUpdate:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds) { return; } @@ -301,12 +301,12 @@ } - (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index mask:(MouseButton)mask pressed:(bool)pressed { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); MouseButton last_button_state = ds->mouse_get_button_state(); if (pressed) { @@ -356,12 +356,12 @@ } - (void)mouseMoved:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); NSPoint delta = NSMakePoint([event deltaX], [event deltaY]); NSPoint mpos = [event locationInWindow]; @@ -438,38 +438,38 @@ } - (void)mouseExited:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) { - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_EXIT); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_MOUSE_EXIT); } } - (void)mouseEntered:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) { - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_ENTER); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_MOUSE_ENTER); } ds->cursor_update_shape(); } - (void)magnifyWithEvent:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); Ref<InputEventMagnifyGesture> ev; ev.instantiate(); @@ -497,12 +497,12 @@ // MARK: Keyboard - (void)keyDown:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ignore_momentum_scroll = true; @@ -511,7 +511,7 @@ NSString *characters = [event characters]; NSUInteger length = [characters length]; - if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]))) { + if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]))) { // Fallback unicode character handler used if IME is not active. Char16String text; text.resize([characters length] + 1); @@ -523,28 +523,28 @@ for (int i = 0; i < u32text.length(); i++) { const char32_t codepoint = u32text[i]; - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; - ke.osx_state = [event modifierFlags]; + ke.macos_state = [event modifierFlags]; ke.pressed = true; ke.echo = [event isARepeat]; - ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]); - ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]); + ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]); + ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.raw = true; ke.unicode = codepoint; ds->push_to_key_event_buffer(ke); } } else { - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; - ke.osx_state = [event modifierFlags]; + ke.macos_state = [event modifierFlags]; ke.pressed = true; ke.echo = [event isARepeat]; - ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]); - ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]); + ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]); + ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.raw = false; ke.unicode = 0; @@ -559,7 +559,7 @@ } - (void)flagsChanged:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } @@ -567,7 +567,7 @@ // Ignore all input if IME input is in progress if (!ime_input_event_in_progress) { - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; ke.echo = false; @@ -608,9 +608,9 @@ return; } - ke.osx_state = mod; - ke.keycode = KeyMappingOSX::remap_key(key, mod); - ke.physical_keycode = KeyMappingOSX::translate_key(key); + ke.macos_state = mod; + ke.keycode = KeyMappingMacOS::remap_key(key, mod); + ke.physical_keycode = KeyMappingMacOS::translate_key(key); ke.unicode = 0; ds->push_to_key_event_buffer(ke); @@ -618,12 +618,12 @@ } - (void)keyUp:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); // Ignore all input if IME input is in progress. if (!ime_input_event_in_progress) { @@ -631,7 +631,7 @@ NSUInteger length = [characters length]; // Fallback unicode character handler used if IME is not active. - if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]))) { + if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]))) { Char16String text; text.resize([characters length] + 1); [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])]; @@ -641,28 +641,28 @@ for (int i = 0; i < u32text.length(); i++) { const char32_t codepoint = u32text[i]; - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; - ke.osx_state = [event modifierFlags]; + ke.macos_state = [event modifierFlags]; ke.pressed = false; ke.echo = [event isARepeat]; - ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]); - ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]); + ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]); + ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.raw = true; ke.unicode = codepoint; ds->push_to_key_event_buffer(ke); } } else { - DisplayServerOSX::KeyEvent ke; + DisplayServerMacOS::KeyEvent ke; ke.window_id = window_id; - ke.osx_state = [event modifierFlags]; + ke.macos_state = [event modifierFlags]; ke.pressed = false; ke.echo = [event isARepeat]; - ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]); - ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]); + ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]); + ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.raw = true; ke.unicode = 0; @@ -674,12 +674,12 @@ // MARK: Scroll and pan - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); MouseButton mask = mouse_button_to_mask(button); Ref<InputEventMouseButton> sc; @@ -713,12 +713,12 @@ } - (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); Ref<InputEventPanGesture> pg; pg.instantiate(); @@ -732,12 +732,12 @@ } - (void)scrollWheel:(NSEvent *)event { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ds->update_mouse_pos(wd, [event locationInWindow]); double delta_x = [event scrollingDeltaX]; diff --git a/platform/osx/godot_main_osx.mm b/platform/macos/godot_main_macos.mm index 722928ad60..66071f1404 100644 --- a/platform/osx/godot_main_osx.mm +++ b/platform/macos/godot_main_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_main_osx.mm */ +/* godot_main_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #include "main/main.h" -#include "os_osx.h" +#include "os_macos.h" #include <string.h> #include <unistd.h> @@ -68,7 +68,7 @@ int main(int argc, char **argv) { printf("Current path: %s\n", cwd); #endif - OS_OSX os; + OS_MacOS os; Error err; // We must override main when testing is enabled. diff --git a/platform/osx/godot_menu_item.h b/platform/macos/godot_menu_item.h index 2c12897f10..2c12897f10 100644 --- a/platform/osx/godot_menu_item.h +++ b/platform/macos/godot_menu_item.h diff --git a/platform/osx/godot_window.h b/platform/macos/godot_window.h index 16ff101142..9fc5599e86 100644 --- a/platform/osx/godot_window.h +++ b/platform/macos/godot_window.h @@ -44,4 +44,4 @@ @end -#endif //GODOT_WINDOW_H +#endif // GODOT_WINDOW_H diff --git a/platform/osx/godot_window.mm b/platform/macos/godot_window.mm index d43853a94b..e205e7546d 100644 --- a/platform/osx/godot_window.mm +++ b/platform/macos/godot_window.mm @@ -30,7 +30,7 @@ #include "godot_window.h" -#include "display_server_osx.h" +#include "display_server_macos.h" @implementation GodotWindow @@ -40,29 +40,29 @@ return self; } -- (void)setWindowID:(DisplayServerOSX::WindowID)wid { +- (void)setWindowID:(DisplayServerMacOS::WindowID)wid { window_id = wid; } - (BOOL)canBecomeKeyWindow { // Required for NSWindowStyleMaskBorderless windows. - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return YES; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); return !wd.no_focus && !wd.is_popup; } - (BOOL)canBecomeMainWindow { // Required for NSWindowStyleMaskBorderless windows. - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return YES; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); return !wd.no_focus && !wd.is_popup; } diff --git a/platform/osx/godot_window_delegate.h b/platform/macos/godot_window_delegate.h index 8a1f681fcd..98c226aa2f 100644 --- a/platform/osx/godot_window_delegate.h +++ b/platform/macos/godot_window_delegate.h @@ -44,4 +44,4 @@ @end -#endif //GODOT_WINDOW_DELEGATE_H +#endif // GODOT_WINDOW_DELEGATE_H diff --git a/platform/osx/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm index 521127f01b..2d9329ab3c 100644 --- a/platform/osx/godot_window_delegate.mm +++ b/platform/macos/godot_window_delegate.mm @@ -30,7 +30,7 @@ #include "godot_window_delegate.h" -#include "display_server_osx.h" +#include "display_server_macos.h" @implementation GodotWindowDelegate @@ -39,42 +39,42 @@ } - (BOOL)windowShouldClose:(id)sender { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return YES; } - ds->send_window_event(ds->get_window(window_id), DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + ds->send_window_event(ds->get_window(window_id), DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST); return NO; } - (void)windowWillClose:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } ds->popup_close(window_id); - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); while (wd.transient_children.size()) { - ds->window_set_transient(*wd.transient_children.begin(), DisplayServerOSX::INVALID_WINDOW_ID); + ds->window_set_transient(*wd.transient_children.begin(), DisplayServerMacOS::INVALID_WINDOW_ID); } - if (wd.transient_parent != DisplayServerOSX::INVALID_WINDOW_ID) { - ds->window_set_transient(window_id, DisplayServerOSX::INVALID_WINDOW_ID); + if (wd.transient_parent != DisplayServerMacOS::INVALID_WINDOW_ID) { + ds->window_set_transient(window_id, DisplayServerMacOS::INVALID_WINDOW_ID); } ds->window_destroy(window_id); } - (void)windowDidEnterFullScreen:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); wd.fullscreen = true; // Reset window size limits. [wd.window_object setContentMinSize:NSMakeSize(0, 0)]; @@ -85,12 +85,12 @@ } - (void)windowDidExitFullScreen:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); wd.fullscreen = false; // Set window size limits. @@ -119,12 +119,12 @@ } - (void)windowDidChangeBackingProperties:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); CGFloat new_scale_factor = [wd.window_object backingScaleFactor]; CGFloat old_scale_factor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; @@ -137,7 +137,7 @@ wd.size.width = content_rect.size.width * scale; wd.size.height = content_rect.size.height * scale; - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_DPI_CHANGE); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_DPI_CHANGE); CALayer *layer = [wd.window_view layer]; if (layer) { @@ -150,26 +150,26 @@ } - (void)windowWillStartLiveResize:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { ds->set_is_resizing(true); } } - (void)windowDidEndLiveResize:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (ds) { ds->set_is_resizing(false); } } - (void)windowDidResize:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); const NSRect content_rect = [wd.window_view frame]; const float scale = ds->screen_get_max_scale(); wd.size.width = content_rect.size.width * scale; @@ -187,17 +187,17 @@ Variant *sizep = &size; Variant ret; Callable::CallError ce; - wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + wd.rect_changed_callback.callp((const Variant **)&sizep, 1, ret, ce); } } - (void)windowDidMove:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ds->release_pressed_events(); if (!wd.rect_changed_callback.is_null()) { @@ -205,17 +205,17 @@ Variant *sizep = &size; Variant ret; Callable::CallError ce; - wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + wd.rect_changed_callback.callp((const Variant **)&sizep, 1, ret, ce); } } - (void)windowDidBecomeKey:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if (ds->mouse_get_mode() == DisplayServer::MOUSE_MODE_CAPTURED) { const NSRect content_rect = [wd.window_view frame]; @@ -228,43 +228,43 @@ } ds->set_last_focused_window(window_id); - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN); } - (void)windowDidResignKey:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ds->release_pressed_events(); - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT); } - (void)windowDidMiniaturize:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ds->release_pressed_events(); - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT); } - (void)windowDidDeminiaturize:(NSNotification *)notification { - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; } - DisplayServerOSX::WindowData &wd = ds->get_window(window_id); + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); ds->set_last_focused_window(window_id); - ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN); } @end diff --git a/platform/osx/joypad_osx.cpp b/platform/macos/joypad_macos.cpp index be9567e17c..1ddcfec1b5 100644 --- a/platform/osx/joypad_osx.cpp +++ b/platform/macos/joypad_macos.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad_osx.cpp */ +/* joypad_macos.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "joypad_osx.h" +#include "joypad_macos.h" #include <machine/endian.h> #define GODOT_JOY_LOOP_RUN_MODE CFSTR("GodotJoypad") -static JoypadOSX *self = nullptr; +static JoypadMacOS *self = nullptr; joypad::joypad() { ff_constant_force.lMagnitude = 10000; @@ -235,7 +235,7 @@ static bool is_joypad(IOHIDDeviceRef p_device_ref) { return true; } -void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) { +void JoypadMacOS::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) { if (p_res != kIOReturnSuccess || have_device(p_device)) { return; } @@ -258,7 +258,7 @@ void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) { IOHIDDeviceScheduleWithRunLoop(p_device, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE); } -void JoypadOSX::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) { +void JoypadMacOS::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) { int device = get_joy_ref(p_device); ERR_FAIL_COND(device == -1); @@ -278,7 +278,7 @@ static String _hex_str(uint8_t p_byte) { return ret; } -bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) { +bool JoypadMacOS::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) { p_joy->device_ref = p_device_ref; // Get device name. String name; @@ -445,7 +445,7 @@ static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offse return hat_value; } -void JoypadOSX::poll_joypads() const { +void JoypadMacOS::poll_joypads() const { while (CFRunLoopRunInMode(GODOT_JOY_LOOP_RUN_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) { // No-op. Pending callbacks will fire. } @@ -456,7 +456,7 @@ static float axis_correct(int p_value, int p_min, int p_max) { return 2.0f * (p_value - p_min) / (p_max - p_min) - 1.0f; } -void JoypadOSX::process_joypads() { +void JoypadMacOS::process_joypads() { poll_joypads(); for (int i = 0; i < device_list.size(); i++) { @@ -494,7 +494,7 @@ void JoypadOSX::process_joypads() { } } -void JoypadOSX::joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp) { +void JoypadMacOS::joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp) { joypad *joy = &device_list.write[get_joy_index(p_id)]; joy->ff_timestamp = p_timestamp; joy->ff_effect.dwDuration = p_duration * FF_SECONDS; @@ -503,13 +503,13 @@ void JoypadOSX::joypad_vibration_start(int p_id, float p_magnitude, float p_dura FFEffectStart(joy->ff_object, 1, 0); } -void JoypadOSX::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { +void JoypadMacOS::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { joypad *joy = &device_list.write[get_joy_index(p_id)]; joy->ff_timestamp = p_timestamp; FFEffectStop(joy->ff_object); } -int JoypadOSX::get_joy_index(int p_id) const { +int JoypadMacOS::get_joy_index(int p_id) const { for (int i = 0; i < device_list.size(); i++) { if (device_list[i].id == p_id) { return i; @@ -518,7 +518,7 @@ int JoypadOSX::get_joy_index(int p_id) const { return -1; } -int JoypadOSX::get_joy_ref(IOHIDDeviceRef p_device) const { +int JoypadMacOS::get_joy_ref(IOHIDDeviceRef p_device) const { for (int i = 0; i < device_list.size(); i++) { if (device_list[i].device_ref == p_device) { return i; @@ -527,7 +527,7 @@ int JoypadOSX::get_joy_ref(IOHIDDeviceRef p_device) const { return -1; } -bool JoypadOSX::have_device(IOHIDDeviceRef p_device) const { +bool JoypadMacOS::have_device(IOHIDDeviceRef p_device) const { for (int i = 0; i < device_list.size(); i++) { if (device_list[i].device_ref == p_device) { return true; @@ -561,7 +561,7 @@ static CFDictionaryRef create_match_dictionary(const UInt32 page, const UInt32 u return retval; } -void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const { +void JoypadMacOS::config_hid_manager(CFArrayRef p_matching_array) const { CFRunLoopRef runloop = CFRunLoopGetCurrent(); IOReturn ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); ERR_FAIL_COND(ret != kIOReturnSuccess); @@ -576,7 +576,7 @@ void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const { } } -JoypadOSX::JoypadOSX(Input *in) { +JoypadMacOS::JoypadMacOS(Input *in) { self = this; input = in; @@ -604,7 +604,7 @@ JoypadOSX::JoypadOSX(Input *in) { } } -JoypadOSX::~JoypadOSX() { +JoypadMacOS::~JoypadMacOS() { for (int i = 0; i < device_list.size(); i++) { device_list.write[i].free(); } diff --git a/platform/osx/joypad_osx.h b/platform/macos/joypad_macos.h index 3f89048ce6..4b14fed6d5 100644 --- a/platform/osx/joypad_osx.h +++ b/platform/macos/joypad_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad_osx.h */ +/* joypad_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JOYPADOSX_H -#define JOYPADOSX_H +#ifndef JOYPAD_MACOS_H +#define JOYPAD_MACOS_H #ifdef MACOS_10_0_4 #import <IOKit/hidsystem/IOHIDUsageTables.h> @@ -88,7 +88,7 @@ struct joypad { joypad(); }; -class JoypadOSX { +class JoypadMacOS { enum { JOYPADS_MAX = 16, }; @@ -117,8 +117,8 @@ public: void _device_added(IOReturn p_res, IOHIDDeviceRef p_device); void _device_removed(IOReturn p_res, IOHIDDeviceRef p_device); - JoypadOSX(Input *in); - ~JoypadOSX(); + JoypadMacOS(Input *in); + ~JoypadMacOS(); }; -#endif // JOYPADOSX_H +#endif // JOYPAD_MACOS_H diff --git a/platform/osx/key_mapping_osx.h b/platform/macos/key_mapping_macos.h index 252cc907bb..fc5b791e44 100644 --- a/platform/osx/key_mapping_osx.h +++ b/platform/macos/key_mapping_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_osx.h */ +/* key_mapping_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef KEY_MAPPING_OSX_H -#define KEY_MAPPING_OSX_H +#ifndef KEY_MAPPING_MACOS_H +#define KEY_MAPPING_MACOS_H #include "core/os/keyboard.h" -class KeyMappingOSX { - KeyMappingOSX() {} +class KeyMappingMacOS { + KeyMappingMacOS() {} static bool is_numpad_key(unsigned int key); @@ -49,4 +49,4 @@ public: static unsigned int keycode_get_native_mask(Key p_keycode); }; -#endif // KEY_MAPPING_OSX_H +#endif // KEY_MAPPING_MACOS_H diff --git a/platform/osx/key_mapping_osx.mm b/platform/macos/key_mapping_macos.mm index 0bf6bc7d1c..f6cff7124b 100644 --- a/platform/osx/key_mapping_osx.mm +++ b/platform/macos/key_mapping_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_osx.mm */ +/* key_mapping_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "key_mapping_osx.h" +#include "key_mapping_macos.h" #import <Carbon/Carbon.h> #import <Cocoa/Cocoa.h> -bool KeyMappingOSX::is_numpad_key(unsigned int key) { +bool KeyMappingMacOS::is_numpad_key(unsigned int key) { static const unsigned int table[] = { 0x41, /* kVK_ANSI_KeypadDecimal */ 0x43, /* kVK_ANSI_KeypadMultiply */ @@ -65,7 +65,7 @@ bool KeyMappingOSX::is_numpad_key(unsigned int key) { } // Keyboard symbol translation table. -static const Key _osx_to_godot_table[128] = { +static const Key _macos_to_godot_table[128] = { /* 00 */ Key::A, /* 01 */ Key::S, /* 02 */ Key::D, @@ -197,18 +197,18 @@ static const Key _osx_to_godot_table[128] = { }; // Translates a OS X keycode to a Godot keycode. -Key KeyMappingOSX::translate_key(unsigned int key) { +Key KeyMappingMacOS::translate_key(unsigned int key) { if (key >= 128) { return Key::UNKNOWN; } - return _osx_to_godot_table[key]; + return _macos_to_godot_table[key]; } -// Translates a Godot keycode back to a OSX keycode. -unsigned int KeyMappingOSX::unmap_key(Key key) { +// Translates a Godot keycode back to a macOS keycode. +unsigned int KeyMappingMacOS::unmap_key(Key key) { for (int i = 0; i <= 126; i++) { - if (_osx_to_godot_table[i] == key) { + if (_macos_to_godot_table[i] == key) { return i; } } @@ -279,7 +279,7 @@ static const _KeyCodeMap _keycodes[55] = { }; // Remap key according to current keyboard layout. -Key KeyMappingOSX::remap_key(unsigned int key, unsigned int state) { +Key KeyMappingMacOS::remap_key(unsigned int key, unsigned int state) { if (is_numpad_key(key)) { return translate_key(key); } @@ -463,7 +463,7 @@ static const _KeyCodeText _native_keycodes[] = { /* clang-format on */ }; -String KeyMappingOSX::keycode_get_native_string(Key p_keycode) { +String KeyMappingMacOS::keycode_get_native_string(Key p_keycode) { const _KeyCodeText *kct = &_native_keycodes[0]; while (kct->text) { @@ -475,7 +475,7 @@ String KeyMappingOSX::keycode_get_native_string(Key p_keycode) { return String(); } -unsigned int KeyMappingOSX::keycode_get_native_mask(Key p_keycode) { +unsigned int KeyMappingMacOS::keycode_get_native_mask(Key p_keycode) { unsigned int mask = 0; if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE) { mask |= NSEventModifierFlagControl; diff --git a/platform/osx/logo.png b/platform/macos/logo.png Binary files differindex b5a660b165..b5a660b165 100644 --- a/platform/osx/logo.png +++ b/platform/macos/logo.png diff --git a/platform/osx/osx_terminal_logger.h b/platform/macos/macos_terminal_logger.h index 8413509c4b..a811a5cbaf 100644 --- a/platform/osx/osx_terminal_logger.h +++ b/platform/macos/macos_terminal_logger.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_terminal_logger.h */ +/* macos_terminal_logger.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OSX_TERMINAL_LOGGER_H -#define OSX_TERMINAL_LOGGER_H +#ifndef MACOS_TERMINAL_LOGGER_H +#define MACOS_TERMINAL_LOGGER_H -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #include "core/io/logger.h" -class OSXTerminalLogger : public StdLogger { +class MacOSTerminalLogger : public StdLogger { public: virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) override; }; -#endif // OSX_ENABLED -#endif // OSX_TERMINAL_LOGGER_H +#endif // MACOS_ENABLED + +#endif // MACOS_TERMINAL_LOGGER_H diff --git a/platform/osx/osx_terminal_logger.mm b/platform/macos/macos_terminal_logger.mm index 48e26f42bf..b5ea2938ee 100644 --- a/platform/osx/osx_terminal_logger.mm +++ b/platform/macos/macos_terminal_logger.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_terminal_logger.mm */ +/* macos_terminal_logger.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "osx_terminal_logger.h" +#include "macos_terminal_logger.h" -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #include <os/log.h> -void OSXTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { +void MacOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { if (!should_log(true)) { return; } @@ -79,4 +79,4 @@ void OSXTerminalLogger::log_error(const char *p_function, const char *p_file, in } } -#endif // OSX_ENABLED +#endif // MACOS_ENABLED diff --git a/platform/osx/os_osx.h b/platform/macos/os_macos.h index b105be4a06..a1eb0f7f69 100644 --- a/platform/osx/os_osx.h +++ b/platform/macos/os_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* os_osx.h */ +/* os_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OS_OSX_H -#define OS_OSX_H +#ifndef OS_MACOS_H +#define OS_MACOS_H #include "core/input/input.h" -#include "crash_handler_osx.h" +#include "crash_handler_macos.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/coremidi/midi_driver_coremidi.h" #include "drivers/unix/os_unix.h" -#include "joypad_osx.h" +#include "joypad_macos.h" #include "servers/audio_server.h" -class OS_OSX : public OS_Unix { +class OS_MacOS : public OS_Unix { bool force_quit = false; - JoypadOSX *joypad_osx = nullptr; + JoypadMacOS *joypad_macos = nullptr; #ifdef COREAUDIO_ENABLED AudioDriverCoreAudio audio_driver; @@ -97,6 +97,8 @@ public: virtual String get_locale() const override; + virtual Vector<String> get_system_fonts() const override; + virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override; virtual String get_executable_path() const override; virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override; virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override; @@ -113,8 +115,8 @@ public: void run(); - OS_OSX(); - ~OS_OSX(); + OS_MacOS(); + ~OS_MacOS(); }; -#endif +#endif // OS_MACOS_H diff --git a/platform/osx/os_osx.mm b/platform/macos/os_macos.mm index 5230ed4155..cc550043de 100644 --- a/platform/osx/os_osx.mm +++ b/platform/macos/os_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* os_osx.mm */ +/* os_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "os_osx.h" +#include "os_macos.h" #include "core/version_generated.gen.h" #include "main/main.h" -#include "dir_access_osx.h" -#include "display_server_osx.h" +#include "dir_access_macos.h" +#include "display_server_macos.h" #include "godot_application.h" #include "godot_application_delegate.h" -#include "osx_terminal_logger.h" +#include "macos_terminal_logger.h" #include <dlfcn.h> #include <libproc.h> @@ -45,7 +45,7 @@ #include <os/log.h> #include <sys/sysctl.h> -_FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) { +_FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) { // Append framework executable name, or return as is if p_path is not a framework. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (da->dir_exists(p_path) && da->file_exists(p_path.plus_file(p_path.get_file().get_basename()))) { @@ -55,10 +55,10 @@ _FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) { } } -void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) { +void OS_MacOS::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) { // Prevent main loop from sleeping and redraw window during resize / modal popups. - DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton(); + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (get_singleton()->get_main_loop() && ds && (get_singleton()->get_render_thread_mode() != RENDER_SEPARATE_THREAD || !ds->get_is_resizing())) { Main::force_redraw(); if (!Main::is_iterating()) { // Avoid cyclic loop. @@ -69,13 +69,13 @@ void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActi CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping. } -void OS_OSX::initialize() { +void OS_MacOS::initialize() { crash_handler.initialize(); initialize_core(); } -String OS_OSX::get_processor_name() const { +String OS_MacOS::get_processor_name() const { char buffer[256]; size_t buffer_len = 256; if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) { @@ -84,35 +84,35 @@ String OS_OSX::get_processor_name() const { ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string.")); } -void OS_OSX::initialize_core() { +void OS_MacOS::initialize_core() { OS_Unix::initialize_core(); - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_RESOURCES); - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_USERDATA); - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_FILESYSTEM); + DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_USERDATA); + DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_FILESYSTEM); } -void OS_OSX::finalize() { +void OS_MacOS::finalize() { #ifdef COREMIDI_ENABLED midi_driver.close(); #endif delete_main_loop(); - if (joypad_osx) { - memdelete(joypad_osx); + if (joypad_macos) { + memdelete(joypad_macos); } } -void OS_OSX::initialize_joypads() { - joypad_osx = memnew(JoypadOSX(Input::get_singleton())); +void OS_MacOS::initialize_joypads() { + joypad_macos = memnew(JoypadMacOS(Input::get_singleton())); } -void OS_OSX::set_main_loop(MainLoop *p_main_loop) { +void OS_MacOS::set_main_loop(MainLoop *p_main_loop) { main_loop = p_main_loop; } -void OS_OSX::delete_main_loop() { +void OS_MacOS::delete_main_loop() { if (!main_loop) { return; } @@ -121,19 +121,19 @@ void OS_OSX::delete_main_loop() { main_loop = nullptr; } -void OS_OSX::set_cmdline_platform_args(const List<String> &p_args) { +void OS_MacOS::set_cmdline_platform_args(const List<String> &p_args) { launch_service_args = p_args; } -List<String> OS_OSX::get_cmdline_platform_args() const { +List<String> OS_MacOS::get_cmdline_platform_args() const { return launch_service_args; } -String OS_OSX::get_name() const { +String OS_MacOS::get_name() const { return "macOS"; } -void OS_OSX::alert(const String &p_alert, const String &p_title) { +void OS_MacOS::alert(const String &p_alert, const String &p_title) { NSAlert *window = [[NSAlert alloc] init]; NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()]; @@ -150,7 +150,7 @@ void OS_OSX::alert(const String &p_alert, const String &p_title) { } } -Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { +Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { String path = get_framework_executable(p_path); if (!FileAccess::exists(path)) { @@ -173,11 +173,11 @@ Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, return OK; } -MainLoop *OS_OSX::get_main_loop() const { +MainLoop *OS_MacOS::get_main_loop() const { return main_loop; } -String OS_OSX::get_config_path() const { +String OS_MacOS::get_config_path() const { // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_CONFIG_HOME")) { if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) { @@ -192,7 +192,7 @@ String OS_OSX::get_config_path() const { return "."; } -String OS_OSX::get_data_path() const { +String OS_MacOS::get_data_path() const { // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_DATA_HOME")) { if (get_environment("XDG_DATA_HOME").is_absolute_path()) { @@ -204,7 +204,7 @@ String OS_OSX::get_data_path() const { return get_config_path(); } -String OS_OSX::get_cache_path() const { +String OS_MacOS::get_cache_path() const { // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_CACHE_HOME")) { if (get_environment("XDG_CACHE_HOME").is_absolute_path()) { @@ -219,7 +219,7 @@ String OS_OSX::get_cache_path() const { return get_config_path(); } -String OS_OSX::get_bundle_resource_dir() const { +String OS_MacOS::get_bundle_resource_dir() const { String ret; NSBundle *main = [NSBundle mainBundle]; @@ -230,7 +230,7 @@ String OS_OSX::get_bundle_resource_dir() const { return ret; } -String OS_OSX::get_bundle_icon_path() const { +String OS_MacOS::get_bundle_icon_path() const { String ret; NSBundle *main = [NSBundle mainBundle]; @@ -244,11 +244,11 @@ String OS_OSX::get_bundle_icon_path() const { } // Get properly capitalized engine name for system paths -String OS_OSX::get_godot_dir_name() const { +String OS_MacOS::get_godot_dir_name() const { return String(VERSION_SHORT_NAME).capitalize(); } -String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const { +String OS_MacOS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const { NSSearchPathDirectory id; bool found = true; @@ -287,7 +287,7 @@ String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const { return ret; } -Error OS_OSX::shell_open(String p_uri) { +Error OS_MacOS::shell_open(String p_uri) { NSString *string = [NSString stringWithUTF8String:p_uri.utf8().get_data()]; NSURL *uri = [[NSURL alloc] initWithString:string]; // Escape special characters in filenames @@ -298,12 +298,86 @@ Error OS_OSX::shell_open(String p_uri) { return OK; } -String OS_OSX::get_locale() const { +String OS_MacOS::get_locale() const { NSString *locale_code = [[NSLocale preferredLanguages] objectAtIndex:0]; return String([locale_code UTF8String]).replace("-", "_"); } -String OS_OSX::get_executable_path() const { +Vector<String> OS_MacOS::get_system_fonts() const { + HashSet<String> font_names; + CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames(); + if (fonts) { + for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) { + CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i); + if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) { + NSString *ns_name = (__bridge NSString *)cf_name; + font_names.insert(String::utf8([ns_name UTF8String])); + } + } + CFRelease(fonts); + } + + Vector<String> ret; + for (const String &E : font_names) { + ret.push_back(E); + } + return ret; +} + +String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { + String ret; + + String font_name = p_font_name; + if (font_name.to_lower() == "sans-serif") { + font_name = "Helvetica"; + } else if (font_name.to_lower() == "serif") { + font_name = "Times"; + } else if (font_name.to_lower() == "monospace") { + font_name = "Courier"; + } else if (font_name.to_lower() == "fantasy") { + font_name = "Papyrus"; + } else if (font_name.to_lower() == "cursive") { + font_name = "Apple Chancery"; + }; + + CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8); + + CTFontSymbolicTraits traits = 0; + if (p_bold) { + traits |= kCTFontBoldTrait; + } + if (p_italic) { + traits |= kCTFontItalicTrait; + } + + CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits); + CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); + CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits); + + CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name); + CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict); + + CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes); + if (font) { + CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute); + if (url) { + NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]]; + ret = String::utf8([font_path UTF8String]); + CFRelease(url); + } + CFRelease(font); + } + + CFRelease(attributes); + CFRelease(traits_dict); + CFRelease(sym_traits); + CFRelease(name); + + return ret; +} + +String OS_MacOS::get_executable_path() const { char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; int pid = getpid(); pid_t ret = proc_pidpath(pid, pathbuf, sizeof(pathbuf)); @@ -317,7 +391,7 @@ String OS_OSX::get_executable_path() const { } } -Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) { +Error OS_MacOS::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) { // Use NSWorkspace if path is an .app bundle. NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())]; NSBundle *bundle = [NSBundle bundleWithURL:url]; @@ -375,7 +449,7 @@ Error OS_OSX::create_process(const String &p_path, const List<String> &p_argumen } } -Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_child_id) { +Error OS_MacOS::create_instance(const List<String> &p_arguments, ProcessID *r_child_id) { // If executable is bundled, always execute editor instances as an app bundle to ensure app window is registered and activated correctly. NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; if (nsappname != nil) { @@ -387,7 +461,7 @@ Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_chil } } -String OS_OSX::get_unique_id() const { +String OS_MacOS::get_unique_id() const { static String serial_number; if (serial_number.is_empty()) { @@ -412,19 +486,19 @@ String OS_OSX::get_unique_id() const { return serial_number; } -bool OS_OSX::_check_internal_feature_support(const String &p_feature) { +bool OS_MacOS::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc"; } -void OS_OSX::disable_crash_handler() { +void OS_MacOS::disable_crash_handler() { crash_handler.disable(); } -bool OS_OSX::is_disable_crash_handler() const { +bool OS_MacOS::is_disable_crash_handler() const { return crash_handler.is_disabled(); } -Error OS_OSX::move_to_trash(const String &p_path) { +Error OS_MacOS::move_to_trash(const String &p_path) { NSFileManager *fm = [NSFileManager defaultManager]; NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())]; NSError *err; @@ -437,7 +511,7 @@ Error OS_OSX::move_to_trash(const String &p_path) { return OK; } -void OS_OSX::run() { +void OS_MacOS::run() { force_quit = false; if (!main_loop) { @@ -452,7 +526,7 @@ void OS_OSX::run() { if (DisplayServer::get_singleton()) { DisplayServer::get_singleton()->process_events(); // Get rid of pending events. } - joypad_osx->process_joypads(); + joypad_macos->process_joypads(); if (Main::iteration()) { quit = true; @@ -465,19 +539,19 @@ void OS_OSX::run() { main_loop->finalize(); } -OS_OSX::OS_OSX() { +OS_MacOS::OS_MacOS() { main_loop = nullptr; force_quit = false; Vector<Logger *> loggers; - loggers.push_back(memnew(OSXTerminalLogger)); + loggers.push_back(memnew(MacOSTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); #ifdef COREAUDIO_ENABLED AudioDriverManager::add_driver(&audio_driver); #endif - DisplayServerOSX::register_osx_driver(); + DisplayServerMacOS::register_macos_driver(); // Implicitly create shared NSApplication instance. [GodotApplication sharedApplication]; @@ -518,7 +592,7 @@ OS_OSX::OS_OSX() { [NSApp activateIgnoringOtherApps:YES]; } -OS_OSX::~OS_OSX() { +OS_MacOS::~OS_MacOS() { CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes); CFRelease(pre_wait_observer); } diff --git a/platform/osx/platform_config.h b/platform/macos/platform_config.h index e114606b82..e114606b82 100644 --- a/platform/osx/platform_config.h +++ b/platform/macos/platform_config.h diff --git a/platform/osx/platform_osx_builders.py b/platform/macos/platform_macos_builders.py index 953ed479db..3a1cc92bd2 100644 --- a/platform/osx/platform_osx_builders.py +++ b/platform/macos/platform_macos_builders.py @@ -7,7 +7,7 @@ import os from platform_methods import subprocess_main -def make_debug_osx(target, source, env): +def make_debug_macos(target, source, env): if env["macports_clang"] != "no": mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local") mpclangver = env["macports_clang"] diff --git a/platform/osx/tts_osx.h b/platform/macos/tts_macos.h index 449418e48f..344676868a 100644 --- a/platform/osx/tts_osx.h +++ b/platform/macos/tts_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* tts_osx.h */ +/* tts_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TTS_OSX_H -#define TTS_OSX_H +#ifndef TTS_MACOS_H +#define TTS_MACOS_H #include "core/string/ustring.h" #include "core/templates/list.h" @@ -45,7 +45,7 @@ #import <AVFoundation/AVFoundation.h> #endif -@interface TTS_OSX : NSObject <AVSpeechSynthesizerDelegate> { +@interface TTS_MacOS : NSObject <AVSpeechSynthesizerDelegate> { // AVSpeechSynthesizer bool speaking; HashMap<id, int> ids; @@ -68,4 +68,4 @@ - (Array)getVoices; @end -#endif // TTS_OSX_H +#endif // TTS_MACOS_H diff --git a/platform/osx/tts_osx.mm b/platform/macos/tts_macos.mm index e6a5236cd9..3c101b9531 100644 --- a/platform/osx/tts_osx.mm +++ b/platform/macos/tts_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* tts_osx.mm */ +/* tts_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "tts_osx.h" +#include "tts_macos.h" -@implementation TTS_OSX +@implementation TTS_MacOS - (id)init { self = [super init]; diff --git a/platform/osx/vulkan_context_osx.h b/platform/macos/vulkan_context_macos.h index ade0f4a4c9..579c42b042 100644 --- a/platform/osx/vulkan_context_osx.h +++ b/platform/macos/vulkan_context_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* vulkan_context_osx.h */ +/* vulkan_context_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VULKAN_DEVICE_OSX_H -#define VULKAN_DEVICE_OSX_H +#ifndef VULKAN_CONTEXT_MACOS_H +#define VULKAN_CONTEXT_MACOS_H #include "drivers/vulkan/vulkan_context.h" #import <AppKit/AppKit.h> -class VulkanContextOSX : public VulkanContext { +class VulkanContextMacOS : public VulkanContext { virtual const char *_get_platform_surface_extension() const; public: Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height); - VulkanContextOSX(); - ~VulkanContextOSX(); + VulkanContextMacOS(); + ~VulkanContextMacOS(); }; -#endif // VULKAN_DEVICE_OSX_H +#endif // VULKAN_CONTEXT_MACOS_H diff --git a/platform/osx/vulkan_context_osx.mm b/platform/macos/vulkan_context_macos.mm index bdabc24c28..cf317f3c68 100644 --- a/platform/osx/vulkan_context_osx.mm +++ b/platform/macos/vulkan_context_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* vulkan_context_osx.mm */ +/* vulkan_context_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "vulkan_context_osx.h" +#include "vulkan_context_macos.h" #ifdef USE_VOLK #include <volk.h> #else #include <vulkan/vulkan.h> #endif -const char *VulkanContextOSX::_get_platform_surface_extension() const { +const char *VulkanContextMacOS::_get_platform_surface_extension() const { return VK_MVK_MACOS_SURFACE_EXTENSION_NAME; } -Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) { +Error VulkanContextMacOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) { VkMacOSSurfaceCreateInfoMVK createInfo; createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; createInfo.pNext = nullptr; @@ -52,8 +52,8 @@ Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, Displ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height); } -VulkanContextOSX::VulkanContextOSX() { +VulkanContextMacOS::VulkanContextMacOS() { } -VulkanContextOSX::~VulkanContextOSX() { +VulkanContextMacOS::~VulkanContextMacOS() { } diff --git a/platform/osx/SCsub b/platform/osx/SCsub deleted file mode 100644 index 3a4c95613d..0000000000 --- a/platform/osx/SCsub +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -from platform_methods import run_in_subprocess -import platform_osx_builders - -files = [ - "os_osx.mm", - "godot_application.mm", - "godot_application_delegate.mm", - "crash_handler_osx.mm", - "osx_terminal_logger.mm", - "display_server_osx.mm", - "godot_content_view.mm", - "godot_window_delegate.mm", - "godot_window.mm", - "key_mapping_osx.mm", - "godot_main_osx.mm", - "dir_access_osx.mm", - "tts_osx.mm", - "joypad_osx.cpp", - "vulkan_context_osx.mm", - "gl_manager_osx_legacy.mm", -] - -prog = env.add_program("#bin/godot", files) - -if env["debug_symbols"] and env["separate_debug_symbols"]: - env.AddPostAction(prog, run_in_subprocess(platform_osx_builders.make_debug_osx)) diff --git a/platform/register_platform_apis.h b/platform/register_platform_apis.h index 8b6d23a7a4..9dd90d9b20 100644 --- a/platform/register_platform_apis.h +++ b/platform/register_platform_apis.h @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REGISTER_APIS_H -#define REGISTER_APIS_H +#ifndef REGISTER_PLATFORM_APIS_H +#define REGISTER_PLATFORM_APIS_H void register_platform_apis(); void unregister_platform_apis(); -#endif +#endif // REGISTER_PLATFORM_APIS_H diff --git a/platform/uwp/app_uwp.h b/platform/uwp/app_uwp.h index 9aadcfac75..82ad3ca01a 100644 --- a/platform/uwp/app_uwp.h +++ b/platform/uwp/app_uwp.h @@ -112,4 +112,5 @@ namespace GodotUWP } /* clang-format on */ + #endif // APP_UWP_H diff --git a/platform/uwp/export/app_packager.h b/platform/uwp/export/app_packager.h index dc5a5259ec..18db3eb806 100644 --- a/platform/uwp/export/app_packager.h +++ b/platform/uwp/export/app_packager.h @@ -40,7 +40,7 @@ #include "core/io/zip_io.h" #include "core/object/class_db.h" #include "core/version.h" -#include "editor/editor_export.h" +#include "editor/export/editor_export_platform.h" #include "thirdparty/minizip/unzip.h" #include "thirdparty/minizip/zip.h" @@ -146,4 +146,4 @@ public: ~AppxPackager(); }; -#endif +#endif // UWP_APP_PACKAGER_H diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index efba006985..31105824a5 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/editor_settings.h" #include "export_plugin.h" void register_uwp_exporter() { diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index 19b43d50be..070c46242f 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -30,6 +30,7 @@ #include "export_plugin.h" +#include "editor/editor_settings.h" #include "platform/uwp/logo.gen.h" String EditorExportPlatformUWP::get_name() const { @@ -49,27 +50,17 @@ Ref<Texture2D> EditorExportPlatformUWP::get_logo() const { return logo; } -void EditorExportPlatformUWP::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { +void EditorExportPlatformUWP::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { r_features->push_back("s3tc"); r_features->push_back("etc"); - switch ((int)p_preset->get("architecture/target")) { - case EditorExportPlatformUWP::ARM: { - r_features->push_back("arm"); - } break; - case EditorExportPlatformUWP::X86: { - r_features->push_back("32"); - } break; - case EditorExportPlatformUWP::X64: { - r_features->push_back("64"); - } break; - } + r_features->push_back(p_preset->get("binary_format/architecture")); } void EditorExportPlatformUWP::get_export_options(List<ExportOption> *r_options) { r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "architecture/target", PROPERTY_HINT_ENUM, "arm,x86,x64"), 1)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm32"), "x86_64")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), "")); @@ -143,23 +134,18 @@ bool EditorExportPlatformUWP::can_export(const Ref<EditorExportPreset> &p_preset bool valid = false; // Look for export templates (first official, and if defined custom templates). - - Platform arch = (Platform)(int)(p_preset->get("architecture/target")); - String platform_infix; - switch (arch) { - case EditorExportPlatformUWP::ARM: { - platform_infix = "arm"; - } break; - case EditorExportPlatformUWP::X86: { - platform_infix = "x86"; - } break; - case EditorExportPlatformUWP::X64: { - platform_infix = "x64"; - } break; + String arch = p_preset->get("binary_format/architecture"); + String arch_infix; + if (arch == "arm32") { + arch_infix = "arm"; + } else if (arch == "x86_32") { + arch_infix = "x86"; + } else if (arch == "x86_64") { + arch_infix = "x64"; } - bool dvalid = exists_export_template("uwp_" + platform_infix + "_debug.zip", &err); - bool rvalid = exists_export_template("uwp_" + platform_infix + "_release.zip", &err); + bool dvalid = exists_export_template("uwp_" + arch_infix + "_debug.zip", &err); + bool rvalid = exists_export_template("uwp_" + arch_infix + "_release.zip", &err); if (p_preset->get("custom_template/debug") != "") { dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); @@ -263,25 +249,21 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p src_appx = src_appx.strip_edges(); - Platform arch = (Platform)(int)p_preset->get("architecture/target"); + String arch = p_preset->get("binary_format/architecture"); if (src_appx.is_empty()) { - String err, infix; - switch (arch) { - case ARM: { - infix = "_arm_"; - } break; - case X86: { - infix = "_x86_"; - } break; - case X64: { - infix = "_x64_"; - } break; + String err, arch_infix; + if (arch == "arm32") { + arch_infix = "arm"; + } else if (arch == "x86_32") { + arch_infix = "x86"; + } else if (arch == "x86_64") { + arch_infix = "x64"; } if (p_debug) { - src_appx = find_export_template("uwp" + infix + "debug.zip", &err); + src_appx = find_export_template("uwp_" + arch_infix + "_debug.zip", &err); } else { - src_appx = find_export_template("uwp" + infix + "release.zip", &err); + src_appx = find_export_template("uwp_" + arch_infix + "_release.zip", &err); } if (src_appx.is_empty()) { EditorNode::add_io_error(err); @@ -494,7 +476,7 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p return OK; } -void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) { +void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) const { r_features->push_back("pc"); r_features->push_back("uwp"); } diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h index d92687075c..4a3c5db377 100644 --- a/platform/uwp/export/export_plugin.h +++ b/platform/uwp/export/export_plugin.h @@ -39,9 +39,9 @@ #include "core/io/zip_io.h" #include "core/object/class_db.h" #include "core/version.h" -#include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" +#include "editor/export/editor_export_platform.h" #include "thirdparty/minizip/unzip.h" #include "thirdparty/minizip/zip.h" @@ -90,12 +90,6 @@ class EditorExportPlatformUWP : public EditorExportPlatform { Ref<ImageTexture> logo; - enum Platform { - ARM, - X86, - X64 - }; - bool _valid_resource_name(const String &p_name) const { if (p_name.is_empty()) { return false; @@ -215,8 +209,8 @@ class EditorExportPlatformUWP : public EditorExportPlatform { String version = itos(p_preset->get("version/major")) + "." + itos(p_preset->get("version/minor")) + "." + itos(p_preset->get("version/build")) + "." + itos(p_preset->get("version/revision")); result = result.replace("$version_string$", version); - Platform arch = (Platform)(int)p_preset->get("architecture/target"); - String architecture = arch == ARM ? "arm" : (arch == X86 ? "x86" : "x64"); + String arch = p_preset->get("binary_format/architecture"); + String architecture = arch == "arm32" ? "arm" : (arch == "x86_32" ? "x86" : "x64"); result = result.replace("$architecture$", architecture); result = result.replace("$display_name$", String(p_preset->get("package/display_name")).is_empty() ? (String)ProjectSettings::get_singleton()->get("application/config/name") : String(p_preset->get("package/display_name"))); @@ -431,7 +425,7 @@ public: virtual Ref<Texture2D> get_logo() const override; - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; @@ -439,11 +433,11 @@ public: virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; - virtual void get_platform_features(List<String> *r_features) override; + virtual void get_platform_features(List<String> *r_features) const override; virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override; EditorExportPlatformUWP(); }; -#endif +#endif // UWP_EXPORT_PLUGIN_H diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h index 0869f1961d..81f84152b9 100644 --- a/platform/uwp/joypad_uwp.h +++ b/platform/uwp/joypad_uwp.h @@ -78,4 +78,4 @@ private: void joypad_vibration_stop(int p_device, uint64_t p_timestamp); }; -#endif +#endif // JOYPAD_UWP_H diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 1614bfdcc3..40f93bb18b 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -275,7 +275,7 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a display_request->RequestActive(); } - set_keep_screen_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true)); + set_keep_screen_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); return OK; } @@ -557,6 +557,7 @@ uint64_t OS_UWP::get_ticks_usec() const { void OS_UWP::process_events() { joypad->process_controllers(); process_key_events(); + input->flush_buffered_events(); } void OS_UWP::process_key_events() { @@ -715,7 +716,7 @@ bool OS_UWP::has_virtual_keyboard() const { return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryShow(); } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index bddf63ff18..fe61f60548 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -231,7 +231,7 @@ public: virtual bool has_touchscreen_ui_hint() const; virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr); @@ -252,4 +252,4 @@ public: ~OS_UWP(); }; -#endif +#endif // OS_UWP_H diff --git a/platform/windows/detect.py b/platform/windows/detect.py index b82fe5e7ad..dd2df1f004 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -198,7 +198,6 @@ def configure_msvc(env, manual_msvc_config): elif env["target"] == "debug": env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"]) # Allow big objects. Only needed for debug, see MinGW branch for rationale. - env.AppendUnique(CCFLAGS=["/bigobj"]) env.Append(LINKFLAGS=["/DEBUG"]) if env["debug_symbols"]: @@ -221,6 +220,10 @@ def configure_msvc(env, manual_msvc_config): env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"]) env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding. env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++ + # Once it was thought that only debug builds would be too large, + # but this has recently stopped being true. See the mingw function + # for notes on why this shouldn't be enabled for gcc + env.AppendUnique(CCFLAGS=["/bigobj"]) if manual_msvc_config: # should be automatic if SCons found it if os.getenv("WindowsSdkDir") is not None: @@ -267,6 +270,7 @@ def configure_msvc(env, manual_msvc_config): "bcrypt", "Avrt", "dwmapi", + "dwrite", ] if env["vulkan"]: @@ -438,6 +442,7 @@ def configure_mingw(env): "avrt", "uuid", "dwmapi", + "dwrite", ] ) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 91e0fbe0dc..8c8dbef8a4 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -531,10 +531,43 @@ DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(in } void DisplayServerWindows::screen_set_keep_on(bool p_enable) { + if (keep_screen_on == p_enable) { + return; + } + + if (p_enable) { + const String reason = "Godot Engine running with display/window/energy_saving/keep_screen_on = true"; + Char16String reason_utf16 = reason.utf16(); + + REASON_CONTEXT context; + context.Version = POWER_REQUEST_CONTEXT_VERSION; + context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; + context.Reason.SimpleReasonString = (LPWSTR)(reason_utf16.ptrw()); + power_request = PowerCreateRequest(&context); + if (power_request == INVALID_HANDLE_VALUE) { + print_error("Failed to enable screen_keep_on."); + return; + } + if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired) == 0) { + print_error("Failed to request system sleep override."); + return; + } + if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired) == 0) { + print_error("Failed to request display timeout override."); + return; + } + } else { + PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired); + PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired); + CloseHandle(power_request); + power_request = nullptr; + } + + keep_screen_on = p_enable; } bool DisplayServerWindows::screen_is_kept_on() const { - return false; + return keep_screen_on; } Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const { @@ -2035,7 +2068,7 @@ void DisplayServerWindows::_send_window_event(const WindowData &wd, WindowEvent Variant *eventp = &event; Variant ret; Callable::CallError ce; - wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce); } } @@ -2062,7 +2095,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) if (windows.has(E->get())) { Callable callable = windows[E->get()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } in_dispatch_input_event = false; @@ -2076,7 +2109,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) if (windows.has(event_from_window->get_window_id())) { Callable callable = windows[event_from_window->get_window_id()].input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } else { @@ -2084,7 +2117,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) for (const KeyValue<WindowID, WindowData> &E : windows) { const Callable callable = E.value.input_event_callback; if (callable.is_valid()) { - callable.call((const Variant **)&evp, 1, ret, ce); + callable.callp((const Variant **)&evp, 1, ret, ce); } } } @@ -3039,7 +3072,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA const Variant *args[] = { &size }; Variant ret; Callable::CallError ce; - window.rect_changed_callback.call(args, 1, ret, ce); + window.rect_changed_callback.callp(args, 1, ret, ce); } } @@ -3199,7 +3232,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA Variant *vp = &v; Variant ret; Callable::CallError ce; - windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + windows[window_id].drop_files_callback.callp((const Variant **)&vp, 1, ret, ce); } } break; default: { @@ -3458,6 +3491,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, windows.erase(id); ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create Windows OS window."); } + if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { + wd.fullscreen = true; + if (p_mode == WINDOW_MODE_FULLSCREEN) { + wd.multiwindow_fs = true; + } + } if (p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { wd.pre_fs_valid = true; } @@ -3613,6 +3652,9 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win // Init TTS tts = memnew(TTS_Windows); + // Enforce default keep screen on value. + screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); + // Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); if (wintab_lib) { @@ -3816,6 +3858,9 @@ DisplayServerWindows::~DisplayServerWindows() { SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); } + // Close power request handle. + screen_set_keep_on(false); + #ifdef GLES3_ENABLED // destroy windows .. NYI? // FIXME wglDeleteContext is never called diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index ddbf674c64..db9b589304 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -331,6 +331,8 @@ class DisplayServerWindows : public DisplayServer { HINSTANCE hInstance; // Holds The Instance Of The Application String rendering_driver; bool app_focused = false; + bool keep_screen_on = false; + HANDLE power_request; TTS_Windows *tts = nullptr; diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index af19f24f09..20320470b8 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/export/editor_export.h" #include "export_plugin.h" void register_windows_exporter() { diff --git a/platform/windows/export/export.h b/platform/windows/export/export.h index 09399f2bee..1054e04b1e 100644 --- a/platform/windows/export/export.h +++ b/platform/windows/export/export.h @@ -33,4 +33,4 @@ void register_windows_exporter(); -#endif +#endif // WINDOWS_EXPORT_H diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 16c67345e0..febef5ad12 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -104,7 +104,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> } String EditorExportPlatformWindows::get_template_file_name(const String &p_target, const String &p_arch) const { - return "windows_" + p_arch + "_" + p_target + ".exe"; + return "windows_" + p_target + "_" + p_arch + ".exe"; } List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const { @@ -123,6 +123,7 @@ bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_o void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { EditorExportPlatformPC::get_export_options(r_options); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32"), "x86_64")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); @@ -230,13 +231,13 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset String str; Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable, configure rcedit path in the Editor Settings (Export > Windows > Rcedit).")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > Rcedit), or disable \"Application > Modify Resources\" in the export preset.")); return err; } print_line("rcedit (" + p_path + "): " + str); if (str.find("Fatal error") != -1) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("rcedit failed to modify executable:\n%s"), str)); + add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("rcedit failed to modify executable: %s."), str)); return FAILED; } @@ -378,7 +379,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p String str; Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable, configure signtool path in the Editor Settings (Export > Windows > Signtool).")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > Signtool), or disable \"Codesign\" in the export preset.")); return err; } @@ -388,7 +389,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p #else if (str.find("Failed") != -1) { #endif - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Signtool failed to sign executable:\n%s"), str)); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Signtool failed to sign executable: %s."), str)); return FAILED; } diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 51f98365a9..b9e59829a0 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -33,8 +33,8 @@ #include "core/io/file_access.h" #include "core/os/os.h" -#include "editor/editor_export.h" #include "editor/editor_settings.h" +#include "editor/export/editor_export_platform_pc.h" #include "platform/windows/logo.gen.h" class EditorExportPlatformWindows : public EditorExportPlatformPC { @@ -54,4 +54,4 @@ public: virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; }; -#endif +#endif // WINDOWS_EXPORT_PLUGIN_H diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index bb855e4ac8..cdd1c14978 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -40,11 +40,13 @@ <DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString> <DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString> <DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString> - <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform}</DisplayString> + <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform3d}</DisplayString> + <DisplayString Condition="type == Variant::PROJECTION">{_data._projection}</DisplayString> <DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::VECTOR4">{*(Vector4 *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::QUATERNION">{*(Quaternion *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString> @@ -72,7 +74,7 @@ <Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item> <Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item> <Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item> - <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform</Item> + <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform3d</Item> <Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item> diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 6f414c094c..ad4be950cc 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -48,6 +48,7 @@ #include <avrt.h> #include <bcrypt.h> #include <direct.h> +#include <dwrite.h> #include <knownfolders.h> #include <process.h> #include <regstr.h> @@ -621,6 +622,135 @@ Error OS_Windows::set_cwd(const String &p_cwd) { return OK; } +Vector<String> OS_Windows::get_system_fonts() const { + Vector<String> ret; + HashSet<String> font_names; + + ComAutoreleaseRef<IDWriteFactory> dwrite_factory; + HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference)); + ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), ret); + + ComAutoreleaseRef<IDWriteFontCollection> font_collection; + hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false); + ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), ret); + + UINT32 family_count = font_collection->GetFontFamilyCount(); + for (UINT32 i = 0; i < family_count; i++) { + ComAutoreleaseRef<IDWriteFontFamily> family; + hr = font_collection->GetFontFamily(i, &family.reference); + ERR_CONTINUE(FAILED(hr) || family.is_null()); + + ComAutoreleaseRef<IDWriteLocalizedStrings> family_names; + hr = family->GetFamilyNames(&family_names.reference); + ERR_CONTINUE(FAILED(hr) || family_names.is_null()); + + UINT32 index = 0; + BOOL exists = false; + UINT32 length = 0; + Char16String name; + + hr = family_names->FindLocaleName(L"en-us", &index, &exists); + ERR_CONTINUE(FAILED(hr)); + + hr = family_names->GetStringLength(index, &length); + ERR_CONTINUE(FAILED(hr)); + + name.resize(length + 1); + hr = family_names->GetString(index, (WCHAR *)name.ptrw(), length + 1); + ERR_CONTINUE(FAILED(hr)); + + font_names.insert(String::utf16(name.ptr(), length)); + } + + for (const String &E : font_names) { + ret.push_back(E); + } + return ret; +} + +String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { + String font_name = p_font_name; + if (font_name.to_lower() == "sans-serif") { + font_name = "Arial"; + } else if (font_name.to_lower() == "serif") { + font_name = "Times New Roman"; + } else if (font_name.to_lower() == "monospace") { + font_name = "Courier New"; + } else if (font_name.to_lower() == "cursive") { + font_name = "Comic Sans MS"; + } else if (font_name.to_lower() == "fantasy") { + font_name = "Gabriola"; + } + + ComAutoreleaseRef<IDWriteFactory> dwrite_factory; + HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference)); + ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), String()); + + ComAutoreleaseRef<IDWriteFontCollection> font_collection; + hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false); + ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), String()); + + UINT32 index = 0; + BOOL exists = false; + font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists); + if (FAILED(hr)) { + return String(); + } + + ComAutoreleaseRef<IDWriteFontFamily> family; + hr = font_collection->GetFontFamily(index, &family.reference); + if (FAILED(hr) || family.is_null()) { + return String(); + } + + ComAutoreleaseRef<IDWriteFont> dwrite_font; + hr = family->GetFirstMatchingFont(p_bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, p_italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, &dwrite_font.reference); + if (FAILED(hr) || dwrite_font.is_null()) { + return String(); + } + + ComAutoreleaseRef<IDWriteFontFace> dwrite_face; + hr = dwrite_font->CreateFontFace(&dwrite_face.reference); + if (FAILED(hr) || dwrite_face.is_null()) { + return String(); + } + + UINT32 number_of_files = 0; + hr = dwrite_face->GetFiles(&number_of_files, nullptr); + if (FAILED(hr)) { + return String(); + } + Vector<ComAutoreleaseRef<IDWriteFontFile>> files; + files.resize(number_of_files); + hr = dwrite_face->GetFiles(&number_of_files, (IDWriteFontFile **)files.ptrw()); + if (FAILED(hr)) { + return String(); + } + + for (UINT32 i = 0; i < number_of_files; i++) { + void const *reference_key = nullptr; + UINT32 reference_key_size = 0; + ComAutoreleaseRef<IDWriteLocalFontFileLoader> loader; + + hr = files.write[i]->GetLoader((IDWriteFontFileLoader **)&loader.reference); + if (FAILED(hr) || loader.is_null()) { + continue; + } + hr = files.write[i]->GetReferenceKey(&reference_key, &reference_key_size); + if (FAILED(hr)) { + continue; + } + + WCHAR file_path[MAX_PATH]; + hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], MAX_PATH); + if (FAILED(hr)) { + continue; + } + return String::utf16((const char16_t *)&file_path[0]); + } + return String(); +} + String OS_Windows::get_executable_path() const { WCHAR bufname[4096]; GetModuleFileNameW(nullptr, bufname, 4096); @@ -951,9 +1081,9 @@ 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::utf16((const char16_t *)(HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN); + HW_PROFILE_INFOA HwProfInfo; + ERR_FAIL_COND_V(!GetCurrentHwProfileA(&HwProfInfo), ""); + return String((HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN); } bool OS_Windows::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index dc702c66e1..80fc860738 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -62,6 +62,26 @@ #define WINDOWS_DEBUG_OUTPUT_ENABLED #endif +template <class T> +class ComAutoreleaseRef { +public: + T *reference = nullptr; + + _FORCE_INLINE_ T *operator->() { return reference; } + _FORCE_INLINE_ const T *operator->() const { return reference; } + _FORCE_INLINE_ T *operator*() { return reference; } + _FORCE_INLINE_ const T *operator*() const { return reference; } + _FORCE_INLINE_ bool is_valid() const { return reference != nullptr; } + _FORCE_INLINE_ bool is_null() const { return reference == nullptr; } + ComAutoreleaseRef() {} + ~ComAutoreleaseRef() { + if (reference != nullptr) { + reference->Release(); + reference = nullptr; + } + } +}; + class JoypadWindows; class OS_Windows : public OS { #ifdef STDOUT_FILE @@ -147,6 +167,9 @@ public: virtual String get_environment(const String &p_var) const override; virtual bool set_environment(const String &p_var, const String &p_value) const override; + virtual Vector<String> get_system_fonts() const override; + virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override; + virtual String get_executable_path() const override; virtual String get_locale() const override; @@ -185,4 +208,4 @@ public: ~OS_Windows(); }; -#endif +#endif // OS_WINDOWS_H diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h index e68f0125ca..d5950a129a 100644 --- a/platform/windows/vulkan_context_win.h +++ b/platform/windows/vulkan_context_win.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VULKAN_DEVICE_WIN_H -#define VULKAN_DEVICE_WIN_H +#ifndef VULKAN_CONTEXT_WIN_H +#define VULKAN_CONTEXT_WIN_H #include "drivers/vulkan/vulkan_context.h" @@ -46,4 +46,4 @@ public: ~VulkanContextWindows(); }; -#endif // VULKAN_DEVICE_WIN_H +#endif // VULKAN_CONTEXT_WIN_H diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h index 1045f12201..348a49c845 100644 --- a/platform/windows/windows_terminal_logger.h +++ b/platform/windows/windows_terminal_logger.h @@ -44,4 +44,4 @@ public: #endif -#endif +#endif // WINDOWS_TERMINAL_LOGGER_H diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 3a41f810dc..ec38795a1a 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -114,4 +114,4 @@ public: AnimatedSprite2D(); }; -#endif // ANIMATED_SPRITE_H +#endif // ANIMATED_SPRITE_2D_H diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index dfc1016c84..7890348314 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -184,8 +184,8 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i E->value.rc = 0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -277,8 +277,8 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i E->value.rc = 0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_entered, node); } diff --git a/scene/2d/audio_listener_2d.h b/scene/2d/audio_listener_2d.h index 172d388efc..5cd1bfb251 100644 --- a/scene/2d/audio_listener_2d.h +++ b/scene/2d/audio_listener_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LISTENER_2D_H -#define LISTENER_2D_H +#ifndef AUDIO_LISTENER_2D_H +#define AUDIO_LISTENER_2D_H #include "scene/2d/node_2d.h" #include "scene/main/window.h" @@ -56,4 +56,4 @@ public: bool is_current() const; }; -#endif +#endif // AUDIO_LISTENER_2D_H diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index eaab58c4ae..94d22111ea 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -69,7 +69,7 @@ void AudioStreamPlayer2D::_notification(int p_what) { if (setplay.get() >= 0 && stream.is_valid()) { active.set(); - Ref<AudioStreamPlayback> new_playback = stream->instance_playback(); + Ref<AudioStreamPlayback> new_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback."); AudioServer::get_singleton()->start_playback_stream(new_playback, _get_actual_bus(), volume_vector, setplay.get(), pitch_scale); stream_playbacks.push_back(new_playback); diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index a22782fe44..d1c4dc4fdf 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -135,4 +135,4 @@ public: ~AudioStreamPlayer2D(); }; -#endif +#endif // AUDIO_STREAM_PLAYER_2D_H diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index 4e7cac1f3e..1f2d5810b0 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BACKBUFFERCOPY_H -#define BACKBUFFERCOPY_H +#ifndef BACK_BUFFER_COPY_H +#define BACK_BUFFER_COPY_H #include "scene/2d/node_2d.h" @@ -71,4 +71,4 @@ public: VARIANT_ENUM_CAST(BackBufferCopy::CopyMode); -#endif // BACKBUFFERCOPY_H +#endif // BACK_BUFFER_COPY_H diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 2616d1f09e..c43a796170 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -247,8 +247,8 @@ void Camera2D::_notification(int p_what) { add_to_group(canvas_group_name); _update_process_callback(); - _update_scroll(); first = true; + _update_scroll(); } break; case NOTIFICATION_EXIT_TREE: { @@ -439,7 +439,9 @@ void Camera2D::clear_current() { void Camera2D::set_limit(Side p_side, int p_limit) { ERR_FAIL_INDEX((int)p_side, 4); limit[p_side] = p_limit; - update(); + Point2 old_smoothed_camera_pos = smoothed_camera_pos; + _update_scroll(); + smoothed_camera_pos = old_smoothed_camera_pos; } int Camera2D::get_limit(Side p_side) const { diff --git a/scene/2d/canvas_group.h b/scene/2d/canvas_group.h index 9bc1772ee2..557e7e23dc 100644 --- a/scene/2d/canvas_group.h +++ b/scene/2d/canvas_group.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CANVASGROUP_H -#define CANVASGROUP_H +#ifndef CANVAS_GROUP_H +#define CANVAS_GROUP_H #include "scene/2d/node_2d.h" @@ -56,4 +56,4 @@ public: ~CanvasGroup(); }; -#endif // CANVASGROUP_H +#endif // CANVAS_GROUP_H diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index ec37449f8f..1fd54898f8 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CANVASMODULATE_H -#define CANVASMODULATE_H +#ifndef CANVAS_MODULATE_H +#define CANVAS_MODULATE_H #include "scene/2d/node_2d.h" @@ -52,4 +52,4 @@ public: ~CanvasModulate(); }; -#endif // CANVASMODULATE_H +#endif // CANVAS_MODULATE_H diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 4155d0797f..26204a3b1a 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -1470,7 +1470,7 @@ CPUParticles2D::CPUParticles2D() { set_emitting(true); set_amount(8); - set_use_local_coordinates(true); + set_use_local_coordinates(false); set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0); set_param_min(PARAM_ANGULAR_VELOCITY, 0); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index a869cf2525..075421a26d 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -660,7 +660,7 @@ GPUParticles2D::GPUParticles2D() { set_explosiveness_ratio(0); set_randomness_ratio(0); set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200))); - set_use_local_coordinates(true); + set_use_local_coordinates(false); set_draw_order(DRAW_ORDER_LIFETIME); set_speed_scale(1); set_fixed_fps(30); diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index 3c7f4cd9b5..a4231cc45d 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PARTICLES_2D_H -#define PARTICLES_2D_H +#ifndef GPU_PARTICLES_2D_H +#define GPU_PARTICLES_2D_H #include "scene/2d/node_2d.h" @@ -167,4 +167,4 @@ public: VARIANT_ENUM_CAST(GPUParticles2D::DrawOrder) VARIANT_ENUM_CAST(GPUParticles2D::EmitFlags) -#endif // PARTICLES_2D_H +#endif // GPU_PARTICLES_2D_H diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index 4acfeaf781..b61e23464a 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LIGHTOCCLUDER2D_H -#define LIGHTOCCLUDER2D_H +#ifndef LIGHT_OCCLUDER_2D_H +#define LIGHT_OCCLUDER_2D_H #include "scene/2d/node_2d.h" @@ -111,4 +111,4 @@ public: ~LightOccluder2D(); }; -#endif // LIGHTOCCLUDER2D_H +#endif // LIGHT_OCCLUDER_2D_H diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 5322c5a5fe..27c510171a 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LINE2D_H -#define LINE2D_H +#ifndef LINE_2D_H +#define LINE_2D_H #include "node_2d.h" @@ -138,4 +138,4 @@ private: bool _antialiased = false; }; -#endif // LINE2D_H +#endif // LINE_2D_H diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 032a15cad2..76eba20058 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -163,4 +163,4 @@ private: void _check_distance_to_target(); }; -#endif +#endif // NAVIGATION_AGENT_2D_H diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 948cf5b61a..afda05956a 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -74,4 +74,4 @@ private: real_t estimate_agent_radius() const; }; -#endif +#endif // NAVIGATION_OBSTACLE_2D_H diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 6e8fd891cb..cdf7c5afa9 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" +#include "servers/navigation_server_3d.h" #include "thirdparty/misc/polypartition.h" @@ -371,9 +372,11 @@ void NavigationRegion2D::set_enabled(bool p_enabled) { NavigationServer2D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); } - if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) { +#ifdef DEBUG_ENABLED + if (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) { update(); } +#endif // DEBUG_ENABLED } bool NavigationRegion2D::is_enabled() const { @@ -419,7 +422,7 @@ real_t NavigationRegion2D::get_enter_cost() const { void NavigationRegion2D::set_travel_cost(real_t p_travel_cost) { ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive."); travel_cost = MAX(p_travel_cost, 0.0); - NavigationServer2D::get_singleton()->region_set_enter_cost(region, travel_cost); + NavigationServer2D::get_singleton()->region_set_travel_cost(region, travel_cost); } real_t NavigationRegion2D::get_travel_cost() const { @@ -462,7 +465,8 @@ void NavigationRegion2D::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) { +#ifdef DEBUG_ENABLED + if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) && navpoly.is_valid()) { Vector<Vector2> verts = navpoly->get_vertices(); if (verts.size() < 3) { return; @@ -470,11 +474,11 @@ void NavigationRegion2D::_notification(int p_what) { Color color; if (enabled) { - color = get_tree()->get_debug_navigation_color(); + color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); } else { - color = get_tree()->get_debug_navigation_disabled_color(); + color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color(); } - Color doors_color = color.lightened(0.2); + Color doors_color = NavigationServer3D::get_singleton()->get_debug_navigation_edge_connection_color(); RandomPCG rand; @@ -516,6 +520,7 @@ void NavigationRegion2D::_notification(int p_what) { draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color); } } +#endif // DEBUG_ENABLED } break; } } @@ -552,10 +557,13 @@ void NavigationRegion2D::_navpoly_changed() { NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly); } } + void NavigationRegion2D::_map_changed(RID p_map) { - if (enabled && get_world_2d()->get_navigation_map() == p_map) { +#ifdef DEBUG_ENABLED + if (is_inside_tree() && get_world_2d()->get_navigation_map() == p_map) { update(); } +#endif // DEBUG_ENABLED } TypedArray<String> NavigationRegion2D::get_configuration_warnings() const { @@ -605,8 +613,18 @@ NavigationRegion2D::NavigationRegion2D() { region = NavigationServer2D::get_singleton()->region_create(); NavigationServer2D::get_singleton()->region_set_enter_cost(region, get_enter_cost()); NavigationServer2D::get_singleton()->region_set_travel_cost(region, get_travel_cost()); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); + NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); +#endif // DEBUG_ENABLED } NavigationRegion2D::~NavigationRegion2D() { NavigationServer2D::get_singleton()->free(region); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton_mut()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); + NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); +#endif // DEBUG_ENABLED } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 473c34768f..0d8a31e6bb 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NODE2D_H -#define NODE2D_H +#ifndef NODE_2D_H +#define NODE_2D_H #include "scene/main/canvas_item.h" @@ -124,4 +124,4 @@ public: Node2D() {} }; -#endif // NODE2D_H +#endif // NODE_2D_H diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 8eb48ffb30..9862c4bfb1 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -304,6 +304,7 @@ void PathFollow2D::_bind_methods() { } void PathFollow2D::set_offset(real_t p_offset) { + ERR_FAIL_COND(!isfinite(p_offset)); offset = p_offset; if (path) { if (path->get_curve().is_valid()) { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index e60a5ed034..ce22f32b01 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -387,8 +387,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_scene = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree).bind(objid)); if (E->value.in_scene) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 8953813452..68e5ffdcf9 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -240,7 +240,7 @@ void RayCast2D::_draw_debug_shape() { Transform2D xf; xf.rotate(target_position.angle()); - xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); + xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); Vector<Vector2> pts = { xf.xform(Vector2(arrow_size, 0)), diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp index ae810156a2..316988d298 100644 --- a/scene/2d/shape_cast_2d.cpp +++ b/scene/2d/shape_cast_2d.cpp @@ -217,7 +217,7 @@ void ShapeCast2D::_notification(int p_what) { if (shape.is_null()) { break; } - Color draw_col = get_tree()->get_debug_collisions_color(); + Color draw_col = collided ? Color(1.0, 0.01, 0) : get_tree()->get_debug_collisions_color(); if (!enabled) { float g = draw_col.get_v(); draw_col.r = g; @@ -235,18 +235,25 @@ void ShapeCast2D::_notification(int p_what) { // Draw an arrow indicating where the ShapeCast is pointing to. if (target_position != Vector2()) { - Transform2D xf; - xf.rotate(target_position.angle()); - xf.translate(Vector2(target_position.length(), 0)); + const real_t max_arrow_size = 6; + const real_t line_width = 1.4; + bool no_line = target_position.length() < line_width; + real_t arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size); - draw_line(Vector2(), target_position, draw_col, 2); + if (no_line) { + arrow_size = target_position.length(); + } else { + draw_line(Vector2(), target_position - target_position.normalized() * arrow_size, draw_col, line_width); + } - float tsize = 8; + Transform2D xf; + xf.rotate(target_position.angle()); + xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); Vector<Vector2> pts = { - xf.xform(Vector2(tsize, 0)), - xf.xform(Vector2(0, Math_SQRT12 * tsize)), - xf.xform(Vector2(0, -Math_SQRT12 * tsize)) + xf.xform(Vector2(arrow_size, 0)), + xf.xform(Vector2(0, 0.5 * arrow_size)), + xf.xform(Vector2(0, -0.5 * arrow_size)) }; Vector<Color> cols = { draw_col, draw_col, draw_col }; @@ -291,6 +298,8 @@ void ShapeCast2D::_update_shapecast_state() { collision_safe_fraction = 0.0; collision_unsafe_fraction = 0.0; + bool prev_collision_state = collided; + if (target_position != Vector2()) { dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction); if (collision_unsafe_fraction < 1.0) { @@ -314,6 +323,10 @@ void ShapeCast2D::_update_shapecast_state() { } } collided = !result.is_empty(); + + if (prev_collision_state != collided) { + update(); + } } void ShapeCast2D::force_shapecast_update() { diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h index 7ff080aed0..660e52f189 100644 --- a/scene/2d/shape_cast_2d.h +++ b/scene/2d/shape_cast_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHAPE_CAST_2D -#define SHAPE_CAST_2D +#ifndef SHAPE_CAST_2D_H +#define SHAPE_CAST_2D_H #include "scene/2d/node_2d.h" #include "scene/resources/shape_2d.h" @@ -120,4 +120,4 @@ public: TypedArray<String> get_configuration_warnings() const override; }; -#endif +#endif // SHAPE_CAST_2D_H diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h index 6893e92d4a..5b33bb6802 100644 --- a/scene/2d/sprite_2d.h +++ b/scene/2d/sprite_2d.h @@ -125,4 +125,4 @@ public: ~Sprite2D(); }; -#endif // SPRITE_H +#endif // SPRITE_2D_H diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index cf8b6b8f94..5ba8c95a06 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -2652,7 +2652,7 @@ void TileMap::clear_layer(int p_layer) { // Remove all tiles. _clear_layer_internals(p_layer); layers[p_layer].tile_map.clear(); - + _recreate_layer_internals(p_layer); used_rect_cache_dirty = true; } @@ -2662,6 +2662,7 @@ void TileMap::clear() { for (unsigned int i = 0; i < layers.size(); i++) { layers[i].tile_map.clear(); } + _recreate_internals(); used_rect_cache_dirty = true; } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 0ac94b9d45..012bf01df9 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -130,7 +130,7 @@ public: } String to_string() const { - return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priotity:%d}", base_cell_coords, bit, terrain, priority); + return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priority:%d}", base_cell_coords, bit, terrain, priority); } Vector2i get_base_cell_coords() const { diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 4a4a2a1da0..9dea69cd64 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -131,7 +131,7 @@ void TouchScreenButton::_notification(int p_what) { pos = texture_normal->get_size() * 0.5; } - draw_set_transform_matrix(get_canvas_transform().translated(pos)); + draw_set_transform_matrix(get_canvas_transform().translated_local(pos)); shape->draw(get_canvas_item(), draw_col); } } break; @@ -258,7 +258,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { pos = texture_normal->get_size() * 0.5; } - touched = shape->collide(Transform2D().translated(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5))); + touched = shape->collide(Transform2D().translated_local(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5))); } if (bitmask.is_valid()) { diff --git a/scene/2d/visible_on_screen_notifier_2d.h b/scene/2d/visible_on_screen_notifier_2d.h index 38b508e2f6..ac7fad95a5 100644 --- a/scene/2d/visible_on_screen_notifier_2d.h +++ b/scene/2d/visible_on_screen_notifier_2d.h @@ -102,4 +102,4 @@ public: VARIANT_ENUM_CAST(VisibleOnScreenEnabler2D::EnableMode); -#endif // VISIBILITY_NOTIFIER_2D_H +#endif // VISIBLE_ON_SCREEN_NOTIFIER_2D_H diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index fb0c59daa1..e9e19488e9 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -239,8 +239,8 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i E->value.rc = 0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -426,8 +426,8 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i E->value.rc = 0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_entered, node); } diff --git a/scene/3d/audio_listener_3d.h b/scene/3d/audio_listener_3d.h index ebc37673ed..44c49f526e 100644 --- a/scene/3d/audio_listener_3d.h +++ b/scene/3d/audio_listener_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LISTENER_3D_H -#define LISTENER_3D_H +#ifndef AUDIO_LISTENER_3D_H +#define AUDIO_LISTENER_3D_H #include "scene/3d/node_3d.h" @@ -67,4 +67,4 @@ public: ~AudioListener3D(); }; -#endif +#endif // AUDIO_LISTENER_3D_H diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 824ea0407e..65b00742ee 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -281,7 +281,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (setplay.get() >= 0 && stream.is_valid()) { active.set(); - Ref<AudioStreamPlayback> new_playback = stream->instance_playback(); + Ref<AudioStreamPlayback> new_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback."); HashMap<StringName, Vector<AudioFrame>> bus_map; bus_map[_get_actual_bus()] = volume_vector; diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 85ece6d8d5..647b18a4a7 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -196,4 +196,5 @@ public: VARIANT_ENUM_CAST(AudioStreamPlayer3D::AttenuationModel) VARIANT_ENUM_CAST(AudioStreamPlayer3D::DopplerTracking) + #endif // AUDIO_STREAM_PLAYER_3D_H diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h index 137360b141..3224361a25 100644 --- a/scene/3d/bone_attachment_3d.h +++ b/scene/3d/bone_attachment_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BONE_ATTACHMENT_H -#define BONE_ATTACHMENT_H +#ifndef BONE_ATTACHMENT_3D_H +#define BONE_ATTACHMENT_3D_H #include "scene/3d/skeleton_3d.h" #ifdef TOOLS_ENABLED @@ -99,4 +99,4 @@ public: BoneAttachment3D(); }; -#endif // BONE_ATTACHMENT_H +#endif // BONE_ATTACHMENT_3D_H diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 10348b1eb6..f654373ee5 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -31,7 +31,7 @@ #include "camera_3d.h" #include "collision_object_3d.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "scene/main/viewport.h" void Camera3D::_update_audio_listener_state() { @@ -197,7 +197,7 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea update_gizmos(); } -void Camera3D::set_projection(Camera3D::Projection p_mode) { +void Camera3D::set_projection(ProjectionType p_mode) { if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) { mode = p_mode; _update_camera_mode(); @@ -265,7 +265,7 @@ Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const { if (mode == PROJECTION_ORTHOGONAL) { ray = Vector3(0, 0, -1); } else { - CameraMatrix cm; + Projection cm; cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); Vector2 screen_he = cm.get_viewport_half_extents(); ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized(); @@ -314,7 +314,7 @@ Vector<Vector3> Camera3D::get_near_plane_points() const { Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm; + Projection cm; if (mode == PROJECTION_ORTHOGONAL) { cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); @@ -340,7 +340,7 @@ Point2 Camera3D::unproject_position(const Vector3 &p_pos) const { Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm; + Projection cm; if (mode == PROJECTION_ORTHOGONAL) { cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); @@ -368,7 +368,7 @@ Vector3 Camera3D::project_position(const Point2 &p_point, real_t p_z_depth) cons } Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm; + Projection cm; if (mode == PROJECTION_ORTHOGONAL) { cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); @@ -507,7 +507,7 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.01,suffix:m"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.001,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_frustum_offset", "get_frustum_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far"); @@ -544,7 +544,7 @@ real_t Camera3D::get_far() const { return far; } -Camera3D::Projection Camera3D::get_projection() const { +Camera3D::ProjectionType Camera3D::get_projection() const { return mode; } @@ -607,7 +607,7 @@ Vector<Plane> Camera3D::get_frustum() const { ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>()); Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm; + Projection cm; if (mode == PROJECTION_PERSPECTIVE) { cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); } else { diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index 9f2f8ceed1..cedd976890 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -40,7 +40,7 @@ class Camera3D : public Node3D { GDCLASS(Camera3D, Node3D); public: - enum Projection { + enum ProjectionType { PROJECTION_PERSPECTIVE, PROJECTION_ORTHOGONAL, PROJECTION_FRUSTUM @@ -62,7 +62,7 @@ private: bool current = false; Viewport *viewport = nullptr; - Projection mode = PROJECTION_PERSPECTIVE; + ProjectionType mode = PROJECTION_PERSPECTIVE; real_t fov = 0.0; real_t size = 1.0; @@ -112,7 +112,7 @@ public: void set_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far); void set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far); void set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far); - void set_projection(Camera3D::Projection p_mode); + void set_projection(Camera3D::ProjectionType p_mode); void make_current(); void clear_current(bool p_enable_next = true); @@ -127,7 +127,7 @@ public: real_t get_near() const; Vector2 get_frustum_offset() const; - Projection get_projection() const; + ProjectionType get_projection() const; void set_fov(real_t p_fov); void set_size(real_t p_size); @@ -181,8 +181,8 @@ public: ~Camera3D(); }; -VARIANT_ENUM_CAST(Camera3D::Projection); +VARIANT_ENUM_CAST(Camera3D::ProjectionType); VARIANT_ENUM_CAST(Camera3D::KeepAspect); VARIANT_ENUM_CAST(Camera3D::DopplerTracking); -#endif +#endif // CAMERA_3D_H diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index a36357555a..9a5d4f5480 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -319,7 +319,7 @@ bool CollisionObject3D::_are_collision_shapes_visible() { void CollisionObject3D::_update_shape_data(uint32_t p_owner) { if (_are_collision_shapes_visible()) { if (debug_shapes_to_update.is_empty()) { - callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0); + callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferredp({}, 0); } debug_shapes_to_update.insert(p_owner); } @@ -365,8 +365,7 @@ void CollisionObject3D::_update_debug_shapes() { RS::get_singleton()->instance_set_scenario(s.debug_shape, get_world_3d()->get_scenario()); if (!s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) { - s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed), - varray(s.shape), CONNECT_DEFERRED); + s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed).bind(s.shape), CONNECT_DEFERRED); } ++debug_shapes_count; @@ -404,6 +403,9 @@ void CollisionObject3D::_on_transform_changed() { debug_shape_old_transform = get_global_transform(); for (KeyValue<uint32_t, ShapeData> &E : shapes) { ShapeData &shapedata = E.value; + if (shapedata.disabled) { + continue; // If disabled then there are no debug shapes to update. + } const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr(); for (int i = 0; i < shapedata.shapes.size(); i++) { RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index 098f573551..3ec3aa0fc1 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -166,4 +166,4 @@ public: VARIANT_ENUM_CAST(CollisionObject3D::DisableMode); -#endif // COLLISION_OBJECT__H +#endif // COLLISION_OBJECT_3D_H diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h index a24d485af2..74e5867a2f 100644 --- a/scene/3d/collision_polygon_3d.h +++ b/scene/3d/collision_polygon_3d.h @@ -79,4 +79,4 @@ public: CollisionPolygon3D(); }; -#endif // COLLISION_POLYGON_H +#endif // COLLISION_POLYGON_3D_H diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index 5c32230942..124c0d166d 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_SHAPE_H -#define COLLISION_SHAPE_H +#ifndef COLLISION_SHAPE_3D_H +#define COLLISION_SHAPE_3D_H #include "scene/3d/node_3d.h" #include "scene/resources/shape_3d.h" @@ -68,4 +68,4 @@ public: ~CollisionShape3D(); }; -#endif // BODY_VOLUME_H +#endif // COLLISION_SHAPE_3D_H diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h index 7f225ee98d..e26c301038 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CPU_PARTICLES_H -#define CPU_PARTICLES_H +#ifndef CPU_PARTICLES_3D_H +#define CPU_PARTICLES_3D_H #include "scene/3d/visual_instance_3d.h" @@ -138,7 +138,7 @@ private: real_t randomness_ratio = 0.0; double lifetime_randomness = 0.0; double speed_scale = 1.0; - bool local_coords = true; + bool local_coords = false; int fixed_fps = 0; bool fractional_delta = true; @@ -317,4 +317,4 @@ VARIANT_ENUM_CAST(CPUParticles3D::Parameter) VARIANT_ENUM_CAST(CPUParticles3D::ParticleFlags) VARIANT_ENUM_CAST(CPUParticles3D::EmissionShape) -#endif // CPU_PARTICLES_H +#endif // CPU_PARTICLES_3D_H diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp index 01cab493ec..0112f24e0c 100644 --- a/scene/3d/decal.cpp +++ b/scene/3d/decal.cpp @@ -215,11 +215,13 @@ void Decal::_bind_methods() { ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_GROUP("Textures", "texture_"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ORM); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); + ADD_GROUP("Parameters", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate"); @@ -227,13 +229,16 @@ void Decal::_bind_methods() { // A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface. // Due to this, limit Normal Fade to 0.999. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade"); + ADD_GROUP("Vertical Fade", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade"); + ADD_GROUP("Distance Fade", "distance_fade_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_NONE, "suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_NONE, "suffix:m"), "set_distance_fade_length", "get_distance_fade_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length"); + ADD_GROUP("Cull Mask", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); diff --git a/scene/3d/decal.h b/scene/3d/decal.h index d5990272c6..38da4c14e3 100644 --- a/scene/3d/decal.h +++ b/scene/3d/decal.h @@ -57,8 +57,8 @@ private: real_t upper_fade = 0.3; real_t lower_fade = 0.3; bool distance_fade_enabled = false; - real_t distance_fade_begin = 10.0; - real_t distance_fade_length = 1.0; + real_t distance_fade_begin = 40.0; + real_t distance_fade_length = 10.0; protected: static void _bind_methods(); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index b352114c7f..2ee126e161 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -222,7 +222,7 @@ void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) { draw_passes.write[p_pass] = p_mesh; if (Engine::get_singleton()->is_editor_hint() && draw_passes.write[p_pass].is_valid()) { - draw_passes.write[p_pass]->connect("changed", callable_mp((Node *)this, &Node::update_configuration_warnings), varray(), CONNECT_DEFERRED); + draw_passes.write[p_pass]->connect("changed", callable_mp((Node *)this, &Node::update_configuration_warnings), CONNECT_DEFERRED); } RID mesh_rid; @@ -631,7 +631,7 @@ GPUParticles3D::GPUParticles3D() { set_randomness_ratio(0); set_trail_length(0.3); set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))); - set_use_local_coordinates(true); + set_use_local_coordinates(false); set_draw_passes(1); set_draw_order(DRAW_ORDER_INDEX); set_speed_scale(1); diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index adce45a0a9..0c745dd734 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PARTICLES_H -#define PARTICLES_H +#ifndef GPU_PARTICLES_3D_H +#define GPU_PARTICLES_3D_H #include "scene/3d/visual_instance_3d.h" #include "scene/resources/skin.h" @@ -179,4 +179,4 @@ VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder) VARIANT_ENUM_CAST(GPUParticles3D::TransformAlign) VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags) -#endif // PARTICLES_H +#endif // GPU_PARTICLES_3D_H diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index da0789ccd5..1cfd889272 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -30,6 +30,7 @@ #include "gpu_particles_collision_3d.h" +#include "core/object/worker_thread_pool.h" #include "mesh_instance_3d.h" #include "scene/3d/camera_3d.h" #include "scene/main/viewport.h" @@ -126,6 +127,10 @@ GPUParticlesCollisionBox3D::~GPUParticlesCollisionBox3D() { void GPUParticlesCollisionSDF3D::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); if (mi && mi->is_visible_in_tree()) { + if ((mi->get_layer_mask() & bake_mask) == 0) { + return; + } + Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); @@ -339,15 +344,12 @@ void GPUParticlesCollisionSDF3D::_compute_sdf_z(uint32_t p_z, ComputeSDFParams * } void GPUParticlesCollisionSDF3D::_compute_sdf(ComputeSDFParams *params) { - ThreadWorkPool work_pool; - work_pool.init(); - work_pool.begin_work(params->size.z, this, &GPUParticlesCollisionSDF3D::_compute_sdf_z, params); - while (!work_pool.is_done_dispatching()) { + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GPUParticlesCollisionSDF3D::_compute_sdf_z, params, params->size.z); + while (!WorkerThreadPool::get_singleton()->is_group_task_completed(group_task)) { OS::get_singleton()->delay_usec(10000); - bake_step_function(work_pool.get_work_index() * 100 / params->size.z, "Baking SDF"); + bake_step_function(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF"); } - work_pool.end_work(); - work_pool.finish(); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } Vector3i GPUParticlesCollisionSDF3D::get_estimated_cell_size() const { @@ -447,7 +449,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() { //compute bvh - ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>()); + ERR_FAIL_COND_V_MSG(faces.size() <= 1, Ref<Image>(), "No faces detected during GPUParticlesCollisionSDF3D bake. Check whether there are visible meshes matching the bake mask within its extents."); LocalVector<FacePos> face_pos; @@ -501,6 +503,16 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() { return ret; } +TypedArray<String> GPUParticlesCollisionSDF3D::get_configuration_warnings() const { + TypedArray<String> warnings = Node::get_configuration_warnings(); + + if (bake_mask == 0) { + warnings.push_back(RTR("The Bake Mask has no bits enabled, which means baking will not produce any collision for this GPUParticlesCollisionSDF3D.\nTo resolve this, enable at least one bit in the Bake Mask property.")); + } + + return warnings; +} + void GPUParticlesCollisionSDF3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF3D::set_extents); ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF3D::get_extents); @@ -514,9 +526,15 @@ void GPUParticlesCollisionSDF3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF3D::set_thickness); ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF3D::get_thickness); + ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &GPUParticlesCollisionSDF3D::set_bake_mask); + ClassDB::bind_method(D_METHOD("get_bake_mask"), &GPUParticlesCollisionSDF3D::get_bake_mask); + ClassDB::bind_method(D_METHOD("set_bake_mask_value", "layer_number", "value"), &GPUParticlesCollisionSDF3D::set_bake_mask_value); + ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &GPUParticlesCollisionSDF3D::get_bake_mask_value); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512,suffix:px"), "set_resolution", "get_resolution"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_thickness", "get_thickness"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); BIND_ENUM_CONSTANT(RESOLUTION_16); @@ -555,6 +573,31 @@ GPUParticlesCollisionSDF3D::Resolution GPUParticlesCollisionSDF3D::get_resolutio return resolution; } +void GPUParticlesCollisionSDF3D::set_bake_mask(uint32_t p_mask) { + bake_mask = p_mask; + update_configuration_warnings(); +} + +uint32_t GPUParticlesCollisionSDF3D::get_bake_mask() const { + return bake_mask; +} + +void GPUParticlesCollisionSDF3D::set_bake_mask_value(int p_layer_number, bool p_value) { + ERR_FAIL_COND_MSG(p_layer_number < 1 || p_layer_number > 20, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number)); + uint32_t mask = get_bake_mask(); + if (p_value) { + mask |= 1 << (p_layer_number - 1); + } else { + mask &= ~(1 << (p_layer_number - 1)); + } + set_bake_mask(mask); +} + +bool GPUParticlesCollisionSDF3D::get_bake_mask_value(int p_layer_number) const { + ERR_FAIL_COND_V_MSG(p_layer_number < 1 || p_layer_number > 20, false, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number)); + return bake_mask & (1 << (p_layer_number - 1)); +} + void GPUParticlesCollisionSDF3D::set_texture(const Ref<Texture3D> &p_texture) { texture = p_texture; RID tex = texture.is_valid() ? texture->get_rid() : RID(); diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h index 4b2cb930fa..712bd015ff 100644 --- a/scene/3d/gpu_particles_collision_3d.h +++ b/scene/3d/gpu_particles_collision_3d.h @@ -110,6 +110,7 @@ public: private: Vector3 extents = Vector3(1, 1, 1); Resolution resolution = RESOLUTION_64; + uint32_t bake_mask = 0xFFFFFFFF; Ref<Texture3D> texture; float thickness = 1.0; @@ -161,6 +162,8 @@ protected: static void _bind_methods(); public: + virtual TypedArray<String> get_configuration_warnings() const override; + void set_thickness(float p_thickness); float get_thickness() const; @@ -170,6 +173,12 @@ public: void set_resolution(Resolution p_resolution); Resolution get_resolution() const; + void set_bake_mask(uint32_t p_mask); + uint32_t get_bake_mask() const; + + void set_bake_mask_value(int p_layer_number, bool p_enable); + bool get_bake_mask_value(int p_layer_number) const; + void set_texture(const Ref<Texture3D> &p_texture); Ref<Texture3D> get_texture() const; diff --git a/scene/3d/importer_mesh_instance_3d.h b/scene/3d/importer_mesh_instance_3d.h index 3daf06771d..223b6fc80a 100644 --- a/scene/3d/importer_mesh_instance_3d.h +++ b/scene/3d/importer_mesh_instance_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_IMPORTER_MESH_INSTANCE_3D_H -#define SCENE_IMPORTER_MESH_INSTANCE_3D_H +#ifndef IMPORTER_MESH_INSTANCE_3D_H +#define IMPORTER_MESH_INSTANCE_3D_H #include "scene/3d/node_3d.h" #include "scene/resources/immediate_mesh.h" @@ -61,4 +61,5 @@ public: void set_skeleton_path(const NodePath &p_path); NodePath get_skeleton_path() const; }; -#endif + +#endif // IMPORTER_MESH_INSTANCE_3D_H diff --git a/scene/3d/joint_3d.cpp b/scene/3d/joint_3d.cpp index 0b824ef28b..b0509475a7 100644 --- a/scene/3d/joint_3d.cpp +++ b/scene/3d/joint_3d.cpp @@ -737,7 +737,8 @@ void Generic6DOFJoint3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flag_z", "flag", "value"), &Generic6DOFJoint3D::set_flag_z); ClassDB::bind_method(D_METHOD("get_flag_z", "flag"), &Generic6DOFJoint3D::get_flag_z); - // X + ADD_GROUP("Linear Limit", "linear_limit_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT); @@ -745,15 +746,53 @@ void Generic6DOFJoint3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING); + + ADD_GROUP("Linear Motor", "linear_motor_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + + ADD_GROUP("Linear Spring", "linear_spring_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + + ADD_GROUP("Angular Limit", "angular_limit_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x"); @@ -763,68 +802,15 @@ void Generic6DOFJoint3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); - - // Y - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); - - // Z - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z"); @@ -834,10 +820,32 @@ void Generic6DOFJoint3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP); + ADD_GROUP("Angular Motor", "angular_motor_"); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_GROUP("Angular Spring", "angular_spring_"); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING); diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 0e5771bdb1..712a37e745 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -126,7 +126,7 @@ void Label3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority"); ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_outline_render_priority", "get_outline_render_priority"); @@ -452,10 +452,10 @@ void Label3D::_shape() { } lines_rid.clear(); - uint16_t autowrap_flags = TextServer::BREAK_MANDATORY; + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; switch (autowrap_mode) { case TextServer::AUTOWRAP_WORD_SMART: - autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; break; case TextServer::AUTOWRAP_WORD: autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 6c999d85e2..53c072c318 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -224,7 +224,7 @@ bool Light3D::is_editor_only() const { } void Light3D::_validate_property(PropertyInfo &property) const { - if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) { + if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_opacity" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) { property.usage = PROPERTY_USAGE_NO_EDITOR; } @@ -291,6 +291,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_SPECULAR); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); + ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS); @@ -298,13 +299,18 @@ void Light3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR); + + ADD_GROUP("Distance Fade", "distance_fade_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_shadow", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_shadow", "get_distance_fade_shadow"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length"); + ADD_GROUP("Editor", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only"); + ADD_GROUP("", ""); BIND_ENUM_CONSTANT(PARAM_ENERGY); @@ -323,6 +329,7 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS); BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS); BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE); + BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY); BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR); BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE); BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS); @@ -370,6 +377,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5); set_param(PARAM_SHADOW_FADE_START, 0.8); set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0); + set_param(PARAM_SHADOW_OPACITY, 1.0); set_param(PARAM_SHADOW_BLUR, 1.0); set_param(PARAM_SHADOW_BIAS, 0.03); set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 6ff332df5a..ef003e133d 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -54,6 +54,7 @@ public: PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS, PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE, + PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY, PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR, PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE, PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS, diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index abe942b97a..6b6a2eff9e 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -146,7 +146,7 @@ Array LightmapGIData::_get_light_textures_data() const { texture_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); for (int j = 0; j < texture_slice_count; j++) { - texture_image->blit_rect(images[i * slices_per_texture + j], Rect2(0, 0, slice_width, slice_height), Point2(0, slice_height * j)); + texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); } String texture_path = texture_count > 1 ? base_name + "_" + itos(i) + ".exr" : base_name + ".exr"; @@ -291,7 +291,7 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data); ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK), "set_light_texture", "get_light_texture"); // property usage default but no save + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); // property usage default but no save ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); @@ -1219,7 +1219,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa } data->set_path(p_image_data_path); - Error err = ResourceSaver::save(p_image_data_path, data); + Error err = ResourceSaver::save(data); if (err != OK) { return BAKE_ERROR_CANT_CREATE_IMAGE; diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index f7a23c776a..85150b833f 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -271,4 +271,4 @@ VARIANT_ENUM_CAST(LightmapGI::GenerateProbes); VARIANT_ENUM_CAST(LightmapGI::BakeError); VARIANT_ENUM_CAST(LightmapGI::EnvironmentMode); -#endif // BAKED_LIGHTMAP_H +#endif // LIGHTMAP_GI_H diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h index dc9c64fa41..48d76b9a88 100644 --- a/scene/3d/mesh_instance_3d.h +++ b/scene/3d/mesh_instance_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef MESH_INSTANCE_H -#define MESH_INSTANCE_H +#ifndef MESH_INSTANCE_3D_H +#define MESH_INSTANCE_3D_H #include "core/templates/local_vector.h" #include "scene/3d/visual_instance_3d.h" @@ -98,4 +98,4 @@ public: ~MeshInstance3D(); }; -#endif +#endif // MESH_INSTANCE_3D_H diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h index 111f1e9c09..2fa8dd965f 100644 --- a/scene/3d/multimesh_instance_3d.h +++ b/scene/3d/multimesh_instance_3d.h @@ -53,4 +53,4 @@ public: ~MultiMeshInstance3D(); }; -#endif // MULTIMESH_INSTANCE_H +#endif // MULTIMESH_INSTANCE_3D_H diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 0a00d769c3..e05f0287f7 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NAVIGATION_AGENT_H -#define NAVIGATION_AGENT_H +#ifndef NAVIGATION_AGENT_3D_H +#define NAVIGATION_AGENT_3D_H #include "scene/main/node.h" @@ -175,4 +175,4 @@ private: void _check_distance_to_target(); }; -#endif +#endif // NAVIGATION_AGENT_3D_H diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h index 0ddde64c0e..0316fc37a8 100644 --- a/scene/3d/navigation_obstacle_3d.h +++ b/scene/3d/navigation_obstacle_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NAVIGATION_OBSTACLE_H -#define NAVIGATION_OBSTACLE_H +#ifndef NAVIGATION_OBSTACLE_3D_H +#define NAVIGATION_OBSTACLE_3D_H #include "scene/3d/node_3d.h" @@ -73,4 +73,4 @@ private: real_t estimate_agent_radius() const; }; -#endif +#endif // NAVIGATION_OBSTACLE_3D_H diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 2a8149c6f6..4150b01651 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -49,14 +49,29 @@ void NavigationRegion3D::set_enabled(bool p_enabled) { NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); } - if (debug_view) { - MeshInstance3D *dm = Object::cast_to<MeshInstance3D>(debug_view); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); +#ifdef DEBUG_ENABLED + if (debug_instance.is_valid()) { + if (!is_enabled()) { + if (debug_mesh.is_valid()) { + if (debug_mesh->get_surface_count() > 0) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material()->get_rid()); + } + if (debug_mesh->get_surface_count() > 1) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material()->get_rid()); + } + } } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + if (debug_mesh.is_valid()) { + if (debug_mesh->get_surface_count() > 0) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, RID()); + } + if (debug_mesh->get_surface_count() > 1) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, RID()); + } + } } } +#endif // DEBUG_ENABLED update_gizmos(); } @@ -104,7 +119,7 @@ real_t NavigationRegion3D::get_enter_cost() const { void NavigationRegion3D::set_travel_cost(real_t p_travel_cost) { ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive."); travel_cost = MAX(p_travel_cost, 0.0); - NavigationServer3D::get_singleton()->region_set_enter_cost(region, travel_cost); + NavigationServer3D::get_singleton()->region_set_travel_cost(region, travel_cost); } real_t NavigationRegion3D::get_travel_cost() const { @@ -124,30 +139,36 @@ void NavigationRegion3D::_notification(int p_what) { NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map()); } - if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { - MeshInstance3D *dm = memnew(MeshInstance3D); - dm->set_mesh(navmesh->get_debug_mesh()); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); - } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); - } - add_child(dm); - debug_view = dm; +#ifdef DEBUG_ENABLED + if (NavigationServer3D::get_singleton()->get_debug_enabled()) { + _update_debug_mesh(); } +#endif // DEBUG_ENABLED + } break; case NOTIFICATION_TRANSFORM_CHANGED: { NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform()); + +#ifdef DEBUG_ENABLED + if (is_inside_tree() && debug_instance.is_valid()) { + RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform()); + } +#endif // DEBUG_ENABLED + } break; case NOTIFICATION_EXIT_TREE: { NavigationServer3D::get_singleton()->region_set_map(region, RID()); - if (debug_view) { - debug_view->queue_delete(); - debug_view = nullptr; +#ifdef DEBUG_ENABLED + if (debug_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_instance, false); + } + if (debug_edge_connections_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); } +#endif // DEBUG_ENABLED } break; } } @@ -169,20 +190,21 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh); - if (debug_view == nullptr && is_inside_tree() && navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { - MeshInstance3D *dm = memnew(MeshInstance3D); - dm->set_mesh(navmesh->get_debug_mesh()); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); +#ifdef DEBUG_ENABLED + if (is_inside_tree() && NavigationServer3D::get_singleton()->get_debug_enabled()) { + if (navmesh.is_valid()) { + _update_debug_mesh(); + _update_debug_edge_connections_mesh(); } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + if (debug_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_instance, false); + } + if (debug_edge_connections_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); + } } - add_child(dm); - debug_view = dm; - } - if (debug_view && navmesh.is_valid()) { - Object::cast_to<MeshInstance3D>(debug_view)->set_mesh(navmesh->get_debug_mesh()); } +#endif // DEBUG_ENABLED emit_signal(SNAME("navigation_mesh_changed")); @@ -287,13 +309,31 @@ void NavigationRegion3D::_bind_methods() { void NavigationRegion3D::_navigation_changed() { update_gizmos(); update_configuration_warnings(); + +#ifdef DEBUG_ENABLED + _update_debug_edge_connections_mesh(); +#endif // DEBUG_ENABLED +} + +#ifdef DEBUG_ENABLED +void NavigationRegion3D::_navigation_map_changed(RID p_map) { + if (is_inside_tree() && p_map == get_world_3d()->get_navigation_map()) { + _update_debug_edge_connections_mesh(); + } } +#endif // DEBUG_ENABLED NavigationRegion3D::NavigationRegion3D() { set_notify_transform(true); region = NavigationServer3D::get_singleton()->region_create(); NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost()); NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost()); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion3D::_navigation_map_changed)); + NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_mesh)); + NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_edge_connections_mesh)); +#endif // DEBUG_ENABLED } NavigationRegion3D::~NavigationRegion3D() { @@ -301,4 +341,245 @@ NavigationRegion3D::~NavigationRegion3D() { navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed)); } NavigationServer3D::get_singleton()->free(region); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton_mut()->disconnect("map_changed", callable_mp(this, &NavigationRegion3D::_navigation_map_changed)); + NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_mesh)); + NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_edge_connections_mesh)); + if (debug_instance.is_valid()) { + RenderingServer::get_singleton()->free(debug_instance); + } + if (debug_mesh.is_valid()) { + RenderingServer::get_singleton()->free(debug_mesh->get_rid()); + } + if (debug_edge_connections_instance.is_valid()) { + RenderingServer::get_singleton()->free(debug_edge_connections_instance); + } + if (debug_edge_connections_mesh.is_valid()) { + RenderingServer::get_singleton()->free(debug_edge_connections_mesh->get_rid()); + } +#endif // DEBUG_ENABLED +} + +#ifdef DEBUG_ENABLED +void NavigationRegion3D::_update_debug_mesh() { + if (!NavigationServer3D::get_singleton()->get_debug_enabled()) { + if (debug_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_instance, false); + } + return; + } + + if (!navmesh.is_valid()) { + if (debug_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_instance, false); + } + return; + } + + if (!debug_instance.is_valid()) { + debug_instance = RenderingServer::get_singleton()->instance_create(); + } + + if (!debug_mesh.is_valid()) { + debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + } + + debug_mesh->clear_surfaces(); + + bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color(); + bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines(); + + Vector<Vector3> vertices = navmesh->get_vertices(); + if (vertices.size() == 0) { + return; + } + + int polygon_count = navmesh->get_polygon_count(); + if (polygon_count == 0) { + return; + } + + Vector<Vector3> face_vertex_array; + face_vertex_array.resize(polygon_count * 3); + + Vector<Color> face_color_array; + if (enabled_geometry_face_random_color) { + face_color_array.resize(polygon_count * 3); + } + + Vector<Vector3> line_vertex_array; + if (enabled_edge_lines) { + line_vertex_array.resize(polygon_count * 6); + } + + Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); + + Ref<StandardMaterial3D> face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material(); + Ref<StandardMaterial3D> line_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material(); + + Color polygon_color = debug_navigation_geometry_face_color; + + for (int i = 0; i < polygon_count; i++) { + if (enabled_geometry_face_random_color) { + polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf())); + } + + Vector<int> polygon = navmesh->get_polygon(i); + + face_vertex_array.push_back(vertices[polygon[0]]); + face_vertex_array.push_back(vertices[polygon[1]]); + face_vertex_array.push_back(vertices[polygon[2]]); + if (enabled_geometry_face_random_color) { + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + } + + if (enabled_edge_lines) { + line_vertex_array.push_back(vertices[polygon[0]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[0]]); + } + } + + Array face_mesh_array; + face_mesh_array.resize(Mesh::ARRAY_MAX); + face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array; + if (enabled_geometry_face_random_color) { + face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array; + } + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); + debug_mesh->surface_set_material(0, face_material); + + if (enabled_edge_lines) { + Array line_mesh_array; + line_mesh_array.resize(Mesh::ARRAY_MAX); + line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array; + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array); + debug_mesh->surface_set_material(1, line_material); + } + + RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid()); + if (is_inside_tree()) { + RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree()); + } + if (!is_enabled()) { + if (debug_mesh.is_valid()) { + if (debug_mesh->get_surface_count() > 0) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material()->get_rid()); + } + if (debug_mesh->get_surface_count() > 1) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material()->get_rid()); + } + } + } else { + if (debug_mesh.is_valid()) { + if (debug_mesh->get_surface_count() > 0) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, RID()); + } + if (debug_mesh->get_surface_count() > 1) { + RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, RID()); + } + } + } +} +#endif // DEBUG_ENABLED + +#ifdef DEBUG_ENABLED +void NavigationRegion3D::_update_debug_edge_connections_mesh() { + if (!NavigationServer3D::get_singleton()->get_debug_enabled()) { + if (debug_edge_connections_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); + } + return; + } + + if (!is_inside_tree()) { + return; + } + + if (!navmesh.is_valid()) { + if (debug_edge_connections_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); + } + return; + } + + if (!debug_edge_connections_instance.is_valid()) { + debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create(); + } + + if (!debug_edge_connections_mesh.is_valid()) { + debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + } + + debug_edge_connections_mesh->clear_surfaces(); + + float edge_connection_margin = NavigationServer3D::get_singleton()->map_get_edge_connection_margin(get_world_3d()->get_navigation_map()); + float half_edge_connection_margin = edge_connection_margin * 0.5; + int connections_count = NavigationServer3D::get_singleton()->region_get_connections_count(region); + + if (connections_count == 0) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); + return; + } + + Vector<Vector3> vertex_array; + + for (int i = 0; i < connections_count; i++) { + Vector3 connection_pathway_start = NavigationServer3D::get_singleton()->region_get_connection_pathway_start(region, i); + Vector3 connection_pathway_end = NavigationServer3D::get_singleton()->region_get_connection_pathway_end(region, i); + + Vector3 direction_start_end = connection_pathway_start.direction_to(connection_pathway_end); + Vector3 direction_end_start = connection_pathway_end.direction_to(connection_pathway_start); + + Vector3 start_right_dir = direction_start_end.cross(Vector3(0, 1, 0)); + Vector3 start_left_dir = -start_right_dir; + + Vector3 end_right_dir = direction_end_start.cross(Vector3(0, 1, 0)); + Vector3 end_left_dir = -end_right_dir; + + Vector3 left_start_pos = connection_pathway_start + (start_left_dir * half_edge_connection_margin); + Vector3 right_start_pos = connection_pathway_start + (start_right_dir * half_edge_connection_margin); + Vector3 left_end_pos = connection_pathway_end + (end_right_dir * half_edge_connection_margin); + Vector3 right_end_pos = connection_pathway_end + (end_left_dir * half_edge_connection_margin); + + vertex_array.push_back(right_end_pos); + vertex_array.push_back(left_start_pos); + vertex_array.push_back(right_start_pos); + + vertex_array.push_back(left_end_pos); + vertex_array.push_back(right_end_pos); + vertex_array.push_back(right_start_pos); + } + + if (vertex_array.size() == 0) { + return; + } + + Ref<StandardMaterial3D> edge_connections_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_edge_connections_material(); + + Array mesh_array; + mesh_array.resize(Mesh::ARRAY_MAX); + mesh_array[Mesh::ARRAY_VERTEX] = vertex_array; + + debug_edge_connections_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mesh_array); + debug_edge_connections_mesh->surface_set_material(0, edge_connections_material); + + RS::get_singleton()->instance_set_base(debug_edge_connections_instance, debug_edge_connections_mesh->get_rid()); + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, is_visible_in_tree()); + if (is_inside_tree()) { + RS::get_singleton()->instance_set_scenario(debug_edge_connections_instance, get_world_3d()->get_scenario()); + } + + bool enable_edge_connections = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections(); + if (!enable_edge_connections) { + RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false); + } } +#endif // DEBUG_ENABLED diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index aaaf5dd3b8..ba326abb46 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NAVIGATION_REGION_H -#define NAVIGATION_REGION_H +#ifndef NAVIGATION_REGION_3D_H +#define NAVIGATION_REGION_3D_H #include "scene/3d/node_3d.h" #include "scene/resources/navigation_mesh.h" @@ -44,11 +44,22 @@ class NavigationRegion3D : public Node3D { real_t enter_cost = 0.0; real_t travel_cost = 1.0; - Node *debug_view = nullptr; Thread bake_thread; void _navigation_changed(); +#ifdef DEBUG_ENABLED + RID debug_instance; + RID debug_edge_connections_instance; + Ref<ArrayMesh> debug_mesh; + Ref<ArrayMesh> debug_edge_connections_mesh; + +private: + void _update_debug_mesh(); + void _update_debug_edge_connections_mesh(); + void _navigation_map_changed(RID p_map); +#endif // DEBUG_ENABLED + protected: void _notification(int p_what); static void _bind_methods(); @@ -85,4 +96,4 @@ public: ~NavigationRegion3D(); }; -#endif // NAVIGATION_REGION_H +#endif // NAVIGATION_REGION_3D_H diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 04b1081516..1de85d57a3 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -733,7 +733,7 @@ void Node3D::rotate_z(real_t p_angle) { void Node3D::translate(const Vector3 &p_offset) { Transform3D t = get_transform(); - t.translate(p_offset); + t.translate_local(p_offset); set_transform(t); } @@ -741,7 +741,7 @@ void Node3D::translate_object_local(const Vector3 &p_offset) { Transform3D t = get_transform(); Transform3D s; - s.translate(p_offset); + s.translate_local(p_offset); set_transform(t * s); } diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 66d0a8c4e2..c1c309fdbe 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -670,7 +670,7 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake_scene(Node *p_from_node, occ->set_arrays(vertices, indices); - Error err = ResourceSaver::save(p_occluder_path, occ); + Error err = ResourceSaver::save(occ, p_occluder_path); if (err != OK) { return BAKE_ERROR_CANT_SAVE; diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h index ed6610074e..11d731b989 100644 --- a/scene/3d/occluder_instance_3d.h +++ b/scene/3d/occluder_instance_3d.h @@ -211,4 +211,4 @@ public: ~OccluderInstance3D(); }; -#endif +#endif // OCCLUDER_INSTANCE_3D_H diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index f53e783fbd..25226ad384 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -296,7 +296,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { } } - t.translate(Vector3(h_offset, v_offset, 0)); + t.translate_local(Vector3(h_offset, v_offset, 0)); } else { t.origin = pos + Vector3(h_offset, v_offset, 0); } @@ -397,6 +397,7 @@ void PathFollow3D::_bind_methods() { } void PathFollow3D::set_offset(real_t p_offset) { + ERR_FAIL_COND(!isfinite(p_offset)); prev_offset = offset; offset = p_offset; diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index 7c7284534e..b4cc6db7e3 100644 --- a/scene/3d/path_3d.h +++ b/scene/3d/path_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PATH_H -#define PATH_H +#ifndef PATH_3D_H +#define PATH_3D_H #include "scene/3d/node_3d.h" #include "scene/resources/curve.h" @@ -119,4 +119,4 @@ public: VARIANT_ENUM_CAST(PathFollow3D::RotationMode); -#endif // PATH_H +#endif // PATH_3D_H diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 30f7a025fa..993608c306 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -439,8 +439,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 22dcb218bc..e4a41be6c0 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -784,4 +784,4 @@ private: VARIANT_ENUM_CAST(PhysicalBone3D::JointType); VARIANT_ENUM_CAST(PhysicalBone3D::DampMode); -#endif // PHYSICS_BODY__H +#endif // PHYSICS_BODY_3D_H diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index c69c910efb..aa62f6927e 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -126,4 +126,4 @@ public: RayCast3D(); }; -#endif // RAY_CAST_H +#endif // RAY_CAST_3D_H diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 424976d895..a161717ece 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REFLECTIONPROBE_H -#define REFLECTIONPROBE_H +#ifndef REFLECTION_PROBE_H +#define REFLECTION_PROBE_H #include "scene/3d/visual_instance_3d.h" @@ -121,4 +121,4 @@ public: VARIANT_ENUM_CAST(ReflectionProbe::AmbientMode); VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode); -#endif // REFLECTIONPROBE_H +#endif // REFLECTION_PROBE_H diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h index 03bb253578..ab134c1261 100644 --- a/scene/3d/remote_transform_3d.h +++ b/scene/3d/remote_transform_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REMOTETRANSFORM_H -#define REMOTETRANSFORM_H +#ifndef REMOTE_TRANSFORM_3D_H +#define REMOTE_TRANSFORM_3D_H #include "scene/3d/node_3d.h" @@ -75,4 +75,4 @@ public: RemoteTransform3D(); }; -#endif // REMOTETRANSFORM_H +#endif // REMOTE_TRANSFORM_3D_H diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp new file mode 100644 index 0000000000..d324e09df5 --- /dev/null +++ b/scene/3d/shape_cast_3d.cpp @@ -0,0 +1,634 @@ +/*************************************************************************/ +/* shape_cast_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "shape_cast_3d.h" + +#include "collision_object_3d.h" +#include "mesh_instance_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" + +void ShapeCast3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (Engine::get_singleton()->is_editor_hint()) { + _update_debug_shape_vertices(); + } + if (enabled && !Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } else { + set_physics_process_internal(false); + } + + if (get_tree()->is_debugging_collisions_hint()) { + _update_debug_shape(); + } + + if (Object::cast_to<CollisionObject3D>(get_parent())) { + if (exclude_parent_body) { + exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid()); + } else { + exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid()); + } + } + } break; + + case NOTIFICATION_EXIT_TREE: { + if (enabled) { + set_physics_process_internal(false); + } + + if (debug_shape) { + _clear_debug_shape(); + } + } break; + + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (!enabled) { + break; + } + + bool prev_collision_state = collided; + _update_shapecast_state(); + if (get_tree()->is_debugging_collisions_hint()) { + if (prev_collision_state != collided) { + _update_debug_shape_material(true); + } + if (collided) { + _update_debug_shape(); + } + if (prev_collision_state == collided && !collided) { + _update_debug_shape(); + } + } + } break; + } +} + +void ShapeCast3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &ShapeCast3D::resource_changed); + + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &ShapeCast3D::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &ShapeCast3D::is_enabled); + + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &ShapeCast3D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &ShapeCast3D::get_shape); + + ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &ShapeCast3D::set_target_position); + ClassDB::bind_method(D_METHOD("get_target_position"), &ShapeCast3D::get_target_position); + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ShapeCast3D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &ShapeCast3D::get_margin); + + ClassDB::bind_method(D_METHOD("set_max_results", "max_results"), &ShapeCast3D::set_max_results); + ClassDB::bind_method(D_METHOD("get_max_results"), &ShapeCast3D::get_max_results); + + ClassDB::bind_method(D_METHOD("is_colliding"), &ShapeCast3D::is_colliding); + ClassDB::bind_method(D_METHOD("get_collision_count"), &ShapeCast3D::get_collision_count); + + ClassDB::bind_method(D_METHOD("force_shapecast_update"), &ShapeCast3D::force_shapecast_update); + + ClassDB::bind_method(D_METHOD("get_collider", "index"), &ShapeCast3D::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_shape", "index"), &ShapeCast3D::get_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_point", "index"), &ShapeCast3D::get_collision_point); + ClassDB::bind_method(D_METHOD("get_collision_normal", "index"), &ShapeCast3D::get_collision_normal); + + ClassDB::bind_method(D_METHOD("get_closest_collision_safe_fraction"), &ShapeCast3D::get_closest_collision_safe_fraction); + ClassDB::bind_method(D_METHOD("get_closest_collision_unsafe_fraction"), &ShapeCast3D::get_closest_collision_unsafe_fraction); + + ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &ShapeCast3D::add_exception_rid); + ClassDB::bind_method(D_METHOD("add_exception", "node"), &ShapeCast3D::add_exception); + + ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &ShapeCast3D::remove_exception_rid); + ClassDB::bind_method(D_METHOD("remove_exception", "node"), &ShapeCast3D::remove_exception); + + ClassDB::bind_method(D_METHOD("clear_exceptions"), &ShapeCast3D::clear_exceptions); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ShapeCast3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &ShapeCast3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &ShapeCast3D::set_collision_mask_value); + ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &ShapeCast3D::get_collision_mask_value); + + ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &ShapeCast3D::set_exclude_parent_body); + ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &ShapeCast3D::get_exclude_parent_body); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &ShapeCast3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &ShapeCast3D::is_collide_with_areas_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &ShapeCast3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &ShapeCast3D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("_get_collision_result"), &ShapeCast3D::_get_collision_result); + + ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &ShapeCast3D::set_debug_shape_custom_color); + ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &ShapeCast3D::get_debug_shape_custom_color); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "suffix:m"), "set_target_position", "get_target_position"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:m"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result"); + + ADD_GROUP("Collide With", "collide_with"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + + ADD_GROUP("Debug Shape", "debug_shape"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_shape_custom_color"), "set_debug_shape_custom_color", "get_debug_shape_custom_color"); +} + +TypedArray<String> ShapeCast3D::get_configuration_warnings() const { + TypedArray<String> warnings = Node3D::get_configuration_warnings(); + + if (shape.is_null()) { + warnings.push_back(RTR("This node cannot interact with other objects unless a Shape3D is assigned.")); + } + if (shape.is_valid() && Object::cast_to<ConcavePolygonShape3D>(*shape)) { + warnings.push_back(RTR("ShapeCast3D does not support ConcavePolygonShape3Ds. Collisions will not be reported.")); + } + return warnings; +} + +void ShapeCast3D::set_enabled(bool p_enabled) { + enabled = p_enabled; + update_gizmos(); + + if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(p_enabled); + } + if (!p_enabled) { + collided = false; + } + + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { + if (p_enabled) { + _update_debug_shape(); + } else { + _clear_debug_shape(); + } + } +} + +bool ShapeCast3D::is_enabled() const { + return enabled; +} + +void ShapeCast3D::set_target_position(const Vector3 &p_point) { + target_position = p_point; + if (is_inside_tree()) { + _update_debug_shape(); + } + update_gizmos(); + + if (Engine::get_singleton()->is_editor_hint()) { + if (is_inside_tree()) { + _update_debug_shape_vertices(); + } + } else if (debug_shape) { + _update_debug_shape(); + } +} + +Vector3 ShapeCast3D::get_target_position() const { + return target_position; +} + +void ShapeCast3D::set_margin(real_t p_margin) { + margin = p_margin; +} + +real_t ShapeCast3D::get_margin() const { + return margin; +} + +void ShapeCast3D::set_max_results(int p_max_results) { + max_results = p_max_results; +} + +int ShapeCast3D::get_max_results() const { + return max_results; +} + +void ShapeCast3D::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; +} + +uint32_t ShapeCast3D::get_collision_mask() const { + return collision_mask; +} + +void ShapeCast3D::set_collision_mask_value(int p_layer_number, bool p_value) { + ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); + uint32_t mask = get_collision_mask(); + if (p_value) { + mask |= 1 << (p_layer_number - 1); + } else { + mask &= ~(1 << (p_layer_number - 1)); + } + set_collision_mask(mask); +} + +bool ShapeCast3D::get_collision_mask_value(int p_layer_number) const { + ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); + return get_collision_mask() & (1 << (p_layer_number - 1)); +} + +int ShapeCast3D::get_collision_count() const { + return result.size(); +} + +bool ShapeCast3D::is_colliding() const { + return collided; +} + +Object *ShapeCast3D::get_collider(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), nullptr, "No collider found."); + + if (result[p_idx].collider_id.is_null()) { + return nullptr; + } + return ObjectDB::get_instance(result[p_idx].collider_id); +} + +int ShapeCast3D::get_collider_shape(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), -1, "No collider shape found."); + return result[p_idx].shape; +} + +Vector3 ShapeCast3D::get_collision_point(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector3(), "No collision point found."); + return result[p_idx].point; +} + +Vector3 ShapeCast3D::get_collision_normal(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector3(), "No collision normal found."); + return result[p_idx].normal; +} + +real_t ShapeCast3D::get_closest_collision_safe_fraction() const { + return collision_safe_fraction; +} + +real_t ShapeCast3D::get_closest_collision_unsafe_fraction() const { + return collision_unsafe_fraction; +} + +void ShapeCast3D::resource_changed(Ref<Resource> p_res) { + if (is_inside_tree()) { + _update_debug_shape(); + } + update_gizmos(); +} + +void ShapeCast3D::set_shape(const Ref<Shape3D> &p_shape) { + if (p_shape == shape) { + return; + } + if (!shape.is_null()) { + shape->unregister_owner(this); + } + shape = p_shape; + if (!shape.is_null()) { + shape->register_owner(this); + } + if (p_shape.is_valid()) { + shape_rid = shape->get_rid(); + } + + if (is_inside_tree()) { + _update_debug_shape(); + } + + update_gizmos(); + update_configuration_warnings(); +} + +Ref<Shape3D> ShapeCast3D::get_shape() const { + return shape; +} + +void ShapeCast3D::set_exclude_parent_body(bool p_exclude_parent_body) { + if (exclude_parent_body == p_exclude_parent_body) { + return; + } + exclude_parent_body = p_exclude_parent_body; + + if (!is_inside_tree()) { + return; + } + if (Object::cast_to<CollisionObject3D>(get_parent())) { + if (exclude_parent_body) { + exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid()); + } else { + exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid()); + } + } +} + +bool ShapeCast3D::get_exclude_parent_body() const { + return exclude_parent_body; +} + +void ShapeCast3D::_update_shapecast_state() { + result.clear(); + + ERR_FAIL_COND_MSG(shape.is_null(), "Null reference to shape. ShapeCast3D requires a Shape3D to sweep for collisions."); + + Ref<World3D> w3d = get_world_3d(); + ERR_FAIL_COND(w3d.is_null()); + + PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space()); + ERR_FAIL_COND(!dss); + + Transform3D gt = get_global_transform(); + + PhysicsDirectSpaceState3D::ShapeParameters params; + params.shape_rid = shape_rid; + params.transform = gt; + params.motion = gt.basis.xform(target_position); + params.margin = margin; + params.exclude = exclude; + params.collision_mask = collision_mask; + params.collide_with_bodies = collide_with_bodies; + params.collide_with_areas = collide_with_areas; + + collision_safe_fraction = 0.0; + collision_unsafe_fraction = 0.0; + + if (target_position != Vector3()) { + dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction); + if (collision_unsafe_fraction < 1.0) { + // Move shape transform to the point of impact, + // so we can collect contact info at that point. + gt.set_origin(gt.get_origin() + params.motion * (collision_unsafe_fraction + CMP_EPSILON)); + params.transform = gt; + } + } + // Regardless of whether the shape is stuck or it's moved along + // the motion vector, we'll only consider static collisions from now on. + params.motion = Vector3(); + + bool intersected = true; + while (intersected && result.size() < max_results) { + PhysicsDirectSpaceState3D::ShapeRestInfo info; + intersected = dss->rest_info(params, &info); + if (intersected) { + result.push_back(info); + params.exclude.insert(info.rid); + } + } + collided = !result.is_empty(); +} + +void ShapeCast3D::force_shapecast_update() { + _update_shapecast_state(); +} + +void ShapeCast3D::add_exception_rid(const RID &p_rid) { + exclude.insert(p_rid); +} + +void ShapeCast3D::add_exception(const Object *p_object) { + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object); + if (!co) { + return; + } + add_exception_rid(co->get_rid()); +} + +void ShapeCast3D::remove_exception_rid(const RID &p_rid) { + exclude.erase(p_rid); +} + +void ShapeCast3D::remove_exception(const Object *p_object) { + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object); + if (!co) { + return; + } + remove_exception_rid(co->get_rid()); +} + +void ShapeCast3D::clear_exceptions() { + exclude.clear(); +} + +void ShapeCast3D::set_collide_with_areas(bool p_clip) { + collide_with_areas = p_clip; +} + +bool ShapeCast3D::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + +void ShapeCast3D::set_collide_with_bodies(bool p_clip) { + collide_with_bodies = p_clip; +} + +bool ShapeCast3D::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +Array ShapeCast3D::_get_collision_result() const { + Array ret; + + for (int i = 0; i < result.size(); ++i) { + const PhysicsDirectSpaceState3D::ShapeRestInfo &sri = result[i]; + + Dictionary col; + col["point"] = sri.point; + col["normal"] = sri.normal; + col["rid"] = sri.rid; + col["collider"] = ObjectDB::get_instance(sri.collider_id); + col["collider_id"] = sri.collider_id; + col["shape"] = sri.shape; + col["linear_velocity"] = sri.linear_velocity; + + ret.push_back(col); + } + return ret; +} + +void ShapeCast3D::_update_debug_shape_vertices() { + debug_shape_vertices.clear(); + debug_line_vertices.clear(); + + if (!shape.is_null()) { + debug_shape_vertices.append_array(shape->get_debug_mesh_lines()); + for (int i = 0; i < debug_shape_vertices.size(); i++) { + debug_shape_vertices.set(i, debug_shape_vertices[i] + Vector3(target_position * get_closest_collision_safe_fraction())); + } + } + + if (target_position == Vector3()) { + return; + } + + debug_line_vertices.push_back(Vector3()); + debug_line_vertices.push_back(target_position); +} + +const Vector<Vector3> &ShapeCast3D::get_debug_shape_vertices() const { + return debug_shape_vertices; +} + +const Vector<Vector3> &ShapeCast3D::get_debug_line_vertices() const { + return debug_line_vertices; +} + +void ShapeCast3D::set_debug_shape_custom_color(const Color &p_color) { + debug_shape_custom_color = p_color; + if (debug_material.is_valid()) { + _update_debug_shape_material(); + } +} + +Ref<StandardMaterial3D> ShapeCast3D::get_debug_material() { + _update_debug_shape_material(); + return debug_material; +} + +const Color &ShapeCast3D::get_debug_shape_custom_color() const { + return debug_shape_custom_color; +} + +void ShapeCast3D::_create_debug_shape() { + _update_debug_shape_material(); + + Ref<ArrayMesh> mesh = memnew(ArrayMesh); + + MeshInstance3D *mi = memnew(MeshInstance3D); + mi->set_mesh(mesh); + + add_child(mi); + debug_shape = mi; +} + +void ShapeCast3D::_update_debug_shape_material(bool p_check_collision) { + if (!debug_material.is_valid()) { + Ref<StandardMaterial3D> material = memnew(StandardMaterial3D); + debug_material = material; + + material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + // Use double-sided rendering so that the RayCast can be seen if the camera is inside. + material->set_cull_mode(BaseMaterial3D::CULL_DISABLED); + material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA); + } + + Color color = debug_shape_custom_color; + if (color == Color(0.0, 0.0, 0.0)) { + // Use the default debug shape color defined in the Project Settings. + color = get_tree()->get_debug_collisions_color(); + } + + if (p_check_collision && collided) { + if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) { + // If base color is already quite reddish, highlight collision with green color + color = Color(0.0, 1.0, 0.0, color.a); + } else { + // Else, highlight collision with red color + color = Color(1.0, 0, 0, color.a); + } + } + + Ref<StandardMaterial3D> material = static_cast<Ref<StandardMaterial3D>>(debug_material); + material->set_albedo(color); +} + +void ShapeCast3D::_update_debug_shape() { + if (!enabled) { + return; + } + + if (!debug_shape) { + _create_debug_shape(); + } + + _update_debug_shape_vertices(); + + if (Engine::get_singleton()->is_editor_hint()) { + return; + } + + MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape); + Ref<ArrayMesh> mesh = mi->get_mesh(); + if (!mesh.is_valid()) { + return; + } + + mesh->clear_surfaces(); + + Array a; + a.resize(Mesh::ARRAY_MAX); + + uint32_t flags = 0; + int surface_count = 0; + + if (!debug_shape_vertices.is_empty()) { + a[Mesh::ARRAY_VERTEX] = debug_shape_vertices; + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags); + mesh->surface_set_material(surface_count, debug_material); + ++surface_count; + } + + if (!debug_line_vertices.is_empty()) { + a[Mesh::ARRAY_VERTEX] = debug_line_vertices; + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags); + mesh->surface_set_material(surface_count, debug_material); + ++surface_count; + } +} + +void ShapeCast3D::_clear_debug_shape() { + if (!debug_shape) { + return; + } + + MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape); + if (mi->is_inside_tree()) { + mi->queue_delete(); + } else { + memdelete(mi); + } + + debug_shape = nullptr; +} + +ShapeCast3D::~ShapeCast3D() { + if (!shape.is_null()) { + shape->unregister_owner(this); + } +} diff --git a/scene/3d/shape_cast_3d.h b/scene/3d/shape_cast_3d.h new file mode 100644 index 0000000000..5bda15e4b0 --- /dev/null +++ b/scene/3d/shape_cast_3d.h @@ -0,0 +1,142 @@ +/*************************************************************************/ +/* shape_cast_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 SHAPE_CAST_3D_H +#define SHAPE_CAST_3D_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/shape_3d.h" + +class ShapeCast3D : public Node3D { + GDCLASS(ShapeCast3D, Node3D); + + bool enabled = true; + void resource_changed(Ref<Resource> p_res); + + Ref<Shape3D> shape; + RID shape_rid; + Vector3 target_position = Vector3(0, -1, 0); + + HashSet<RID> exclude; + real_t margin = 0.0; + uint32_t collision_mask = 1; + bool exclude_parent_body = true; + bool collide_with_areas = false; + bool collide_with_bodies = true; + + Node *debug_shape = nullptr; + Ref<Material> debug_material; + Color debug_shape_custom_color = Color(0.0, 0.0, 0.0); + Vector<Vector3> debug_shape_vertices; + Vector<Vector3> debug_line_vertices; + + void _create_debug_shape(); + void _update_debug_shape(); + void _update_debug_shape_material(bool p_check_collision = false); + void _update_debug_shape_vertices(); + void _clear_debug_shape(); + + // Result + int max_results = 32; + Vector<PhysicsDirectSpaceState3D::ShapeRestInfo> result; + bool collided = false; + real_t collision_safe_fraction = 1.0; + real_t collision_unsafe_fraction = 1.0; + + Array _get_collision_result() const; + + ~ShapeCast3D(); + +protected: + void _notification(int p_what); + void _update_shapecast_state(); + static void _bind_methods(); + +public: + void set_collide_with_areas(bool p_clip); + bool is_collide_with_areas_enabled() const; + + void set_collide_with_bodies(bool p_clip); + bool is_collide_with_bodies_enabled() const; + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_shape(const Ref<Shape3D> &p_shape); + Ref<Shape3D> get_shape() const; + + void set_target_position(const Vector3 &p_point); + Vector3 get_target_position() const; + + void set_margin(real_t p_margin); + real_t get_margin() const; + + void set_max_results(int p_max_results); + int get_max_results() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_mask_value(int p_layer_number, bool p_value); + bool get_collision_mask_value(int p_layer_number) const; + + void set_exclude_parent_body(bool p_exclude_parent_body); + bool get_exclude_parent_body() const; + + const Color &get_debug_shape_custom_color() const; + void set_debug_shape_custom_color(const Color &p_color); + + const Vector<Vector3> &get_debug_shape_vertices() const; + const Vector<Vector3> &get_debug_line_vertices() const; + + Ref<StandardMaterial3D> get_debug_material(); + + int get_collision_count() const; + Object *get_collider(int p_idx) const; + int get_collider_shape(int p_idx) const; + Vector3 get_collision_point(int p_idx) const; + Vector3 get_collision_normal(int p_idx) const; + + real_t get_closest_collision_safe_fraction() const; + real_t get_closest_collision_unsafe_fraction() const; + + void force_shapecast_update(); + bool is_colliding() const; + + void add_exception_rid(const RID &p_rid); + void add_exception(const Object *p_object); + void remove_exception_rid(const RID &p_rid); + void remove_exception(const Object *p_object); + void clear_exceptions(); + + virtual TypedArray<String> get_configuration_warnings() const override; +}; + +#endif // SHAPE_CAST_3D_H diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index fbd5f31dd5..4c38fccc8b 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -493,6 +493,19 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) { return bones[p_bone].rest_bone_forward_axis; } +void Skeleton3D::set_motion_scale(float p_motion_scale) { + if (p_motion_scale <= 0) { + motion_scale = 1; + ERR_FAIL_MSG("Motion scale must be larger than 0."); + } + motion_scale = p_motion_scale; +} + +float Skeleton3D::get_motion_scale() const { + ERR_FAIL_COND_V(motion_scale <= 0, 1); + return motion_scale; +} + // Skeleton creation api void Skeleton3D::add_bone(const String &p_name) { @@ -639,6 +652,7 @@ void Skeleton3D::remove_bone_child(int p_bone, int p_child) { } Vector<int> Skeleton3D::get_parentless_bones() { + _update_process_order(); return parentless_bones; } @@ -765,8 +779,6 @@ void Skeleton3D::_make_dirty() { } void Skeleton3D::localize_rests() { - _update_process_order(); - Vector<int> bones_to_process = get_parentless_bones(); while (bones_to_process.size() > 0) { int current_bone_idx = bones_to_process[0]; @@ -958,7 +970,6 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { skin.instantiate(); skin->set_bind_count(bones.size()); - _update_process_order(); // Just in case. // Pose changed, rebuild cache of inverses. const Bone *bonesptr = bones.ptr(); @@ -1257,6 +1268,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms); ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms); + ClassDB::bind_method(D_METHOD("set_motion_scale", "motion_scale"), &Skeleton3D::set_motion_scale); + ClassDB::bind_method(D_METHOD("get_motion_scale"), &Skeleton3D::get_motion_scale); + // Helper functions ClassDB::bind_method(D_METHOD("global_pose_to_world_transform", "global_pose"), &Skeleton3D::global_pose_to_world_transform); ClassDB::bind_method(D_METHOD("world_transform_to_global_pose", "world_transform"), &Skeleton3D::world_transform_to_global_pose); @@ -1280,15 +1294,13 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton3D::get_modification_stack); ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton3D::execute_modifications); -#ifndef _3D_DISABLED + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motion_scale", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater"), "set_motion_scale", "get_motion_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only"), "set_show_rest_only", "is_show_rest_only"); +#ifndef _3D_DISABLED ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED -#ifdef TOOLS_ENABLED ADD_SIGNAL(MethodInfo("pose_updated")); -#endif // TOOLS_ENABLED - ADD_SIGNAL(MethodInfo("bone_pose_changed", PropertyInfo(Variant::INT, "bone_idx"))); ADD_SIGNAL(MethodInfo("bone_enabled_changed", PropertyInfo(Variant::INT, "bone_idx"))); ADD_SIGNAL(MethodInfo("show_rest_only_changed")); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index cb4c82d232..8b69410a39 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -146,6 +146,7 @@ private: bool rest_dirty = false; bool show_rest_only = false; + float motion_scale = 1.0; uint64_t version = 1; @@ -211,6 +212,9 @@ public: bool is_show_rest_only() const; void clear_bones(); + void set_motion_scale(float p_motion_scale); + float get_motion_scale() const; + // posing api void set_bone_pose_position(int p_bone, const Vector3 &p_position); @@ -288,4 +292,4 @@ public: ~Skeleton3D(); }; -#endif +#endif // SKELETON_3D_H diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h index 0f656187de..6ae86a2bf6 100644 --- a/scene/3d/skeleton_ik_3d.h +++ b/scene/3d/skeleton_ik_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETON_IK_H -#define SKELETON_IK_H +#ifndef SKELETON_IK_3D_H +#define SKELETON_IK_3D_H #ifndef _3D_DISABLED @@ -192,4 +192,4 @@ private: #endif // _3D_DISABLED -#endif // SKELETON_IK_H +#endif // SKELETON_IK_3D_H diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp index d68e7fd527..15f050defb 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_dynamic_body_3d.cpp @@ -83,7 +83,16 @@ void SoftDynamicBodyRenderingServerHandler::set_vertex(int p_vertex_id, const vo } void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { - memcpy(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3); + // Store normal vector in A2B10G10R10 format. + Vector3 n; + memcpy(&n, p_vector3, sizeof(Vector3)); + n *= Vector3(0.5, 0.5, 0.5); + n += Vector3(0.5, 0.5, 0.5); + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + memcpy(&write_buffer[p_vertex_id * stride + offset_normal], &value, sizeof(uint32_t)); } void SoftDynamicBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h index e11e5c73df..04f3365f72 100644 --- a/scene/3d/soft_dynamic_body_3d.h +++ b/scene/3d/soft_dynamic_body_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SOFT_DYNAMIC_BODY_H -#define SOFT_DYNAMIC_BODY_H +#ifndef SOFT_DYNAMIC_BODY_3D_H +#define SOFT_DYNAMIC_BODY_3D_H #include "scene/3d/mesh_instance_3d.h" #include "servers/physics_server_3d.h" @@ -199,4 +199,4 @@ private: VARIANT_ENUM_CAST(SoftDynamicBody3D::DisableMode); -#endif // SOFT_DYNAMIC_BODY_H +#endif // SOFT_DYNAMIC_BODY_3D_H diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h index 0b5307acf7..1a6f03abe4 100644 --- a/scene/3d/spring_arm_3d.h +++ b/scene/3d/spring_arm_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPRING_ARM_H -#define SPRING_ARM_H +#ifndef SPRING_ARM_3D_H +#define SPRING_ARM_3D_H #include "scene/3d/node_3d.h" @@ -68,4 +68,4 @@ private: void process_spring(); }; -#endif +#endif // SPRING_ARM_3D_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index cb6354f7a8..ef2b9e1ce5 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -377,7 +377,7 @@ SpriteBase3D::SpriteBase3D() { RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1)); RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0)); RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1)); - RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98); + RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.5); mesh = RenderingServer::get_singleton()->mesh_create(); diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 0ef8bd7482..2f3a37af2a 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VEHICLE_BODY_H -#define VEHICLE_BODY_H +#ifndef VEHICLE_BODY_3D_H +#define VEHICLE_BODY_3D_H #include "scene/3d/physics_body_3d.h" @@ -210,4 +210,4 @@ public: VehicleBody3D(); }; -#endif // VEHICLE_BODY_H +#endif // VEHICLE_BODY_3D_H diff --git a/scene/3d/velocity_tracker_3d.h b/scene/3d/velocity_tracker_3d.h index 7fdcacc9c1..6b27cdffc2 100644 --- a/scene/3d/velocity_tracker_3d.h +++ b/scene/3d/velocity_tracker_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPATIAL_VELOCITY_TRACKER_H -#define SPATIAL_VELOCITY_TRACKER_H +#ifndef VELOCITY_TRACKER_3D_H +#define VELOCITY_TRACKER_3D_H #include "scene/3d/node_3d.h" @@ -58,4 +58,4 @@ public: VelocityTracker3D(); }; -#endif // SPATIAL_VELOCITY_TRACKER_H +#endif // VELOCITY_TRACKER_3D_H diff --git a/scene/3d/visible_on_screen_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h index fe17f1e444..60461569f4 100644 --- a/scene/3d/visible_on_screen_notifier_3d.h +++ b/scene/3d/visible_on_screen_notifier_3d.h @@ -96,4 +96,4 @@ public: VARIANT_ENUM_CAST(VisibleOnScreenEnabler3D::EnableMode); -#endif // VISIBILITY_NOTIFIER_H +#endif // VISIBLE_ON_SCREEN_NOTIFIER_3D_H diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 69917f6992..5af06cff29 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -227,8 +227,8 @@ const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringNa StringName *r = instance_uniform_property_remap.getptr(p_name); if (!r) { String s = p_name; - if (s.begins_with("shader_params/")) { - StringName name = s.replace("shader_params/", ""); + if (s.begins_with("shader_uniforms/")) { + StringName name = s.replace("shader_uniforms/", ""); instance_uniform_property_remap[p_name] = name; return instance_uniform_property_remap.getptr(p_name); } @@ -242,7 +242,7 @@ const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringNa bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) { const StringName *r = _instance_uniform_get_remap(p_name); if (r) { - set_shader_instance_uniform(*r, p_value); + set_instance_shader_uniform(*r, p_value); return true; } #ifndef DISABLE_DEPRECATED @@ -262,7 +262,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const { const StringName *r = _instance_uniform_get_remap(p_name); if (r) { - r_ret = get_shader_instance_uniform(*r); + r_ret = get_instance_shader_uniform(*r); return true; } @@ -271,10 +271,10 @@ bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const { void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> pinfo; - RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo); + RS::get_singleton()->instance_geometry_get_shader_uniform_list(get_instance(), &pinfo); for (PropertyInfo &pi : pinfo) { bool has_def_value = false; - Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name); + Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), pi.name); if (def_value.get_type() != Variant::NIL) { has_def_value = true; } @@ -284,7 +284,7 @@ void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const { pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : PROPERTY_USAGE_NONE); //do not save if not changed } - pi.name = "shader_params/" + pi.name; + pi.name = "shader_uniforms/" + pi.name; p_list->push_back(pi); } } @@ -319,24 +319,24 @@ float GeometryInstance3D::get_lod_bias() const { return lod_bias; } -void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value) { +void GeometryInstance3D::set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { - Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_uniform); - RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, def_value); + Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), p_uniform); + RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, def_value); instance_uniforms.erase(p_value); } else { instance_uniforms[p_uniform] = p_value; if (p_value.get_type() == Variant::OBJECT) { RID tex_id = p_value; - RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, tex_id); + RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, tex_id); } else { - RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value); + RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, p_value); } } } -Variant GeometryInstance3D::get_shader_instance_uniform(const StringName &p_uniform) const { - return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_uniform); +Variant GeometryInstance3D::get_instance_shader_uniform(const StringName &p_uniform) const { + return RS::get_singleton()->instance_geometry_get_shader_uniform(get_instance(), p_uniform); } void GeometryInstance3D::set_custom_aabb(AABB aabb) { @@ -434,8 +434,8 @@ void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visibility_range_fade_mode", "mode"), &GeometryInstance3D::set_visibility_range_fade_mode); ClassDB::bind_method(D_METHOD("get_visibility_range_fade_mode"), &GeometryInstance3D::get_visibility_range_fade_mode); - ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform); - ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform); + ClassDB::bind_method(D_METHOD("set_instance_shader_uniform", "uniform", "value"), &GeometryInstance3D::set_instance_shader_uniform); + ClassDB::bind_method(D_METHOD("get_instance_shader_uniform", "uniform"), &GeometryInstance3D::get_instance_shader_uniform); ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin); ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin); @@ -461,15 +461,16 @@ void GeometryInstance3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01,suffix:m"), "set_extra_cull_margin", "get_extra_cull_margin"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_occlusion_culling"), "set_ignore_occlusion_culling", "is_ignoring_occlusion_culling"); + ADD_GROUP("Global Illumination", "gi_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)"), "set_gi_mode", "get_gi_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale"); ADD_GROUP("Visibility Range", "visibility_range_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end", "get_visibility_range_end"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end_margin", "get_visibility_range_end_margin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_end", "get_visibility_range_end"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_end_margin", "get_visibility_range_end_margin"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_range_fade_mode", PROPERTY_HINT_ENUM, "Disabled,Self,Dependencies"), "set_visibility_range_fade_mode", "get_visibility_range_fade_mode"); BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index 9e0d9b9a2a..f7cdcbf411 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUAL_INSTANCE_H -#define VISUAL_INSTANCE_H +#ifndef VISUAL_INSTANCE_3D_H +#define VISUAL_INSTANCE_3D_H #include "scene/3d/node_3d.h" @@ -178,8 +178,8 @@ public: void set_lightmap_scale(LightmapScale p_scale); LightmapScale get_lightmap_scale() const; - void set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value); - Variant get_shader_instance_uniform(const StringName &p_uniform) const; + void set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value); + Variant get_instance_shader_uniform(const StringName &p_uniform) const; void set_custom_aabb(AABB aabb); @@ -196,4 +196,4 @@ VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale); VARIANT_ENUM_CAST(GeometryInstance3D::GIMode); VARIANT_ENUM_CAST(GeometryInstance3D::VisibilityRangeFadeMode); -#endif +#endif // VISUAL_INSTANCE_3D_H diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index e1a38dd7a0..6d173dea87 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -49,9 +49,9 @@ class VoxelGIData : public Resource { float energy = 1.0; float bias = 1.5; float normal_bias = 0.0; - float propagation = 0.7; + float propagation = 0.5; bool interior = false; - bool use_two_bounces = false; + bool use_two_bounces = true; protected: static void _bind_methods(); diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index 0179795ddc..68bce768b7 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VOXEL_LIGHT_BAKER_H -#define VOXEL_LIGHT_BAKER_H +#ifndef VOXELIZER_H +#define VOXELIZER_H #include "scene/resources/multimesh.h" @@ -129,4 +129,4 @@ public: Voxelizer(); }; -#endif // VOXEL_LIGHT_BAKER_H +#endif // VOXELIZER_H diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 8dbb57364c..9955aa72a8 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENARIO_FX_H -#define SCENARIO_FX_H +#ifndef WORLD_ENVIRONMENT_H +#define WORLD_ENVIRONMENT_H #include "scene/main/node.h" #include "scene/resources/camera_effects.h" @@ -60,4 +60,4 @@ public: WorldEnvironment(); }; -#endif +#endif // WORLD_ENVIRONMENT_H diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 1dad6078b4..40a43043c6 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -120,7 +120,7 @@ Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { Vector3 ray; // Just use the first view, if multiple views are supported this function has no good result - CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); + Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); Vector2 screen_he = cm.get_viewport_half_extents(); ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_near()).normalized(); @@ -143,7 +143,7 @@ Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const { Size2 viewport_size = get_viewport()->get_visible_rect().size; // Just use the first view, if multiple views are supported this function has no good result - CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); + Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); Plane p(get_camera_transform().xform_inv(p_pos), 1.0); @@ -173,7 +173,7 @@ Vector3 XRCamera3D::project_position(const Point2 &p_point, real_t p_z_depth) co Size2 viewport_size = get_viewport()->get_visible_rect().size; // Just use the first view, if multiple views are supported this function has no good result - CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); + Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); Vector2 vp_he = cm.get_viewport_half_extents(); @@ -202,7 +202,7 @@ Vector<Plane> XRCamera3D::get_frustum() const { Size2 viewport_size = get_viewport()->get_visible_rect().size; // TODO Just use the first view for now, this is mostly for debugging so we may look into using our combined projection here. - CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); + Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far()); return cm.get_projection_planes(get_camera_transform()); }; diff --git a/scene/SCsub b/scene/SCsub index a7b23af598..92288211bb 100644 --- a/scene/SCsub +++ b/scene/SCsub @@ -9,7 +9,6 @@ env.add_source_files(env.scene_sources, "*.cpp") # Chain load SCsubs SConscript("main/SCsub") -SConscript("multiplayer/SCsub") SConscript("gui/SCsub") if not env["disable_3d"]: SConscript("3d/SCsub") diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index 594f98410e..b42e426f51 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -78,6 +78,9 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label); ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label); + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync); + ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point); for (int i = 0; i < MAX_BLEND_POINTS; i++) { @@ -89,6 +92,7 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync"); } void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) { @@ -117,7 +121,7 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_ blend_points[p_at_index].node = p_node; blend_points[p_at_index].position = p_position; - blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); blend_points_used++; emit_signal(SNAME("tree_changed")); @@ -138,7 +142,7 @@ void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<Anim } blend_points[p_point].node = p_node; - blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -211,6 +215,14 @@ String AnimationNodeBlendSpace1D::get_value_label() const { return value_label; } +void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeBlendSpace1D::is_using_sync() const { + return sync; +} + void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node) { if (p_index == blend_points_used) { add_blend_point(p_node, 0); @@ -226,7 +238,7 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see if (blend_points_used == 1) { // only one point available, just play that animation - return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); } double blend_pos = get_parameter(blend_position); @@ -295,9 +307,12 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see double max_time_remaining = 0.0; for (int i = 0; i < blend_points_used; i++) { - double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, false); - - max_time_remaining = MAX(max_time_remaining, remaining); + if (i == point_lower || i == point_higher) { + double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, true); + max_time_remaining = MAX(max_time_remaining, remaining); + } else { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } } return max_time_remaining; diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h index b2075c8c93..346e8a3a2f 100644 --- a/scene/animation/animation_blend_space_1d.h +++ b/scene/animation/animation_blend_space_1d.h @@ -63,6 +63,8 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode { StringName blend_position = "blend_position"; protected: + bool sync = false; + virtual void _validate_property(PropertyInfo &property) const override; static void _bind_methods(); @@ -93,6 +95,9 @@ public: void set_value_label(const String &p_label); String get_value_label() const; + void set_use_sync(bool p_sync); + bool is_using_sync() const; + double process(double p_time, bool p_seek, bool p_seek_root) override; String get_caption() const override; diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index acdce2d7de..6b5851a977 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -80,7 +80,7 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_ blend_points[p_at_index].node = p_node; blend_points[p_at_index].position = p_position; - blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED); blend_points_used++; _queue_auto_triangles(); @@ -102,7 +102,7 @@ void AnimationNodeBlendSpace2D::set_blend_point_node(int p_point, const Ref<Anim blend_points[p_point].node->disconnect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed)); } blend_points[p_point].node = p_node; - blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -502,7 +502,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see for (int j = 0; j < 3; j++) { if (i == triangle_points[j]) { //blend with the given weight - double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, blend_weights[j], FILTER_IGNORE, false); + double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, blend_weights[j], FILTER_IGNORE, true); if (first || t < mind) { mind = t; first = false; @@ -513,8 +513,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see } if (!found) { - //ignore - blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, false); + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); } } } else { @@ -539,16 +538,22 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see na_n->set_backward(na_c->is_backward()); } //see how much animation remains - from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, false); + from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, true); } - mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 1.0, FILTER_IGNORE, false); + mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 1.0, FILTER_IGNORE, true); length_internal = from + mind; closest = new_closest; } else { - mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); + mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); + } + + for (int i = 0; i < blend_points_used; i++) { + if (i != closest) { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } } } @@ -604,6 +609,14 @@ AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode() return blend_mode; } +void AnimationNodeBlendSpace2D::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeBlendSpace2D::is_using_sync() const { + return sync; +} + void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("set_blend_point_position", "point", "pos"), &AnimationNodeBlendSpace2D::set_blend_point_position); @@ -644,6 +657,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode); ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace2D::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace2D::is_using_sync); + ClassDB::bind_method(D_METHOD("_update_triangles"), &AnimationNodeBlendSpace2D::_update_triangles); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_triangles", "get_auto_triangles"); @@ -661,6 +677,7 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_x_label", "get_x_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_y_label", "get_y_label"); ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync"); ADD_SIGNAL(MethodInfo("triangles_updated")); BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED); diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h index 01f53ed25a..689b96e356 100644 --- a/scene/animation/animation_blend_space_2d.h +++ b/scene/animation/animation_blend_space_2d.h @@ -88,6 +88,8 @@ protected: void _tree_changed(); protected: + bool sync = false; + virtual void _validate_property(PropertyInfo &property) const override; static void _bind_methods(); @@ -137,6 +139,9 @@ public: void set_blend_mode(BlendMode p_blend_mode); BlendMode get_blend_mode() const; + void set_use_sync(bool p_sync); + bool is_using_sync() const; + virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override; AnimationNodeBlendSpace2D(); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 4f6975deb1..fe2fb1b7a1 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -179,6 +179,26 @@ AnimationNodeAnimation::AnimationNodeAnimation() { //////////////////////////////////////////////////////// +void AnimationNodeSync::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeSync::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeSync::is_using_sync); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); +} + +void AnimationNodeSync::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeSync::is_using_sync() const { + return sync; +} + +AnimationNodeSync::AnimationNodeSync() { +} + +//////////////////////////////////////////////////////// + void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const { r_list->push_back(PropertyInfo(Variant::BOOL, active)); r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); @@ -276,7 +296,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo } if (!active) { - return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); + return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync); } } @@ -313,12 +333,12 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo double main_rem; if (mix == MIX_MODE_ADD) { - main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); + main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync); } else { - main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_BLEND, !sync); + main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_BLEND, sync); } - double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, false); + double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, true); if (do_start) { remaining = os_rem; @@ -343,14 +363,6 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo return MAX(main_rem, remaining); } -void AnimationNodeOneShot::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeOneShot::is_using_sync() const { - return sync; -} - void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_fadein_time", "time"), &AnimationNodeOneShot::set_fadein_time); ClassDB::bind_method(D_METHOD("get_fadein_time"), &AnimationNodeOneShot::get_fadein_time); @@ -370,9 +382,6 @@ void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mix_mode", "mode"), &AnimationNodeOneShot::set_mix_mode); ClassDB::bind_method(D_METHOD("get_mix_mode"), &AnimationNodeOneShot::get_mix_mode); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_fadein_time", "get_fadein_time"); @@ -384,9 +393,6 @@ void AnimationNodeOneShot::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_delay", "get_autorestart_delay"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_random_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_random_delay", "get_autorestart_random_delay"); - ADD_GROUP("", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); - BIND_ENUM_CONSTANT(MIX_MODE_BLEND); BIND_ENUM_CONSTANT(MIX_MODE_ADD); } @@ -410,31 +416,19 @@ String AnimationNodeAdd2::get_caption() const { return "Add2"; } -void AnimationNodeAdd2::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeAdd2::is_using_sync() const { - return sync; -} - bool AnimationNodeAdd2::has_filter() const { return true; } double AnimationNodeAdd2::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(add_amount); - double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); - blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync); + blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, sync); return rem0; } void AnimationNodeAdd2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd2::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd2::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd2::AnimationNodeAdd2() { @@ -456,32 +450,20 @@ String AnimationNodeAdd3::get_caption() const { return "Add3"; } -void AnimationNodeAdd3::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeAdd3::is_using_sync() const { - return sync; -} - bool AnimationNodeAdd3::has_filter() const { return true; } double AnimationNodeAdd3::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(add_amount); - blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_PASS, !sync); - double rem0 = blend_input(1, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); - blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_PASS, !sync); + blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_PASS, sync); + double rem0 = blend_input(1, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync); + blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_PASS, sync); return rem0; } void AnimationNodeAdd3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd3::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd3::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd3::AnimationNodeAdd3() { @@ -507,29 +489,17 @@ String AnimationNodeBlend2::get_caption() const { double AnimationNodeBlend2::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(blend_amount); - double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - amount, FILTER_BLEND, !sync); - double rem1 = blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - amount, FILTER_BLEND, sync); + double rem1 = blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, sync); return amount > 0.5 ? rem1 : rem0; //hacky but good enough } -void AnimationNodeBlend2::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeBlend2::is_using_sync() const { - return sync; -} - bool AnimationNodeBlend2::has_filter() const { return true; } void AnimationNodeBlend2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend2::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend2::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend2::AnimationNodeBlend2() { @@ -551,35 +521,22 @@ String AnimationNodeBlend3::get_caption() const { return "Blend3"; } -void AnimationNodeBlend3::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeBlend3::is_using_sync() const { - return sync; -} - double AnimationNodeBlend3::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(blend_amount); - double rem0 = blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_IGNORE, !sync); - double rem1 = blend_input(1, p_time, p_seek, p_seek_root, 1.0 - ABS(amount), FILTER_IGNORE, !sync); - double rem2 = blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_IGNORE, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_IGNORE, sync); + double rem1 = blend_input(1, p_time, p_seek, p_seek_root, 1.0 - ABS(amount), FILTER_IGNORE, sync); + double rem2 = blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_IGNORE, sync); return amount > 0.5 ? rem2 : (amount < -0.5 ? rem0 : rem1); //hacky but good enough } void AnimationNodeBlend3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend3::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend3::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend3::AnimationNodeBlend3() { add_input("-blend"); add_input("in"); add_input("+blend"); - sync = false; } ///////////////////////////////// @@ -599,9 +556,9 @@ String AnimationNodeTimeScale::get_caption() const { double AnimationNodeTimeScale::process(double p_time, bool p_seek, bool p_seek_root) { double scale = get_parameter(this->scale); if (p_seek) { - return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true); } else { - return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, true); } } @@ -629,13 +586,13 @@ String AnimationNodeTimeSeek::get_caption() const { double AnimationNodeTimeSeek::process(double p_time, bool p_seek, bool p_seek_root) { double seek_pos = get_parameter(this->seek_pos); if (p_seek) { - return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true); } else if (seek_pos >= 0) { - double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, false); + double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, true); set_parameter(this->seek_pos, -1.0); //reset return ret; } else { - return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, true); } } @@ -727,6 +684,14 @@ float AnimationNodeTransition::get_cross_fade_time() const { return xfade; } +void AnimationNodeTransition::set_from_start(bool p_from_start) { + from_start = p_from_start; +} + +bool AnimationNodeTransition::is_from_start() const { + return from_start; +} + double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_root) { int current = get_parameter(this->current); int prev = get_parameter(this->prev); @@ -753,9 +718,15 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_ double rem = 0.0; + for (int i = 0; i < enabled_inputs; i++) { + if (i != current && i != prev) { + blend_input(i, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } + } + if (prev < 0) { // process current animation, check for transition - rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); if (p_seek) { time = p_time; @@ -771,18 +742,18 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_ float blend = xfade == 0 ? 0 : (prev_xfading / xfade); - if (!p_seek && switched) { //just switched, seek to start of current + if (from_start && !p_seek && switched) { //just switched, seek to start of current - rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, true); } else { - rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, true); } - if (p_seek) { // don't seek prev animation - blend_input(prev, 0, false, p_seek_root, blend, FILTER_IGNORE, false); + if (p_seek) { + blend_input(prev, p_time, true, p_seek_root, blend, FILTER_IGNORE, true); time = p_time; } else { - blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, false); + blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, true); time += p_time; prev_xfading -= p_time; if (prev_xfading < 0) { @@ -824,8 +795,12 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time); ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time); + ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start); + ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start); + ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_cross_fade_time", "get_cross_fade_time"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start"); for (int i = 0; i < MAX_INPUTS; i++) { ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_caption", "get_input_caption", i); @@ -846,7 +821,7 @@ String AnimationNodeOutput::get_caption() const { } double AnimationNodeOutput::process(double p_time, bool p_seek, bool p_seek_root) { - return blend_input(0, p_time, p_seek, p_seek_root, 1.0); + return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); } AnimationNodeOutput::AnimationNodeOutput() { @@ -869,8 +844,8 @@ void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNod emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); - p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_name), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), CONNECT_REFERENCE_COUNTED); + p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_name), CONNECT_REFERENCE_COUNTED); } Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) const { @@ -970,7 +945,7 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN } } //connection must be done with new name - nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_new_name), CONNECT_REFERENCE_COUNTED); + nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_new_name), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -1060,7 +1035,7 @@ String AnimationNodeBlendTree::get_caption() const { double AnimationNodeBlendTree::process(double p_time, bool p_seek, bool p_seek_root) { Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node; - return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0); + return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); } void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 0a2305b8d6..d35ff04f30 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -77,8 +77,23 @@ private: VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode) -class AnimationNodeOneShot : public AnimationNode { - GDCLASS(AnimationNodeOneShot, AnimationNode); +class AnimationNodeSync : public AnimationNode { + GDCLASS(AnimationNodeSync, AnimationNode); + +protected: + bool sync = false; + + static void _bind_methods(); + +public: + void set_use_sync(bool p_sync); + bool is_using_sync() const; + + AnimationNodeSync(); +}; + +class AnimationNodeOneShot : public AnimationNodeSync { + GDCLASS(AnimationNodeOneShot, AnimationNodeSync); public: enum MixMode { @@ -95,8 +110,6 @@ private: float autorestart_random_delay = 0.0; MixMode mix = MIX_MODE_BLEND; - bool sync = false; - /* bool active; bool do_start; float time; @@ -134,9 +147,6 @@ public: void set_mix_mode(MixMode p_mix); MixMode get_mix_mode() const; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; @@ -145,11 +155,10 @@ public: VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode) -class AnimationNodeAdd2 : public AnimationNode { - GDCLASS(AnimationNodeAdd2, AnimationNode); +class AnimationNodeAdd2 : public AnimationNodeSync { + GDCLASS(AnimationNodeAdd2, AnimationNodeSync); StringName add_amount = PNAME("add_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -160,20 +169,16 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd2(); }; -class AnimationNodeAdd3 : public AnimationNode { - GDCLASS(AnimationNodeAdd3, AnimationNode); +class AnimationNodeAdd3 : public AnimationNodeSync { + GDCLASS(AnimationNodeAdd3, AnimationNodeSync); StringName add_amount = PNAME("add_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -184,20 +189,16 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd3(); }; -class AnimationNodeBlend2 : public AnimationNode { - GDCLASS(AnimationNodeBlend2, AnimationNode); +class AnimationNodeBlend2 : public AnimationNodeSync { + GDCLASS(AnimationNodeBlend2, AnimationNodeSync); StringName blend_amount = PNAME("blend_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -209,18 +210,14 @@ public: virtual String get_caption() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; AnimationNodeBlend2(); }; -class AnimationNodeBlend3 : public AnimationNode { - GDCLASS(AnimationNodeBlend3, AnimationNode); +class AnimationNodeBlend3 : public AnimationNodeSync { + GDCLASS(AnimationNodeBlend3, AnimationNodeSync); StringName blend_amount = PNAME("blend_amount"); - bool sync; protected: static void _bind_methods(); @@ -231,9 +228,6 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeBlend3(); }; @@ -276,8 +270,8 @@ public: AnimationNodeTimeSeek(); }; -class AnimationNodeTransition : public AnimationNode { - GDCLASS(AnimationNodeTransition, AnimationNode); +class AnimationNodeTransition : public AnimationNodeSync { + GDCLASS(AnimationNodeTransition, AnimationNodeSync); enum { MAX_INPUTS = 32 @@ -304,6 +298,7 @@ class AnimationNodeTransition : public AnimationNode { StringName prev_current = "prev_current"; float xfade = 0.0; + bool from_start = true; void _update_inputs(); @@ -329,6 +324,9 @@ public: void set_cross_fade_time(float p_fade); float get_cross_fade_time() const; + void set_from_start(bool p_from_start); + bool is_from_start() const; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeTransition(); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 2ee7f4fa43..793967d9ad 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -395,7 +395,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s current = p_state_machine->start_node; } - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 1.0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 1.0, AnimationNode::FILTER_IGNORE, true); pos_current = 0; } @@ -420,10 +420,10 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } } - float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, false); + float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true); if (fading_from != StringName()) { - p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_seek_root, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, false); + p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_seek_root, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, true); } //guess playback position @@ -577,12 +577,12 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } current = next; if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) { - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true); pos_current = MIN(pos_current, len_current); - p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); + p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true); } else { - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true); pos_current = 0; } @@ -630,7 +630,7 @@ bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Ref<Anima Node *expression_base = tree_base->get_node_or_null(advance_expression_base_node_path); if (expression_base) { Ref<Expression> exp = transition->expression; - bool ret = exp->execute(Array(), tree_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls. + bool ret = exp->execute(Array(), expression_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls. if (!exp->has_execute_failed()) { if (ret) { return true; @@ -723,7 +723,7 @@ void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<Animation emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<AnimationNode> p_node) { @@ -743,7 +743,7 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<Anima emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } bool AnimationNodeStateMachine::can_edit_node(const StringName &p_name) const { @@ -830,20 +830,12 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri anodesm->state_machine_name = p_new_name; } - for (int i = 0; i < transitions.size(); i++) { - if (transitions[i].local_from == p_name) { - _rename_transition(transitions[i].from, String(transitions[i].from).replace_first(p_name, p_new_name)); - } - - if (transitions[i].local_to == p_name) { - _rename_transition(transitions[i].to, String(transitions[i].to).replace_first(p_name, p_new_name)); - } - } + _rename_transitions(p_name, p_new_name); emit_signal("tree_changed"); } -void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, const StringName &p_new_name) { +void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, const StringName &p_new_name) { if (updating_transitions) { return; } @@ -854,12 +846,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].to).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_from == p_name) { + transitions.write[i].local_from = p_new_name; + } + transitions.write[i].from = p_new_name; } @@ -867,12 +863,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].from).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_to == p_name) { + transitions.write[i].local_to = p_new_name; + } + transitions.write[i].to = p_new_name; } @@ -1032,7 +1032,7 @@ void AnimationNodeStateMachine::add_transition(const StringName &p_from, const S tr.local_to = local_to; tr.transition = p_transition; - tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); transitions.push_back(tr); diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index d4e58ca3d3..ead914db7a 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -185,7 +185,7 @@ private: void _tree_changed(); void _remove_transition(const Ref<AnimationNodeStateMachineTransition> p_transition); - void _rename_transition(const StringName &p_name, const StringName &p_new_name); + void _rename_transitions(const StringName &p_name, const StringName &p_new_name); bool _can_connect(const StringName &p_name, Vector<AnimationNodeStateMachine *> p_parents = Vector<AnimationNodeStateMachine *>()); StringName _get_shortest_path(const StringName &p_path) const; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 2e87dbf9da..636c9e26a5 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -64,7 +64,7 @@ void AnimatedValuesBackup::restore() const { if (arr.size() == 3) { Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]); Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]); - Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[0]); + Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]); } } } @@ -325,7 +325,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov { if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) { - child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed), make_binds(child), CONNECT_ONESHOT); + child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONESHOT); } } @@ -370,6 +370,10 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov node_cache->node_3d = nullptr; ERR_CONTINUE(node_cache->bone_idx < 0); } + Transform3D rest = node_cache->skeleton->get_bone_rest(bone_idx); + node_cache->init_loc = rest.origin; + node_cache->init_rot = rest.basis.get_rotation_quaternion(); + node_cache->init_scale = rest.basis.get_scale(); } else { // no property, just use spatialnode node_cache->skeleton = nullptr; @@ -450,6 +454,23 @@ static void _call_object(Object *p_object, const StringName &p_method, const Vec } } +Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { + switch (p_anim->track_get_type(p_track)) { +#ifndef _3D_DISABLED + case Animation::TYPE_POSITION_3D: { + if (p_object_idx >= 0) { + const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object); + return Vector3(p_value) * skel->get_motion_scale(); + } + return p_value; + } break; +#endif // _3D_DISABLED + default: { + } break; + } + return p_value; +} + void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); @@ -494,14 +515,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + loc = _post_process_key_value(a, i, loc, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; nc->loc_accum = loc; - nc->rot_accum = Quaternion(); - nc->scale_accum = Vector3(); + nc->rot_accum = nc->init_rot; + nc->scale_accum = nc->init_scale; } else { nc->loc_accum = nc->loc_accum.lerp(loc, p_interp); } @@ -521,14 +543,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + rot = _post_process_key_value(a, i, rot, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; - nc->loc_accum = Vector3(); + nc->loc_accum = nc->init_loc; nc->rot_accum = rot; - nc->scale_accum = Vector3(); + nc->scale_accum = nc->init_scale; } else { nc->rot_accum = nc->rot_accum.slerp(rot, p_interp); } @@ -548,13 +571,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + scale = _post_process_key_value(a, i, scale, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; - nc->loc_accum = Vector3(); - nc->rot_accum = Quaternion(); + nc->loc_accum = nc->init_loc; + nc->rot_accum = nc->init_rot; nc->scale_accum = scale; } else { nc->scale_accum = nc->scale_accum.lerp(scale, p_interp); @@ -575,6 +599,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + blend = _post_process_key_value(a, i, blend, nc->node_blend_shape, nc->blend_shape_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); @@ -627,9 +652,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (p_time < first_key_time) { double c = Math::ease(p_time / first_key_time, transition); Variant first_value = a->track_get_key_value(i, first_key); + first_value = _post_process_key_value(a, i, first_value, nc->node); Variant interp_value; Variant::interpolate(pa->capture, first_value, c, interp_value); - if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); cache_update_prop[cache_update_prop_size++] = pa; @@ -649,6 +674,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (value == Variant()) { continue; } + value = _post_process_key_value(a, i, value, nc->node); if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); @@ -665,6 +691,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double for (int &F : indices) { Variant value = a->track_get_key_value(i, F); + value = _post_process_key_value(a, i, value, nc->node); switch (pa->special) { case SP_NONE: { bool valid; @@ -749,6 +776,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double TrackNodeCache::BezierAnim *ba = &E->value; real_t bezier = a->bezier_track_interpolate(i, p_time); + bezier = _post_process_key_value(a, i, bezier, nc->node); if (ba->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX); cache_update_bezier[cache_update_bezier_size++] = ba; @@ -1173,11 +1201,15 @@ void AnimationPlayer::_animation_process(double p_delta) { emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name); } } else { - //stop(); playing = false; _set_process(false); if (end_notify) { emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned); + + if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) { + print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path())); + get_tree()->quit(); + } } } end_reached = false; @@ -1345,9 +1377,9 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref animation_libraries.insert(insert_pos, ald); - ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name)); - ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name)); - ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_name)); + ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); + ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); + ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name)); _animation_set_cache_update(); @@ -1385,7 +1417,7 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) { } void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) { - Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED); + Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED); } void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) { @@ -1411,9 +1443,9 @@ void AnimationPlayer::rename_animation_library(const StringName &p_name, const S animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added)); animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed)); - animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name)); - animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name)); - animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_new_name)); for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) { StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key)); @@ -1864,6 +1896,14 @@ AnimationPlayer::AnimationMethodCallMode AnimationPlayer::get_method_call_mode() return method_call_mode; } +void AnimationPlayer::set_movie_quit_on_finish_enabled(bool p_enabled) { + movie_quit_on_finish = p_enabled; +} + +bool AnimationPlayer::is_movie_quit_on_finish_enabled() const { + return movie_quit_on_finish; +} + void AnimationPlayer::_set_process(bool p_process, bool p_force) { if (processing == p_process && !p_force) { return; @@ -2084,6 +2124,9 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode); ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode); + ClassDB::bind_method(D_METHOD("set_movie_quit_on_finish_enabled"), &AnimationPlayer::set_movie_quit_on_finish_enabled); + ClassDB::bind_method(D_METHOD("is_movie_quit_on_finish_enabled"), &AnimationPlayer::is_movie_quit_on_finish_enabled); + ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position); ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length); @@ -2105,6 +2148,8 @@ void AnimationPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "method_call_mode", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_method_call_mode", "get_method_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled"); + ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name"))); ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name"))); ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name"))); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index d3eb37a345..b6d8dab1ed 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -109,6 +109,9 @@ private: bool loc_used = false; bool rot_used = false; bool scale_used = false; + Vector3 init_loc = Vector3(0, 0, 0); + Quaternion init_rot = Quaternion(0, 0, 0, 1); + Vector3 init_scale = Vector3(1, 1, 1); Vector3 loc_accum; Quaternion rot_accum; @@ -259,6 +262,7 @@ private: bool reset_on_save = true; AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE; AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED; + bool movie_quit_on_finish = false; bool processing = false; bool active = true; @@ -313,6 +317,8 @@ protected: static void _bind_methods(); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); + public: StringName find_animation(const Ref<Animation> &p_animation) const; StringName find_animation_library(const Ref<Animation> &p_animation) const; @@ -368,6 +374,9 @@ public: void set_method_call_mode(AnimationMethodCallMode p_mode); AnimationMethodCallMode get_method_call_mode() const; + void set_movie_quit_on_finish_enabled(bool p_enabled); + bool is_movie_quit_on_finish_enabled() const; + void seek(double p_time, bool p_update = false); void seek_delta(double p_time, float p_delta); float get_current_animation_position() const; @@ -395,4 +404,4 @@ public: VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback); VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode); -#endif +#endif // ANIMATION_PLAYER_H diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 8c8822ac3f..14cf64afad 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -150,7 +150,7 @@ void AnimationNode::make_invalid(const String &p_reason) { state->invalid_reasons += String::utf8("• ") + p_reason; } -double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) { +double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync) { ERR_FAIL_INDEX_V(p_input, inputs.size(), 0); ERR_FAIL_COND_V(!state, 0); @@ -169,7 +169,7 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool //inputs.write[p_input].last_pass = state->last_pass; real_t activity = 0.0; - double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize, &activity); + double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_sync, &activity); Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path); @@ -180,11 +180,11 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool return ret; } -double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) { - return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize); +double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync) { + return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_sync); } -double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize, real_t *r_max) { +double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync, real_t *r_max) { ERR_FAIL_COND_V(!p_node.is_valid(), 0); ERR_FAIL_COND_V(!state, 0); @@ -292,9 +292,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri } // If tracks for blending don't exist for one of the animations, Rest or RESET animation is blended as init animation instead. - // Then, blend weight is 0 means that the init animation blend weight is 1. + // Then blend weight is 0 means that the init animation blend weight is 1. + // In that case, processing only the animation with the lacking track will not process the lacking track, and will not properly apply the Reset value. + // This means that all tracks which the animations in the branch that may be blended have must be processed. // Therefore, the blending process must be executed even if the blend weight is 0. - if (!p_seek && p_optimize && !any_valid) { + if (!p_seek && !p_sync && !any_valid) { return p_node->_pre_process(new_path, new_parent, state, 0, p_seek, p_seek_root, p_connections); } return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_seek_root, p_connections); @@ -428,8 +430,8 @@ void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters); ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "seek_root", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "sync"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_parameter", "name", "value"), &AnimationNode::set_parameter); ClassDB::bind_method(D_METHOD("get_parameter", "name"), &AnimationNode::get_parameter); @@ -587,7 +589,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } if (!child->is_connected("tree_exited", callable_mp(this, &AnimationTree::_node_removed))) { - child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed), varray(child)); + child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed).bind(child)); } switch (track_type) { @@ -1052,7 +1054,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, (double)a->get_length(), &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = 0; } @@ -1062,7 +1066,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, 0, &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = (double)a->get_length(); } @@ -1072,8 +1078,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, time, &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); @@ -1090,6 +1098,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc = _post_process_key_value(a, i, loc, t->object, t->bone_idx); t->loc += (loc - t->init_loc) * blend; } @@ -1148,7 +1157,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); + rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } @@ -1158,6 +1169,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, 0, &rot[1]); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = (double)a->get_length(); @@ -1168,8 +1180,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, time, &rot[1]); + rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = !backward ? 0 : (double)a->get_length(); @@ -1186,6 +1200,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot = _post_process_key_value(a, i, rot, t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized(); } @@ -1244,8 +1259,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]); t->scale += (scale[1] - scale[0]) * blend; + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); prev_time = 0; } } else { @@ -1254,7 +1271,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, 0, &scale[1]); + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); t->scale += (scale[1] - scale[0]) * blend; prev_time = (double)a->get_length(); } @@ -1264,8 +1283,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, time, &scale[1]); + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); t->scale += (scale[1] - scale[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); @@ -1282,6 +1303,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale = _post_process_key_value(a, i, scale, t->object, t->bone_idx); t->scale += (scale - t->init_scale) * blend; } @@ -1304,6 +1326,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + value = _post_process_key_value(a, i, value, t->object, t->shape_index); t->value += (value - t->init_value) * blend; #endif // _3D_DISABLED @@ -1315,6 +1338,7 @@ void AnimationTree::_process_graph(double p_delta) { if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { Variant value = a->value_track_interpolate(i, time); + value = _post_process_key_value(a, i, value, t->object); if (value == Variant()) { continue; @@ -1342,12 +1366,14 @@ void AnimationTree::_process_graph(double p_delta) { continue; } Variant value = a->track_get_key_value(i, idx); + value = _post_process_key_value(a, i, value, t->object); t->object->set_indexed(t->subpath, value); } else { List<int> indices; a->value_track_get_key_indices(i, time, delta, &indices, pingponged); for (int &F : indices) { Variant value = a->track_get_key_value(i, F); + value = _post_process_key_value(a, i, value, t->object); t->object->set_indexed(t->subpath, value); } } @@ -1386,6 +1412,7 @@ void AnimationTree::_process_graph(double p_delta) { TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); real_t bezier = a->bezier_track_interpolate(i, time); + bezier = _post_process_key_value(a, i, bezier, t->object); if (t->process_pass != process_pass) { t->process_pass = process_pass; @@ -1661,6 +1688,23 @@ void AnimationTree::_process_graph(double p_delta) { } } +Variant AnimationTree::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { + switch (p_anim->track_get_type(p_track)) { +#ifndef _3D_DISABLED + case Animation::TYPE_POSITION_3D: { + if (p_object_idx >= 0) { + const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object); + return Vector3(p_value) * skel->get_motion_scale(); + } + return p_value; + } break; +#endif // _3D_DISABLED + default: { + } break; + } + return p_value; +} + void AnimationTree::advance(real_t p_time) { _process_graph(p_time); } diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 0bfe615c9b..99851d140e 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ANIMATION_GRAPH_PLAYER_H -#define ANIMATION_GRAPH_PLAYER_H +#ifndef ANIMATION_TREE_H +#define ANIMATION_TREE_H #include "animation_player.h" #include "scene/3d/node_3d.h" @@ -99,12 +99,12 @@ public: Array _get_filters() const; void _set_filters(const Array &p_filters); friend class AnimationNodeBlendTree; - double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr); + double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true, real_t *r_max = nullptr); protected: void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_seek_root, real_t p_blend, int p_pingponged = 0); - double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); - double blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); + double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true); + double blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true); void make_invalid(const String &p_reason); AnimationTree *get_animation_tree() const; @@ -321,6 +321,8 @@ protected: void _notification(int p_what); static void _bind_methods(); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); + public: void set_tree_root(const Ref<AnimationNode> &p_root); Ref<AnimationNode> get_tree_root() const; @@ -359,4 +361,4 @@ public: VARIANT_ENUM_CAST(AnimationTree::AnimationProcessCallback) -#endif // ANIMATION_GRAPH_PLAYER_H +#endif // ANIMATION_TREE_H diff --git a/scene/animation/easing_equations.h b/scene/animation/easing_equations.h index 6d246c7a93..094829e406 100644 --- a/scene/animation/easing_equations.h +++ b/scene/animation/easing_equations.h @@ -402,4 +402,4 @@ static real_t out_in(real_t t, real_t b, real_t c, real_t d) { } }; // namespace back -#endif +#endif // EASING_EQUATIONS_H diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 5457da472f..dbc71cd9e7 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -464,6 +464,17 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f APPLY_EQUATION(columns[2][1]); return r; } + case Variant::VECTOR4: { + Vector4 i = p_initial_val; + Vector4 d = p_delta_val; + Vector4 r; + + APPLY_EQUATION(x); + APPLY_EQUATION(y); + APPLY_EQUATION(z); + APPLY_EQUATION(w); + return r; + } case Variant::QUATERNION: { Quaternion i = p_initial_val; @@ -853,7 +864,7 @@ bool CallbackTweener::step(float &r_delta) { if (elapsed_time >= delay) { Variant result; Callable::CallError ce; - callback.call(nullptr, 0, result, ce); + callback.callp(nullptr, 0, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce)); } @@ -924,7 +935,7 @@ bool MethodTweener::step(float &r_delta) { Variant result; Callable::CallError ce; - callback.call(argptr, 1, result, ce); + callback.callp(argptr, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce)); } diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 40268405cf..b57ec2e5e7 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -283,4 +283,4 @@ private: Callable callback; }; -#endif +#endif // TWEEN_H diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index efb647af29..04debcab05 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -136,7 +136,7 @@ void AudioStreamPlayer::play(float p_from_pos) { if (stream->is_monophonic() && is_playing()) { stop(); } - Ref<AudioStreamPlayback> stream_playback = stream->instance_playback(); + Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback."); AudioServer::get_singleton()->start_playback_stream(stream_playback, bus, _get_volume_vector(), p_from_pos, pitch_scale); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index e9c33b1839..4c5a63e52c 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -299,7 +299,7 @@ void SceneDebugger::_save_node(ObjectID id, const String &p_path) { Ref<PackedScene> ps = memnew(PackedScene); ps->pack(node); - ResourceSaver::save(p_path, ps); + ResourceSaver::save(ps, p_path); } void SceneDebugger::_send_object_id(ObjectID p_id, int p_max_size) { diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 4ed126d36e..911363f45d 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -174,4 +174,4 @@ public: }; #endif -#endif +#endif // SCENE_DEBUGGER_H diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index ba3852ec98..7cf8de6432 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -155,4 +155,4 @@ public: ButtonGroup(); }; -#endif +#endif // BASE_BUTTON_H diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index d8de22d27c..0a163b65ff 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -34,39 +34,14 @@ #include "servers/rendering_server.h" Size2 Button::get_minimum_size() const { - Size2 minsize = text_buf->get_size(); - if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { - minsize.width = 0; - } - - if (!expand_icon) { - Ref<Texture2D> _icon; - if (icon.is_null() && has_theme_icon(SNAME("icon"))) { - _icon = Control::get_theme_icon(SNAME("icon")); - } else { - _icon = icon; - } - - if (!_icon.is_null()) { - minsize.height = MAX(minsize.height, _icon->get_height()); - - if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) { - minsize.width += _icon->get_width(); - if (!xl_text.is_empty()) { - minsize.width += get_theme_constant(SNAME("h_separation")); - } - } else { - minsize.width = MAX(minsize.width, _icon->get_width()); - } - } - } - if (!xl_text.is_empty()) { - Ref<Font> font = get_theme_font(SNAME("font")); - float font_height = font->get_height(get_theme_font_size(SNAME("font_size"))); - minsize.height = MAX(font_height, minsize.height); + Ref<Texture2D> _icon; + if (icon.is_null() && has_theme_icon(SNAME("icon"))) { + _icon = Control::get_theme_icon(SNAME("icon")); + } else { + _icon = icon; } - return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize; + return get_minimum_size_for_text_and_icon("", _icon); } void Button::_set_internal_margin(Side p_side, float p_value) { @@ -283,7 +258,8 @@ void Button::_notification(int p_what) { } if (icon_region.size.width > 0) { - draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon); + Rect2 icon_region_rounded = Rect2(icon_region.position.round(), icon_region.size.round()); + draw_texture_rect(_icon, icon_region_rounded, false, color_icon); } } @@ -352,18 +328,62 @@ void Button::_notification(int p_what) { } } -void Button::_shape() { +Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Texture2D> p_icon) const { + Ref<TextParagraph> paragraph; + if (p_text.is_empty()) { + paragraph = text_buf; + } else { + paragraph.instantiate(); + const_cast<Button *>(this)->_shape(paragraph, p_text); + } + + Size2 minsize = paragraph->get_size(); + if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { + minsize.width = 0; + } + + if (!expand_icon && !p_icon.is_null()) { + minsize.height = MAX(minsize.height, p_icon->get_height()); + + if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) { + minsize.width += p_icon->get_width(); + if (!xl_text.is_empty() || !p_text.is_empty()) { + minsize.width += get_theme_constant(SNAME("hseparation")); + } + } else { + minsize.width = MAX(minsize.width, p_icon->get_width()); + } + } + + if (!xl_text.is_empty() || !p_text.is_empty()) { + Ref<Font> font = get_theme_font(SNAME("font")); + float font_height = font->get_height(get_theme_font_size(SNAME("font_size"))); + minsize.height = MAX(font_height, minsize.height); + } + + return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize; +} + +void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) { + if (p_paragraph.is_null()) { + p_paragraph = text_buf; + } + + if (p_text.is_empty()) { + p_text = xl_text; + } + Ref<Font> font = get_theme_font(SNAME("font")); int font_size = get_theme_font_size(SNAME("font_size")); - text_buf->clear(); + p_paragraph->clear(); if (text_direction == Control::TEXT_DIRECTION_INHERITED) { - text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); + p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); } else { - text_buf->set_direction((TextServer::Direction)text_direction); + p_paragraph->set_direction((TextServer::Direction)text_direction); } - text_buf->add_string(xl_text, font, font_size, language); - text_buf->set_text_overrun_behavior(overrun_behavior); + p_paragraph->add_string(p_text, font, font_size, language); + p_paragraph->set_text_overrun_behavior(overrun_behavior); } void Button::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) { @@ -526,7 +546,7 @@ void Button::_bind_methods() { Button::Button(const String &p_text) { text_buf.instantiate(); - text_buf->set_flags(TextServer::BREAK_MANDATORY); + text_buf->set_break_flags(TextServer::BREAK_MANDATORY); set_mouse_filter(MOUSE_FILTER_STOP); set_text(p_text); diff --git a/scene/gui/button.h b/scene/gui/button.h index 7a29cba677..23b5c78166 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -54,7 +54,7 @@ private: HorizontalAlignment icon_alignment = HORIZONTAL_ALIGNMENT_LEFT; float _internal_margin[4] = {}; - void _shape(); + void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = ""); protected: void _set_internal_margin(Side p_side, float p_value); @@ -64,6 +64,8 @@ protected: public: virtual Size2 get_minimum_size() const override; + Size2 get_minimum_size_for_text_and_icon(const String &p_text, Ref<Texture2D> p_icon) const; + void set_text(const String &p_text); String get_text() const; @@ -98,4 +100,4 @@ public: ~Button(); }; -#endif +#endif // BUTTON_H diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 22f968eac7..8968c1cc17 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -407,7 +407,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } /* Ctrl + Hover symbols */ -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (k->get_keycode() == Key::META) { #else if (k->get_keycode() == Key::CTRL) { diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index a431d8a5b2..08bd91a368 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CODEEDIT_H -#define CODEEDIT_H +#ifndef CODE_EDIT_H +#define CODE_EDIT_H #include "scene/gui/text_edit.h" @@ -433,4 +433,4 @@ public: VARIANT_ENUM_CAST(CodeEdit::CodeCompletionKind); -#endif // CODEEDIT_H +#endif // CODE_EDIT_H diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp index af78d67e5a..ebd86e0937 100644 --- a/scene/gui/color_mode.cpp +++ b/scene/gui/color_mode.cpp @@ -159,7 +159,7 @@ void ColorModeHSV::slider_draw(int p_which) { } else if (p_which == 0) { Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); - slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true); + slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(margin, size.x)), false); return; } else { Color s_col; @@ -306,7 +306,7 @@ void ColorModeOKHSL::slider_draw(int p_which) { } else if (p_which == 0) { Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); - slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true); + slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(margin, size.x)), false); return; } else { Color s_col; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 492a81f933..8cbe14c492 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -171,6 +171,9 @@ uniform float v = 1.0; void fragment() { float x = UV.x - 0.5; float y = UV.y - 0.5; + float h = atan(y, x) / (2.0 * M_PI); + float s = sqrt(x * x + y * y) * 2.0; + vec3 col = okhsl_to_srgb(vec3(h, s, v)); x += 0.001; y += 0.001; float b = float(sqrt(x * x + y * y) < 0.5); @@ -180,9 +183,6 @@ void fragment() { float b3 = float(sqrt(x * x + y * y) < 0.5); x += 0.002; float b4 = float(sqrt(x * x + y * y) < 0.5); - float s = sqrt(x * x + y * y); - float h = atan(y, x) / (2.0*M_PI); - vec3 col = okhsl_to_srgb(vec3(h, s, v)); COLOR = vec4(col, (b + b2 + b3 + b4) / 4.00); })"); } @@ -264,15 +264,7 @@ void ColorPicker::_update_controls() { void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) { color = p_color; if (color != last_color) { - if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - h = color.get_ok_hsl_h(); - s = color.get_ok_hsl_s(); - v = color.get_ok_hsl_l(); - } else { - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); - } + _copy_color_to_hsv(); last_color = color; } @@ -357,7 +349,7 @@ void ColorPicker::create_slider(GridContainer *gc, int idx) { s->set_h_size_flags(SIZE_EXPAND_FILL); s->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed)); - s->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(idx)); + s->connect("draw", callable_mp(this, &ColorPicker::_slider_draw).bind(idx)); if (idx < SLIDER_COUNT) { sliders[idx] = s; @@ -386,6 +378,26 @@ Vector<float> ColorPicker::get_active_slider_values() { return values; } +void ColorPicker::_copy_color_to_hsv() { + if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { + h = color.get_ok_hsl_h(); + s = color.get_ok_hsl_s(); + v = color.get_ok_hsl_l(); + } else { + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); + } +} + +void ColorPicker::_copy_hsv_to_color() { + if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { + color.set_ok_hsl(h, s, v, color.a); + } else { + color.set_hsv(h, s, v, color.a); + } +} + ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const { return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape; } @@ -499,6 +511,8 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) { ERR_FAIL_INDEX(p_shape, SHAPE_MAX); current_shape = p_shape; + _copy_color_to_hsv(); + _update_controls(); _update_color(); } @@ -515,7 +529,7 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) { ColorPresetButton *btn_preset = memnew(ColorPresetButton(p_color)); btn_preset->set_preset_color(p_color); btn_preset->set_custom_minimum_size(Size2(p_size, p_size)); - btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input), varray(p_color)); + btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input).bind(p_color)); btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1))); preset_container->add_child(btn_preset); } @@ -640,8 +654,7 @@ void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) { const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); if (rect_old.has_point(mb->get_position())) { // Revert to the old color when left-clicking the old color sample. - color = old_color; - _update_color(); + set_pick_color(old_color); emit_signal(SNAME("color_changed"), color); } } @@ -834,7 +847,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } else if (p_which == 2) { c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1)); if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { - circle_mat->set_shader_param("v", v); + circle_mat->set_shader_uniform("v", v); } } } @@ -887,17 +900,14 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { v = 1.0 - (y - c->get_position().y - corner_y) / real_size.y; } } + changing_color = true; - if (current_picker == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(h, s, v, color.a); - } else { - color.set_hsv(h, s, v, color.a); - } + _copy_hsv_to_color(); last_color = color; - set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -940,14 +950,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { v = 1.0 - (y - corner_y) / real_size.y; } } - if (current_picker != SHAPE_OKHSL_CIRCLE) { - color.set_hsv(h, s, v, color.a); - } else { - color.set_ok_hsl(h, s, v, color.a); - } + + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -970,14 +978,12 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { } else { changing_color = false; } - if (actual_shape != SHAPE_OKHSL_CIRCLE) { - color.set_hsv(h, s, v, color.a); - } else { - color.set_ok_hsl(h, s, v, color.a); - } + + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } else if (!bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { @@ -998,15 +1004,11 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { h = y / w_edit->get_size().height; } - if (current_mode == MODE_HSV) { - color.set_hsv(h, s, v, color.a); - } else if (current_mode == MODE_OKHSL) { - color.set_ok_hsl(h, s, v, color.a); - } - + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -1019,7 +1021,6 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_c if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { set_pick_color(p_color); - _update_color(); emit_signal(SNAME("color_changed"), p_color); } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && presets_enabled) { erase_preset(p_color); @@ -1071,11 +1072,11 @@ void ColorPicker::_screen_pick_pressed() { screen = memnew(Control); r->add_child(screen); screen->set_as_top_level(true); - screen->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); screen->set_default_cursor_shape(CURSOR_POINTING_HAND); screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input)); // It immediately toggles off in the first press otherwise. - screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed"), varray(false)); + screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false)); } else { screen->show(); } @@ -1204,11 +1205,11 @@ ColorPicker::ColorPicker() : uv_edit = memnew(Control); hb_edit->add_child(uv_edit); - uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(uv_edit)); + uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(uv_edit)); uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); - uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit)); + uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit)); HBoxContainer *hb_smpl = memnew(HBoxContainer); add_child(hb_smpl, false, INTERNAL_MODE_FRONT); @@ -1295,19 +1296,19 @@ ColorPicker::ColorPicker() : wheel = memnew(Control); wheel_margin->add_child(wheel); wheel->set_mouse_filter(MOUSE_FILTER_PASS); - wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(2, wheel)); + wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(2, wheel)); wheel_uv = memnew(Control); wheel_margin->add_child(wheel_uv); - wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(wheel_uv)); - wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv)); + wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(wheel_uv)); + wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, wheel_uv)); w_edit = memnew(Control); hb_edit->add_child(w_edit); w_edit->set_h_size_flags(SIZE_FILL); w_edit->set_v_size_flags(SIZE_EXPAND_FILL); w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input)); - w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(1, w_edit)); + w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(1, w_edit)); _update_controls(); updating = false; @@ -1456,7 +1457,7 @@ void ColorPickerButton::_update_picker() { popup = memnew(PopupPanel); popup->set_wrap_controls(true); picker = memnew(ColorPicker); - picker->set_anchors_and_offsets_preset(PRESET_WIDE); + picker->set_anchors_and_offsets_preset(PRESET_FULL_RECT); popup->add_child(picker); add_child(popup, false, INTERNAL_MODE_FRONT); picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed)); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index e219c78319..05b760b109 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -156,6 +156,9 @@ private: float v = 0.0; Color last_color; + void _copy_color_to_hsv(); + void _copy_hsv_to_color(); + PickerShapeType _get_actual_shape() const; void create_slider(GridContainer *gc, int idx); void _reset_theme(); @@ -276,4 +279,5 @@ public: VARIANT_ENUM_CAST(ColorPicker::PickerShapeType); VARIANT_ENUM_CAST(ColorPicker::ColorModeType); + #endif // COLOR_PICKER_H diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 15ff1d3ed6..06aa913eb1 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -50,6 +50,9 @@ #include "editor/plugins/control_editor_plugin.h" #endif +// Editor plugin interoperability. + +// TODO: Decouple controls from their editor plugin and get rid of this. #ifdef TOOLS_ENABLED Dictionary Control::_edit_get_state() const { Dictionary s; @@ -181,6 +184,49 @@ Size2 Control::_edit_get_minimum_size() const { } #endif +// Editor integration. + +void Control::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + Node::get_argument_options(p_function, p_idx, r_options); + + if (p_idx == 0) { + List<StringName> sn; + String pf = p_function; + if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") { + Theme::get_default()->get_color_list(get_class(), &sn); + } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") { + Theme::get_default()->get_stylebox_list(get_class(), &sn); + } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") { + Theme::get_default()->get_font_list(get_class(), &sn); + } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") { + Theme::get_default()->get_font_size_list(get_class(), &sn); + } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") { + Theme::get_default()->get_constant_list(get_class(), &sn); + } + + sn.sort_custom<StringName::AlphCompare>(); + for (const StringName &name : sn) { + r_options->push_back(String(name).quote()); + } + } +} + +TypedArray<String> Control::get_configuration_warnings() const { + TypedArray<String> warnings = Node::get_configuration_warnings(); + + if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) { + warnings.push_back(RTR("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\".")); + } + + return warnings; +} + +bool Control::is_text_field() const { + return false; +} + +// Dynamic properties. + String Control::properties_managed_by_container[] = { "offset_left", "offset_top", @@ -196,58 +242,6 @@ String Control::properties_managed_by_container[] = { "size" }; -void Control::accept_event() { - if (is_inside_tree()) { - get_viewport()->_gui_accept_event(); - } -} - -void Control::set_custom_minimum_size(const Size2 &p_custom) { - if (p_custom == data.custom_minimum_size) { - return; - } - data.custom_minimum_size = p_custom; - update_minimum_size(); -} - -Size2 Control::get_custom_minimum_size() const { - return data.custom_minimum_size; -} - -void Control::_update_minimum_size_cache() { - Size2 minsize = get_minimum_size(); - minsize.x = MAX(minsize.x, data.custom_minimum_size.x); - minsize.y = MAX(minsize.y, data.custom_minimum_size.y); - - bool size_changed = false; - if (data.minimum_size_cache != minsize) { - size_changed = true; - } - - data.minimum_size_cache = minsize; - data.minimum_size_valid = true; - - if (size_changed) { - update_minimum_size(); - } -} - -Size2 Control::get_combined_minimum_size() const { - if (!data.minimum_size_valid) { - const_cast<Control *>(this)->_update_minimum_size_cache(); - } - return data.minimum_size_cache; -} - -Transform2D Control::_get_internal_transform() const { - Transform2D rot_scale; - rot_scale.set_rotation_and_scale(data.rotation, data.scale); - Transform2D offset; - offset.set_origin(-data.pivot_offset); - - return offset.affine_inverse() * (rot_scale * offset); -} - bool Control::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (!name.begins_with("theme_override")) { @@ -258,21 +252,21 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { if (name.begins_with("theme_override_icons/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { - data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); } data.icon_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("theme_override_styles/")) { String dname = name.get_slicec('/', 1); if (data.style_override.has(dname)) { - data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); } data.style_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("theme_override_fonts/")) { String dname = name.get_slicec('/', 1); if (data.font_override.has(dname)) { - data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); } data.font_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); @@ -318,21 +312,6 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { return true; } -void Control::_update_minimum_size() { - if (!is_inside_tree()) { - return; - } - - Size2 minsize = get_combined_minimum_size(); - data.updating_last_minimum_size = false; - - if (minsize != data.last_minimum_size) { - data.last_minimum_size = minsize; - _size_changed(); - emit_signal(SceneStringNames::get_singleton()->minimum_size_changed); - } -} - bool Control::_get(const StringName &p_name, Variant &r_ret) const { String sname = p_name; if (!sname.begins_with("theme_override")) { @@ -586,6 +565,12 @@ void Control::_validate_property(PropertyInfo &property) const { } } +// Global relations. + +bool Control::is_top_level_control() const { + return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_top_level()); +} + Control *Control::get_parent_control() const { return data.parent; } @@ -594,97 +579,64 @@ Window *Control::get_parent_window() const { return data.parent_window; } -void Control::set_layout_direction(Control::LayoutDirection p_direction) { - ERR_FAIL_INDEX((int)p_direction, 4); - - data.layout_dir = p_direction; - data.is_rtl_dirty = true; - - propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED); -} +Control *Control::get_root_parent_control() const { + const CanvasItem *ci = this; + const Control *root = this; -Control::LayoutDirection Control::get_layout_direction() const { - return data.layout_dir; -} + while (ci) { + const Control *c = Object::cast_to<Control>(ci); + if (c) { + root = c; -bool Control::is_layout_rtl() const { - if (data.is_rtl_dirty) { - const_cast<Control *>(this)->data.is_rtl_dirty = false; - if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) { - Window *parent_window = get_parent_window(); - Control *parent_control = get_parent_control(); - if (parent_control) { - const_cast<Control *>(this)->data.is_rtl = parent_control->is_layout_rtl(); - } else if (parent_window) { - const_cast<Control *>(this)->data.is_rtl = parent_window->is_layout_rtl(); - } else { - if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { - const_cast<Control *>(this)->data.is_rtl = true; - } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); - } - } - } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) { - if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { - const_cast<Control *>(this)->data.is_rtl = true; - } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + if (c->data.RI || c->is_top_level_control()) { + break; } - } else { - const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL); } - } - return data.is_rtl; -} -void Control::set_auto_translate(bool p_enable) { - if (p_enable == data.auto_translate) { - return; + ci = ci->get_parent_item(); } - data.auto_translate = p_enable; - - notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); -} - -bool Control::is_auto_translating() const { - return data.auto_translate; -} - -void Control::_clear_size_warning() { - data.size_warning = false; + return const_cast<Control *>(root); } -//moved theme configuration here, so controls can set up even if still not inside active scene - -void Control::add_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff +Rect2 Control::get_parent_anchorable_rect() const { + if (!is_inside_tree()) { + return Rect2(); } - Window *child_w = Object::cast_to<Window>(p_child); + Rect2 parent_rect; + if (data.parent_canvas_item) { + parent_rect = data.parent_canvas_item->get_anchorable_rect(); + } else { +#ifdef TOOLS_ENABLED + Node *edited_root = get_tree()->get_edited_scene_root(); + if (edited_root && (this == edited_root || edited_root->is_ancestor_of(this))) { + parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/viewport_width"), ProjectSettings::get_singleton()->get("display/window/size/viewport_height")); + } else { + parent_rect = get_viewport()->get_visible_rect(); + } - if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff +#else + parent_rect = get_viewport()->get_visible_rect(); +#endif } + + return parent_rect; } -void Control::remove_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); +Size2 Control::get_parent_area_size() const { + return get_parent_anchorable_rect().size; +} - if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { - _propagate_theme_changed(child_c, nullptr, nullptr); - } +// Positioning and sizing. - Window *child_w = Object::cast_to<Window>(p_child); +Transform2D Control::_get_internal_transform() const { + Transform2D rot_scale; + rot_scale.set_rotation_and_scale(data.rotation, data.scale); + Transform2D offset; + offset.set_origin(-data.pivot_offset); - if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { - _propagate_theme_changed(child_w, nullptr, nullptr); - } + return offset.affine_inverse() * (rot_scale * offset); } void Control::_update_canvas_item_transform() { @@ -699,815 +651,146 @@ void Control::_update_canvas_item_transform() { RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } -void Control::_notification(int p_notification) { - switch (p_notification) { - case NOTIFICATION_POST_ENTER_TREE: { - data.minimum_size_valid = false; - data.is_rtl_dirty = true; - _size_changed(); - } break; - - case NOTIFICATION_EXIT_TREE: { - release_focus(); - get_viewport()->_gui_remove_control(this); - } break; - - case NOTIFICATION_READY: { -#ifdef DEBUG_ENABLED - connect("ready", callable_mp(this, &Control::_clear_size_warning), varray(), CONNECT_DEFERRED | CONNECT_ONESHOT); -#endif - } break; - - case NOTIFICATION_ENTER_CANVAS: { - data.parent = Object::cast_to<Control>(get_parent()); - data.parent_window = Object::cast_to<Window>(get_parent()); - data.is_rtl_dirty = true; - - if (data.theme.is_null()) { - if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) { - data.theme_owner = data.parent->data.theme_owner; - data.theme_owner_window = data.parent->data.theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) { - data.theme_owner = data.parent_window->theme_owner; - data.theme_owner_window = data.parent_window->theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } - } - - CanvasItem *node = this; - bool has_parent_control = false; - - while (!node->is_set_as_top_level()) { - CanvasItem *parent = Object::cast_to<CanvasItem>(node->get_parent()); - if (!parent) { - break; - } - - Control *parent_control = Object::cast_to<Control>(parent); - if (parent_control) { - has_parent_control = true; - break; - } - - node = parent; - } - - if (has_parent_control) { - // Do nothing, has a parent control. - } else { - // Is a regular root control or top_level. - Viewport *viewport = get_viewport(); - ERR_FAIL_COND(!viewport); - data.RI = viewport->_gui_add_root_control(this); - } - - data.parent_canvas_item = get_parent_item(); - - if (data.parent_canvas_item) { - data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed)); - } else { - // Connect viewport. - Viewport *viewport = get_viewport(); - ERR_FAIL_COND(!viewport); - viewport->connect("size_changed", callable_mp(this, &Control::_size_changed)); - } - } break; - - case NOTIFICATION_EXIT_CANVAS: { - if (data.parent_canvas_item) { - data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed)); - data.parent_canvas_item = nullptr; - } else if (!is_set_as_top_level()) { - //disconnect viewport - Viewport *viewport = get_viewport(); - ERR_FAIL_COND(!viewport); - viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed)); - } - - if (data.RI) { - get_viewport()->_gui_remove_root_control(data.RI); - data.RI = nullptr; - } - - data.parent = nullptr; - data.parent_canvas_item = nullptr; - data.parent_window = nullptr; - data.is_rtl_dirty = true; - } break; - - case NOTIFICATION_MOVED_IN_PARENT: { - // some parents need to know the order of the children to draw (like TabContainer) - // update if necessary - if (data.parent) { - data.parent->update(); - } - update(); - - if (data.RI) { - get_viewport()->_gui_set_root_order_dirty(); - } - } break; - - case NOTIFICATION_RESIZED: { - emit_signal(SceneStringNames::get_singleton()->resized); - } break; - - case NOTIFICATION_DRAW: { - _update_canvas_item_transform(); - RenderingServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size())); - RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents); - } break; - - case NOTIFICATION_MOUSE_ENTER: { - emit_signal(SceneStringNames::get_singleton()->mouse_entered); - } break; - - case NOTIFICATION_MOUSE_EXIT: { - emit_signal(SceneStringNames::get_singleton()->mouse_exited); - } break; - - case NOTIFICATION_FOCUS_ENTER: { - emit_signal(SceneStringNames::get_singleton()->focus_entered); - update(); - } break; - - case NOTIFICATION_FOCUS_EXIT: { - emit_signal(SceneStringNames::get_singleton()->focus_exited); - update(); - } break; - - case NOTIFICATION_THEME_CHANGED: { - update_minimum_size(); - update(); - } break; - - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible_in_tree()) { - if (get_viewport() != nullptr) { - get_viewport()->_gui_hide_control(this); - } - } else { - data.minimum_size_valid = false; - _update_minimum_size(); - _size_changed(); - } - } break; - - case NOTIFICATION_TRANSLATION_CHANGED: - case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { - if (is_inside_tree()) { - data.is_rtl_dirty = true; - _size_changed(); - } - } break; - } -} - -bool Control::has_point(const Point2 &p_point) const { - bool ret; - if (GDVIRTUAL_CALL(_has_point, p_point, ret)) { - return ret; - } - return Rect2(Point2(), get_size()).has_point(p_point); -} - -void Control::set_drag_forwarding(Object *p_target) { - if (p_target) { - data.drag_owner = p_target->get_instance_id(); - } else { - data.drag_owner = ObjectID(); - } -} - -Variant Control::get_drag_data(const Point2 &p_point) { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - return obj->call("_get_drag_data_fw", p_point, this); - } - } - - Variant dd; - if (GDVIRTUAL_CALL(_get_drag_data, p_point, dd)) { - return dd; - } - - return Variant(); -} - -bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - return obj->call("_can_drop_data_fw", p_point, p_data, this); - } - } - - bool ret; - if (GDVIRTUAL_CALL(_can_drop_data, p_point, p_data, ret)) { - return ret; - } - return false; -} - -void Control::drop_data(const Point2 &p_point, const Variant &p_data) { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - obj->call("_drop_data_fw", p_point, p_data, this); - return; - } - } - - GDVIRTUAL_CALL(_drop_data, p_point, p_data); -} - -void Control::force_drag(const Variant &p_data, Control *p_control) { - ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(p_data.get_type() == Variant::NIL); - - get_viewport()->_gui_force_drag(this, p_data, p_control); -} - -void Control::set_drag_preview(Control *p_control) { - ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(!get_viewport()->gui_is_dragging()); - get_viewport()->_gui_set_drag_preview(this, p_control); -} - -bool Control::is_drag_successful() const { - return is_inside_tree() && get_viewport()->gui_is_drag_successful(); -} - -void Control::_call_gui_input(const Ref<InputEvent> &p_event) { - emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it) - if (!is_inside_tree() || get_viewport()->is_input_handled()) { - return; //input was handled, abort - } - GDVIRTUAL_CALL(_gui_input, p_event); - if (!is_inside_tree() || get_viewport()->is_input_handled()) { - return; //input was handled, abort - } - gui_input(p_event); -} -void Control::gui_input(const Ref<InputEvent> &p_event) { +Transform2D Control::get_transform() const { + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); + return xform; } -Size2 Control::get_minimum_size() const { - Vector2 ms; - if (GDVIRTUAL_CALL(_get_minimum_size, ms)) { - return ms; - } - return Vector2(); -} +/// Anchors and offsets. -template <class T> -T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { - ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified."); - - // First, look through each control or window node in the branch, until no valid parent can be found. - // Only nodes with a theme resource attached are considered. - Control *theme_owner = p_theme_owner; - Window *theme_owner_window = p_theme_owner_window; - - while (theme_owner || theme_owner_window) { - // For each theme resource check the theme types provided and see if p_name exists with any of them. - for (const StringName &E : p_theme_types) { - if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) { - return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E); - } - - if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) { - return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E); - } - } - - Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - } else { - theme_owner = nullptr; - theme_owner_window = nullptr; - } - } - } - - // Secondly, check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { - for (const StringName &E : p_theme_types) { - if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { - return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E); - } - } - } - - // Lastly, fall back on the items defined in the default Theme, if they exist. - for (const StringName &E : p_theme_types) { - if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { - return Theme::get_default()->get_theme_item(p_data_type, p_name, E); - } - } - // If they don't exist, use any type to return the default/empty value. - return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]); +void Control::_set_anchor(Side p_side, real_t p_anchor) { + set_anchor(p_side, p_anchor); } -bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { - ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified."); - - // First, look through each control or window node in the branch, until no valid parent can be found. - // Only nodes with a theme resource attached are considered. - Control *theme_owner = p_theme_owner; - Window *theme_owner_window = p_theme_owner_window; - - while (theme_owner || theme_owner_window) { - // For each theme resource check the theme types provided and see if p_name exists with any of them. - for (const StringName &E : p_theme_types) { - if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) { - return true; - } - - if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) { - return true; - } - } - - Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - } else { - theme_owner = nullptr; - theme_owner_window = nullptr; - } - } - } +void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) { + ERR_FAIL_INDEX((int)p_side, 4); - // Secondly, check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { - for (const StringName &E : p_theme_types) { - if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { - return true; - } - } - } + Rect2 parent_rect = get_parent_anchorable_rect(); + real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y; + real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range; + real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range; - // Lastly, fall back on the items defined in the default Theme, if they exist. - for (const StringName &E : p_theme_types) { - if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { - return true; - } - } - return false; -} + data.anchor[p_side] = p_anchor; -void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) { - Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); + if (((p_side == SIDE_LEFT || p_side == SIDE_TOP) && data.anchor[p_side] > data.anchor[(p_side + 2) % 4]) || + ((p_side == SIDE_RIGHT || p_side == SIDE_BOTTOM) && data.anchor[p_side] < data.anchor[(p_side + 2) % 4])) { + if (p_push_opposite_anchor) { + data.anchor[(p_side + 2) % 4] = data.anchor[p_side]; } else { - Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); - } - } else { - Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); - } -} - -Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); - if (tex) { - return *tex; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); -} - -Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const Ref<StyleBox> *style = data.style_override.getptr(p_name); - if (style) { - return *style; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); -} - -Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const Ref<Font> *font = data.font_override.getptr(p_name); - if (font) { - return *font; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); -} - -int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const int *font_size = data.font_size_override.getptr(p_name); - if (font_size && (*font_size) > 0) { - return *font_size; + data.anchor[p_side] = data.anchor[(p_side + 2) % 4]; } } - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); -} - -Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const Color *color = data.color_override.getptr(p_name); - if (color) { - return *color; + if (!p_keep_offset) { + data.offset[p_side] = previous_pos - data.anchor[p_side] * parent_range; + if (p_push_opposite_anchor) { + data.offset[(p_side + 2) % 4] = previous_opposite_pos - data.anchor[(p_side + 2) % 4] * parent_range; } } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); -} - -int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - const int *constant = data.constant_override.getptr(p_name); - if (constant) { - return *constant; - } + if (is_inside_tree()) { + _size_changed(); } - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); -} - -bool Control::has_theme_icon_override(const StringName &p_name) const { - const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); - return tex != nullptr; -} - -bool Control::has_theme_stylebox_override(const StringName &p_name) const { - const Ref<StyleBox> *style = data.style_override.getptr(p_name); - return style != nullptr; -} - -bool Control::has_theme_font_override(const StringName &p_name) const { - const Ref<Font> *font = data.font_override.getptr(p_name); - return font != nullptr; -} - -bool Control::has_theme_font_size_override(const StringName &p_name) const { - const int *font_size = data.font_size_override.getptr(p_name); - return font_size != nullptr; -} - -bool Control::has_theme_color_override(const StringName &p_name) const { - const Color *color = data.color_override.getptr(p_name); - return color != nullptr; -} - -bool Control::has_theme_constant_override(const StringName &p_name) const { - const int *constant = data.constant_override.getptr(p_name); - return constant != nullptr; + update(); } -bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_icon_override(p_name)) { - return true; - } - } +real_t Control::get_anchor(Side p_side) const { + ERR_FAIL_INDEX_V(int(p_side), 4, 0.0); - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); + return data.anchor[p_side]; } -bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_stylebox_override(p_name)) { - return true; - } - } +void Control::set_offset(Side p_side, real_t p_value) { + ERR_FAIL_INDEX((int)p_side, 4); - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); + data.offset[p_side] = p_value; + _size_changed(); } -bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_font_override(p_name)) { - return true; - } - } +real_t Control::get_offset(Side p_side) const { + ERR_FAIL_INDEX_V((int)p_side, 4, 0); - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); + return data.offset[p_side]; } -bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_font_size_override(p_name)) { - return true; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); +void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor) { + set_anchor(p_side, p_anchor, false, p_push_opposite_anchor); + set_offset(p_side, p_pos); } -bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_color_override(p_name)) { - return true; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); +void Control::set_begin(const Size2 &p_point) { + data.offset[0] = p_point.x; + data.offset[1] = p_point.y; + _size_changed(); } -bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { - if (has_theme_constant_override(p_name)) { - return true; - } - } - - List<StringName> theme_types; - _get_theme_type_dependencies(p_theme_type, &theme_types); - return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); +Size2 Control::get_begin() const { + return Size2(data.offset[0], data.offset[1]); } -float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window) { - // First, look through each control or window node in the branch, until no valid parent can be found. - // Only nodes with a theme resource attached are considered. - // For each theme resource see if their assigned theme has the default value defined and valid. - Control *theme_owner = p_theme_owner; - Window *theme_owner_window = p_theme_owner_window; - - while (theme_owner || theme_owner_window) { - if (theme_owner && theme_owner->data.theme->has_default_base_scale()) { - return theme_owner->data.theme->get_default_base_scale(); - } - - if (theme_owner_window && theme_owner_window->theme->has_default_base_scale()) { - return theme_owner_window->theme->get_default_base_scale(); - } - - Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - } else { - theme_owner = nullptr; - theme_owner_window = nullptr; - } - } - } - - // Secondly, check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_default_base_scale()) { - return Theme::get_project_default()->get_default_base_scale(); - } - } - - // Lastly, fall back on the default Theme. - if (Theme::get_default()->has_default_base_scale()) { - return Theme::get_default()->get_default_base_scale(); - } - return Theme::get_fallback_base_scale(); +void Control::set_end(const Size2 &p_point) { + data.offset[2] = p_point.x; + data.offset[3] = p_point.y; + _size_changed(); } -float Control::get_theme_default_base_scale() const { - return fetch_theme_default_base_scale(data.theme_owner, data.theme_owner_window); +Size2 Control::get_end() const { + return Size2(data.offset[2], data.offset[3]); } -Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window) { - // First, look through each control or window node in the branch, until no valid parent can be found. - // Only nodes with a theme resource attached are considered. - // For each theme resource see if their assigned theme has the default value defined and valid. - Control *theme_owner = p_theme_owner; - Window *theme_owner_window = p_theme_owner_window; - - while (theme_owner || theme_owner_window) { - if (theme_owner && theme_owner->data.theme->has_default_font()) { - return theme_owner->data.theme->get_default_font(); - } - - if (theme_owner_window && theme_owner_window->theme->has_default_font()) { - return theme_owner_window->theme->get_default_font(); - } - - Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - } else { - theme_owner = nullptr; - theme_owner_window = nullptr; - } - } - } - - // Secondly, check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_default_font()) { - return Theme::get_project_default()->get_default_font(); - } - } +void Control::set_h_grow_direction(GrowDirection p_direction) { + ERR_FAIL_INDEX((int)p_direction, 3); - // Lastly, fall back on the default Theme. - if (Theme::get_default()->has_default_font()) { - return Theme::get_default()->get_default_font(); - } - return Theme::get_fallback_font(); + data.h_grow = p_direction; + _size_changed(); } -Ref<Font> Control::get_theme_default_font() const { - return fetch_theme_default_font(data.theme_owner, data.theme_owner_window); +Control::GrowDirection Control::get_h_grow_direction() const { + return data.h_grow; } -int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window) { - // First, look through each control or window node in the branch, until no valid parent can be found. - // Only nodes with a theme resource attached are considered. - // For each theme resource see if their assigned theme has the default value defined and valid. - Control *theme_owner = p_theme_owner; - Window *theme_owner_window = p_theme_owner_window; - - while (theme_owner || theme_owner_window) { - if (theme_owner && theme_owner->data.theme->has_default_font_size()) { - return theme_owner->data.theme->get_default_font_size(); - } - - if (theme_owner_window && theme_owner_window->theme->has_default_font_size()) { - return theme_owner_window->theme->get_default_font_size(); - } - - Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - } else { - theme_owner = nullptr; - theme_owner_window = nullptr; - } - } - } - - // Secondly, check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_default_font_size()) { - return Theme::get_project_default()->get_default_font_size(); - } - } +void Control::set_v_grow_direction(GrowDirection p_direction) { + ERR_FAIL_INDEX((int)p_direction, 3); - // Lastly, fall back on the default Theme. - if (Theme::get_default()->has_default_font_size()) { - return Theme::get_default()->get_default_font_size(); - } - return Theme::get_fallback_font_size(); + data.v_grow = p_direction; + _size_changed(); } -int Control::get_theme_default_font_size() const { - return fetch_theme_default_font_size(data.theme_owner, data.theme_owner_window); +Control::GrowDirection Control::get_v_grow_direction() const { + return data.v_grow; } -Rect2 Control::get_parent_anchorable_rect() const { - if (!is_inside_tree()) { - return Rect2(); - } - - Rect2 parent_rect; - if (data.parent_canvas_item) { - parent_rect = data.parent_canvas_item->get_anchorable_rect(); - } else { -#ifdef TOOLS_ENABLED - Node *edited_root = get_tree()->get_edited_scene_root(); - if (edited_root && (this == edited_root || edited_root->is_ancestor_of(this))) { - parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/viewport_width"), ProjectSettings::get_singleton()->get("display/window/size/viewport_height")); - } else { - parent_rect = get_viewport()->get_visible_rect(); - } +void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) { + Size2 parent_rect_size = get_parent_anchorable_rect().size; + ERR_FAIL_COND(parent_rect_size.x == 0.0); + ERR_FAIL_COND(parent_rect_size.y == 0.0); -#else - parent_rect = get_viewport()->get_visible_rect(); -#endif + real_t x = p_rect.position.x; + if (is_layout_rtl()) { + x = parent_rect_size.x - x - p_rect.size.x; } - - return parent_rect; -} - -Size2 Control::get_parent_area_size() const { - return get_parent_anchorable_rect().size; + r_anchors[0] = (x - p_offsets[0]) / parent_rect_size.x; + r_anchors[1] = (p_rect.position.y - p_offsets[1]) / parent_rect_size.y; + r_anchors[2] = (x + p_rect.size.x - p_offsets[2]) / parent_rect_size.x; + r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y; } -void Control::_size_changed() { - Rect2 parent_rect = get_parent_anchorable_rect(); - - real_t edge_pos[4]; - - for (int i = 0; i < 4; i++) { - real_t area = parent_rect.size[i & 1]; - edge_pos[i] = data.offset[i] + (data.anchor[i] * area); - } - - Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]); - Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache; - - Size2 minimum_size = get_combined_minimum_size(); - - if (minimum_size.width > new_size_cache.width) { - if (data.h_grow == GROW_DIRECTION_BEGIN) { - new_pos_cache.x += new_size_cache.width - minimum_size.width; - } else if (data.h_grow == GROW_DIRECTION_BOTH) { - new_pos_cache.x += 0.5 * (new_size_cache.width - minimum_size.width); - } - - new_size_cache.width = minimum_size.width; - } +void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) { + Size2 parent_rect_size = get_parent_anchorable_rect().size; + real_t x = p_rect.position.x; if (is_layout_rtl()) { - new_pos_cache.x = parent_rect.size.x - new_pos_cache.x - new_size_cache.x; - } - - if (minimum_size.height > new_size_cache.height) { - if (data.v_grow == GROW_DIRECTION_BEGIN) { - new_pos_cache.y += new_size_cache.height - minimum_size.height; - } else if (data.v_grow == GROW_DIRECTION_BOTH) { - new_pos_cache.y += 0.5 * (new_size_cache.height - minimum_size.height); - } - - new_size_cache.height = minimum_size.height; - } - - bool pos_changed = new_pos_cache != data.pos_cache; - bool size_changed = new_size_cache != data.size_cache; - - data.pos_cache = new_pos_cache; - data.size_cache = new_size_cache; - - if (is_inside_tree()) { - if (size_changed) { - notification(NOTIFICATION_RESIZED); - } - if (pos_changed || size_changed) { - item_rect_changed(size_changed); - _notify_transform(); - } - - if (pos_changed && !size_changed) { - _update_canvas_item_transform(); //move because it won't be updated - } + x = parent_rect_size.x - x - p_rect.size.x; } + r_offsets[0] = x - (p_anchors[0] * parent_rect_size.x); + r_offsets[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y); + r_offsets[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x); + r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y); } +/// Presets and layout modes. + void Control::_set_layout_mode(LayoutMode p_mode) { bool list_changed = false; @@ -1557,47 +840,6 @@ Control::LayoutMode Control::_get_layout_mode() const { return LayoutMode::LAYOUT_MODE_POSITION; } -void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) { - ERR_FAIL_INDEX((int)p_side, 4); - - Rect2 parent_rect = get_parent_anchorable_rect(); - real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y; - real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range; - real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range; - - data.anchor[p_side] = p_anchor; - - if (((p_side == SIDE_LEFT || p_side == SIDE_TOP) && data.anchor[p_side] > data.anchor[(p_side + 2) % 4]) || - ((p_side == SIDE_RIGHT || p_side == SIDE_BOTTOM) && data.anchor[p_side] < data.anchor[(p_side + 2) % 4])) { - if (p_push_opposite_anchor) { - data.anchor[(p_side + 2) % 4] = data.anchor[p_side]; - } else { - data.anchor[p_side] = data.anchor[(p_side + 2) % 4]; - } - } - - if (!p_keep_offset) { - data.offset[p_side] = previous_pos - data.anchor[p_side] * parent_range; - if (p_push_opposite_anchor) { - data.offset[(p_side + 2) % 4] = previous_opposite_pos - data.anchor[(p_side + 2) % 4] * parent_range; - } - } - if (is_inside_tree()) { - _size_changed(); - } - - update(); -} - -void Control::_set_anchor(Side p_side, real_t p_anchor) { - set_anchor(p_side, p_anchor); -} - -void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor) { - set_anchor(p_side, p_anchor, false, p_push_opposite_anchor); - set_offset(p_side, p_pos); -} - void Control::_set_anchors_layout_preset(int p_preset) { bool list_changed = false; @@ -1642,7 +884,7 @@ void Control::_set_anchors_layout_preset(int p_preset) { case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_offsets_preset(preset, LayoutPresetMode::PRESET_MODE_MINSIZE); break; } @@ -1718,7 +960,7 @@ int Control::_get_anchors_layout_preset() const { } if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_END) { - return (int)LayoutPreset::PRESET_WIDE; + return (int)LayoutPreset::PRESET_FULL_RECT; } // Does not match any preset, return "Custom". @@ -1737,7 +979,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) { case PRESET_BOTTOM_WIDE: case PRESET_LEFT_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_anchor(SIDE_LEFT, ANCHOR_BEGIN, p_keep_offsets); break; @@ -1765,7 +1007,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) { case PRESET_RIGHT_WIDE: case PRESET_TOP_WIDE: case PRESET_VCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_anchor(SIDE_TOP, ANCHOR_BEGIN, p_keep_offsets); break; @@ -1807,7 +1049,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) { case PRESET_RIGHT_WIDE: case PRESET_BOTTOM_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_anchor(SIDE_RIGHT, ANCHOR_END, p_keep_offsets); break; } @@ -1835,7 +1077,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) { case PRESET_RIGHT_WIDE: case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_anchor(SIDE_BOTTOM, ANCHOR_END, p_keep_offsets); break; } @@ -1870,7 +1112,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_BOTTOM_WIDE: case PRESET_LEFT_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: data.offset[0] = x * (0.0 - data.anchor[0]) + p_margin + parent_rect.position.x; break; @@ -1898,7 +1140,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_RIGHT_WIDE: case PRESET_TOP_WIDE: case PRESET_VCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: data.offset[1] = parent_rect.size.y * (0.0 - data.anchor[1]) + p_margin + parent_rect.position.y; break; @@ -1940,7 +1182,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_RIGHT_WIDE: case PRESET_BOTTOM_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: data.offset[2] = x * (1.0 - data.anchor[2]) - p_margin + parent_rect.position.x; break; } @@ -1968,7 +1210,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_RIGHT_WIDE: case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: data.offset[3] = parent_rect.size.y * (1.0 - data.anchor[3]) - p_margin + parent_rect.position.y; break; } @@ -2003,7 +1245,7 @@ void Control::set_grow_direction_preset(LayoutPreset p_preset) { case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_h_grow_direction(GrowDirection::GROW_DIRECTION_BOTH); break; } @@ -2031,49 +1273,43 @@ void Control::set_grow_direction_preset(LayoutPreset p_preset) { case PRESET_RIGHT_WIDE: case PRESET_VCENTER_WIDE: case PRESET_HCENTER_WIDE: - case PRESET_WIDE: + case PRESET_FULL_RECT: set_v_grow_direction(GrowDirection::GROW_DIRECTION_BOTH); break; } } -real_t Control::get_anchor(Side p_side) const { - ERR_FAIL_INDEX_V(int(p_side), 4, 0.0); +/// Manual positioning. - return data.anchor[p_side]; +void Control::_set_position(const Size2 &p_point) { + set_position(p_point); } -void Control::set_offset(Side p_side, real_t p_value) { - ERR_FAIL_INDEX((int)p_side, 4); - - data.offset[p_side] = p_value; +void Control::set_position(const Size2 &p_point, bool p_keep_offsets) { + if (p_keep_offsets) { + _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor); + } else { + _compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset); + } _size_changed(); } -void Control::set_begin(const Size2 &p_point) { - data.offset[0] = p_point.x; - data.offset[1] = p_point.y; - _size_changed(); +Size2 Control::get_position() const { + return data.pos_cache; } -void Control::set_end(const Size2 &p_point) { - data.offset[2] = p_point.x; - data.offset[3] = p_point.y; - _size_changed(); +void Control::_set_global_position(const Point2 &p_point) { + set_global_position(p_point); } -real_t Control::get_offset(Side p_side) const { - ERR_FAIL_INDEX_V((int)p_side, 4, 0); - - return data.offset[p_side]; -} +void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) { + Transform2D inv; -Size2 Control::get_begin() const { - return Size2(data.offset[0], data.offset[1]); -} + if (data.parent_canvas_item) { + inv = data.parent_canvas_item->get_global_transform().affine_inverse(); + } -Size2 Control::get_end() const { - return Size2(data.offset[2], data.offset[3]); + set_position(inv.xform(p_point), p_keep_offsets); } Point2 Control::get_global_position() const { @@ -2091,72 +1327,6 @@ Point2 Control::get_screen_position() const { return global_pos; } -void Control::_set_global_position(const Point2 &p_point) { - set_global_position(p_point); -} - -void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) { - Transform2D inv; - - if (data.parent_canvas_item) { - inv = data.parent_canvas_item->get_global_transform().affine_inverse(); - } - - set_position(inv.xform(p_point), p_keep_offsets); -} - -void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) { - Size2 parent_rect_size = get_parent_anchorable_rect().size; - ERR_FAIL_COND(parent_rect_size.x == 0.0); - ERR_FAIL_COND(parent_rect_size.y == 0.0); - - real_t x = p_rect.position.x; - if (is_layout_rtl()) { - x = parent_rect_size.x - x - p_rect.size.x; - } - r_anchors[0] = (x - p_offsets[0]) / parent_rect_size.x; - r_anchors[1] = (p_rect.position.y - p_offsets[1]) / parent_rect_size.y; - r_anchors[2] = (x + p_rect.size.x - p_offsets[2]) / parent_rect_size.x; - r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y; -} - -void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) { - Size2 parent_rect_size = get_parent_anchorable_rect().size; - - real_t x = p_rect.position.x; - if (is_layout_rtl()) { - x = parent_rect_size.x - x - p_rect.size.x; - } - r_offsets[0] = x - (p_anchors[0] * parent_rect_size.x); - r_offsets[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y); - r_offsets[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x); - r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y); -} - -void Control::_set_position(const Size2 &p_point) { - set_position(p_point); -} - -void Control::set_position(const Size2 &p_point, bool p_keep_offsets) { - if (p_keep_offsets) { - _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor); - } else { - _compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset); - } - _size_changed(); -} - -void Control::set_rect(const Rect2 &p_rect) { - for (int i = 0; i < 4; i++) { - data.anchor[i] = ANCHOR_BEGIN; - } - - _compute_offsets(p_rect, data.anchor, data.offset); - if (is_inside_tree()) { - _size_changed(); - } -} - void Control::_set_size(const Size2 &p_size) { #ifdef DEBUG_ENABLED if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) { @@ -2184,10 +1354,6 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) { _size_changed(); } -Size2 Control::get_position() const { - return data.pos_cache; -} - Size2 Control::get_size() const { return data.size_cache; } @@ -2196,6 +1362,21 @@ void Control::reset_size() { set_size(Size2()); } +void Control::set_rect(const Rect2 &p_rect) { + for (int i = 0; i < 4; i++) { + data.anchor[i] = ANCHOR_BEGIN; + } + + _compute_offsets(p_rect, data.anchor, data.offset); + if (is_inside_tree()) { + _size_changed(); + } +} + +Rect2 Control::get_rect() const { + return Rect2(get_position(), get_size()); +} + Rect2 Control::get_global_rect() const { return Rect2(get_global_position(), get_size()); } @@ -2220,118 +1401,382 @@ Rect2 Control::get_window_rect() const { return gr; } -Rect2 Control::get_rect() const { - return Rect2(get_position(), get_size()); -} - Rect2 Control::get_anchorable_rect() const { return Rect2(Point2(), get_size()); } -void Control::begin_bulk_theme_override() { - data.bulk_theme_override = true; +void Control::set_scale(const Vector2 &p_scale) { + data.scale = p_scale; + // Avoid having 0 scale values, can lead to errors in physics and rendering. + if (data.scale.x == 0) { + data.scale.x = CMP_EPSILON; + } + if (data.scale.y == 0) { + data.scale.y = CMP_EPSILON; + } + update(); + _notify_transform(); } -void Control::end_bulk_theme_override() { - ERR_FAIL_COND(!data.bulk_theme_override); +Vector2 Control::get_scale() const { + return data.scale; +} - data.bulk_theme_override = false; - _notify_theme_changed(); +void Control::set_rotation(real_t p_radians) { + data.rotation = p_radians; + update(); + _notify_transform(); } -void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { - ERR_FAIL_COND(!p_icon.is_valid()); +real_t Control::get_rotation() const { + return data.rotation; +} - if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); +void Control::set_pivot_offset(const Vector2 &p_pivot) { + data.pivot_offset = p_pivot; + update(); + _notify_transform(); +} + +Vector2 Control::get_pivot_offset() const { + return data.pivot_offset; +} + +/// Sizes. + +void Control::_update_minimum_size() { + if (!is_inside_tree()) { + return; } - data.icon_override[p_name] = p_icon; - data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + Size2 minsize = get_combined_minimum_size(); + data.updating_last_minimum_size = false; + + if (minsize != data.last_minimum_size) { + data.last_minimum_size = minsize; + _size_changed(); + emit_signal(SceneStringNames::get_singleton()->minimum_size_changed); + } } -void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { - ERR_FAIL_COND(!p_style.is_valid()); +void Control::update_minimum_size() { + if (!is_inside_tree() || data.block_minimum_size_adjust) { + return; + } - if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + Control *invalidate = this; + + //invalidate cache upwards + while (invalidate && invalidate->data.minimum_size_valid) { + invalidate->data.minimum_size_valid = false; + if (invalidate->is_set_as_top_level()) { + break; // do not go further up + } + if (!invalidate->data.parent && get_parent()) { + Window *parent_window = Object::cast_to<Window>(get_parent()); + if (parent_window && parent_window->is_wrapping_controls()) { + parent_window->child_controls_changed(); + } + } + invalidate = invalidate->data.parent; } - data.style_override[p_name] = p_style; - data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + if (!is_visible_in_tree()) { + return; + } + + if (data.updating_last_minimum_size) { + return; + } + + data.updating_last_minimum_size = true; + + MessageQueue::get_singleton()->push_call(this, "_update_minimum_size"); } -void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { - ERR_FAIL_COND(!p_font.is_valid()); +void Control::set_block_minimum_size_adjust(bool p_block) { + data.block_minimum_size_adjust = p_block; +} - if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); +bool Control::is_minimum_size_adjust_blocked() const { + return data.block_minimum_size_adjust; +} + +Size2 Control::get_minimum_size() const { + Vector2 ms; + if (GDVIRTUAL_CALL(_get_minimum_size, ms)) { + return ms; } + return Vector2(); +} - data.font_override[p_name] = p_font; - data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); +void Control::set_custom_minimum_size(const Size2 &p_custom) { + if (p_custom == data.custom_minimum_size) { + return; + } + data.custom_minimum_size = p_custom; + update_minimum_size(); } -void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) { - data.font_size_override[p_name] = p_font_size; - _notify_theme_changed(); +Size2 Control::get_custom_minimum_size() const { + return data.custom_minimum_size; } -void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) { - data.color_override[p_name] = p_color; - _notify_theme_changed(); +void Control::_update_minimum_size_cache() { + Size2 minsize = get_minimum_size(); + minsize.x = MAX(minsize.x, data.custom_minimum_size.x); + minsize.y = MAX(minsize.y, data.custom_minimum_size.y); + + bool size_changed = false; + if (data.minimum_size_cache != minsize) { + size_changed = true; + } + + data.minimum_size_cache = minsize; + data.minimum_size_valid = true; + + if (size_changed) { + update_minimum_size(); + } } -void Control::add_theme_constant_override(const StringName &p_name, int p_constant) { - data.constant_override[p_name] = p_constant; - _notify_theme_changed(); +Size2 Control::get_combined_minimum_size() const { + if (!data.minimum_size_valid) { + const_cast<Control *>(this)->_update_minimum_size_cache(); + } + return data.minimum_size_cache; } -void Control::remove_theme_icon_override(const StringName &p_name) { - if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); +void Control::_size_changed() { + Rect2 parent_rect = get_parent_anchorable_rect(); + + real_t edge_pos[4]; + + for (int i = 0; i < 4; i++) { + real_t area = parent_rect.size[i & 1]; + edge_pos[i] = data.offset[i] + (data.anchor[i] * area); } - data.icon_override.erase(p_name); - _notify_theme_changed(); + Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]); + Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache; + + Size2 minimum_size = get_combined_minimum_size(); + + if (minimum_size.width > new_size_cache.width) { + if (data.h_grow == GROW_DIRECTION_BEGIN) { + new_pos_cache.x += new_size_cache.width - minimum_size.width; + } else if (data.h_grow == GROW_DIRECTION_BOTH) { + new_pos_cache.x += 0.5 * (new_size_cache.width - minimum_size.width); + } + + new_size_cache.width = minimum_size.width; + } + + if (is_layout_rtl()) { + new_pos_cache.x = parent_rect.size.x - new_pos_cache.x - new_size_cache.x; + } + + if (minimum_size.height > new_size_cache.height) { + if (data.v_grow == GROW_DIRECTION_BEGIN) { + new_pos_cache.y += new_size_cache.height - minimum_size.height; + } else if (data.v_grow == GROW_DIRECTION_BOTH) { + new_pos_cache.y += 0.5 * (new_size_cache.height - minimum_size.height); + } + + new_size_cache.height = minimum_size.height; + } + + bool pos_changed = new_pos_cache != data.pos_cache; + bool size_changed = new_size_cache != data.size_cache; + + data.pos_cache = new_pos_cache; + data.size_cache = new_size_cache; + + if (is_inside_tree()) { + if (size_changed) { + notification(NOTIFICATION_RESIZED); + } + if (pos_changed || size_changed) { + item_rect_changed(size_changed); + _notify_transform(); + } + + if (pos_changed && !size_changed) { + _update_canvas_item_transform(); //move because it won't be updated + } + } } -void Control::remove_theme_style_override(const StringName &p_name) { - if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); +void Control::_clear_size_warning() { + data.size_warning = false; +} + +// Container sizing. + +void Control::set_h_size_flags(int p_flags) { + if (data.h_size_flags == p_flags) { + return; } + data.h_size_flags = p_flags; + emit_signal(SceneStringNames::get_singleton()->size_flags_changed); +} - data.style_override.erase(p_name); - _notify_theme_changed(); +int Control::get_h_size_flags() const { + return data.h_size_flags; } -void Control::remove_theme_font_override(const StringName &p_name) { - if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); +void Control::set_v_size_flags(int p_flags) { + if (data.v_size_flags == p_flags) { + return; } + data.v_size_flags = p_flags; + emit_signal(SceneStringNames::get_singleton()->size_flags_changed); +} - data.font_override.erase(p_name); - _notify_theme_changed(); +int Control::get_v_size_flags() const { + return data.v_size_flags; } -void Control::remove_theme_font_size_override(const StringName &p_name) { - data.font_size_override.erase(p_name); - _notify_theme_changed(); +void Control::set_stretch_ratio(real_t p_ratio) { + if (data.expand == p_ratio) { + return; + } + + data.expand = p_ratio; + emit_signal(SceneStringNames::get_singleton()->size_flags_changed); } -void Control::remove_theme_color_override(const StringName &p_name) { - data.color_override.erase(p_name); - _notify_theme_changed(); +real_t Control::get_stretch_ratio() const { + return data.expand; } -void Control::remove_theme_constant_override(const StringName &p_name) { - data.constant_override.erase(p_name); - _notify_theme_changed(); +// Input events. + +void Control::_call_gui_input(const Ref<InputEvent> &p_event) { + emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it) + if (!is_inside_tree() || get_viewport()->is_input_handled()) { + return; //input was handled, abort + } + GDVIRTUAL_CALL(_gui_input, p_event); + if (!is_inside_tree() || get_viewport()->is_input_handled()) { + return; //input was handled, abort + } + gui_input(p_event); +} + +void Control::gui_input(const Ref<InputEvent> &p_event) { +} + +void Control::accept_event() { + if (is_inside_tree()) { + get_viewport()->_gui_accept_event(); + } +} + +bool Control::has_point(const Point2 &p_point) const { + bool ret; + if (GDVIRTUAL_CALL(_has_point, p_point, ret)) { + return ret; + } + return Rect2(Point2(), get_size()).has_point(p_point); +} + +void Control::set_mouse_filter(MouseFilter p_filter) { + ERR_FAIL_INDEX(p_filter, 3); + data.mouse_filter = p_filter; + notify_property_list_changed(); + update_configuration_warnings(); +} + +Control::MouseFilter Control::get_mouse_filter() const { + return data.mouse_filter; +} + +void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) { + data.force_pass_scroll_events = p_force_pass_scroll_events; +} + +bool Control::is_force_pass_scroll_events() const { + return data.force_pass_scroll_events; +} + +void Control::warp_mouse(const Point2 &p_position) { + ERR_FAIL_COND(!is_inside_tree()); + get_viewport()->warp_mouse(get_global_transform_with_canvas().xform(p_position)); +} + +// Drag and drop handling. + +void Control::set_drag_forwarding(Object *p_target) { + if (p_target) { + data.drag_owner = p_target->get_instance_id(); + } else { + data.drag_owner = ObjectID(); + } +} + +Variant Control::get_drag_data(const Point2 &p_point) { + if (data.drag_owner.is_valid()) { + Object *obj = ObjectDB::get_instance(data.drag_owner); + if (obj) { + return obj->call("_get_drag_data_fw", p_point, this); + } + } + + Variant dd; + if (GDVIRTUAL_CALL(_get_drag_data, p_point, dd)) { + return dd; + } + + return Variant(); +} + +bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const { + if (data.drag_owner.is_valid()) { + Object *obj = ObjectDB::get_instance(data.drag_owner); + if (obj) { + return obj->call("_can_drop_data_fw", p_point, p_data, this); + } + } + + bool ret; + if (GDVIRTUAL_CALL(_can_drop_data, p_point, p_data, ret)) { + return ret; + } + return false; +} + +void Control::drop_data(const Point2 &p_point, const Variant &p_data) { + if (data.drag_owner.is_valid()) { + Object *obj = ObjectDB::get_instance(data.drag_owner); + if (obj) { + obj->call("_drop_data_fw", p_point, p_data, this); + return; + } + } + + GDVIRTUAL_CALL(_drop_data, p_point, p_data); +} + +void Control::force_drag(const Variant &p_data, Control *p_control) { + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND(p_data.get_type() == Variant::NIL); + + get_viewport()->_gui_force_drag(this, p_data, p_control); +} + +void Control::set_drag_preview(Control *p_control) { + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND(!get_viewport()->gui_is_dragging()); + get_viewport()->_gui_set_drag_preview(this, p_control); +} + +bool Control::is_drag_successful() const { + return is_inside_tree() && get_viewport()->gui_is_drag_successful(); } +// Focus. + void Control::set_focus_mode(FocusMode p_focus_mode) { ERR_FAIL_INDEX((int)p_focus_mode, 3); @@ -2342,6 +1787,41 @@ void Control::set_focus_mode(FocusMode p_focus_mode) { data.focus_mode = p_focus_mode; } +Control::FocusMode Control::get_focus_mode() const { + return data.focus_mode; +} + +bool Control::has_focus() const { + return is_inside_tree() && get_viewport()->_gui_control_has_focus(this); +} + +void Control::grab_focus() { + ERR_FAIL_COND(!is_inside_tree()); + + if (data.focus_mode == FOCUS_NONE) { + WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus."); + return; + } + + get_viewport()->_gui_control_grab_focus(this); +} + +void Control::grab_click_focus() { + ERR_FAIL_COND(!is_inside_tree()); + + get_viewport()->_gui_grab_click_focus(this); +} + +void Control::release_focus() { + ERR_FAIL_COND(!is_inside_tree()); + + if (!has_focus()) { + return; + } + + get_viewport()->gui_release_focus(); +} + static Control *_next_control(Control *p_from) { if (p_from->is_set_as_top_level()) { return nullptr; // Can't go above. @@ -2520,181 +2000,6 @@ Control *Control::find_prev_valid_focus() const { return nullptr; } -Control::FocusMode Control::get_focus_mode() const { - return data.focus_mode; -} - -bool Control::has_focus() const { - return is_inside_tree() && get_viewport()->_gui_control_has_focus(this); -} - -void Control::grab_focus() { - ERR_FAIL_COND(!is_inside_tree()); - - if (data.focus_mode == FOCUS_NONE) { - WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus."); - return; - } - - get_viewport()->_gui_control_grab_focus(this); -} - -void Control::release_focus() { - ERR_FAIL_COND(!is_inside_tree()); - - if (!has_focus()) { - return; - } - - get_viewport()->gui_release_focus(); -} - -bool Control::is_top_level_control() const { - return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_top_level()); -} - -void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { - Control *c = Object::cast_to<Control>(p_at); - - if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated - return; - } - - Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; - - if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated - return; - } - - for (int i = 0; i < p_at->get_child_count(); i++) { - CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); - if (child) { - _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); - } else { - Window *window = Object::cast_to<Window>(p_at->get_child(i)); - if (window) { - _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); - } - } - } - - if (c) { - if (p_assign) { - c->data.theme_owner = p_owner; - c->data.theme_owner_window = p_owner_window; - } - c->notification(Control::NOTIFICATION_THEME_CHANGED); - c->emit_signal(SceneStringNames::get_singleton()->theme_changed); - } - - if (w) { - if (p_assign) { - w->theme_owner = p_owner; - w->theme_owner_window = p_owner_window; - } - w->notification(Window::NOTIFICATION_THEME_CHANGED); - w->emit_signal(SceneStringNames::get_singleton()->theme_changed); - } -} - -void Control::_theme_changed() { - _propagate_theme_changed(this, this, nullptr, false); -} - -void Control::_notify_theme_changed() { - if (!data.bulk_theme_override) { - notification(NOTIFICATION_THEME_CHANGED); - } -} - -void Control::set_theme(const Ref<Theme> &p_theme) { - if (data.theme == p_theme) { - return; - } - - if (data.theme.is_valid()) { - data.theme->disconnect("changed", callable_mp(this, &Control::_theme_changed)); - } - - data.theme = p_theme; - if (!p_theme.is_null()) { - data.theme_owner = this; - data.theme_owner_window = nullptr; - _propagate_theme_changed(this, this, nullptr); - } else { - Control *parent_c = Object::cast_to<Control>(get_parent()); - - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); - } else { - Control::_propagate_theme_changed(this, nullptr, nullptr); - } - } - } - - if (data.theme.is_valid()) { - data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), varray(), CONNECT_DEFERRED); - } -} - -Ref<Theme> Control::get_theme() const { - return data.theme; -} - -void Control::set_theme_type_variation(const StringName &p_theme_type) { - data.theme_type_variation = p_theme_type; - _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); -} - -StringName Control::get_theme_type_variation() const { - return data.theme_type_variation; -} - -void Control::set_tooltip(const String &p_tooltip) { - data.tooltip = p_tooltip; - update_configuration_warnings(); -} - -String Control::get_tooltip(const Point2 &p_pos) const { - return data.tooltip; -} - -Control *Control::make_custom_tooltip(const String &p_text) const { - Object *ret = nullptr; - if (GDVIRTUAL_CALL(_make_custom_tooltip, p_text, ret)) { - return Object::cast_to<Control>(ret); - } - return nullptr; -} - -void Control::set_default_cursor_shape(CursorShape p_shape) { - ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX); - - data.default_cursor = p_shape; -} - -Control::CursorShape Control::get_default_cursor_shape() const { - return data.default_cursor; -} - -Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { - return data.default_cursor; -} - -Transform2D Control::get_transform() const { - Transform2D xform = _get_internal_transform(); - xform[2] += get_position(); - return xform; -} - -String Control::_get_tooltip() const { - return data.tooltip; -} - void Control::set_focus_neighbor(Side p_side, const NodePath &p_neighbor) { ERR_FAIL_INDEX((int)p_side, 4); data.focus_neighbor[p_side] = p_neighbor; @@ -2861,273 +2166,1011 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons } } -void Control::set_h_size_flags(int p_flags) { - if (data.h_size_flags == p_flags) { +// Rendering. + +void Control::set_default_cursor_shape(CursorShape p_shape) { + ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX); + + data.default_cursor = p_shape; +} + +Control::CursorShape Control::get_default_cursor_shape() const { + return data.default_cursor; +} + +Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { + return data.default_cursor; +} + +void Control::set_disable_visibility_clip(bool p_ignore) { + data.disable_visibility_clip = p_ignore; + update(); +} + +bool Control::is_visibility_clip_disabled() const { + return data.disable_visibility_clip; +} + +void Control::set_clip_contents(bool p_clip) { + data.clip_contents = p_clip; + update(); +} + +bool Control::is_clipping_contents() { + return data.clip_contents; +} + +// Theming. + +void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { + Control *c = Object::cast_to<Control>(p_at); + + if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated return; } - data.h_size_flags = p_flags; - emit_signal(SceneStringNames::get_singleton()->size_flags_changed); + + Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; + + if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated + return; + } + + for (int i = 0; i < p_at->get_child_count(); i++) { + CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); + if (child) { + _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); + } else { + Window *window = Object::cast_to<Window>(p_at->get_child(i)); + if (window) { + _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); + } + } + } + + if (c) { + if (p_assign) { + c->data.theme_owner = p_owner; + c->data.theme_owner_window = p_owner_window; + } + c->notification(Control::NOTIFICATION_THEME_CHANGED); + c->emit_signal(SceneStringNames::get_singleton()->theme_changed); + } + + if (w) { + if (p_assign) { + w->theme_owner = p_owner; + w->theme_owner_window = p_owner_window; + } + w->notification(Window::NOTIFICATION_THEME_CHANGED); + w->emit_signal(SceneStringNames::get_singleton()->theme_changed); + } } -int Control::get_h_size_flags() const { - return data.h_size_flags; +void Control::_theme_changed() { + _propagate_theme_changed(this, this, nullptr, false); } -void Control::set_v_size_flags(int p_flags) { - if (data.v_size_flags == p_flags) { - return; +void Control::_theme_property_override_changed() { + notification(NOTIFICATION_THEME_CHANGED); + emit_signal(SceneStringNames::get_singleton()->theme_changed); + update_minimum_size(); // Overrides are likely to affect minimum size. +} + +void Control::_notify_theme_changed() { + if (!data.bulk_theme_override) { + notification(NOTIFICATION_THEME_CHANGED); } - data.v_size_flags = p_flags; - emit_signal(SceneStringNames::get_singleton()->size_flags_changed); } -void Control::set_stretch_ratio(real_t p_ratio) { - if (data.expand == p_ratio) { +void Control::set_theme(const Ref<Theme> &p_theme) { + if (data.theme == p_theme) { return; } - data.expand = p_ratio; - emit_signal(SceneStringNames::get_singleton()->size_flags_changed); + if (data.theme.is_valid()) { + data.theme->disconnect("changed", callable_mp(this, &Control::_theme_changed)); + } + + data.theme = p_theme; + if (!p_theme.is_null()) { + data.theme_owner = this; + data.theme_owner_window = nullptr; + _propagate_theme_changed(this, this, nullptr); + } else { + Control *parent_c = Object::cast_to<Control>(get_parent()); + + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); + } else { + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); + } else { + Control::_propagate_theme_changed(this, nullptr, nullptr); + } + } + } + + if (data.theme.is_valid()) { + data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED); + } } -real_t Control::get_stretch_ratio() const { - return data.expand; +Ref<Theme> Control::get_theme() const { + return data.theme; } -void Control::grab_click_focus() { - ERR_FAIL_COND(!is_inside_tree()); +void Control::set_theme_type_variation(const StringName &p_theme_type) { + data.theme_type_variation = p_theme_type; + _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); +} - get_viewport()->_gui_grab_click_focus(this); +StringName Control::get_theme_type_variation() const { + return data.theme_type_variation; } -void Control::update_minimum_size() { - if (!is_inside_tree() || data.block_minimum_size_adjust) { - return; +/// Theme property lookup. + +template <class T> +T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { + ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified."); + + // First, look through each control or window node in the branch, until no valid parent can be found. + // Only nodes with a theme resource attached are considered. + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; + + while (theme_owner || theme_owner_window) { + // For each theme resource check the theme types provided and see if p_name exists with any of them. + for (const StringName &E : p_theme_types) { + if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) { + return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E); + } + + if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) { + return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E); + } + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + theme_owner = nullptr; + theme_owner_window = nullptr; + } + } } - Control *invalidate = this; + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + for (const StringName &E : p_theme_types) { + if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { + return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E); + } + } + } - //invalidate cache upwards - while (invalidate && invalidate->data.minimum_size_valid) { - invalidate->data.minimum_size_valid = false; - if (invalidate->is_set_as_top_level()) { - break; // do not go further up + // Lastly, fall back on the items defined in the default Theme, if they exist. + for (const StringName &E : p_theme_types) { + if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { + return Theme::get_default()->get_theme_item(p_data_type, p_name, E); } - if (!invalidate->data.parent && get_parent()) { - Window *parent_window = Object::cast_to<Window>(get_parent()); - if (parent_window && parent_window->is_wrapping_controls()) { - parent_window->child_controls_changed(); + } + // If they don't exist, use any type to return the default/empty value. + return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]); +} + +bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { + ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified."); + + // First, look through each control or window node in the branch, until no valid parent can be found. + // Only nodes with a theme resource attached are considered. + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; + + while (theme_owner || theme_owner_window) { + // For each theme resource check the theme types provided and see if p_name exists with any of them. + for (const StringName &E : p_theme_types) { + if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) { + return true; + } + + if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) { + return true; + } + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + theme_owner = nullptr; + theme_owner_window = nullptr; } } - invalidate = invalidate->data.parent; } - if (!is_visible_in_tree()) { - return; + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + for (const StringName &E : p_theme_types) { + if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { + return true; + } + } } - if (data.updating_last_minimum_size) { - return; + // Lastly, fall back on the items defined in the default Theme, if they exist. + for (const StringName &E : p_theme_types) { + if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { + return true; + } } + return false; +} - data.updating_last_minimum_size = true; +void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) { + Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); + } else { + Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); + } + } else { + Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); + } +} - MessageQueue::get_singleton()->push_call(this, "_update_minimum_size"); +Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); + if (tex) { + return *tex; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -int Control::get_v_size_flags() const { - return data.v_size_flags; +Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const Ref<StyleBox> *style = data.style_override.getptr(p_name); + if (style) { + return *style; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -void Control::set_mouse_filter(MouseFilter p_filter) { - ERR_FAIL_INDEX(p_filter, 3); - data.mouse_filter = p_filter; - notify_property_list_changed(); - update_configuration_warnings(); +Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const Ref<Font> *font = data.font_override.getptr(p_name); + if (font) { + return *font; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -Control::MouseFilter Control::get_mouse_filter() const { - return data.mouse_filter; +int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const int *font_size = data.font_size_override.getptr(p_name); + if (font_size && (*font_size) > 0) { + return *font_size; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } -void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) { - data.force_pass_scroll_events = p_force_pass_scroll_events; +Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const Color *color = data.color_override.getptr(p_name); + if (color) { + return *color; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); } -bool Control::is_force_pass_scroll_events() const { - return data.force_pass_scroll_events; +int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + const int *constant = data.constant_override.getptr(p_name); + if (constant) { + return *constant; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } -void Control::warp_mouse(const Point2 &p_position) { - ERR_FAIL_COND(!is_inside_tree()); - get_viewport()->warp_mouse(get_global_transform_with_canvas().xform(p_position)); +bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_icon_override(p_name)) { + return true; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -bool Control::is_text_field() const { - return false; +bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_stylebox_override(p_name)) { + return true; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { - if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) { - Array ret; - if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) { - return ret; - } else { - return Array(); +bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_font_override(p_name)) { + return true; } - } else { - return TS->parse_structured_text(p_parser_type, p_args, p_text); } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -void Control::set_rotation(real_t p_radians) { - data.rotation = p_radians; - update(); - _notify_transform(); +bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_font_size_override(p_name)) { + return true; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } -real_t Control::get_rotation() const { - return data.rotation; +bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_color_override(p_name)) { + return true; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); } -void Control::_override_changed() { - notification(NOTIFICATION_THEME_CHANGED); - emit_signal(SceneStringNames::get_singleton()->theme_changed); - update_minimum_size(); // Overrides are likely to affect minimum size. +bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (has_theme_constant_override(p_name)) { + return true; + } + } + + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } -void Control::set_pivot_offset(const Vector2 &p_pivot) { - data.pivot_offset = p_pivot; - update(); - _notify_transform(); +/// Local property overrides. + +void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { + ERR_FAIL_COND(!p_icon.is_valid()); + + if (data.icon_override.has(p_name)) { + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + } + + data.icon_override[p_name] = p_icon; + data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_changed(); } -Vector2 Control::get_pivot_offset() const { - return data.pivot_offset; +void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { + ERR_FAIL_COND(!p_style.is_valid()); + + if (data.style_override.has(p_name)) { + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + } + + data.style_override[p_name] = p_style; + data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_changed(); } -void Control::set_scale(const Vector2 &p_scale) { - data.scale = p_scale; - // Avoid having 0 scale values, can lead to errors in physics and rendering. - if (data.scale.x == 0) { - data.scale.x = CMP_EPSILON; +void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { + ERR_FAIL_COND(!p_font.is_valid()); + + if (data.font_override.has(p_name)) { + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); } - if (data.scale.y == 0) { - data.scale.y = CMP_EPSILON; + + data.font_override[p_name] = p_font; + data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_changed(); +} + +void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) { + data.font_size_override[p_name] = p_font_size; + _notify_theme_changed(); +} + +void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) { + data.color_override[p_name] = p_color; + _notify_theme_changed(); +} + +void Control::add_theme_constant_override(const StringName &p_name, int p_constant) { + data.constant_override[p_name] = p_constant; + _notify_theme_changed(); +} + +void Control::remove_theme_icon_override(const StringName &p_name) { + if (data.icon_override.has(p_name)) { + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); } - update(); - _notify_transform(); + + data.icon_override.erase(p_name); + _notify_theme_changed(); } -Vector2 Control::get_scale() const { - return data.scale; +void Control::remove_theme_style_override(const StringName &p_name) { + if (data.style_override.has(p_name)) { + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + } + + data.style_override.erase(p_name); + _notify_theme_changed(); } -Control *Control::get_root_parent_control() const { - const CanvasItem *ci = this; - const Control *root = this; +void Control::remove_theme_font_override(const StringName &p_name) { + if (data.font_override.has(p_name)) { + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + } - while (ci) { - const Control *c = Object::cast_to<Control>(ci); - if (c) { - root = c; + data.font_override.erase(p_name); + _notify_theme_changed(); +} - if (c->data.RI || c->is_top_level_control()) { - break; +void Control::remove_theme_font_size_override(const StringName &p_name) { + data.font_size_override.erase(p_name); + _notify_theme_changed(); +} + +void Control::remove_theme_color_override(const StringName &p_name) { + data.color_override.erase(p_name); + _notify_theme_changed(); +} + +void Control::remove_theme_constant_override(const StringName &p_name) { + data.constant_override.erase(p_name); + _notify_theme_changed(); +} + +bool Control::has_theme_icon_override(const StringName &p_name) const { + const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); + return tex != nullptr; +} + +bool Control::has_theme_stylebox_override(const StringName &p_name) const { + const Ref<StyleBox> *style = data.style_override.getptr(p_name); + return style != nullptr; +} + +bool Control::has_theme_font_override(const StringName &p_name) const { + const Ref<Font> *font = data.font_override.getptr(p_name); + return font != nullptr; +} + +bool Control::has_theme_font_size_override(const StringName &p_name) const { + const int *font_size = data.font_size_override.getptr(p_name); + return font_size != nullptr; +} + +bool Control::has_theme_color_override(const StringName &p_name) const { + const Color *color = data.color_override.getptr(p_name); + return color != nullptr; +} + +bool Control::has_theme_constant_override(const StringName &p_name) const { + const int *constant = data.constant_override.getptr(p_name); + return constant != nullptr; +} + +/// Default theme properties. + +float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window) { + // First, look through each control or window node in the branch, until no valid parent can be found. + // Only nodes with a theme resource attached are considered. + // For each theme resource see if their assigned theme has the default value defined and valid. + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; + + while (theme_owner || theme_owner_window) { + if (theme_owner && theme_owner->data.theme->has_default_base_scale()) { + return theme_owner->data.theme->get_default_base_scale(); + } + + if (theme_owner_window && theme_owner_window->theme->has_default_base_scale()) { + return theme_owner_window->theme->get_default_base_scale(); + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + theme_owner = nullptr; + theme_owner_window = nullptr; } } + } - ci = ci->get_parent_item(); + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_default_base_scale()) { + return Theme::get_project_default()->get_default_base_scale(); + } } - return const_cast<Control *>(root); + // Lastly, fall back on the default Theme. + if (Theme::get_default()->has_default_base_scale()) { + return Theme::get_default()->get_default_base_scale(); + } + return Theme::get_fallback_base_scale(); } -void Control::set_block_minimum_size_adjust(bool p_block) { - data.block_minimum_size_adjust = p_block; +float Control::get_theme_default_base_scale() const { + return fetch_theme_default_base_scale(data.theme_owner, data.theme_owner_window); } -bool Control::is_minimum_size_adjust_blocked() const { - return data.block_minimum_size_adjust; -} +Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window) { + // First, look through each control or window node in the branch, until no valid parent can be found. + // Only nodes with a theme resource attached are considered. + // For each theme resource see if their assigned theme has the default value defined and valid. + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; -void Control::set_disable_visibility_clip(bool p_ignore) { - data.disable_visibility_clip = p_ignore; - update(); + while (theme_owner || theme_owner_window) { + if (theme_owner && theme_owner->data.theme->has_default_font()) { + return theme_owner->data.theme->get_default_font(); + } + + if (theme_owner_window && theme_owner_window->theme->has_default_font()) { + return theme_owner_window->theme->get_default_font(); + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + theme_owner = nullptr; + theme_owner_window = nullptr; + } + } + } + + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_default_font()) { + return Theme::get_project_default()->get_default_font(); + } + } + + // Lastly, fall back on the default Theme. + if (Theme::get_default()->has_default_font()) { + return Theme::get_default()->get_default_font(); + } + return Theme::get_fallback_font(); } -bool Control::is_visibility_clip_disabled() const { - return data.disable_visibility_clip; +Ref<Font> Control::get_theme_default_font() const { + return fetch_theme_default_font(data.theme_owner, data.theme_owner_window); } -void Control::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - Node::get_argument_options(p_function, p_idx, r_options); +int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window) { + // First, look through each control or window node in the branch, until no valid parent can be found. + // Only nodes with a theme resource attached are considered. + // For each theme resource see if their assigned theme has the default value defined and valid. + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; - if (p_idx == 0) { - List<StringName> sn; - String pf = p_function; - if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") { - Theme::get_default()->get_color_list(get_class(), &sn); - } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") { - Theme::get_default()->get_stylebox_list(get_class(), &sn); - } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") { - Theme::get_default()->get_font_list(get_class(), &sn); - } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") { - Theme::get_default()->get_font_size_list(get_class(), &sn); - } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") { - Theme::get_default()->get_constant_list(get_class(), &sn); + while (theme_owner || theme_owner_window) { + if (theme_owner && theme_owner->data.theme->has_default_font_size()) { + return theme_owner->data.theme->get_default_font_size(); } - sn.sort_custom<StringName::AlphCompare>(); - for (const StringName &name : sn) { - r_options->push_back(String(name).quote()); + if (theme_owner_window && theme_owner_window->theme->has_default_font_size()) { + return theme_owner_window->theme->get_default_font_size(); + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + theme_owner = nullptr; + theme_owner_window = nullptr; + } } } + + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_default_font_size()) { + return Theme::get_project_default()->get_default_font_size(); + } + } + + // Lastly, fall back on the default Theme. + if (Theme::get_default()->has_default_font_size()) { + return Theme::get_default()->get_default_font_size(); + } + return Theme::get_fallback_font_size(); } -TypedArray<String> Control::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +int Control::get_theme_default_font_size() const { + return fetch_theme_default_font_size(data.theme_owner, data.theme_owner_window); +} - if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) { - warnings.push_back(RTR("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\".")); +/// Bulk actions. + +void Control::begin_bulk_theme_override() { + data.bulk_theme_override = true; +} + +void Control::end_bulk_theme_override() { + ERR_FAIL_COND(!data.bulk_theme_override); + + data.bulk_theme_override = false; + _notify_theme_changed(); +} + +// Internationalization. + +Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) { + Array ret; + if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) { + return ret; + } else { + return Array(); + } + } else { + return TS->parse_structured_text(p_parser_type, p_args, p_text); } +} - return warnings; +void Control::set_layout_direction(Control::LayoutDirection p_direction) { + ERR_FAIL_INDEX((int)p_direction, 4); + + data.layout_dir = p_direction; + data.is_rtl_dirty = true; + + propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED); } -void Control::set_clip_contents(bool p_clip) { - data.clip_contents = p_clip; - update(); +Control::LayoutDirection Control::get_layout_direction() const { + return data.layout_dir; } -bool Control::is_clipping_contents() { - return data.clip_contents; +bool Control::is_layout_rtl() const { + if (data.is_rtl_dirty) { + const_cast<Control *>(this)->data.is_rtl_dirty = false; + if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) { + Window *parent_window = get_parent_window(); + Control *parent_control = get_parent_control(); + if (parent_control) { + const_cast<Control *>(this)->data.is_rtl = parent_control->is_layout_rtl(); + } else if (parent_window) { + const_cast<Control *>(this)->data.is_rtl = parent_window->is_layout_rtl(); + } else { + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + const_cast<Control *>(this)->data.is_rtl = true; + } else { + String locale = TranslationServer::get_singleton()->get_tool_locale(); + const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + } + } + } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) { + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + const_cast<Control *>(this)->data.is_rtl = true; + } else { + String locale = TranslationServer::get_singleton()->get_tool_locale(); + const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + } + } else { + const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL); + } + } + return data.is_rtl; } -void Control::set_h_grow_direction(GrowDirection p_direction) { - ERR_FAIL_INDEX((int)p_direction, 3); +void Control::set_auto_translate(bool p_enable) { + if (p_enable == data.auto_translate) { + return; + } - data.h_grow = p_direction; - _size_changed(); + data.auto_translate = p_enable; + + notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); } -Control::GrowDirection Control::get_h_grow_direction() const { - return data.h_grow; +bool Control::is_auto_translating() const { + return data.auto_translate; } -void Control::set_v_grow_direction(GrowDirection p_direction) { - ERR_FAIL_INDEX((int)p_direction, 3); +// Extra properties. - data.v_grow = p_direction; - _size_changed(); +void Control::set_tooltip(const String &p_tooltip) { + data.tooltip = p_tooltip; + update_configuration_warnings(); } -Control::GrowDirection Control::get_v_grow_direction() const { - return data.v_grow; +String Control::_get_tooltip() const { + return data.tooltip; +} + +String Control::get_tooltip(const Point2 &p_pos) const { + return data.tooltip; +} + +Control *Control::make_custom_tooltip(const String &p_text) const { + Object *ret = nullptr; + if (GDVIRTUAL_CALL(_make_custom_tooltip, p_text, ret)) { + return Object::cast_to<Control>(ret); + } + return nullptr; +} + +// Base object overrides. + +void Control::add_child_notify(Node *p_child) { + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } +} + +void Control::remove_child_notify(Node *p_child) { + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { + _propagate_theme_changed(child_c, nullptr, nullptr); + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { + _propagate_theme_changed(child_w, nullptr, nullptr); + } +} + +void Control::_notification(int p_notification) { + switch (p_notification) { + case NOTIFICATION_POST_ENTER_TREE: { + data.minimum_size_valid = false; + data.is_rtl_dirty = true; + _size_changed(); + } break; + + case NOTIFICATION_EXIT_TREE: { + release_focus(); + get_viewport()->_gui_remove_control(this); + } break; + + case NOTIFICATION_READY: { +#ifdef DEBUG_ENABLED + connect("ready", callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONESHOT); +#endif + } break; + + case NOTIFICATION_ENTER_CANVAS: { + data.parent = Object::cast_to<Control>(get_parent()); + data.parent_window = Object::cast_to<Window>(get_parent()); + data.is_rtl_dirty = true; + + if (data.theme.is_null()) { + if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) { + data.theme_owner = data.parent->data.theme_owner; + data.theme_owner_window = data.parent->data.theme_owner_window; + notification(NOTIFICATION_THEME_CHANGED); + } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) { + data.theme_owner = data.parent_window->theme_owner; + data.theme_owner_window = data.parent_window->theme_owner_window; + notification(NOTIFICATION_THEME_CHANGED); + } + } + + CanvasItem *node = this; + bool has_parent_control = false; + + while (!node->is_set_as_top_level()) { + CanvasItem *parent = Object::cast_to<CanvasItem>(node->get_parent()); + if (!parent) { + break; + } + + Control *parent_control = Object::cast_to<Control>(parent); + if (parent_control) { + has_parent_control = true; + break; + } + + node = parent; + } + + if (has_parent_control) { + // Do nothing, has a parent control. + } else { + // Is a regular root control or top_level. + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + data.RI = viewport->_gui_add_root_control(this); + } + + data.parent_canvas_item = get_parent_item(); + + if (data.parent_canvas_item) { + data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed)); + } else { + // Connect viewport. + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->connect("size_changed", callable_mp(this, &Control::_size_changed)); + } + } break; + + case NOTIFICATION_EXIT_CANVAS: { + if (data.parent_canvas_item) { + data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed)); + data.parent_canvas_item = nullptr; + } else if (!is_set_as_top_level()) { + //disconnect viewport + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed)); + } + + if (data.RI) { + get_viewport()->_gui_remove_root_control(data.RI); + data.RI = nullptr; + } + + data.parent = nullptr; + data.parent_canvas_item = nullptr; + data.parent_window = nullptr; + data.is_rtl_dirty = true; + } break; + + case NOTIFICATION_MOVED_IN_PARENT: { + // some parents need to know the order of the children to draw (like TabContainer) + // update if necessary + if (data.parent) { + data.parent->update(); + } + update(); + + if (data.RI) { + get_viewport()->_gui_set_root_order_dirty(); + } + } break; + + case NOTIFICATION_RESIZED: { + emit_signal(SceneStringNames::get_singleton()->resized); + } break; + + case NOTIFICATION_DRAW: { + _update_canvas_item_transform(); + RenderingServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size())); + RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents); + } break; + + case NOTIFICATION_MOUSE_ENTER: { + emit_signal(SceneStringNames::get_singleton()->mouse_entered); + } break; + + case NOTIFICATION_MOUSE_EXIT: { + emit_signal(SceneStringNames::get_singleton()->mouse_exited); + } break; + + case NOTIFICATION_FOCUS_ENTER: { + emit_signal(SceneStringNames::get_singleton()->focus_entered); + update(); + } break; + + case NOTIFICATION_FOCUS_EXIT: { + emit_signal(SceneStringNames::get_singleton()->focus_exited); + update(); + } break; + + case NOTIFICATION_THEME_CHANGED: { + update_minimum_size(); + update(); + } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible_in_tree()) { + if (get_viewport() != nullptr) { + get_viewport()->_gui_hide_control(this); + } + } else { + data.minimum_size_valid = false; + _update_minimum_size(); + _size_changed(); + } + } break; + + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { + if (is_inside_tree()) { + data.is_rtl_dirty = true; + _size_changed(); + } + } break; + } } void Control::_bind_methods() { - //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event); ClassDB::bind_method(D_METHOD("_update_minimum_size"), &Control::_update_minimum_size); ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event); @@ -3300,7 +3343,7 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); - const String anchors_presets_options = "Custom:-1,PresetWide:15," + const String anchors_presets_options = "Custom:-1,PresetFullRect:15," "PresetTopLeft:0,PresetTopRight:1,PresetBottomRight:3,PresetBottomLeft:2," "PresetCenterLeft:4,PresetCenterTop:5,PresetCenterRight:6,PresetCenterBottom:7,PresetCenter:8," "PresetLeftWide:9,PresetTopWide:10,PresetRightWide:11,PresetBottomWide:12,PresetVCenterWide:13,PresetHCenterWide:14"; @@ -3408,7 +3451,7 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(PRESET_BOTTOM_WIDE); BIND_ENUM_CONSTANT(PRESET_VCENTER_WIDE); BIND_ENUM_CONSTANT(PRESET_HCENTER_WIDE); - BIND_ENUM_CONSTANT(PRESET_WIDE); + BIND_ENUM_CONSTANT(PRESET_FULL_RECT); BIND_ENUM_CONSTANT(PRESET_MODE_MINSIZE); BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_WIDTH); diff --git a/scene/gui/control.h b/scene/gui/control.h index f18dd99bff..9f17eccc3b 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -116,7 +116,7 @@ public: PRESET_BOTTOM_WIDE, PRESET_VCENTER_WIDE, PRESET_HCENTER_WIDE, - PRESET_WIDE + PRESET_FULL_RECT }; enum LayoutPresetMode { @@ -159,13 +159,16 @@ private: }; struct Data { - Point2 pos_cache; - Size2 size_cache; - Size2 minimum_size_cache; - bool minimum_size_valid = false; + // Global relations. - Size2 last_minimum_size; - bool updating_last_minimum_size = false; + List<Control *>::Element *RI = nullptr; + + Control *parent = nullptr; + Window *parent_window = nullptr; + CanvasItem *parent_canvas_item = nullptr; + ObjectID drag_owner; + + // Positioning and sizing. real_t offset[4] = { 0.0, 0.0, 0.0, 0.0 }; real_t anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN }; @@ -173,49 +176,51 @@ private: GrowDirection h_grow = GROW_DIRECTION_END; GrowDirection v_grow = GROW_DIRECTION_END; - LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED; - bool is_rtl_dirty = true; - bool is_rtl = false; - - bool auto_translate = true; - real_t rotation = 0.0; Vector2 scale = Vector2(1, 1); Vector2 pivot_offset; + + Point2 pos_cache; + Size2 size_cache; + Size2 minimum_size_cache; + bool minimum_size_valid = false; + + Size2 last_minimum_size; + bool updating_last_minimum_size = false; + bool block_minimum_size_adjust = false; + bool size_warning = true; + // Container sizing. + int h_size_flags = SIZE_FILL; int v_size_flags = SIZE_FILL; real_t expand = 1.0; Point2 custom_minimum_size; + // Input events and rendering. + MouseFilter mouse_filter = MOUSE_FILTER_STOP; bool force_pass_scroll_events = true; bool clip_contents = false; - - bool block_minimum_size_adjust = false; bool disable_visibility_clip = false; - Control *parent = nullptr; - ObjectID drag_owner; - Ref<Theme> theme; - Control *theme_owner = nullptr; - Window *theme_owner_window = nullptr; - Window *parent_window = nullptr; - StringName theme_type_variation; - - String tooltip; CursorShape default_cursor = CURSOR_ARROW; - List<Control *>::Element *RI = nullptr; - - CanvasItem *parent_canvas_item = nullptr; + // Focus. NodePath focus_neighbor[4]; NodePath focus_next; NodePath focus_prev; + // Theming. + + Ref<Theme> theme; + Control *theme_owner = nullptr; + Window *theme_owner_window = nullptr; + StringName theme_type_variation; + bool bulk_theme_override = false; Theme::ThemeIconMap icon_override; Theme::ThemeStyleMap style_override; @@ -224,50 +229,69 @@ private: Theme::ThemeColorMap color_override; Theme::ThemeConstantMap constant_override; + // Internationalization. + + LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED; + bool is_rtl_dirty = true; + bool is_rtl = false; + + bool auto_translate = true; + + // Extra properties. + + String tooltip; + } data; + // Dynamic properties. + static constexpr unsigned properties_managed_by_container_count = 12; static String properties_managed_by_container[properties_managed_by_container_count]; - void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest); - Control *_get_focus_neighbor(Side p_side, int p_count = 0); + // Global relations. + + friend class Viewport; + friend class Window; + + // Positioning and sizing. + + void _update_canvas_item_transform(); + Transform2D _get_internal_transform() const; void _set_anchor(Side p_side, real_t p_anchor); void _set_position(const Point2 &p_point); void _set_global_position(const Point2 &p_point); void _set_size(const Size2 &p_size); + void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]); + void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]); + void _set_layout_mode(LayoutMode p_mode); LayoutMode _get_layout_mode() const; - void _set_anchors_layout_preset(int p_preset); int _get_anchors_layout_preset() const; - void _theme_changed(); - void _notify_theme_changed(); - + void _update_minimum_size_cache(); void _update_minimum_size(); + void _size_changed(); void _clear_size_warning(); - void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]); - void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]); - - void _size_changed(); - String _get_tooltip() const; + // Input events. - void _override_changed(); + void _call_gui_input(const Ref<InputEvent> &p_event); - void _update_canvas_item_transform(); + // Focus. - Transform2D _get_internal_transform() const; + void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest); + Control *_get_focus_neighbor(Side p_side, int p_count = 0); - friend class Viewport; + // Theming. - void _call_gui_input(const Ref<InputEvent> &p_event); + void _theme_changed(); + void _theme_property_override_changed(); + void _notify_theme_changed(); - void _update_minimum_size_cache(); - friend class Window; static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); template <class T> @@ -275,24 +299,31 @@ private: static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const; -protected: - virtual void add_child_notify(Node *p_child) override; - virtual void remove_child_notify(Node *p_child) override; + // Extra properties. - //virtual void _window_gui_input(InputEvent p_event); + String _get_tooltip() const; - virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; +protected: + // Dynamic properties. bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; - virtual void _validate_property(PropertyInfo &property) const override; + // Internationalization. + + virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; + + // Base object overrides. + + virtual void add_child_notify(Node *p_child) override; + virtual void remove_child_notify(Node *p_child) override; + void _notification(int p_notification); static void _bind_methods(); - //bind helpers + // Exposed virtual methods. GDVIRTUAL1RC(bool, _has_point, Vector2) GDVIRTUAL2RC(Array, _structured_text_parser, Array, String) @@ -307,8 +338,6 @@ protected: public: enum { - /* NOTIFICATION_DRAW=30, - NOTIFICATION_VISIBILITY_CHANGED=38*/ NOTIFICATION_RESIZED = 40, NOTIFICATION_MOUSE_ENTER = 41, NOTIFICATION_MOUSE_EXIT = 42, @@ -318,10 +347,11 @@ public: NOTIFICATION_SCROLL_BEGIN = 47, NOTIFICATION_SCROLL_END = 48, NOTIFICATION_LAYOUT_DIRECTION_CHANGED = 49, - }; - /* EDITOR */ + // Editor plugin interoperability. + + // TODO: Decouple controls from their editor plugin and get rid of this. #ifdef TOOLS_ENABLED virtual Dictionary _edit_get_state() const override; virtual void _edit_set_state(const Dictionary &p_state) override; @@ -347,56 +377,50 @@ public: virtual Size2 _edit_get_minimum_size() const override; #endif - virtual void gui_input(const Ref<InputEvent> &p_event); + // Editor integration. - void accept_event(); + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; + TypedArray<String> get_configuration_warnings() const override; - virtual Size2 get_minimum_size() const; - virtual Size2 get_combined_minimum_size() const; - virtual bool has_point(const Point2 &p_point) const; - virtual void set_drag_forwarding(Object *p_target); - virtual Variant get_drag_data(const Point2 &p_point); - virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; - virtual void drop_data(const Point2 &p_point, const Variant &p_data); - void set_drag_preview(Control *p_control); - void force_drag(const Variant &p_data, Control *p_control); - bool is_drag_successful() const; + virtual bool is_text_field() const; - void set_custom_minimum_size(const Size2 &p_custom); - Size2 get_custom_minimum_size() const; + // Global relations. + + bool is_top_level_control() const; Control *get_parent_control() const; Window *get_parent_window() const; + Control *get_root_parent_control() const; - void set_layout_direction(LayoutDirection p_direction); - LayoutDirection get_layout_direction() const; - virtual bool is_layout_rtl() const; - - void set_auto_translate(bool p_enable); - bool is_auto_translating() const; - _FORCE_INLINE_ String atr(const String p_string) const { return is_auto_translating() ? tr(p_string) : p_string; }; + Size2 get_parent_area_size() const; + Rect2 get_parent_anchorable_rect() const; - /* POSITIONING */ + // Positioning and sizing. - void set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets = true); - void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); - void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); - void set_grow_direction_preset(LayoutPreset p_preset); + virtual Transform2D get_transform() const override; void set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true); real_t get_anchor(Side p_side) const; - void set_offset(Side p_side, real_t p_value); real_t get_offset(Side p_side) const; - void set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor = true); - void set_begin(const Point2 &p_point); // helper - void set_end(const Point2 &p_point); // helper - + // TODO: Rename to set_begin/end_offsets ? + void set_begin(const Point2 &p_point); Point2 get_begin() const; + void set_end(const Point2 &p_point); Point2 get_end() const; + void set_h_grow_direction(GrowDirection p_direction); + GrowDirection get_h_grow_direction() const; + void set_v_grow_direction(GrowDirection p_direction); + GrowDirection get_v_grow_direction() const; + + void set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets = true); + void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); + void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); + void set_grow_direction_preset(LayoutPreset p_preset); + void set_position(const Point2 &p_point, bool p_keep_offsets = false); void set_global_position(const Point2 &p_point, bool p_keep_offsets = false); Point2 get_position() const; @@ -407,52 +431,72 @@ public: Size2 get_size() const; void reset_size(); + void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting. Rect2 get_rect() const; Rect2 get_global_rect() const; Rect2 get_screen_rect() const; Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the rendering server Rect2 get_anchorable_rect() const override; - void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting. - + void set_scale(const Vector2 &p_scale); + Vector2 get_scale() const; void set_rotation(real_t p_radians); real_t get_rotation() const; - - void set_h_grow_direction(GrowDirection p_direction); - GrowDirection get_h_grow_direction() const; - - void set_v_grow_direction(GrowDirection p_direction); - GrowDirection get_v_grow_direction() const; - void set_pivot_offset(const Vector2 &p_pivot); Vector2 get_pivot_offset() const; - void set_scale(const Vector2 &p_scale); - Vector2 get_scale() const; + void update_minimum_size(); - void set_theme(const Ref<Theme> &p_theme); - Ref<Theme> get_theme() const; + void set_block_minimum_size_adjust(bool p_block); + bool is_minimum_size_adjust_blocked() const; - void set_theme_type_variation(const StringName &p_theme_type); - StringName get_theme_type_variation() const; + virtual Size2 get_minimum_size() const; + virtual Size2 get_combined_minimum_size() const; + + void set_custom_minimum_size(const Size2 &p_custom); + Size2 get_custom_minimum_size() const; + + // Container sizing. void set_h_size_flags(int p_flags); int get_h_size_flags() const; - void set_v_size_flags(int p_flags); int get_v_size_flags() const; - void set_stretch_ratio(real_t p_ratio); real_t get_stretch_ratio() const; - void update_minimum_size(); + // Input events. + + virtual void gui_input(const Ref<InputEvent> &p_event); + void accept_event(); + + virtual bool has_point(const Point2 &p_point) const; + + void set_mouse_filter(MouseFilter p_filter); + MouseFilter get_mouse_filter() const; + + void set_force_pass_scroll_events(bool p_force_pass_scroll_events); + bool is_force_pass_scroll_events() const; + + void warp_mouse(const Point2 &p_position); + + // Drag and drop handling. + + virtual void set_drag_forwarding(Object *p_target); + virtual Variant get_drag_data(const Point2 &p_point); + virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; + virtual void drop_data(const Point2 &p_point, const Variant &p_data); + void set_drag_preview(Control *p_control); + void force_drag(const Variant &p_data, Control *p_control); + bool is_drag_successful() const; - /* FOCUS */ + // Focus. void set_focus_mode(FocusMode p_focus_mode); FocusMode get_focus_mode() const; bool has_focus() const; void grab_focus(); + void grab_click_focus(); void release_focus(); Control *find_next_valid_focus() const; @@ -466,13 +510,25 @@ public: void set_focus_previous(const NodePath &p_prev); NodePath get_focus_previous() const; - void set_mouse_filter(MouseFilter p_filter); - MouseFilter get_mouse_filter() const; + // Rendering. - void set_force_pass_scroll_events(bool p_force_pass_scroll_events); - bool is_force_pass_scroll_events() const; + void set_default_cursor_shape(CursorShape p_shape); + CursorShape get_default_cursor_shape() const; + virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const; + + void set_clip_contents(bool p_clip); + bool is_clipping_contents(); - /* SKINNING */ + void set_disable_visibility_clip(bool p_ignore); + bool is_visibility_clip_disabled() const; + + // Theming. + + void set_theme(const Ref<Theme> &p_theme); + Ref<Theme> get_theme() const; + + void set_theme_type_variation(const StringName &p_theme_type); + StringName get_theme_type_variation() const; void begin_bulk_theme_override(); void end_bulk_theme_override(); @@ -520,44 +576,23 @@ public: Ref<Font> get_theme_default_font() const; int get_theme_default_font_size() const; - /* TOOLTIP */ - - void set_tooltip(const String &p_tooltip); - virtual String get_tooltip(const Point2 &p_pos) const; - virtual Control *make_custom_tooltip(const String &p_text) const; - - /* CURSOR */ - - void set_default_cursor_shape(CursorShape p_shape); - CursorShape get_default_cursor_shape() const; - virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const; - - virtual Transform2D get_transform() const override; - - bool is_top_level_control() const; + // Internationalization. - Size2 get_parent_area_size() const; - Rect2 get_parent_anchorable_rect() const; - - void grab_click_focus(); - - void warp_mouse(const Point2 &p_position); - - virtual bool is_text_field() const; - - Control *get_root_parent_control() const; - - void set_clip_contents(bool p_clip); - bool is_clipping_contents(); + void set_layout_direction(LayoutDirection p_direction); + LayoutDirection get_layout_direction() const; + virtual bool is_layout_rtl() const; - void set_block_minimum_size_adjust(bool p_block); - bool is_minimum_size_adjust_blocked() const; + void set_auto_translate(bool p_enable); + bool is_auto_translating() const; + _FORCE_INLINE_ String atr(const String p_string) const { + return is_auto_translating() ? tr(p_string) : p_string; + }; - void set_disable_visibility_clip(bool p_ignore); - bool is_visibility_clip_disabled() const; + // Extra properties. - virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; - TypedArray<String> get_configuration_warnings() const override; + void set_tooltip(const String &p_tooltip); + virtual String get_tooltip(const Point2 &p_pos) const; + virtual Control *make_custom_tooltip(const String &p_text) const; Control() {} }; @@ -574,4 +609,4 @@ VARIANT_ENUM_CAST(Control::LayoutMode); VARIANT_ENUM_CAST(Control::LayoutDirection); VARIANT_ENUM_CAST(Control::TextDirection); -#endif +#endif // CONTROL_H diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 44e2bb89eb..942b7d0bf9 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -261,7 +261,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin } if (!p_action.is_empty()) { - button->connect("pressed", callable_mp(this, &AcceptDialog::_custom_action), varray(p_action)); + button->connect("pressed", callable_mp(this, &AcceptDialog::_custom_action).bind(p_action)); } return button; diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index 711361de88..9ebf5ddfb2 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -120,4 +120,4 @@ public: ConfirmationDialog(); }; -#endif +#endif // DIALOGS_H diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 8ec930b753..e26976a402 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -1060,7 +1060,7 @@ FileDialog::FileDialog() { message = memnew(Label); message->hide(); - message->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + message->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); message->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); tree->add_child(message); @@ -1083,9 +1083,9 @@ FileDialog::FileDialog() { _update_drives(); connect("confirmed", callable_mp(this, &FileDialog::_action_pressed)); - tree->connect("multi_selected", callable_mp(this, &FileDialog::_tree_multi_selected), varray(), CONNECT_DEFERRED); - tree->connect("cell_selected", callable_mp(this, &FileDialog::_tree_selected), varray(), CONNECT_DEFERRED); - tree->connect("item_activated", callable_mp(this, &FileDialog::_tree_item_activated), varray()); + tree->connect("multi_selected", callable_mp(this, &FileDialog::_tree_multi_selected), CONNECT_DEFERRED); + tree->connect("cell_selected", callable_mp(this, &FileDialog::_tree_selected), CONNECT_DEFERRED); + tree->connect("item_activated", callable_mp(this, &FileDialog::_tree_item_activated)); tree->connect("nothing_selected", callable_mp(this, &FileDialog::deselect_all)); dir->connect("text_submitted", callable_mp(this, &FileDialog::_dir_submitted)); file->connect("text_submitted", callable_mp(this, &FileDialog::_file_submitted)); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 017c9d8d4f..4945094086 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -196,4 +196,4 @@ public: VARIANT_ENUM_CAST(FileDialog::FileMode); VARIANT_ENUM_CAST(FileDialog::Access); -#endif +#endif // FILE_DIALOG_H diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 9459bed63b..cc27a6b7c2 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -437,6 +437,10 @@ ColorPicker *GradientEdit::get_picker() { return picker; } +PopupPanel *GradientEdit::get_popup() { + return popup; +} + void GradientEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("ramp_changed")); } diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index 3badcd45ba..b7c99f1f1c 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -75,6 +75,7 @@ public: void set_interpolation_mode(Gradient::InterpolationMode p_interp_mode); Gradient::InterpolationMode get_interpolation_mode(); ColorPicker *get_picker(); + PopupPanel *get_popup(); virtual Size2 get_minimum_size() const override; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index c219eafbf7..09efee71a3 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -382,9 +382,9 @@ void GraphEdit::add_child_notify(Node *p_child) { GraphNode *gn = Object::cast_to<GraphNode>(p_child); if (gn) { gn->set_scale(Vector2(zoom, zoom)); - gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved), varray(gn)); - gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated), varray(gn)); - gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised), varray(gn)); + gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved).bind(gn)); + gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated).bind(gn)); + gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised).bind(gn)); gn->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update)); gn->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update)); _graph_node_moved(gn); @@ -710,6 +710,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { int type = gn->get_connection_output_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_output_hotzone(gn, j, mpos, port_size)) { + if (!is_node_hover_valid(gn->get_name(), j, connecting_from, connecting_index)) { + continue; + } connecting_target = true; connecting_to = pos; connecting_target_to = gn->get_name(); @@ -725,6 +728,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { int type = gn->get_connection_input_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_input_hotzone(gn, j, mpos, port_size)) { + if (!is_node_hover_valid(connecting_from, connecting_index, gn->get_name(), j)) { + continue; + } connecting_target = true; connecting_to = pos; connecting_target_to = gn->get_name(); @@ -1453,6 +1459,14 @@ void GraphEdit::force_connection_drag_end() { emit_signal(SNAME("connection_drag_ended")); } +bool GraphEdit::is_node_hover_valid(const StringName &p_from, const int p_from_port, const StringName &p_to, const int p_to_port) { + bool valid; + if (GDVIRTUAL_CALL(_is_node_hover_valid, p_from, p_from_port, p_to, p_to_port, valid)) { + return valid; + } + return true; +} + void GraphEdit::set_panning_scheme(PanningScheme p_scheme) { panning_scheme = p_scheme; panner->set_control_scheme((ViewPanner::ControlScheme)p_scheme); @@ -1809,7 +1823,20 @@ HashMap<int, Vector<StringName>> GraphEdit::_layering(const HashSet<StringName> } if (!selected) { current_layer++; + uint32_t previous_size_z = z.size(); _set_operations(GraphEdit::UNION, z, u); + if (z.size() == previous_size_z) { + WARN_PRINT("Graph contains cycle(s). The cycle(s) will not be rearranged accurately."); + Vector<StringName> t; + if (l.has(0)) { + t.append_array(l[0]); + } + for (const StringName &E : p) { + t.push_back(E); + } + l.insert(0, t); + break; + } } selected = false; } @@ -2124,7 +2151,7 @@ void GraphEdit::arrange_nodes() { HashSet<StringName> s; for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from]); - if (E->get().to == gn->get_name() && p_from->is_selected()) { + if (E->get().to == gn->get_name() && p_from->is_selected() && E->get().to != E->get().from) { if (!s.has(p_from->get_name())) { s.insert(p_from->get_name()); } @@ -2315,6 +2342,7 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected); GDVIRTUAL_BIND(_get_connection_line, "from", "to") + GDVIRTUAL_BIND(_is_node_hover_valid, "from", "from_slot", "to", "to_slot"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_ofs", "get_scroll_ofs"); @@ -2376,7 +2404,7 @@ GraphEdit::GraphEdit() { top_layer = memnew(GraphEditFilter(this)); add_child(top_layer, false, INTERNAL_MODE_BACK); top_layer->set_mouse_filter(MOUSE_FILTER_PASS); - top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + top_layer->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw)); top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input)); top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 02e90e4717..cf35aeb8b2 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -280,6 +280,7 @@ protected: GDVIRTUAL2RC(Vector<Vector2>, _get_connection_line, Vector2, Vector2) GDVIRTUAL3R(bool, _is_in_input_hotzone, Object *, int, Vector2) GDVIRTUAL3R(bool, _is_in_output_hotzone, Object *, int, Vector2) + GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int); public: Error connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); @@ -287,6 +288,7 @@ public: void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); void clear_connections(); void force_connection_drag_end(); + virtual bool is_node_hover_valid(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity); @@ -365,4 +367,4 @@ public: VARIANT_ENUM_CAST(GraphEdit::PanningScheme); -#endif // GRAPHEdit_H +#endif // GRAPH_EDIT_H diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 92016ca42e..112b8c74af 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -450,7 +450,7 @@ void GraphNode::_validate_property(PropertyInfo &property) const { Control::_validate_property(property); GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent()); if (graph) { - if (property.name == "rect_position") { + if (property.name == "position") { property.usage |= PROPERTY_USAGE_READ_ONLY; } } @@ -1051,6 +1051,7 @@ void GraphNode::_bind_methods() { ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); + ADD_GROUP("", ""); ADD_SIGNAL(MethodInfo("position_offset_changed")); ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "idx"))); diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 6f8518a7b0..eaa6943ad2 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -41,8 +41,6 @@ void GridContainer::_notification(int p_what) { int hsep = get_theme_constant(SNAME("h_separation")); int vsep = get_theme_constant(SNAME("v_separation")); - int max_col = MIN(get_child_count(), columns); - int max_row = ceil((float)get_child_count() / (float)columns); // Compute the per-column/per-row data. int valid_controls_index = 0; @@ -79,6 +77,9 @@ void GridContainer::_notification(int p_what) { } } + int max_col = MIN(valid_controls_index, columns); + int max_row = ceil((float)valid_controls_index / (float)columns); + // Consider all empty columns expanded. for (int i = valid_controls_index; i < columns; i++) { col_expanded.insert(i); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 1d4ca4d196..d0a25972f8 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -45,9 +45,9 @@ void ItemList::_shape(int p_idx) { } item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language); if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) { - item.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); + item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); } else { - item.text_buf->set_flags(TextServer::BREAK_NONE); + item.text_buf->set_break_flags(TextServer::BREAK_NONE); } item.text_buf->set_text_overrun_behavior(text_overrun_behavior); item.text_buf->set_max_lines_visible(max_text_lines); @@ -470,10 +470,10 @@ void ItemList::set_max_text_lines(int p_lines) { max_text_lines = p_lines; for (int i = 0; i < items.size(); i++) { if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) { - items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); + items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); items.write[i].text_buf->set_max_lines_visible(p_lines); } else { - items.write[i].text_buf->set_flags(TextServer::BREAK_NONE); + items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE); } } shape_changed = true; @@ -511,9 +511,9 @@ void ItemList::set_icon_mode(IconMode p_mode) { icon_mode = p_mode; for (int i = 0; i < items.size(); i++) { if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) { - items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); + items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND); } else { - items.write[i].text_buf->set_flags(TextServer::BREAK_NONE); + items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE); } } shape_changed = true; diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index c7d87da0b5..21bd22759c 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ITEMLIST_H -#define ITEMLIST_H +#ifndef ITEM_LIST_H +#define ITEM_LIST_H #include "scene/gui/control.h" #include "scene/gui/scroll_bar.h" @@ -259,4 +259,4 @@ public: VARIANT_ENUM_CAST(ItemList::SelectMode); VARIANT_ENUM_CAST(ItemList::IconMode); -#endif // ITEMLIST_H +#endif // ITEM_LIST_H diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 5dec1df4a5..e7f48beb00 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -31,6 +31,7 @@ #include "label.h" #include "core/config/project_settings.h" +#include "core/core_string_names.h" #include "core/string/print_string.h" #include "core/string/translation.h" @@ -64,7 +65,7 @@ bool Label::is_uppercase() const { } int Label::get_line_height(int p_line) const { - Ref<Font> font = get_theme_font(SNAME("font")); + Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font")); if (p_line >= 0 && p_line < lines_rid.size()) { return TS->shaped_text_get_size(lines_rid[p_line]).y; } else if (lines_rid.size() > 0) { @@ -74,7 +75,8 @@ int Label::get_line_height(int p_line) const { } return h; } else { - return font->get_height(get_theme_font_size(SNAME("font_size"))); + int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size")); + return font->get_height(font_size); } } @@ -91,8 +93,8 @@ void Label::_shape() { } else { TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction); } - const Ref<Font> &font = get_theme_font(SNAME("font")); - int font_size = get_theme_font_size(SNAME("font_size")); + const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font")); + int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size")); ERR_FAIL_COND(font.is_null()); String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { @@ -121,10 +123,10 @@ void Label::_shape() { } lines_rid.clear(); - uint16_t autowrap_flags = TextServer::BREAK_MANDATORY; + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; switch (autowrap_mode) { case TextServer::AUTOWRAP_WORD_SMART: - autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; break; case TextServer::AUTOWRAP_WORD: autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; @@ -158,23 +160,23 @@ void Label::_shape() { } if (lines_dirty) { - uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM; + BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; switch (overrun_behavior) { case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_WORD: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); break; case TextServer::OVERRUN_TRIM_CHAR: - overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); break; case TextServer::OVERRUN_NO_TRIMMING: break; @@ -186,7 +188,7 @@ void Label::_shape() { int visible_lines = get_visible_line_count(); bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size(); if (lines_hidden) { - overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); } if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { for (int i = 0; i < lines_rid.size(); i++) { @@ -204,7 +206,7 @@ void Label::_shape() { for (int i = 0; i < lines_rid.size(); i++) { if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { TS->shaped_text_fit_to_width(lines_rid[i], width); - overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE; + overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); } else { @@ -223,9 +225,8 @@ void Label::_shape() { } void Label::_update_visible() { - int line_spacing = get_theme_constant(SNAME("line_spacing"), SNAME("Label")); + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"), SNAME("Label")); Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label")); - Ref<Font> font = get_theme_font(SNAME("font")); int lines_visible = lines_rid.size(); if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { @@ -295,17 +296,19 @@ void Label::_notification(int p_what) { RID ci = get_canvas_item(); + bool has_settings = settings.is_valid(); + Size2 string_size; Size2 size = get_size(); Ref<StyleBox> style = get_theme_stylebox(SNAME("normal")); - Ref<Font> font = get_theme_font(SNAME("font")); - Color font_color = get_theme_color(SNAME("font_color")); - Color font_shadow_color = get_theme_color(SNAME("font_shadow_color")); - Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y"))); - int line_spacing = get_theme_constant(SNAME("line_spacing")); - Color font_outline_color = get_theme_color(SNAME("font_outline_color")); - int outline_size = get_theme_constant(SNAME("outline_size")); - int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size")); + Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font")); + Color font_color = has_settings ? settings->get_font_color() : get_theme_color(SNAME("font_color")); + Color font_shadow_color = has_settings ? settings->get_shadow_color() : get_theme_color(SNAME("font_shadow_color")); + Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y"))); + int line_spacing = has_settings ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing")); + Color font_outline_color = has_settings ? settings->get_outline_color() : get_theme_color(SNAME("font_outline_color")); + int outline_size = has_settings ? settings->get_outline_size() : get_theme_constant(SNAME("outline_size")); + int shadow_outline_size = has_settings ? settings->get_shadow_size() : get_theme_constant(SNAME("shadow_outline_size")); bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL); bool rtl_layout = is_layout_rtl(); @@ -552,8 +555,10 @@ Size2 Label::get_minimum_size() const { Size2 min_size = minsize; - Ref<Font> font = get_theme_font(SNAME("font")); - min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size")))); + const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font")); + int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size")); + + min_size.height = MAX(min_size.height, font->get_height(font_size) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM)); Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size(); if (autowrap_mode != TextServer::AUTOWRAP_OFF) { @@ -578,9 +583,8 @@ int Label::get_line_count() const { } int Label::get_visible_line_count() const { - Ref<Font> font = get_theme_font(SNAME("font")); Ref<StyleBox> style = get_theme_stylebox(SNAME("normal")); - int line_spacing = get_theme_constant(SNAME("line_spacing")); + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing")); int lines_visible = 0; float total_h = 0.0; for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { @@ -641,6 +645,28 @@ void Label::set_text(const String &p_string) { update_minimum_size(); } +void Label::_invalidate() { + font_dirty = true; + update(); +} + +void Label::set_label_settings(const Ref<LabelSettings> &p_settings) { + if (settings != p_settings) { + if (settings.is_valid()) { + settings->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Label::_invalidate)); + } + settings = p_settings; + if (settings.is_valid()) { + settings->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Label::_invalidate), CONNECT_REFERENCE_COUNTED); + } + _invalidate(); + } +} + +Ref<LabelSettings> Label::get_label_settings() const { + return settings; +} + void Label::set_text_direction(Control::TextDirection p_text_direction) { ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); if (text_direction != p_text_direction) { @@ -804,6 +830,8 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &Label::get_vertical_alignment); ClassDB::bind_method(D_METHOD("set_text", "text"), &Label::set_text); ClassDB::bind_method(D_METHOD("get_text"), &Label::get_text); + ClassDB::bind_method(D_METHOD("set_label_settings", "settings"), &Label::set_label_settings); + ClassDB::bind_method(D_METHOD("get_label_settings"), &Label::get_label_settings); ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label::set_text_direction); ClassDB::bind_method(D_METHOD("get_text_direction"), &Label::get_text_direction); ClassDB::bind_method(D_METHOD("set_language", "language"), &Label::set_language); @@ -836,6 +864,7 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &Label::get_structured_text_bidi_override_options); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "label_settings", PROPERTY_HINT_RESOURCE_TYPE, "LabelSettings"), "set_label_settings", "get_label_settings"); ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_vertical_alignment", "get_vertical_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); diff --git a/scene/gui/label.h b/scene/gui/label.h index a59d35950d..cab5b36d68 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -32,6 +32,7 @@ #define LABEL_H #include "scene/gui/control.h" +#include "scene/resources/label_settings.h" class Label : public Control { GDCLASS(Label, Control); @@ -65,8 +66,11 @@ private: int lines_skipped = 0; int max_lines_visible = -1; + Ref<LabelSettings> settings; + void _update_visible(); void _shape(); + void _invalidate(); protected: void _notification(int p_what); @@ -85,6 +89,9 @@ public: void set_text(const String &p_string); String get_text() const; + void set_label_settings(const Ref<LabelSettings> &p_settings); + Ref<LabelSettings> get_label_settings() const; + void set_text_direction(TextDirection p_text_direction); TextDirection get_text_direction() const; @@ -133,4 +140,4 @@ public: ~Label(); }; -#endif +#endif // LABEL_H diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 39f8f23cd8..f315b2bbf1 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1513,9 +1513,9 @@ void LineEdit::clear() { void LineEdit::show_virtual_keyboard() { if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) { if (selection.enabled) { - DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), false, max_length, selection.begin, selection.end); + DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), DisplayServer::VirtualKeyboardType(virtual_keyboard_type), max_length, selection.begin, selection.end); } else { - DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), false, max_length, caret_column); + DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), DisplayServer::VirtualKeyboardType(virtual_keyboard_type), max_length, caret_column); } } } @@ -2040,6 +2040,14 @@ bool LineEdit::is_virtual_keyboard_enabled() const { return virtual_keyboard_enabled; } +void LineEdit::set_virtual_keyboard_type(VirtualKeyboardType p_type) { + virtual_keyboard_type = p_type; +} + +LineEdit::VirtualKeyboardType LineEdit::get_virtual_keyboard_type() const { + return virtual_keyboard_type; +} + void LineEdit::set_middle_mouse_paste_enabled(bool p_enabled) { middle_mouse_paste_enabled = p_enabled; } @@ -2280,6 +2288,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled); ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enable"), &LineEdit::set_virtual_keyboard_enabled); ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &LineEdit::is_virtual_keyboard_enabled); + ClassDB::bind_method(D_METHOD("set_virtual_keyboard_type", "type"), &LineEdit::set_virtual_keyboard_type); + ClassDB::bind_method(D_METHOD("get_virtual_keyboard_type"), &LineEdit::get_virtual_keyboard_type); ClassDB::bind_method(D_METHOD("set_clear_button_enabled", "enable"), &LineEdit::set_clear_button_enabled); ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled); ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled); @@ -2329,6 +2339,15 @@ void LineEdit::_bind_methods() { BIND_ENUM_CONSTANT(MENU_INSERT_SHY); BIND_ENUM_CONSTANT(MENU_MAX); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); @@ -2339,6 +2358,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length_enabled", "is_expand_to_text_length_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "virtual_keyboard_type", PROPERTY_HINT_ENUM, "Default,Multiline,Number,Decimal,Phone,Email,Password,URL"), "set_virtual_keyboard_type", "get_virtual_keyboard_type"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 557da35bfd..a828479b0c 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -70,6 +70,17 @@ public: MENU_MAX }; + enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + }; + private: HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; @@ -120,6 +131,7 @@ private: bool shortcut_keys_enabled = true; bool virtual_keyboard_enabled = true; + VirtualKeyboardType virtual_keyboard_type = KEYBOARD_TYPE_DEFAULT; bool middle_mouse_paste_enabled = true; @@ -311,6 +323,9 @@ public: void set_virtual_keyboard_enabled(bool p_enable); bool is_virtual_keyboard_enabled() const; + void set_virtual_keyboard_type(VirtualKeyboardType p_type); + VirtualKeyboardType get_virtual_keyboard_type() const; + void set_middle_mouse_paste_enabled(bool p_enabled); bool is_middle_mouse_paste_enabled() const; @@ -335,5 +350,6 @@ public: }; VARIANT_ENUM_CAST(LineEdit::MenuItems); +VARIANT_ENUM_CAST(LineEdit::VirtualKeyboardType); -#endif +#endif // LINE_EDIT_H diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index 54a31f06ce..12a6a7618f 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LINKBUTTON_H -#define LINKBUTTON_H +#ifndef LINK_BUTTON_H +#define LINK_BUTTON_H #include "scene/gui/base_button.h" #include "scene/resources/text_line.h" @@ -86,4 +86,4 @@ public: VARIANT_ENUM_CAST(LinkButton::UnderlineMode); -#endif // LINKBUTTON_H +#endif // LINK_BUTTON_H diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 316fee53fe..069a31d9d2 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -239,8 +239,8 @@ MenuButton::MenuButton(const String &p_text) : popup = memnew(PopupMenu); popup->hide(); add_child(popup, false, INTERNAL_MODE_FRONT); - popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(true)); - popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(false)); + popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(true)); + popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(false)); } MenuButton::~MenuButton() { diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 0a6b46c796..97c0d21f1e 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -71,4 +71,4 @@ public: ~MenuButton(); }; -#endif +#endif // MENU_BUTTON_H diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index a86f2bdbc1..c58513df17 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -35,7 +35,12 @@ static const int NONE_SELECTED = -1; Size2 OptionButton::get_minimum_size() const { - Size2 minsize = Button::get_minimum_size(); + Size2 minsize; + if (fit_to_longest_item) { + minsize = _cached_size; + } else { + minsize = Button::get_minimum_size(); + } if (has_theme_icon(SNAME("arrow"))) { const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size(); @@ -107,6 +112,7 @@ void OptionButton::_notification(int p_what) { _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width()); } } + _refresh_size_cache(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -135,6 +141,10 @@ bool OptionButton::_set(const StringName &p_name, const Variant &p_value) { _select(idx, false); } + if (property == "text" || property == "icon") { + _queue_refresh_cache(); + } + return valid; } return false; @@ -208,6 +218,7 @@ void OptionButton::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_l if (first_selectable) { select(get_item_count() - 1); } + _queue_refresh_cache(); } void OptionButton::add_item(const String &p_label, int p_id) { @@ -216,6 +227,7 @@ void OptionButton::add_item(const String &p_label, int p_id) { if (first_selectable) { select(get_item_count() - 1); } + _queue_refresh_cache(); } void OptionButton::set_item_text(int p_idx, const String &p_text) { @@ -224,6 +236,7 @@ void OptionButton::set_item_text(int p_idx, const String &p_text) { if (current == p_idx) { set_text(p_text); } + _queue_refresh_cache(); } void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { @@ -232,6 +245,7 @@ void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { if (current == p_idx) { set_icon(p_icon); } + _queue_refresh_cache(); } void OptionButton::set_item_id(int p_idx, int p_id) { @@ -301,6 +315,7 @@ void OptionButton::set_item_count(int p_count) { } } + _refresh_size_cache(); notify_property_list_changed(); } @@ -333,6 +348,19 @@ int OptionButton::get_item_count() const { return popup->get_item_count(); } +void OptionButton::set_fit_to_longest_item(bool p_fit) { + if (p_fit == fit_to_longest_item) { + return; + } + fit_to_longest_item = p_fit; + + _refresh_size_cache(); +} + +bool OptionButton::is_fit_to_longest_item() const { + return fit_to_longest_item; +} + void OptionButton::add_separator(const String &p_text) { popup->add_separator(p_text); } @@ -341,6 +369,7 @@ void OptionButton::clear() { popup->clear(); set_text(""); current = NONE_SELECTED; + _refresh_size_cache(); } void OptionButton::_select(int p_which, bool p_emit) { @@ -380,6 +409,29 @@ void OptionButton::_select_int(int p_which) { _select(p_which, false); } +void OptionButton::_refresh_size_cache() { + cache_refresh_pending = false; + + if (!fit_to_longest_item) { + return; + } + + _cached_size = Vector2(); + for (int i = 0; i < get_item_count(); i++) { + _cached_size = _cached_size.max(get_minimum_size_for_text_and_icon(get_item_text(i), get_item_icon(i))); + } + update_minimum_size(); +} + +void OptionButton::_queue_refresh_cache() { + if (cache_refresh_pending) { + return; + } + cache_refresh_pending = true; + + callable_mp(this, &OptionButton::_refresh_size_cache).call_deferredp(nullptr, 0); +} + void OptionButton::select(int p_idx) { _select(p_idx, false); } @@ -405,6 +457,7 @@ void OptionButton::remove_item(int p_idx) { if (current == p_idx) { _select(NONE_SELECTED); } + _queue_refresh_cache(); } PopupMenu *OptionButton::get_popup() const { @@ -453,10 +506,13 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count); ClassDB::bind_method(D_METHOD("has_selectable_items"), &OptionButton::has_selectable_items); ClassDB::bind_method(D_METHOD("get_selectable_item", "from_last"), &OptionButton::get_selectable_item, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_fit_to_longest_item", "fit"), &OptionButton::set_fit_to_longest_item); + ClassDB::bind_method(D_METHOD("is_fit_to_longest_item"), &OptionButton::is_fit_to_longest_item); // "selected" property must come after "item_count", otherwise GH-10213 occurs. ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_to_longest_item"), "set_fit_to_longest_item", "is_fit_to_longest_item"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index"))); ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index"))); } @@ -481,7 +537,8 @@ OptionButton::OptionButton(const String &p_text) : add_child(popup, false, INTERNAL_MODE_FRONT); popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected)); popup->connect("id_focused", callable_mp(this, &OptionButton::_focused)); - popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false)); + popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed).bind(false)); + _refresh_size_cache(); } OptionButton::~OptionButton() { diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 7896132626..49b5eee910 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -39,11 +39,16 @@ class OptionButton : public Button { PopupMenu *popup = nullptr; int current = -1; + bool fit_to_longest_item = true; + Vector2 _cached_size; + bool cache_refresh_pending = false; void _focused(int p_which); void _selected(int p_which); void _select(int p_which, bool p_emit = false); void _select_int(int p_which); + void _refresh_size_cache(); + void _queue_refresh_cache(); virtual void pressed() override; @@ -85,6 +90,8 @@ public: void set_item_count(int p_count); int get_item_count() const; + void set_fit_to_longest_item(bool p_fit); + bool is_fit_to_longest_item() const; void add_separator(const String &p_text = ""); @@ -105,4 +112,4 @@ public: ~OptionButton(); }; -#endif +#endif // OPTION_BUTTON_H diff --git a/scene/gui/popup.h b/scene/gui/popup.h index b53c8be50f..70eb8722d0 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -79,4 +79,4 @@ public: PopupPanel(); }; -#endif +#endif // POPUP_H diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 3a31246b17..928bab8842 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1909,7 +1909,7 @@ void PopupMenu::popup(const Rect2 &p_bounds) { PopupMenu::PopupMenu() { // Margin Container margin_container = memnew(MarginContainer); - margin_container->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + margin_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); add_child(margin_container, false, INTERNAL_MODE_FRONT); margin_container->connect("draw", callable_mp(this, &PopupMenu::_draw_background)); @@ -1921,7 +1921,7 @@ PopupMenu::PopupMenu() { // The control which will display the items control = memnew(Control); control->set_clip_contents(false); - control->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); control->set_h_size_flags(Control::SIZE_EXPAND_FILL); control->set_v_size_flags(Control::SIZE_EXPAND_FILL); scroll_container->add_child(control, false, INTERNAL_MODE_FRONT); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index daa38b0e6d..e203793c2e 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -260,4 +260,4 @@ public: ~PopupMenu(); }; -#endif +#endif // POPUP_MENU_H diff --git a/scene/gui/range.h b/scene/gui/range.h index 1274821bd1..87bd0d88af 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -106,4 +106,4 @@ public: ~Range(); }; -#endif +#endif // RANGE_H diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f5ff274683..984f20ee58 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -224,13 +224,21 @@ void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref< for (int i = 0; i < spans; i++) { ItemText *it = reinterpret_cast<ItemText *>((uint64_t)TS->shaped_get_span_meta(t, i)); if (it) { - Ref<Font> font = _find_font(it); - if (font.is_null()) { - font = p_base_font; + Ref<Font> font = p_base_font; + int font_size = p_base_font_size; + + ItemFont *font_it = _find_font(it); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(it); - if (font_size == -1) { - font_size = p_base_font_size; + ItemFontSize *font_size_it = _find_font_size(it); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font->get_opentype_features()); for (int j = 0; j < TextServer::SPACING_MAX; j++) { @@ -431,10 +439,10 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> Line &l = p_frame->lines[p_line]; MutexLock lock(l.text_buf->get_mutex()); - uint16_t autowrap_flags = TextServer::BREAK_MANDATORY; + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; switch (autowrap_mode) { case TextServer::AUTOWRAP_WORD_SMART: - autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; break; case TextServer::AUTOWRAP_WORD: autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; @@ -448,7 +456,8 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> // Clear cache. l.text_buf->clear(); - l.text_buf->set_flags(autowrap_flags | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES); + l.text_buf->set_break_flags(autowrap_flags); + l.text_buf->set_justification_flags(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES); l.char_offset = *r_char_offset; l.char_count = 0; @@ -482,13 +491,21 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> l.dc_ol_color = dc->ol_color; } break; case ITEM_NEWLINE: { - Ref<Font> font = _find_font(it); - if (font.is_null()) { - font = p_base_font; + Ref<Font> font = p_base_font; + int font_size = p_base_font_size; + + ItemFont *font_it = _find_font(it); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(it); - if (font_size == -1) { - font_size = p_base_font_size; + ItemFontSize *font_size_it = _find_font_size(it); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } l.text_buf->add_string("\n", font, font_size); text += "\n"; @@ -497,13 +514,21 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> } break; case ITEM_TEXT: { ItemText *t = static_cast<ItemText *>(it); - Ref<Font> font = _find_font(it); - if (font.is_null()) { - font = p_base_font; + Ref<Font> font = p_base_font; + int font_size = p_base_font_size; + + ItemFont *font_it = _find_font(it); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(it); - if (font_size == -1) { - font_size = p_base_font_size; + ItemFontSize *font_size_it = _find_font_size(it); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } String lang = _find_language(it); String tx = t->text; @@ -749,13 +774,21 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } } if (!prefix.is_empty()) { - Ref<Font> font = _find_font(l.from); - if (font.is_null()) { - font = get_theme_font(SNAME("normal_font")); + Ref<Font> font = get_theme_font(SNAME("normal_font")); + int font_size = get_theme_font_size(SNAME("normal_font_size")); + + ItemFont *font_it = _find_font(l.from); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(l.from); - if (font_size == -1) { - font_size = get_theme_font_size(SNAME("normal_font_size")); + ItemFontSize *font_size_it = _find_font_size(l.from); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } if (rtl) { float offx = 0.0f; @@ -788,17 +821,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o off.y += line_spacing; } - RID rid = l.text_buf->get_line_rid(line); if (p_ofs.y + off.y >= ctrl_size.height) { break; } - if (p_ofs.y + off.y + TS->shaped_text_get_size(rid).y <= 0) { - off.y += TS->shaped_text_get_size(rid).y; + + const Size2 line_size = l.text_buf->get_line_size(line); + if (p_ofs.y + off.y + line_size.y <= 0) { + off.y += line_size.y; continue; } float width = l.text_buf->get_width(); - float length = TS->shaped_text_get_width(rid); + float length = line_size.x; // Draw line. line_count++; @@ -841,6 +875,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } } + RID rid = l.text_buf->get_line_rid(line); //draw_rect(Rect2(p_ofs + off, TS->shaped_text_get_size(rid)), Color(1,0,0), false, 2); //DEBUG_RECTS off.y += TS->shaped_text_get_ascent(rid); @@ -1518,13 +1553,20 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V int stop = text_rect_begin; *r_click_item = _find_indentable(it); while (*r_click_item) { - Ref<Font> font = _find_font(*r_click_item); - if (!font.is_valid()) { - font = get_theme_font(SNAME("normal_font")); + Ref<Font> font = get_theme_font(SNAME("normal_font")); + int font_size = get_theme_font_size(SNAME("normal_font_size")); + ItemFont *font_it = _find_font(*r_click_item); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(*r_click_item); - if (font_size == -1) { - font_size = get_theme_font_size(SNAME("normal_font_size")); + ItemFontSize *font_size_it = _find_font_size(*r_click_item); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } if (rtl) { stop += tab_size * font->get_char_size(' ', font_size).width; @@ -2108,34 +2150,34 @@ RichTextLabel::Item *RichTextLabel::_find_indentable(Item *p_item) { return indentable; } -Ref<Font> RichTextLabel::_find_font(Item *p_item) { +RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) { Item *fontitem = p_item; while (fontitem) { if (fontitem->type == ITEM_FONT) { ItemFont *fi = static_cast<ItemFont *>(fontitem); - return fi->font; + return fi; } fontitem = fontitem->parent; } - return Ref<Font>(); + return nullptr; } -int RichTextLabel::_find_font_size(Item *p_item) { +RichTextLabel::ItemFontSize *RichTextLabel::_find_font_size(Item *p_item) { Item *sizeitem = p_item; while (sizeitem) { if (sizeitem->type == ITEM_FONT_SIZE) { ItemFontSize *fi = static_cast<ItemFontSize *>(sizeitem); - return fi->font_size; + return fi; } sizeitem = sizeitem->parent; } - return -1; + return nullptr; } int RichTextLabel::_find_outline_size(Item *p_item, int p_default) { @@ -2221,24 +2263,40 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int while (item) { if (item->type == ITEM_INDENT) { - Ref<Font> font = _find_font(item); - if (font.is_null()) { - font = p_base_font; + Ref<Font> font = p_base_font; + int font_size = p_base_font_size; + + ItemFont *font_it = _find_font(item); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(item); - if (font_size == -1) { - font_size = p_base_font_size; + ItemFontSize *font_size_it = _find_font_size(item); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } margin += tab_size * font->get_char_size(' ', font_size).width; } else if (item->type == ITEM_LIST) { - Ref<Font> font = _find_font(item); - if (font.is_null()) { - font = p_base_font; + Ref<Font> font = p_base_font; + int font_size = p_base_font_size; + + ItemFont *font_it = _find_font(item); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } - int font_size = _find_font_size(item); - if (font_size == -1) { - font_size = p_base_font_size; + ItemFontSize *font_size_it = _find_font_size(item); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; } margin += tab_size * font->get_char_size(' ', font_size).width; } @@ -2917,7 +2975,7 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref<Font> &p_font _add_item(item, false); } -void RichTextLabel::push_font(const Ref<Font> &p_font) { +void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) { _stop_thread(); MutexLock data_lock(data_mutex); @@ -2926,6 +2984,7 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) { ItemFont *item = memnew(ItemFont); item->font = p_font; + item->font_size = p_size; _add_item(item, true); } @@ -2933,35 +2992,35 @@ void RichTextLabel::push_normal() { Ref<Font> normal_font = get_theme_font(SNAME("normal_font")); ERR_FAIL_COND(normal_font.is_null()); - push_font(normal_font); + push_font(normal_font, get_theme_font_size(SNAME("normal_font_size"))); } void RichTextLabel::push_bold() { Ref<Font> bold_font = get_theme_font(SNAME("bold_font")); ERR_FAIL_COND(bold_font.is_null()); - push_font(bold_font); + push_font(bold_font, get_theme_font_size(SNAME("bold_font_size"))); } void RichTextLabel::push_bold_italics() { Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font")); ERR_FAIL_COND(bold_italics_font.is_null()); - push_font(bold_italics_font); + push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size"))); } void RichTextLabel::push_italics() { Ref<Font> italics_font = get_theme_font(SNAME("italics_font")); ERR_FAIL_COND(italics_font.is_null()); - push_font(italics_font); + push_font(italics_font, get_theme_font_size(SNAME("italics_font_size"))); } void RichTextLabel::push_mono() { Ref<Font> mono_font = get_theme_font(SNAME("mono_font")); ERR_FAIL_COND(mono_font.is_null()); - push_font(mono_font); + push_font(mono_font, get_theme_font_size(SNAME("mono_font_size"))); } void RichTextLabel::push_font_size(int p_font_size) { @@ -3551,9 +3610,9 @@ void RichTextLabel::append_text(const String &p_bbcode) { //use bold font in_bold = true; if (in_italics) { - push_font(bold_italics_font); + push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size"))); } else { - push_font(bold_font); + push_font(bold_font, get_theme_font_size(SNAME("bold_font_size"))); } pos = brk_end + 1; tag_stack.push_front(tag); @@ -3561,15 +3620,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { //use italics font in_italics = true; if (in_bold) { - push_font(bold_italics_font); + push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size"))); } else { - push_font(italics_font); + push_font(italics_font, get_theme_font_size(SNAME("italics_font_size"))); } pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code") { //use monospace font - push_font(mono_font); + push_font(mono_font, get_theme_font_size(SNAME("mono_font_size"))); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag.begins_with("table=")) { @@ -3998,9 +4057,16 @@ void RichTextLabel::append_text(const String &p_bbcode) { String fnt_ftr = tag.substr(18, tag.length()); Vector<String> subtag = fnt_ftr.split(","); if (subtag.size() > 0) { - Ref<Font> font = _find_font(current); - if (font.is_null()) { - font = normal_font; + Ref<Font> font = normal_font; + int font_size = 0; + ItemFont *font_it = _find_font(current); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } } Ref<FontVariation> fc; fc.instantiate(); @@ -4015,7 +4081,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } fc->set_opentype_features(features); - push_font(fc); + push_font(fc, font_size); } pos = brk_end + 1; tag_stack.push_front("opentype_features"); @@ -4036,6 +4102,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { Ref<FontVariation> fc; fc.instantiate(); + int fnt_size = 0; for (int i = 1; i < subtag.size(); i++) { Vector<String> subtag_a = subtag[i].split("=", true, 2); if (subtag_a.size() == 2) { @@ -4046,10 +4113,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { fc->set_base_font(font_data); } } else if (subtag_a[0] == "size" || subtag_a[0] == "s") { - int fnt_size = subtag_a[1].to_int(); - if (fnt_size > 0) { - push_font_size(fnt_size); - } + fnt_size = subtag_a[1].to_int(); } else if (subtag_a[0] == "glyph_spacing" || subtag_a[0] == "gl") { int spacing = subtag_a[1].to_int(); fc->set_spacing(TextServer::SPACING_GLYPH, spacing); @@ -4100,7 +4164,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } } - push_font(fc); + push_font(fc, fnt_size); pos = brk_end + 1; tag_stack.push_front("font"); @@ -4882,11 +4946,10 @@ void RichTextLabel::install_effect(const Variant effect) { Ref<RichTextEffect> rteffect; rteffect = effect; - if (rteffect.is_valid()) { - custom_effects.push_back(effect); - if ((!text.is_empty()) && use_bbcode) { - parse_bbcode(text); - } + ERR_FAIL_COND_MSG(rteffect.is_null(), "Invalid RichTextEffect resource."); + custom_effects.push_back(effect); + if ((!text.is_empty()) && use_bbcode) { + parse_bbcode(text); } } @@ -4929,7 +4992,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER)); ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line); - ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font); + ClassDB::bind_method(D_METHOD("push_font", "font", "font_size"), &RichTextLabel::push_font); ClassDB::bind_method(D_METHOD("push_font_size", "font_size"), &RichTextLabel::push_font_size); ClassDB::bind_method(D_METHOD("push_normal"), &RichTextLabel::push_normal); ClassDB::bind_method(D_METHOD("push_bold"), &RichTextLabel::push_bold); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index c123f38c01..e5f0469c01 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -178,6 +178,7 @@ private: struct ItemFont : public Item { Ref<Font> font; + int font_size = 0; ItemFont() { type = ITEM_FONT; } }; @@ -462,8 +463,8 @@ private: Item *_find_indentable(Item *p_item); Item *_get_item_at_pos(Item *p_item_from, Item *p_item_to, int p_position); void _find_frame(Item *p_item, ItemFrame **r_frame, int *r_line); - int _find_font_size(Item *p_item); - Ref<Font> _find_font(Item *p_item); + ItemFontSize *_find_font_size(Item *p_item); + ItemFont *_find_font(Item *p_item); int _find_outline_size(Item *p_item, int p_default); ItemList *_find_list_item(Item *p_item); ItemDropcap *_find_dc_item(Item *p_item); @@ -518,7 +519,7 @@ public: void add_newline(); bool remove_line(const int p_line); void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); - void push_font(const Ref<Font> &p_font); + void push_font(const Ref<Font> &p_font, int p_size = 0); void push_font_size(int p_font_size); void push_outline_size(int p_font_size); void push_normal(); diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index f387f91a8b..48c57d9b1b 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -303,7 +303,7 @@ void ScrollBar::_notification(int p_what) { if (drag_node) { drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input)); - drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), varray(), CONNECT_ONESHOT); + drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONESHOT); } } break; @@ -595,7 +595,7 @@ void ScrollBar::set_drag_node(const NodePath &p_path) { if (drag_node) { drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input)); - drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), varray(), CONNECT_ONESHOT); + drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONESHOT); } } } diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index 651edd1a74..1823f86a67 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -128,4 +128,4 @@ public: ScrollBar(VERTICAL) { set_h_size_flags(0); } }; -#endif +#endif // SCROLL_BAR_H diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 871cc520e9..8fd547813d 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -38,9 +38,13 @@ Size2 ScrollContainer::get_minimum_size() const { Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg")); Size2 min_size; + // Calculated in this function, as it needs to traverse all child controls once to calculate; + // and needs to be calculated before being used by update_scrollbars(). + largest_child_min_size = Size2(); + for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible()) { continue; } if (c->is_set_as_top_level()) { @@ -49,22 +53,30 @@ Size2 ScrollContainer::get_minimum_size() const { if (c == h_scroll || c == v_scroll) { continue; } - Size2 minsize = c->get_combined_minimum_size(); - if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) { - min_size.x = MAX(min_size.x, minsize.x); - } - if (vertical_scroll_mode == SCROLL_MODE_DISABLED) { - min_size.y = MAX(min_size.y, minsize.y); - } + Size2 child_min_size = c->get_combined_minimum_size(); + + largest_child_min_size.x = MAX(largest_child_min_size.x, child_min_size.x); + largest_child_min_size.y = MAX(largest_child_min_size.y, child_min_size.y); } - if (h_scroll->is_visible_in_tree()) { + if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) { + min_size.x = MAX(min_size.x, largest_child_min_size.x); + } + if (vertical_scroll_mode == SCROLL_MODE_DISABLED) { + min_size.y = MAX(min_size.y, largest_child_min_size.y); + } + + bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > min_size.x); + bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > min_size.y); + + if (h_scroll_show && h_scroll->get_parent() == this) { min_size.y += h_scroll->get_minimum_size().y; } - if (v_scroll->is_visible_in_tree()) { + if (v_scroll_show && v_scroll->get_parent() == this) { min_size.x += v_scroll->get_minimum_size().x; } + min_size += sb->get_minimum_size(); return min_size; } @@ -254,8 +266,8 @@ void ScrollContainer::ensure_control_visible(Control *p_control) { set_v_scroll(get_v_scroll() + (diff.y - global_rect.position.y)); } -void ScrollContainer::_update_dimensions() { - child_max_size = Size2(0, 0); +void ScrollContainer::_reposition_children() { + update_scrollbars(); Size2 size = get_size(); Point2 ofs; @@ -274,7 +286,7 @@ void ScrollContainer::_update_dimensions() { for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible()) { continue; } if (c->is_set_as_top_level()) { @@ -284,25 +296,13 @@ void ScrollContainer::_update_dimensions() { continue; } Size2 minsize = c->get_combined_minimum_size(); - child_max_size.x = MAX(child_max_size.x, minsize.x); - child_max_size.y = MAX(child_max_size.y, minsize.y); Rect2 r = Rect2(-Size2(get_h_scroll(), get_v_scroll()), minsize); - if (horizontal_scroll_mode == SCROLL_MODE_DISABLED || (!h_scroll->is_visible_in_tree() && c->get_h_size_flags() & SIZE_EXPAND)) { - r.position.x = 0; - if (c->get_h_size_flags() & SIZE_EXPAND) { - r.size.width = MAX(size.width, minsize.width); - } else { - r.size.width = minsize.width; - } + if (c->get_h_size_flags() & SIZE_EXPAND) { + r.size.width = MAX(size.width, minsize.width); } - if (vertical_scroll_mode == SCROLL_MODE_DISABLED || (!v_scroll->is_visible_in_tree() && c->get_v_size_flags() & SIZE_EXPAND)) { - r.position.y = 0; - if (c->get_v_size_flags() & SIZE_EXPAND) { - r.size.height = MAX(size.height, minsize.height); - } else { - r.size.height = minsize.height; - } + if (c->get_v_size_flags() & SIZE_EXPAND) { + r.size.height = MAX(size.height, minsize.height); } r.position += ofs; if (rtl && v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) { @@ -329,18 +329,16 @@ void ScrollContainer::_notification(int p_what) { Viewport *viewport = get_viewport(); ERR_FAIL_COND(!viewport); viewport->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed)); - _update_dimensions(); + _reposition_children(); } break; case NOTIFICATION_SORT_CHILDREN: { - _update_dimensions(); + _reposition_children(); } break; case NOTIFICATION_DRAW: { Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg")); draw_style_box(sb, Rect2(Vector2(), get_size())); - - update_scrollbars(); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -418,36 +416,25 @@ void ScrollContainer::update_scrollbars() { Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg")); size -= sb->get_minimum_size(); - Size2 hmin; - Size2 vmin; - if (horizontal_scroll_mode != SCROLL_MODE_DISABLED) { - hmin = h_scroll->get_combined_minimum_size(); - } - if (vertical_scroll_mode != SCROLL_MODE_DISABLED) { - vmin = v_scroll->get_combined_minimum_size(); - } - - Size2 min = child_max_size; + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); - bool hide_scroll_h = horizontal_scroll_mode != SCROLL_MODE_SHOW_ALWAYS && (horizontal_scroll_mode == SCROLL_MODE_DISABLED || horizontal_scroll_mode == SCROLL_MODE_SHOW_NEVER || (horizontal_scroll_mode == SCROLL_MODE_AUTO && min.width <= size.width)); - bool hide_scroll_v = vertical_scroll_mode != SCROLL_MODE_SHOW_ALWAYS && (vertical_scroll_mode == SCROLL_MODE_DISABLED || vertical_scroll_mode == SCROLL_MODE_SHOW_NEVER || (vertical_scroll_mode == SCROLL_MODE_AUTO && min.height <= size.height)); + h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.width > size.width)); + v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.height > size.height)); - h_scroll->set_max(min.width); - h_scroll->set_page(size.width - (hide_scroll_v ? 0 : vmin.width)); - h_scroll->set_visible(!hide_scroll_h); + h_scroll->set_max(largest_child_min_size.width); + h_scroll->set_page((v_scroll->is_visible() && v_scroll->get_parent() == this) ? size.width - vmin.width : size.width); - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - (hide_scroll_h ? 0 : hmin.height)); - v_scroll->set_visible(!hide_scroll_v); + v_scroll->set_max(largest_child_min_size.height); + v_scroll->set_page((h_scroll->is_visible() && h_scroll->get_parent() == this) ? size.height - hmin.height : size.height); // Avoid scrollbar overlapping. - h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, hide_scroll_v ? 0 : -vmin.width); - v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, hide_scroll_h ? 0 : -hmin.height); + h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, (v_scroll->is_visible() && v_scroll->get_parent() == this) ? -vmin.width : 0); + v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, (h_scroll->is_visible() && h_scroll->get_parent() == this) ? -hmin.height : 0); } void ScrollContainer::_scroll_moved(float) { queue_sort(); - update(); }; void ScrollContainer::set_h_scroll(int p_pos) { diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index b9fcf64db6..bfa74cfd0f 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -50,7 +50,7 @@ private: HScrollBar *h_scroll = nullptr; VScrollBar *v_scroll = nullptr; - Size2 child_max_size; + mutable Size2 largest_child_min_size; // The largest one among the min sizes of all available child controls. void update_scrollbars(); @@ -75,7 +75,7 @@ protected: Size2 get_minimum_size() const override; void _gui_focus_changed(Control *p_control); - void _update_dimensions(); + void _reposition_children(); void _notification(int p_what); void _scroll_moved(float); @@ -116,4 +116,4 @@ public: VARIANT_ENUM_CAST(ScrollContainer::ScrollMode); -#endif +#endif // SCROLL_CONTAINER_H diff --git a/scene/gui/separator.h b/scene/gui/separator.h index 1621bb3351..e6578a4d04 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -60,4 +60,4 @@ public: HSeparator(); }; -#endif +#endif // SEPARATOR_H diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 4b680f72cf..64c07007dc 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -96,15 +96,15 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) { if (grab.active) { Size2i size = get_size(); Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber")); - float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos; + double motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos; if (orientation == VERTICAL) { motion = -motion; } - float areasize = orientation == VERTICAL ? size.height - grabber->get_size().height : size.width - grabber->get_size().width; + double areasize = orientation == VERTICAL ? size.height - grabber->get_size().height : size.width - grabber->get_size().width; if (areasize <= 0) { return; } - float umotion = motion / float(areasize); + double umotion = motion / double(areasize); set_as_ratio(grab.uvalue + umotion); } } @@ -180,7 +180,7 @@ void Slider::_notification(int p_what) { if (orientation == VERTICAL) { int widget_width = style->get_minimum_size().width + style->get_center_size().width; - float areasize = size.height - grabber->get_size().height; + double areasize = size.height - grabber->get_size().height; style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height))); grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * ratio - grabber->get_size().height / 2), Size2i(widget_width, areasize * ratio + grabber->get_size().height / 2))); @@ -197,7 +197,7 @@ void Slider::_notification(int p_what) { grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - ratio * areasize - grabber->get_size().height)); } else { int widget_height = style->get_minimum_size().height + style->get_center_size().height; - float areasize = size.width - grabber->get_size().width; + double areasize = size.width - grabber->get_size().width; style->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(size.width, widget_height))); grabber_area->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(areasize * ratio + grabber->get_size().width / 2, widget_height))); @@ -218,11 +218,11 @@ void Slider::_notification(int p_what) { } } -void Slider::set_custom_step(float p_custom_step) { +void Slider::set_custom_step(double p_custom_step) { custom_step = p_custom_step; } -float Slider::get_custom_step() const { +double Slider::get_custom_step() const { return custom_step; } diff --git a/scene/gui/slider.h b/scene/gui/slider.h index 5fbfee2aec..5abaee27aa 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -38,14 +38,14 @@ class Slider : public Range { struct Grab { int pos = 0; - float uvalue = 0.0; + double uvalue = 0.0; bool active = false; } grab; int ticks = 0; bool mouse_inside = false; Orientation orientation; - float custom_step = -1.0; + double custom_step = -1.0; bool editable = true; bool scrollable = true; @@ -58,8 +58,8 @@ protected: public: virtual Size2 get_minimum_size() const override; - void set_custom_step(float p_custom_step); - float get_custom_step() const; + void set_custom_step(double p_custom_step); + double get_custom_step() const; void set_ticks(int p_count); int get_ticks() const; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 890e349afb..8a7f52b0d9 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -88,7 +88,8 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { void SpinBox::_range_click_timeout() { if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); - set_value(get_value() + (up ? get_step() : -get_step())); + double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + set_value(get_value() + (up ? step : -step)); if (range_click_timer->is_one_shot()) { range_click_timer->set_wait_time(0.075); @@ -118,6 +119,8 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; + double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + if (mb.is_valid() && mb->is_pressed()) { bool up = mb->get_position().y < (get_size().height / 2); @@ -125,7 +128,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { case MouseButton::LEFT: { line_edit->grab_focus(); - set_value(get_value() + (up ? get_step() : -get_step())); + set_value(get_value() + (up ? step : -step)); range_click_timer->set_wait_time(0.6); range_click_timer->set_one_shot(true); @@ -140,13 +143,13 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { } break; case MouseButton::WHEEL_UP: { if (line_edit->has_focus()) { - set_value(get_value() + get_step() * mb->get_factor()); + set_value(get_value() + step * mb->get_factor()); accept_event(); } } break; case MouseButton::WHEEL_DOWN: { if (line_edit->has_focus()) { - set_value(get_value() - get_step() * mb->get_factor()); + set_value(get_value() - step * mb->get_factor()); accept_event(); } } break; @@ -167,8 +170,8 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { if (drag.enabled) { drag.diff_y += mm->get_relative().y; - float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SIGN(drag.diff_y); - set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max())); + double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y); + set_value(CLAMP(drag.base_val + step * diff_y, get_min(), get_max())); } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); drag.enabled = true; @@ -272,7 +275,7 @@ void SpinBox::set_update_on_text_changed(bool p_enabled) { update_on_text_changed = p_enabled; if (p_enabled) { - line_edit->connect("text_changed", callable_mp(this, &SpinBox::_text_changed), Vector<Variant>(), CONNECT_DEFERRED); + line_edit->connect("text_changed", callable_mp(this, &SpinBox::_text_changed), CONNECT_DEFERRED); } else { line_edit->disconnect("text_changed", callable_mp(this, &SpinBox::_text_changed)); } @@ -294,6 +297,14 @@ void SpinBox::apply() { _text_submitted(line_edit->get_text()); } +void SpinBox::set_custom_arrow_step(double p_custom_arrow_step) { + custom_arrow_step = p_custom_arrow_step; +} + +double SpinBox::get_custom_arrow_step() const { + return custom_arrow_step; +} + void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &SpinBox::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &SpinBox::get_horizontal_alignment); @@ -302,6 +313,8 @@ void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_prefix", "prefix"), &SpinBox::set_prefix); ClassDB::bind_method(D_METHOD("get_prefix"), &SpinBox::get_prefix); ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &SpinBox::set_editable); + ClassDB::bind_method(D_METHOD("set_custom_arrow_step", "arrow_step"), &SpinBox::set_custom_arrow_step); + ClassDB::bind_method(D_METHOD("get_custom_arrow_step"), &SpinBox::get_custom_arrow_step); ClassDB::bind_method(D_METHOD("is_editable"), &SpinBox::is_editable); ClassDB::bind_method(D_METHOD("set_update_on_text_changed", "enabled"), &SpinBox::set_update_on_text_changed); ClassDB::bind_method(D_METHOD("get_update_on_text_changed"), &SpinBox::get_update_on_text_changed); @@ -313,18 +326,19 @@ void SpinBox::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_on_text_changed"), "set_update_on_text_changed", "get_update_on_text_changed"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step"), "set_custom_arrow_step", "get_custom_arrow_step"); } SpinBox::SpinBox() { line_edit = memnew(LineEdit); add_child(line_edit, false, INTERNAL_MODE_FRONT); - line_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + line_edit->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); line_edit->set_mouse_filter(MOUSE_FILTER_PASS); line_edit->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); - line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), Vector<Variant>(), CONNECT_DEFERRED); - line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), Vector<Variant>(), CONNECT_DEFERRED); + line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), CONNECT_DEFERRED); + line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED); line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input)); range_click_timer = memnew(Timer); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index d118b28334..0aae9efe78 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -52,15 +52,16 @@ class SpinBox : public Range { String prefix; String suffix; + double custom_arrow_step = 0.0; void _line_edit_input(const Ref<InputEvent> &p_event); struct Drag { - float base_val = 0.0; + double base_val = 0.0; bool allowed = false; bool enabled = false; Vector2 capture_pos; - float diff_y = 0.0; + double diff_y = 0.0; } drag; void _line_edit_focus_exit(); @@ -95,6 +96,8 @@ public: bool get_update_on_text_changed() const; void apply(); + void set_custom_arrow_step(const double p_custom_arrow_step); + double get_custom_arrow_step() const; SpinBox(); }; diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index 55b7802aa4..5b488fb79e 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VIEWPORTCONTAINER_H -#define VIEWPORTCONTAINER_H +#ifndef SUBVIEWPORT_CONTAINER_H +#define SUBVIEWPORT_CONTAINER_H #include "scene/gui/container.h" @@ -63,4 +63,4 @@ public: SubViewportContainer(); }; -#endif // VIEWPORTCONTAINER_H +#endif // SUBVIEWPORT_CONTAINER_H diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index fa929344d4..12f91a9873 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -233,7 +233,7 @@ void TabContainer::_repaint() { if (i == current) { c->show(); - c->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + c->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); if (tabs_visible) { c->set_offset(SIDE_TOP, _get_top_margin()); @@ -312,7 +312,7 @@ Vector<Control *> TabContainer::_get_tab_controls() const { Vector<Control *> controls; for (int i = 0; i < get_child_count(); i++) { Control *control = Object::cast_to<Control>(get_child(i)); - if (!control || control->is_set_as_top_level() || control == tab_bar) { + if (!control || control->is_set_as_top_level() || control == tab_bar || control == child_removing) { continue; } @@ -549,7 +549,12 @@ void TabContainer::remove_child_notify(Node *p_child) { return; } - tab_bar->remove_tab(get_tab_idx_from_control(c)); + int idx = get_tab_idx_from_control(c); + + // Before this, the tab control has not changed; after this, the tab control has changed. + child_removing = p_child; + tab_bar->remove_tab(idx); + child_removing = nullptr; _update_margins(); if (get_tab_count() == 0) { diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 9adaa0d844..60c8130939 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -46,6 +46,7 @@ class TabContainer : public Container { bool drag_to_rearrange_enabled = false; bool use_hidden_tabs_for_min_size = false; bool theme_changing = false; + Node *child_removing = nullptr; int _get_top_margin() const; Vector<Control *> _get_tab_controls() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 06553cd0f6..c023b06895 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -443,8 +443,10 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_THEME_CHANGED: { - _update_caches(); - _update_wrap_at_column(true); + if (is_inside_tree()) { + _update_caches(); + _update_wrap_at_column(true); + } } break; case NOTIFICATION_WM_WINDOW_FOCUS_IN: { @@ -1055,7 +1057,7 @@ void TextEdit::_notification(int p_what) { const Variant *argp[] = { &args[0], &args[1], &args[2] }; Callable::CallError ce; Variant ret; - gutter.custom_draw_callback.call(argp, 3, ret, ce); + gutter.custom_draw_callback.callp(argp, 3, ret, ce); } } break; } @@ -1464,7 +1466,7 @@ void TextEdit::_notification(int p_what) { caret_end = caret_start + post_text.length(); } - DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect(), true, -1, caret_start, caret_end); + DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect(), DisplayServer::KEYBOARD_TYPE_MULTILINE, -1, caret_start, caret_end); } } break; @@ -2789,7 +2791,7 @@ String TextEdit::get_tooltip(const Point2 &p_pos) const { const Variant *argp[] = { &args[0] }; Callable::CallError ce; Variant ret; - tooltip_callback.call(argp, 1, ret, ce); + tooltip_callback.callp(argp, 1, ret, ce); ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip."); return ret; } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 5762949acd..9f6f7c1515 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -101,4 +101,5 @@ public: }; VARIANT_ENUM_CAST(TextureButton::StretchMode); + #endif // TEXTURE_BUTTON_H diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index f43a91b85f..1eb6c5a554 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -723,7 +723,12 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) { TreeItem *TreeItem::get_child(int p_idx) { _create_children_cache(); + + if (p_idx < 0) { + p_idx += children_cache.size(); + } ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr); + return children_cache.get(p_idx); } @@ -1844,15 +1849,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 p_item->set_meta("__focus_rect", Rect2(r.position, r.size)); - if (rtl) { - r.position.x = get_size().width - r.position.x - r.size.x; - } - - if (p_item->cells[i].selected) { - if (has_focus()) { - cache.selected_focus->draw(ci, r); - } else { - cache.selected->draw(ci, r); + if (select_mode != SELECT_ROW) { + if (rtl) { + r.position.x = get_size().width - r.position.x - r.size.x; + } + if (p_item->cells[i].selected) { + if (has_focus()) { + cache.selected_focus->draw(ci, r); + } else { + cache.selected->draw(ci, r); + } } } } @@ -5018,7 +5024,7 @@ Tree::Tree() { popup_editor_vb = memnew(VBoxContainer); popup_editor->add_child(popup_editor_vb); popup_editor_vb->add_theme_constant_override("separation", 0); - popup_editor_vb->set_anchors_and_offsets_preset(PRESET_WIDE); + popup_editor_vb->set_anchors_and_offsets_preset(PRESET_FULL_RECT); text_editor = memnew(LineEdit); popup_editor_vb->add_child(text_editor); text_editor->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 1690e7ac57..f0819e2980 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -719,4 +719,5 @@ public: VARIANT_ENUM_CAST(Tree::SelectMode); VARIANT_ENUM_CAST(Tree::DropModeFlags); -#endif + +#endif // TREE_H diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 86334882fa..f20a2ad67b 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -225,7 +225,7 @@ void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) { stream = p_stream; if (stream.is_valid()) { stream->set_audio_track(audio_track); - playback = stream->instance_playback(); + playback = stream->instantiate_playback(); } else { playback = Ref<VideoStreamPlayback>(); } diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp index 892d0aba29..3b7f499a07 100644 --- a/scene/gui/view_panner.cpp +++ b/scene/gui/view_panner.cpp @@ -135,7 +135,7 @@ void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) { Variant result; Callable::CallError ce; - p_callback.call(argptr, p_args.size(), result, ce); + p_callback.callp(argptr, p_args.size(), result, ce); } void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) { diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 5e90615ac1..ce204c6aeb 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -64,9 +64,6 @@ void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) { if (!visible) { return; } - if (p_parent_visible_in_tree && first_draw) { // Avoid propagating it twice. - first_draw = false; - } _handle_visibility_change(p_parent_visible_in_tree); } @@ -133,10 +130,6 @@ void CanvasItem::_update_callback() { RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item()); //todo updating = true - only allow drawing here if (is_visible_in_tree()) { - if (first_draw) { - notification(NOTIFICATION_VISIBILITY_CHANGED); - first_draw = false; - } drawing = true; current_item_drawn = this; notification(NOTIFICATION_DRAW); @@ -230,16 +223,16 @@ void CanvasItem::_enter_canvas() { RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas); - group = "root_canvas" + itos(canvas.get_id()); + canvas_group = "root_canvas" + itos(canvas.get_id()); - add_to_group(group); + add_to_group(canvas_group); if (canvas_layer) { canvas_layer->reset_sort_index(); } else { get_viewport()->gui_reset_canvas_sort_index(); } - get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, group, SNAME("_top_level_raise_self")); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, SNAME("_top_level_raise_self")); } else { CanvasItem *parent = get_parent_item(); @@ -258,14 +251,16 @@ void CanvasItem::_exit_canvas() { notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, RID()); canvas_layer = nullptr; - group = StringName(); + if (canvas_group != StringName()) { + remove_from_group(canvas_group); + canvas_group = StringName(); + } } void CanvasItem::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { ERR_FAIL_COND(!is_inside_tree()); - first_draw = true; Node *parent = get_parent(); if (parent) { @@ -304,6 +299,10 @@ void CanvasItem::_notification(int p_what) { } } + RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change. + if (is_visible_in_tree()) { + notification(NOTIFICATION_VISIBILITY_CHANGED); // Considered invisible until entered. + } _enter_canvas(); _update_texture_filter_changed(false); @@ -319,8 +318,8 @@ void CanvasItem::_notification(int p_what) { break; } - if (group != StringName()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, group, "_top_level_raise_self"); + if (canvas_group != StringName()) { + get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, "_top_level_raise_self"); } else { CanvasItem *p = get_parent_item(); ERR_FAIL_COND(!p); @@ -658,32 +657,32 @@ void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Tex RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid); } -void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); - p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_modulate, p_flags, p_direction, p_orientation); + p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_modulate, p_jst_flags, p_direction, p_orientation); } -void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); - p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_flags, p_direction, p_orientation); + p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_brk_flags, p_jst_flags, p_direction, p_orientation); } -void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); - p_font->draw_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_size, p_modulate, p_flags, p_direction, p_orientation); + p_font->draw_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_size, p_modulate, p_jst_flags, p_direction, p_orientation); } -void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); - p_font->draw_multiline_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_size, p_modulate, p_flags, p_direction, p_orientation); + p_font->draw_multiline_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_size, p_modulate, p_brk_flags, p_jst_flags, p_direction, p_orientation); } void CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, const Color &p_modulate) const { @@ -924,10 +923,10 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>())); ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>())); - ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "jst_flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "font_size", "modulate"), &CanvasItem::draw_char, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0))); ClassDB::bind_method(D_METHOD("draw_char_outline", "font", "pos", "char", "font_size", "size", "modulate"), &CanvasItem::draw_char_outline, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0))); ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1))); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index c88878725f..38e0be1683 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -70,7 +70,7 @@ private: mutable SelfList<Node> xform_change; RID canvas_item; - StringName group; + StringName canvas_group; CanvasLayer *canvas_layer = nullptr; @@ -83,7 +83,6 @@ private: int light_mask = 1; Window *window = nullptr; - bool first_draw = false; bool visible = true; bool parent_visible_in_tree = false; bool clip_children = false; @@ -235,11 +234,11 @@ public: void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1)); void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture); - void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - void draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_size = 1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - void draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + void draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_size = 1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + void draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; void draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const; void draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 49b4b1b30c..4b32188377 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef HTTPREQUEST_H -#define HTTPREQUEST_H +#ifndef HTTP_REQUEST_H +#define HTTP_REQUEST_H #include "core/io/http_client.h" #include "core/os/thread.h" @@ -162,4 +162,4 @@ public: VARIANT_ENUM_CAST(HTTPRequest::Result); -#endif // HTTPREQUEST_H +#endif // HTTP_REQUEST_H diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp new file mode 100644 index 0000000000..95574042a8 --- /dev/null +++ b/scene/main/multiplayer_api.cpp @@ -0,0 +1,416 @@ +/*************************************************************************/ +/* multiplayer_api.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "multiplayer_api.h" + +#include "core/debugger/engine_debugger.h" +#include "core/io/marshalls.h" + +#include <stdint.h> + +#ifdef DEBUG_ENABLED +#include "core/os/os.h" +#endif + +StringName MultiplayerAPI::default_interface = StringName(); + +void MultiplayerAPI::set_default_interface(const StringName &p_interface) { + ERR_FAIL_COND_MSG(!ClassDB::is_parent_class(p_interface, MultiplayerAPI::get_class_static()), vformat("Can't make %s the default multiplayer interface since it does not extend MultiplayerAPI.", p_interface)); + default_interface = p_interface; +} + +StringName MultiplayerAPI::get_default_interface() { + return default_interface; +} + +Ref<MultiplayerAPI> MultiplayerAPI::create_default_interface() { + if (default_interface != StringName()) { + return Ref<MultiplayerAPI>(Object::cast_to<MultiplayerAPI>(ClassDB::instantiate(default_interface))); + } + return Ref<MultiplayerAPI>(memnew(MultiplayerAPIExtension)); +} + +// The variant is compressed and encoded; The first byte contains all the meta +// information and the format is: +// - The first LSB 5 bits are used for the variant type. +// - The next two bits are used to store the encoding mode. +// - The most significant is used to store the boolean value. +#define VARIANT_META_TYPE_MASK 0x1F +#define VARIANT_META_EMODE_MASK 0x60 +#define VARIANT_META_BOOL_MASK 0x80 +#define ENCODE_8 0 << 5 +#define ENCODE_16 1 << 5 +#define ENCODE_32 2 << 5 +#define ENCODE_64 3 << 5 +Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) { + // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 + CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); + + uint8_t *buf = r_buffer; + r_len = 0; + uint8_t encode_mode = 0; + + switch (p_variant.get_type()) { + case Variant::BOOL: { + if (buf) { + // We still have 1 free bit in the meta, so let's use it. + buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0; + buf[0] |= encode_mode | p_variant.get_type(); + } + r_len += 1; + } break; + case Variant::INT: { + if (buf) { + // Reserve the first byte for the meta. + buf += 1; + } + r_len += 1; + int64_t val = p_variant; + if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) { + // Use 8 bit + encode_mode = ENCODE_8; + if (buf) { + buf[0] = val; + } + r_len += 1; + } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) { + // Use 16 bit + encode_mode = ENCODE_16; + if (buf) { + encode_uint16(val, buf); + } + r_len += 2; + } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) { + // Use 32 bit + encode_mode = ENCODE_32; + if (buf) { + encode_uint32(val, buf); + } + r_len += 4; + } else { + // Use 64 bit + encode_mode = ENCODE_64; + if (buf) { + encode_uint64(val, buf); + } + r_len += 8; + } + // Store the meta + if (buf) { + buf -= 1; + buf[0] = encode_mode | p_variant.get_type(); + } + } break; + default: + // Any other case is not yet compressed. + Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding); + if (err != OK) { + return err; + } + if (r_buffer) { + // The first byte is not used by the marshalling, so store the type + // so we know how to decompress and decode this variant. + r_buffer[0] = p_variant.get_type(); + } + } + + return OK; +} + +Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) { + const uint8_t *buf = p_buffer; + int len = p_len; + + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + uint8_t type = buf[0] & VARIANT_META_TYPE_MASK; + uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK; + + ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA); + + switch (type) { + case Variant::BOOL: { + bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0; + r_variant = val; + if (r_len) { + *r_len = 1; + } + } break; + case Variant::INT: { + buf += 1; + len -= 1; + if (r_len) { + *r_len = 1; + } + if (encode_mode == ENCODE_8) { + // 8 bits. + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + int8_t val = buf[0]; + r_variant = val; + if (r_len) { + (*r_len) += 1; + } + } else if (encode_mode == ENCODE_16) { + // 16 bits. + ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA); + int16_t val = decode_uint16(buf); + r_variant = val; + if (r_len) { + (*r_len) += 2; + } + } else if (encode_mode == ENCODE_32) { + // 32 bits. + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t val = decode_uint32(buf); + r_variant = val; + if (r_len) { + (*r_len) += 4; + } + } else { + // 64 bits. + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + int64_t val = decode_uint64(buf); + r_variant = val; + if (r_len) { + (*r_len) += 8; + } + } + } break; + default: + Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding); + if (err != OK) { + return err; + } + } + + return OK; +} + +Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) { + r_len = 0; + int size = 0; + + if (p_count == 0) { + if (r_raw) { + *r_raw = true; + } + return OK; + } + + // Try raw encoding optimization. + if (r_raw && p_count == 1) { + *r_raw = false; + const Variant &v = *(p_variants[0]); + if (v.get_type() == Variant::PACKED_BYTE_ARRAY) { + *r_raw = true; + const PackedByteArray pba = v; + if (p_buffer) { + memcpy(p_buffer, pba.ptr(), pba.size()); + } + r_len += pba.size(); + } else { + encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding); + r_len += size; + } + return OK; + } + + // Regular encoding. + for (int i = 0; i < p_count; i++) { + const Variant &v = *(p_variants[i]); + encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding); + r_len += size; + } + return OK; +} + +Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) { + r_len = 0; + int argc = r_variants.size(); + if (argc == 0 && p_raw) { + return OK; + } + ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA); + if (p_raw) { + r_len = p_len; + PackedByteArray pba; + pba.resize(p_len); + memcpy(pba.ptrw(), p_buffer, p_len); + r_variants.write[0] = pba; + return OK; + } + + Vector<Variant> args; + Vector<const Variant *> argp; + args.resize(argc); + + for (int i = 0; i < argc; i++) { + ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small."); + + int vlen; + Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding); + ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable."); + r_len += vlen; + } + return OK; +} + +Error MultiplayerAPI::_rpc_bind(int p_peer, Object *p_object, const StringName &p_method, Array p_args) { + Vector<Variant> args; + Vector<const Variant *> argsp; + args.resize(p_args.size()); + argsp.resize(p_args.size()); + Variant *ptr = args.ptrw(); + const Variant **pptr = argsp.ptrw(); + for (int i = 0; i < p_args.size(); i++) { + ptr[i] = p_args[i]; + pptr[i] = &ptr[i]; + } + return rpcp(p_object, p_peer, p_method, argsp.size() ? argsp.ptrw() : nullptr, argsp.size()); +} + +void MultiplayerAPI::_bind_methods() { + ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer); + ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer); + ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer); + ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id); + ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server); + ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id); + ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll); + ClassDB::bind_method(D_METHOD("rpc", "peer", "object", "method", "arguments"), &MultiplayerAPI::_rpc_bind, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("object_configuration_add", "object", "configuration"), &MultiplayerAPI::object_configuration_add); + ClassDB::bind_method(D_METHOD("object_configuration_remove", "object", "configuration"), &MultiplayerAPI::object_configuration_remove); + + ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer"); + + ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("set_default_interface", "interface_name"), &MultiplayerAPI::set_default_interface); + ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("get_default_interface"), &MultiplayerAPI::get_default_interface); + ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("create_default_interface"), &MultiplayerAPI::create_default_interface); + + ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("connected_to_server")); + ADD_SIGNAL(MethodInfo("connection_failed")); + ADD_SIGNAL(MethodInfo("server_disconnected")); + + BIND_ENUM_CONSTANT(RPC_MODE_DISABLED); + BIND_ENUM_CONSTANT(RPC_MODE_ANY_PEER); + BIND_ENUM_CONSTANT(RPC_MODE_AUTHORITY); +} + +/// MultiplayerAPIExtension + +Error MultiplayerAPIExtension::poll() { + int err; + if (GDVIRTUAL_CALL(_poll, err)) { + return (Error)err; + } + return OK; +} + +void MultiplayerAPIExtension::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) { + GDVIRTUAL_CALL(_set_multiplayer_peer, p_peer); +} + +Ref<MultiplayerPeer> MultiplayerAPIExtension::get_multiplayer_peer() { + Ref<MultiplayerPeer> peer; + if (GDVIRTUAL_CALL(_get_multiplayer_peer, peer)) { + return peer; + } + return nullptr; +} + +int MultiplayerAPIExtension::get_unique_id() { + int id; + if (GDVIRTUAL_CALL(_get_unique_id, id)) { + return id; + } + return 1; +} + +Vector<int> MultiplayerAPIExtension::get_peer_ids() { + Vector<int> ids; + if (GDVIRTUAL_CALL(_get_peer_ids, ids)) { + return ids; + } + return Vector<int>(); +} + +Error MultiplayerAPIExtension::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { + if (!GDVIRTUAL_IS_OVERRIDDEN(_rpc)) { + return ERR_UNAVAILABLE; + } + Array args; + for (int i = 0; i < p_argcount; i++) { + args.push_back(*p_arg[i]); + } + int ret; + if (GDVIRTUAL_CALL(_rpc, p_peer_id, p_obj, p_method, args, ret)) { + return (Error)ret; + } + return FAILED; +} + +int MultiplayerAPIExtension::get_remote_sender_id() { + int id; + if (GDVIRTUAL_CALL(_get_remote_sender_id, id)) { + return id; + } + return 0; +} + +Error MultiplayerAPIExtension::object_configuration_add(Object *p_object, Variant p_config) { + int err; + if (GDVIRTUAL_CALL(_object_configuration_add, p_object, p_config, err)) { + return (Error)err; + } + return ERR_UNAVAILABLE; +} + +Error MultiplayerAPIExtension::object_configuration_remove(Object *p_object, Variant p_config) { + int err; + if (GDVIRTUAL_CALL(_object_configuration_remove, p_object, p_config, err)) { + return (Error)err; + } + return ERR_UNAVAILABLE; +} + +void MultiplayerAPIExtension::_bind_methods() { + GDVIRTUAL_BIND(_poll); + GDVIRTUAL_BIND(_set_multiplayer_peer, "multiplayer_peer"); + GDVIRTUAL_BIND(_get_multiplayer_peer); + GDVIRTUAL_BIND(_get_unique_id); + GDVIRTUAL_BIND(_get_peer_ids); + GDVIRTUAL_BIND(_rpc, "peer", "object", "method", "args"); + GDVIRTUAL_BIND(_get_remote_sender_id); + GDVIRTUAL_BIND(_object_configuration_add, "object", "configuration"); + GDVIRTUAL_BIND(_object_configuration_remove, "object", "configuration"); +} diff --git a/scene/main/multiplayer_api.h b/scene/main/multiplayer_api.h new file mode 100644 index 0000000000..c1d90d651e --- /dev/null +++ b/scene/main/multiplayer_api.h @@ -0,0 +1,115 @@ +/*************************************************************************/ +/* multiplayer_api.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 MULTIPLAYER_API_H +#define MULTIPLAYER_API_H + +#include "core/object/ref_counted.h" +#include "scene/main/multiplayer_peer.h" + +class MultiplayerAPI : public RefCounted { + GDCLASS(MultiplayerAPI, RefCounted); + +private: + static StringName default_interface; + +protected: + static void _bind_methods(); + Error _rpc_bind(int p_peer, Object *p_obj, const StringName &p_method, Array args = Array()); + +public: + enum RPCMode { + RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) + RPC_MODE_ANY_PEER, // Any peer can call this RPC + RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC + }; + + static Ref<MultiplayerAPI> create_default_interface(); + static void set_default_interface(const StringName &p_interface); + static StringName get_default_interface(); + + static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding); + static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding); + static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false); + static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false); + + virtual Error poll() = 0; + virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) = 0; + virtual Ref<MultiplayerPeer> get_multiplayer_peer() = 0; + virtual int get_unique_id() = 0; + virtual Vector<int> get_peer_ids() = 0; + + virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) = 0; + virtual int get_remote_sender_id() = 0; + + virtual Error object_configuration_add(Object *p_object, Variant p_config) = 0; + virtual Error object_configuration_remove(Object *p_object, Variant p_config) = 0; + + bool has_multiplayer_peer() { return get_multiplayer_peer().is_valid(); } + bool is_server() { return get_unique_id() == MultiplayerPeer::TARGET_PEER_SERVER; } + + MultiplayerAPI() {} + virtual ~MultiplayerAPI() {} +}; + +VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode); + +class MultiplayerAPIExtension : public MultiplayerAPI { + GDCLASS(MultiplayerAPIExtension, MultiplayerAPI); + +protected: + static void _bind_methods(); + +public: + virtual Error poll() override; + virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override; + virtual Ref<MultiplayerPeer> get_multiplayer_peer() override; + virtual int get_unique_id() override; + virtual Vector<int> get_peer_ids() override; + + virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override; + virtual int get_remote_sender_id() override; + + virtual Error object_configuration_add(Object *p_object, Variant p_config) override; + virtual Error object_configuration_remove(Object *p_object, Variant p_config) override; + + // Extensions + GDVIRTUAL0R(int, _poll); + GDVIRTUAL1(_set_multiplayer_peer, Ref<MultiplayerPeer>); + GDVIRTUAL0R(Ref<MultiplayerPeer>, _get_multiplayer_peer); + GDVIRTUAL0RC(int, _get_unique_id); + GDVIRTUAL0RC(PackedInt32Array, _get_peer_ids); + GDVIRTUAL4R(int, _rpc, int, Object *, StringName, Array); + GDVIRTUAL0RC(int, _get_remote_sender_id); + GDVIRTUAL2R(int, _object_configuration_add, Object *, Variant); + GDVIRTUAL2R(int, _object_configuration_remove, Object *, Variant); +}; + +#endif // MULTIPLAYER_API_H diff --git a/core/multiplayer/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp index b262903ce8..aad5baccab 100644 --- a/core/multiplayer/multiplayer_peer.cpp +++ b/scene/main/multiplayer_peer.cpp @@ -62,11 +62,11 @@ int MultiplayerPeer::get_transfer_channel() const { return transfer_channel; } -void MultiplayerPeer::set_transfer_mode(Multiplayer::TransferMode p_mode) { +void MultiplayerPeer::set_transfer_mode(TransferMode p_mode) { transfer_mode = p_mode; } -Multiplayer::TransferMode MultiplayerPeer::get_transfer_mode() const { +MultiplayerPeer::TransferMode MultiplayerPeer::get_transfer_mode() const { return transfer_mode; } @@ -107,6 +107,10 @@ void MultiplayerPeer::_bind_methods() { BIND_CONSTANT(TARGET_PEER_BROADCAST); BIND_CONSTANT(TARGET_PEER_SERVER); + BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE); + BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE_ORDERED); + BIND_ENUM_CONSTANT(TRANSFER_MODE_RELIABLE); + ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("server_disconnected")); @@ -130,6 +134,20 @@ Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buff if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) { return (Error)err; } + if (GDVIRTUAL_IS_OVERRIDDEN(_get_packet_script)) { + if (!GDVIRTUAL_CALL(_get_packet_script, script_buffer)) { + return FAILED; + } + + if (script_buffer.size() == 0) { + return Error::ERR_UNAVAILABLE; + } + + *r_buffer = script_buffer.ptr(); + r_buffer_size = script_buffer.size(); + + return Error::OK; + } WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_native is unimplemented!"); return FAILED; } @@ -139,6 +157,16 @@ Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) { return (Error)err; } + if (GDVIRTUAL_IS_OVERRIDDEN(_put_packet_script)) { + PackedByteArray a; + a.resize(p_buffer_size); + memcpy(a.ptrw(), p_buffer, p_buffer_size); + + if (!GDVIRTUAL_CALL(_put_packet_script, a, err)) { + return FAILED; + } + return (Error)err; + } WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!"); return FAILED; } @@ -167,17 +195,17 @@ int MultiplayerPeerExtension::get_transfer_channel() const { return MultiplayerPeer::get_transfer_channel(); } -void MultiplayerPeerExtension::set_transfer_mode(Multiplayer::TransferMode p_mode) { +void MultiplayerPeerExtension::set_transfer_mode(TransferMode p_mode) { if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) { return; } MultiplayerPeer::set_transfer_mode(p_mode); } -Multiplayer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const { +MultiplayerPeer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const { int mode; if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) { - return (Multiplayer::TransferMode)mode; + return (MultiplayerPeer::TransferMode)mode; } return MultiplayerPeer::get_transfer_mode(); } @@ -254,6 +282,9 @@ void MultiplayerPeerExtension::_bind_methods() { GDVIRTUAL_BIND(_get_available_packet_count); GDVIRTUAL_BIND(_get_max_packet_size); + GDVIRTUAL_BIND(_get_packet_script) + GDVIRTUAL_BIND(_put_packet_script, "p_buffer"); + GDVIRTUAL_BIND(_set_transfer_channel, "p_channel"); GDVIRTUAL_BIND(_get_transfer_channel); diff --git a/core/multiplayer/multiplayer_peer.h b/scene/main/multiplayer_peer.h index dee2be7b4b..8a012d7520 100644 --- a/core/multiplayer/multiplayer_peer.h +++ b/scene/main/multiplayer_peer.h @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NETWORKED_MULTIPLAYER_PEER_H -#define NETWORKED_MULTIPLAYER_PEER_H +#ifndef MULTIPLAYER_PEER_H +#define MULTIPLAYER_PEER_H #include "core/io/packet_peer.h" -#include "core/multiplayer/multiplayer.h" #include "core/object/gdvirtual.gen.inc" #include "core/object/script_language.h" @@ -41,12 +40,19 @@ class MultiplayerPeer : public PacketPeer { GDCLASS(MultiplayerPeer, PacketPeer); +public: + enum TransferMode { + TRANSFER_MODE_UNRELIABLE, + TRANSFER_MODE_UNRELIABLE_ORDERED, + TRANSFER_MODE_RELIABLE + }; + protected: static void _bind_methods(); private: int transfer_channel = 0; - Multiplayer::TransferMode transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; + TransferMode transfer_mode = TRANSFER_MODE_RELIABLE; bool refuse_connections = false; public: @@ -63,8 +69,8 @@ public: virtual void set_transfer_channel(int p_channel); virtual int get_transfer_channel() const; - virtual void set_transfer_mode(Multiplayer::TransferMode p_mode); - virtual Multiplayer::TransferMode get_transfer_mode() const; + virtual void set_transfer_mode(TransferMode p_mode); + virtual TransferMode get_transfer_mode() const; virtual void set_refuse_new_connections(bool p_enable); virtual bool is_refusing_new_connections() const; @@ -86,6 +92,7 @@ public: }; VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus); +VARIANT_ENUM_CAST(MultiplayerPeer::TransferMode); class MultiplayerPeerExtension : public MultiplayerPeer { GDCLASS(MultiplayerPeerExtension, MultiplayerPeer); @@ -93,6 +100,8 @@ class MultiplayerPeerExtension : public MultiplayerPeer { protected: static void _bind_methods(); + PackedByteArray script_buffer; + public: /* PacketPeer */ virtual int get_available_packet_count() const override; @@ -103,8 +112,8 @@ public: /* MultiplayerPeer */ virtual void set_transfer_channel(int p_channel) override; virtual int get_transfer_channel() const override; - virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) override; - virtual Multiplayer::TransferMode get_transfer_mode() const override; + virtual void set_transfer_mode(TransferMode p_mode) override; + virtual TransferMode get_transfer_mode() const override; virtual void set_target_peer(int p_peer_id) override; virtual int get_packet_peer() const override; @@ -126,6 +135,10 @@ public: GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int); GDVIRTUAL0RC(int, _get_max_packet_size); + /* PacketPeer GDScript */ + GDVIRTUAL0R(PackedByteArray, _get_packet_script); + GDVIRTUAL1R(int, _put_packet_script, PackedByteArray); + /* MultiplayerPeer GDExtension */ GDVIRTUAL1(_set_transfer_channel, int); GDVIRTUAL0RC(int, _get_transfer_channel); @@ -141,4 +154,4 @@ public: GDVIRTUAL0RC(int, _get_connection_status); }; -#endif // NETWORKED_MULTIPLAYER_PEER_H +#endif // MULTIPLAYER_PEER_H diff --git a/scene/main/node.cpp b/scene/main/node.cpp index b4701637a4..ea9788de27 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -33,12 +33,12 @@ #include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/io/resource_loader.h" -#include "core/multiplayer/multiplayer_api.h" #include "core/object/message_queue.h" #include "core/string/print_string.h" #include "instance_placeholder.h" #include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" +#include "scene/main/multiplayer_api.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" #include "viewport.h" @@ -582,35 +582,30 @@ bool Node::is_multiplayer_authority() const { /***** RPC CONFIG ********/ -uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local, Multiplayer::TransferMode p_transfer_mode, int p_channel) { - for (int i = 0; i < data.rpc_methods.size(); i++) { - if (data.rpc_methods[i].name == p_method) { - Multiplayer::RPCConfig &nd = data.rpc_methods.write[i]; - nd.rpc_mode = p_rpc_mode; - nd.transfer_mode = p_transfer_mode; - nd.call_local = p_call_local; - nd.channel = p_channel; - return i | (1 << 15); - } +void Node::rpc_config(const StringName &p_method, const Variant &p_config) { + if (data.rpc_config.get_type() != Variant::DICTIONARY) { + data.rpc_config = Dictionary(); + } + Dictionary node_config = data.rpc_config; + if (p_config.get_type() == Variant::NIL) { + node_config.erase(p_method); + } else { + ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY); + node_config[p_method] = p_config; } - // New method - Multiplayer::RPCConfig nd; - nd.name = p_method; - nd.rpc_mode = p_rpc_mode; - nd.transfer_mode = p_transfer_mode; - nd.channel = p_channel; - nd.call_local = p_call_local; - data.rpc_methods.push_back(nd); - return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15); +} + +const Variant Node::get_node_rpc_config() const { + return data.rpc_config; } /***** RPC FUNCTIONS ********/ -void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; - return; + return ERR_INVALID_PARAMETER; } Variant::Type type = p_args[0]->get_type(); @@ -618,28 +613,28 @@ void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING_NAME; - return; + return ERR_INVALID_PARAMETER; } StringName method = (*p_args[0]).operator StringName(); - rpcp(0, method, &p_args[1], p_argcount - 1); - + Error err = rpcp(0, method, &p_args[1], p_argcount - 1); r_error.error = Callable::CallError::CALL_OK; + return err; } -void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Error Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 2; - return; + return ERR_INVALID_PARAMETER; } if (p_args[0]->get_type() != Variant::INT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::INT; - return; + return ERR_INVALID_PARAMETER; } Variant::Type type = p_args[1]->get_type(); @@ -647,20 +642,20 @@ void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallEr r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::STRING_NAME; - return; + return ERR_INVALID_PARAMETER; } int peer_id = *p_args[0]; StringName method = (*p_args[1]).operator StringName(); - rpcp(peer_id, method, &p_args[2], p_argcount - 2); - + Error err = rpcp(peer_id, method, &p_args[2], p_argcount - 2); r_error.error = Callable::CallError::CALL_OK; + return err; } -void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { - ERR_FAIL_COND(!is_inside_tree()); - get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount); +Error Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { + ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED); + return get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount); } Ref<MultiplayerAPI> Node::get_multiplayer() const { @@ -670,10 +665,6 @@ Ref<MultiplayerAPI> Node::get_multiplayer() const { return get_tree()->get_multiplayer(get_path()); } -Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { - return data.rpc_methods; -} - //////////// end of rpc bool Node::can_process_notification(int p_what) const { @@ -2404,7 +2395,7 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { if (copy && copytarget) { const Callable copy_callable = Callable(copytarget, E.callable.get_method()); if (!copy->is_connected(E.signal.get_name(), copy_callable)) { - copy->connect(E.signal.get_name(), copy_callable, E.binds, E.flags); + copy->connect(E.signal.get_name(), copy_callable, E.flags); } } } @@ -2490,7 +2481,7 @@ void Node::_replace_connections_target(Node *p_new_target) { c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method())); bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method()); ERR_CONTINUE_MSG(!valid, vformat("Attempt to connect signal '%s.%s' to nonexistent method '%s.%s'.", c.signal.get_object()->get_class(), c.signal.get_name(), c.callable.get_object()->get_class(), c.callable.get_method())); - c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.binds, c.flags); + c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.flags); } } } @@ -2888,7 +2879,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority); ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); - ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("rpc_config", "method", "config"), &Node::rpc_config); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description); diff --git a/scene/main/node.h b/scene/main/node.h index 3c4727f11c..ccd1d561d2 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -127,7 +127,7 @@ private: Node *process_owner = nullptr; int multiplayer_authority = 1; // Server by default. - Vector<Multiplayer::RPCConfig> rpc_methods; + Variant rpc_config; // Variables used to properly sort the node when processing, ignored otherwise. // TODO: Should move all the stuff below to bits. @@ -183,8 +183,8 @@ private: TypedArray<Node> _get_children(bool p_include_internal = true) const; Array _get_groups() const; - void _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); - void _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); + Error _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); + Error _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); _FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; } _FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; } @@ -491,30 +491,16 @@ public: int get_multiplayer_authority() const; bool is_multiplayer_authority() const; - uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC - Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const; + void rpc_config(const StringName &p_method, const Variant &p_config); // config a local method for RPC + const Variant get_node_rpc_config() const; template <typename... VarArgs> - void rpc(const StringName &p_method, VarArgs... p_args) { - Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. - const Variant *argptrs[sizeof...(p_args) + 1]; - for (uint32_t i = 0; i < sizeof...(p_args); i++) { - argptrs[i] = &args[i]; - } - rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); - } + Error rpc(const StringName &p_method, VarArgs... p_args); template <typename... VarArgs> - void rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) { - Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. - const Variant *argptrs[sizeof...(p_args) + 1]; - for (uint32_t i = 0; i < sizeof...(p_args); i++) { - argptrs[i] = &args[i]; - } - rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); - } + Error rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args); - void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); + Error rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; @@ -526,4 +512,22 @@ VARIANT_ENUM_CAST(Node::DuplicateFlags); typedef HashSet<Node *, Node::Comparator> NodeSet; -#endif +// Template definitions must be in the header so they are always fully initialized before their usage. +// See this StackOverflow question for more information: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file + +template <typename... VarArgs> +Error Node::rpc(const StringName &p_method, VarArgs... p_args) { + return rpc_id(0, p_method, p_args...); +} + +template <typename... VarArgs> +Error Node::rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) { + Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. + const Variant *argptrs[sizeof...(p_args) + 1]; + for (uint32_t i = 0; i < sizeof...(p_args); i++) { + argptrs[i] = &args[i]; + } + return rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); +} + +#endif // NODE_H diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index a76c00efcb..644fb3e9cc 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -34,9 +34,9 @@ #include "core/debugger/engine_debugger.h" #include "core/input/input.h" #include "core/io/dir_access.h" +#include "core/io/image_loader.h" #include "core/io/marshalls.h" #include "core/io/resource_loader.h" -#include "core/multiplayer/multiplayer_api.h" #include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -44,6 +44,7 @@ #include "node.h" #include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" +#include "scene/main/multiplayer_api.h" #include "scene/main/viewport.h" #include "scene/resources/font.h" #include "scene/resources/material.h" @@ -1212,19 +1213,17 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePat if (p_root_path.is_empty()) { ERR_FAIL_COND(!p_multiplayer.is_valid()); if (multiplayer.is_valid()) { - multiplayer->set_root_path(NodePath()); + multiplayer->object_configuration_remove(nullptr, NodePath("/" + root->get_name())); } multiplayer = p_multiplayer; - multiplayer->set_root_path("/" + root->get_name()); + multiplayer->object_configuration_add(nullptr, NodePath("/" + root->get_name())); } else { + if (custom_multiplayers.has(p_root_path)) { + custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path); + } if (p_multiplayer.is_valid()) { custom_multiplayers[p_root_path] = p_multiplayer; - p_multiplayer->set_root_path(p_root_path); - } else { - if (custom_multiplayers.has(p_root_path)) { - custom_multiplayers[p_root_path]->set_root_path(NodePath()); - custom_multiplayers.erase(p_root_path); - } + p_multiplayer->object_configuration_add(nullptr, p_root_path); } } } @@ -1414,7 +1413,7 @@ SceneTree::SceneTree() { #endif // _3D_DISABLED // Initialize network state. - set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI))); + set_multiplayer(MultiplayerAPI::create_default_interface()); root->set_as_audio_listener_2d(true); current_scene = nullptr; @@ -1446,25 +1445,48 @@ SceneTree::SceneTree() { bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false); root->set_snap_2d_vertices_to_pixel(snap_2d_vertices); - int shadowmap_size = GLOBAL_DEF("rendering/shadows/shadow_atlas/size", 4096); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); - GLOBAL_DEF("rendering/shadows/shadow_atlas/size.mobile", 2048); - bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/shadow_atlas/16_bits", true); - int atlas_q0 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_0_subdiv", 2); - int atlas_q1 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_1_subdiv", 2); - int atlas_q2 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_2_subdiv", 3); - int atlas_q3 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_3_subdiv", 4); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - - root->set_shadow_atlas_size(shadowmap_size); - root->set_shadow_atlas_16_bits(shadowmap_16_bits); - root->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0)); - root->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1)); - root->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2)); - root->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3)); + // We setup VRS for the main viewport here, in the editor this will have little effect. + const int vrs_mode = GLOBAL_DEF("rendering/vrs/mode", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/mode", PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR"))); + root->set_vrs_mode(Viewport::VRSMode(vrs_mode)); + const String vrs_texture_path = String(GLOBAL_DEF("rendering/vrs/texture", String())).strip_edges(); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/texture", + PropertyInfo(Variant::STRING, + "rendering/vrs/texture", + PROPERTY_HINT_FILE, "*.png")); + if (vrs_mode == 1 && !vrs_texture_path.is_empty()) { + Ref<Image> vrs_image; + vrs_image.instantiate(); + Error load_err = ImageLoader::load_image(vrs_texture_path, vrs_image); + if (load_err) { + ERR_PRINT("Non-existing or invalid VRS texture at '" + vrs_texture_path + "'."); + } else { + Ref<ImageTexture> vrs_texture; + vrs_texture.instantiate(); + vrs_texture->create_from_image(vrs_image); + root->set_vrs_texture(vrs_texture); + } + } + + int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384")); + GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048); + bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_16_bits", true); + int atlas_q0 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", 2); + int atlas_q1 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", 2); + int atlas_q2 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", 3); + int atlas_q3 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", 4); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + + root->set_positional_shadow_atlas_size(shadowmap_size); + root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits); + root->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0)); + root->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1)); + root->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2)); + root->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3)); Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/2d/sdf/oversize", 1))); root->set_sdf_oversize(sdf_oversize); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index a34aa8e2cd..a512feacc8 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -90,8 +90,8 @@ private: Window *root = nullptr; uint64_t tree_version = 1; - double physics_process_time = 1.0; - double process_time = 1.0; + double physics_process_time = 0.0; + double process_time = 0.0; bool accept_quit = true; bool quit_on_go_back = true; diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index 0049359cad..a621aea9c8 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -64,9 +64,9 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu if (active) { if (o->override.get_type() == Variant::OBJECT) { RID tex_rid = p_value; - RS::get_singleton()->global_variable_set_override(*r, tex_rid); + RS::get_singleton()->global_shader_uniform_set_override(*r, tex_rid); } else { - RS::get_singleton()->global_variable_set_override(*r, p_value); + RS::get_singleton()->global_shader_uniform_set_override(*r, p_value); } } o->in_use = p_value.get_type() != Variant::NIL; @@ -93,13 +93,13 @@ bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const { Vector<StringName> variables; - variables = RS::get_singleton()->global_variable_get_list(); + variables = RS::get_singleton()->global_shader_uniform_get_list(); for (int i = 0; i < variables.size(); i++) { PropertyInfo pinfo; pinfo.name = "params/" + variables[i]; pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; - switch (RS::get_singleton()->global_variable_get_type(variables[i])) { + switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) { case RS::GLOBAL_VAR_TYPE_BOOL: { pinfo.type = Variant::BOOL; } break; @@ -155,7 +155,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const pinfo.type = Variant::VECTOR3; } break; case RS::GLOBAL_VAR_TYPE_VEC4: { - pinfo.type = Variant::QUATERNION; + pinfo.type = Variant::VECTOR4; } break; case RS::GLOBAL_VAR_TYPE_RECT2: { pinfo.type = Variant::RECT2; @@ -169,15 +169,15 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const case RS::GLOBAL_VAR_TYPE_MAT3: { pinfo.type = Variant::BASIS; } break; + case RS::GLOBAL_VAR_TYPE_MAT4: { + pinfo.type = Variant::PROJECTION; + } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { pinfo.type = Variant::TRANSFORM2D; } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM: { pinfo.type = Variant::TRANSFORM3D; } break; - case RS::GLOBAL_VAR_TYPE_MAT4: { - pinfo.type = Variant::PACKED_INT32_ARRAY; - } break; case RS::GLOBAL_VAR_TYPE_SAMPLER2D: { pinfo.type = Variant::OBJECT; pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; @@ -234,9 +234,9 @@ void ShaderGlobalsOverride::_activate() { if (o->in_use && o->override.get_type() != Variant::NIL) { if (o->override.get_type() == Variant::OBJECT) { RID tex_rid = o->override; - RS::get_singleton()->global_variable_set_override(E.key, tex_rid); + RS::get_singleton()->global_shader_uniform_set_override(E.key, tex_rid); } else { - RS::get_singleton()->global_variable_set_override(E.key, o->override); + RS::get_singleton()->global_shader_uniform_set_override(E.key, o->override); } } @@ -258,7 +258,7 @@ void ShaderGlobalsOverride::_notification(int p_what) { for (const KeyValue<StringName, Override> &E : overrides) { const Override *o = &E.value; if (o->in_use) { - RS::get_singleton()->global_variable_set_override(E.key, Variant()); + RS::get_singleton()->global_shader_uniform_set_override(E.key, Variant()); } } } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 0080e899c3..584fad9648 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1037,44 +1037,44 @@ Ref<ViewportTexture> Viewport::get_texture() const { return default_texture; } -void Viewport::set_shadow_atlas_size(int p_size) { - shadow_atlas_size = p_size; - RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size, shadow_atlas_16_bits); +void Viewport::set_positional_shadow_atlas_size(int p_size) { + positional_shadow_atlas_size = p_size; + RS::get_singleton()->viewport_set_positional_shadow_atlas_size(viewport, p_size, positional_shadow_atlas_16_bits); } -int Viewport::get_shadow_atlas_size() const { - return shadow_atlas_size; +int Viewport::get_positional_shadow_atlas_size() const { + return positional_shadow_atlas_size; } -void Viewport::set_shadow_atlas_16_bits(bool p_16_bits) { - if (shadow_atlas_16_bits == p_16_bits) { +void Viewport::set_positional_shadow_atlas_16_bits(bool p_16_bits) { + if (positional_shadow_atlas_16_bits == p_16_bits) { return; } - shadow_atlas_16_bits = p_16_bits; - RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, shadow_atlas_size, shadow_atlas_16_bits); + positional_shadow_atlas_16_bits = p_16_bits; + RS::get_singleton()->viewport_set_positional_shadow_atlas_size(viewport, positional_shadow_atlas_size, positional_shadow_atlas_16_bits); } -bool Viewport::get_shadow_atlas_16_bits() const { - return shadow_atlas_16_bits; +bool Viewport::get_positional_shadow_atlas_16_bits() const { + return positional_shadow_atlas_16_bits; } -void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv) { +void Viewport::set_positional_shadow_atlas_quadrant_subdiv(int p_quadrant, PositionalShadowAtlasQuadrantSubdiv p_subdiv) { ERR_FAIL_INDEX(p_quadrant, 4); ERR_FAIL_INDEX(p_subdiv, SHADOW_ATLAS_QUADRANT_SUBDIV_MAX); - if (shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv) { + if (positional_shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv) { return; } - shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv; + positional_shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv; static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX] = { 0, 1, 4, 16, 64, 256, 1024 }; - RS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]); + RS::get_singleton()->viewport_set_positional_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]); } -Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const { +Viewport::PositionalShadowAtlasQuadrantSubdiv Viewport::get_positional_shadow_atlas_quadrant_subdiv(int p_quadrant) const { ERR_FAIL_INDEX_V(p_quadrant, 4, SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED); - return shadow_atlas_quadrant_subdiv[p_quadrant]; + return positional_shadow_atlas_quadrant_subdiv[p_quadrant]; } Transform2D Viewport::_get_input_pre_xform() const { @@ -1215,7 +1215,7 @@ void Viewport::_gui_show_tooltip() { panel->connect("mouse_entered", callable_mp(this, &Viewport::_gui_cancel_tooltip)); } - base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); panel->set_transient(true); panel->set_flag(Window::FLAG_NO_FOCUS, true); @@ -1234,13 +1234,23 @@ void Viewport::_gui_show_tooltip() { Rect2i vr = window->get_usable_parent_rect(); if (r.size.x + r.position.x > vr.size.x + vr.position.x) { - r.position.x = vr.position.x + vr.size.x - r.size.x; + // Place it in the opposite direction. If it fails, just hug the border. + r.position.x = gui.tooltip_pos.x - r.size.x - tooltip_offset.x; + + if (r.position.x < vr.position.x) { + r.position.x = vr.position.x + vr.size.x - r.size.x; + } } else if (r.position.x < vr.position.x) { r.position.x = vr.position.x; } if (r.size.y + r.position.y > vr.size.y + vr.position.y) { - r.position.y = vr.position.y + vr.size.y - r.size.y; + // Same as above. + r.position.y = gui.tooltip_pos.y - r.size.y - tooltip_offset.y; + + if (r.position.y < vr.position.y) { + r.position.y = vr.position.y + vr.size.y - r.size.y; + } } else if (r.position.y < vr.position.y) { r.position.y = vr.position.y; } @@ -2488,17 +2498,20 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) { Vector2i diff = mm->get_position() - gui.subwindow_drag_from; Size2i min_size = gui.subwindow_focused->get_min_size(); + + Size2i min_size_adjusted = min_size; if (gui.subwindow_focused->is_wrapping_controls()) { Size2i cms = gui.subwindow_focused->get_contents_minimum_size(); - min_size.x = MAX(cms.x, min_size.x); - min_size.y = MAX(cms.y, min_size.y); + min_size_adjusted.x = MAX(cms.x, min_size.x); + min_size_adjusted.y = MAX(cms.y, min_size.y); } - min_size.x = MAX(min_size.x, 1); - min_size.y = MAX(min_size.y, 1); + + min_size_adjusted.x = MAX(min_size_adjusted.x, 1); + min_size_adjusted.y = MAX(min_size_adjusted.y, 1); Rect2i r = gui.subwindow_resize_from_rect; - Size2i limit = r.size - min_size; + Size2i limit = r.size - min_size_adjusted; switch (gui.subwindow_resize_mode) { case SUB_WINDOW_RESIZE_TOP_LEFT: { @@ -2553,6 +2566,19 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { } } + Size2i max_size = gui.subwindow_focused->get_max_size(); + if ((max_size.x > 0 || max_size.y > 0) && (max_size.x >= min_size.x && max_size.y >= min_size.y)) { + max_size.x = MAX(max_size.x, 1); + max_size.y = MAX(max_size.y, 1); + + if (r.size.x > max_size.x) { + r.size.x = max_size.x; + } + if (r.size.y > max_size.y) { + r.size.y = max_size.y; + } + } + gui.subwindow_focused->_rect_changed_callback(r); } @@ -2590,7 +2616,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close")); Rect2 close_rect; - close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs); + close_rect.position = Vector2(r.position.x + r.size.x - close_h_ofs, r.position.y - close_v_ofs); close_rect.size = close_icon->get_size(); if (gui.subwindow_focused != sw.window) { @@ -3080,6 +3106,41 @@ Viewport::DefaultCanvasItemTextureRepeat Viewport::get_default_canvas_item_textu return default_canvas_item_texture_repeat; } +void Viewport::set_vrs_mode(Viewport::VRSMode p_vrs_mode) { + // Note, set this even if not supported on this hardware, it will only be used if it is but we want to save the value as set by the user. + vrs_mode = p_vrs_mode; + + switch (p_vrs_mode) { + case VRS_TEXTURE: { + RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_TEXTURE); + } break; + case VRS_XR: { + RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_XR); + } break; + default: { + RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_DISABLED); + } break; + } + + notify_property_list_changed(); +} + +Viewport::VRSMode Viewport::get_vrs_mode() const { + return vrs_mode; +} + +void Viewport::set_vrs_texture(Ref<Texture2D> p_texture) { + vrs_texture = p_texture; + + // TODO need to add something here in case the RID changes + RID tex = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RS::get_singleton()->viewport_set_vrs_texture(viewport, tex); +} + +Ref<Texture2D> Viewport::get_vrs_texture() const { + return vrs_texture; +} + DisplayServer::WindowID Viewport::get_window_id() const { return DisplayServer::MAIN_WINDOW_ID; } @@ -3586,17 +3647,17 @@ float Viewport::get_fsr_sharpness() const { return fsr_sharpness; } -void Viewport::set_fsr_mipmap_bias(float p_fsr_mipmap_bias) { - if (fsr_mipmap_bias == p_fsr_mipmap_bias) { +void Viewport::set_texture_mipmap_bias(float p_texture_mipmap_bias) { + if (texture_mipmap_bias == p_texture_mipmap_bias) { return; } - fsr_mipmap_bias = p_fsr_mipmap_bias; - RS::get_singleton()->viewport_set_fsr_mipmap_bias(viewport, p_fsr_mipmap_bias); + texture_mipmap_bias = p_texture_mipmap_bias; + RS::get_singleton()->viewport_set_texture_mipmap_bias(viewport, p_texture_mipmap_bias); } -float Viewport::get_fsr_mipmap_bias() const { - return fsr_mipmap_bias; +float Viewport::get_texture_mipmap_bias() const { + return texture_mipmap_bias; } #endif // _3D_DISABLED @@ -3667,11 +3728,11 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_remove_focus_for_window"), &Viewport::_gui_remove_focus_for_window); ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus); - ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size); - ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size); + ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_size", "size"), &Viewport::set_positional_shadow_atlas_size); + ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_size"), &Viewport::get_positional_shadow_atlas_size); - ClassDB::bind_method(D_METHOD("set_shadow_atlas_16_bits", "enable"), &Viewport::set_shadow_atlas_16_bits); - ClassDB::bind_method(D_METHOD("get_shadow_atlas_16_bits"), &Viewport::get_shadow_atlas_16_bits); + ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_16_bits", "enable"), &Viewport::set_positional_shadow_atlas_16_bits); + ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_16_bits"), &Viewport::get_positional_shadow_atlas_16_bits); ClassDB::bind_method(D_METHOD("set_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels); ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled); @@ -3682,8 +3743,8 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_snap_2d_vertices_to_pixel", "enabled"), &Viewport::set_snap_2d_vertices_to_pixel); ClassDB::bind_method(D_METHOD("is_snap_2d_vertices_to_pixel_enabled"), &Viewport::is_snap_2d_vertices_to_pixel_enabled); - ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv); - ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv); + ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_positional_shadow_atlas_quadrant_subdiv); + ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_positional_shadow_atlas_quadrant_subdiv); ClassDB::bind_method(D_METHOD("set_input_as_handled"), &Viewport::set_input_as_handled); ClassDB::bind_method(D_METHOD("is_input_handled"), &Viewport::is_input_handled); @@ -3738,8 +3799,14 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_fsr_sharpness", "fsr_sharpness"), &Viewport::set_fsr_sharpness); ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &Viewport::get_fsr_sharpness); - ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias); - ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias); + ClassDB::bind_method(D_METHOD("set_texture_mipmap_bias", "texture_mipmap_bias"), &Viewport::set_texture_mipmap_bias); + ClassDB::bind_method(D_METHOD("get_texture_mipmap_bias"), &Viewport::get_texture_mipmap_bias); + + ClassDB::bind_method(D_METHOD("set_vrs_mode", "mode"), &Viewport::set_vrs_mode); + ClassDB::bind_method(D_METHOD("get_vrs_mode"), &Viewport::get_vrs_mode); + + ClassDB::bind_method(D_METHOD("set_vrs_texture", "texture"), &Viewport::set_vrs_texture); + ClassDB::bind_method(D_METHOD("get_vrs_texture"), &Viewport::get_vrs_texture); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr"); @@ -3763,9 +3830,12 @@ void Viewport::_bind_methods() { ADD_GROUP("Scaling 3D", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scaling_3d_scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scaling_3d_scale", "get_scaling_3d_scale"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.001"), "set_texture_mipmap_bias", "get_texture_mipmap_bias"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness"); #endif + ADD_GROUP("Variable Rate Shading", "vrs_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vrs_mode", PROPERTY_HINT_ENUM, "Disabled,Texture,Depth buffer,XR"), "set_vrs_mode", "get_vrs_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "vrs_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_vrs_texture", "get_vrs_texture"); ADD_GROUP("Canvas Items", "canvas_item_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat"); @@ -3783,13 +3853,13 @@ void Viewport::_bind_methods() { ADD_GROUP("SDF", "sdf_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale"); - ADD_GROUP("Shadow Atlas", "shadow_atlas_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_atlas_16_bits"), "set_shadow_atlas_16_bits", "get_shadow_atlas_16_bits"); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 3); + ADD_GROUP("Positional Shadow Atlas", "positional_shadow_atlas_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "positional_shadow_atlas_size"), "set_positional_shadow_atlas_size", "get_positional_shadow_atlas_size"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "positional_shadow_atlas_16_bits"), "set_positional_shadow_atlas_16_bits", "get_positional_shadow_atlas_16_bits"); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 0); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 1); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 2); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 3); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform"); @@ -3876,6 +3946,17 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT); BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT); BIND_ENUM_CONSTANT(SDF_SCALE_MAX); + + BIND_ENUM_CONSTANT(VRS_DISABLED); + BIND_ENUM_CONSTANT(VRS_TEXTURE); + BIND_ENUM_CONSTANT(VRS_XR); + BIND_ENUM_CONSTANT(VRS_MAX); +} + +void Viewport::_validate_property(PropertyInfo &property) const { + if (vrs_mode != VRS_TEXTURE && (property.name == "vrs_texture")) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } } Viewport::Viewport() { @@ -3891,15 +3972,15 @@ Viewport::Viewport() { canvas_layers.insert(nullptr); // This eases picking code (interpreted as the canvas of the Viewport). - set_shadow_atlas_size(shadow_atlas_size); + set_positional_shadow_atlas_size(positional_shadow_atlas_size); for (int i = 0; i < 4; i++) { - shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX; + positional_shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX; } - set_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4); - set_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4); - set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16); - set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64); + set_positional_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4); + set_positional_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4); + set_positional_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16); + set_positional_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64); set_mesh_lod_threshold(mesh_lod_threshold); @@ -3923,8 +4004,8 @@ Viewport::Viewport() { float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness"); set_fsr_sharpness(fsr_sharpness); - float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias"); - set_fsr_mipmap_bias(fsr_mipmap_bias); + float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias"); + set_texture_mipmap_bias(texture_mipmap_bias); #endif // _3D_DISABLED set_sdf_oversize(sdf_oversize); // Set to server. diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a22a2acf49..4221baff06 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -95,7 +95,7 @@ public: SCALING_3D_MODE_MAX }; - enum ShadowAtlasQuadrantSubdiv { + enum PositionalShadowAtlasQuadrantSubdiv { SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED, SHADOW_ATLAS_QUADRANT_SUBDIV_1, SHADOW_ATLAS_QUADRANT_SUBDIV_4, @@ -197,6 +197,13 @@ public: SUBWINDOW_CANVAS_LAYER = 1024 }; + enum VRSMode { + VRS_DISABLED, + VRS_TEXTURE, + VRS_XR, + VRS_MAX + }; + private: friend class ViewportTexture; @@ -286,9 +293,9 @@ private: DebugDraw debug_draw = DEBUG_DRAW_DISABLED; - int shadow_atlas_size = 2048; - bool shadow_atlas_16_bits = true; - ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4]; + int positional_shadow_atlas_size = 2048; + bool positional_shadow_atlas_16_bits = true; + PositionalShadowAtlasQuadrantSubdiv positional_shadow_atlas_quadrant_subdiv[4]; MSAA msaa = MSAA_DISABLED; ScreenSpaceAA screen_space_aa = SCREEN_SPACE_AA_DISABLED; @@ -297,7 +304,7 @@ private: Scaling3DMode scaling_3d_mode = SCALING_3D_MODE_BILINEAR; float scaling_3d_scale = 1.0; float fsr_sharpness = 0.2f; - float fsr_mipmap_bias = 0.0f; + float texture_mipmap_bias = 0.0f; bool use_debanding = false; float mesh_lod_threshold = 1.0; bool use_occlusion_culling = false; @@ -333,6 +340,10 @@ private: RID canvas_item; }; + // VRS + VRSMode vrs_mode = VRS_DISABLED; + Ref<Texture2D> vrs_texture; + struct GUI { // info used when this is a window @@ -502,14 +513,14 @@ public: Ref<ViewportTexture> get_texture() const; - void set_shadow_atlas_size(int p_size); - int get_shadow_atlas_size() const; + void set_positional_shadow_atlas_size(int p_size); + int get_positional_shadow_atlas_size() const; - void set_shadow_atlas_16_bits(bool p_16_bits); - bool get_shadow_atlas_16_bits() const; + void set_positional_shadow_atlas_16_bits(bool p_16_bits); + bool get_positional_shadow_atlas_16_bits() const; - void set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv); - ShadowAtlasQuadrantSubdiv get_shadow_atlas_quadrant_subdiv(int p_quadrant) const; + void set_positional_shadow_atlas_quadrant_subdiv(int p_quadrant, PositionalShadowAtlasQuadrantSubdiv p_subdiv); + PositionalShadowAtlasQuadrantSubdiv get_positional_shadow_atlas_quadrant_subdiv(int p_quadrant) const; void set_msaa(MSAA p_msaa); MSAA get_msaa() const; @@ -529,8 +540,8 @@ public: void set_fsr_sharpness(float p_fsr_sharpness); float get_fsr_sharpness() const; - void set_fsr_mipmap_bias(float p_fsr_mipmap_bias); - float get_fsr_mipmap_bias() const; + void set_texture_mipmap_bias(float p_texture_mipmap_bias); + float get_texture_mipmap_bias() const; void set_use_debanding(bool p_use_debanding); bool is_using_debanding() const; @@ -604,6 +615,14 @@ public: void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat); DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const; + // VRS + + void set_vrs_mode(VRSMode p_vrs_mode); + VRSMode get_vrs_mode() const; + + void set_vrs_texture(Ref<Texture2D> p_texture); + Ref<Texture2D> get_vrs_texture() const; + virtual DisplayServer::WindowID get_window_id() const = 0; void set_embedding_subwindows(bool p_embed); @@ -690,6 +709,7 @@ public: bool is_using_xr(); #endif // _3D_DISABLED + virtual void _validate_property(PropertyInfo &property) const override; Viewport(); ~Viewport(); }; @@ -746,16 +766,17 @@ public: }; VARIANT_ENUM_CAST(Viewport::Scaling3DMode); VARIANT_ENUM_CAST(SubViewport::UpdateMode); -VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); +VARIANT_ENUM_CAST(Viewport::PositionalShadowAtlasQuadrantSubdiv); VARIANT_ENUM_CAST(Viewport::MSAA); VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA); VARIANT_ENUM_CAST(Viewport::DebugDraw); VARIANT_ENUM_CAST(Viewport::SDFScale); VARIANT_ENUM_CAST(Viewport::SDFOversize); +VARIANT_ENUM_CAST(Viewport::VRSMode); VARIANT_ENUM_CAST(SubViewport::ClearMode); VARIANT_ENUM_CAST(Viewport::RenderInfo); VARIANT_ENUM_CAST(Viewport::RenderInfoType); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat); -#endif +#endif // VIEWPORT_H diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 73e8f537d9..d40b82f5eb 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -242,8 +242,8 @@ void Window::_make_window() { window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size)); ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id); - DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); - DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); + DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id); + DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id); String tr_title = atr(title); #ifdef DEBUG_ENABLED if (window_id == DisplayServer::MAIN_WINDOW_ID) { @@ -596,20 +596,43 @@ void Window::_update_window_size() { size.x = MAX(size_limit.x, size.x); size.y = MAX(size_limit.y, size.y); - if (max_size.x > 0 && max_size.x > min_size.x && size.x > max_size.x) { - size.x = max_size.x; - } + bool reset_min_first = false; + + bool max_size_valid = false; + if ((max_size.x > 0 || max_size.y > 0) && (max_size.x >= min_size.x && max_size.y >= min_size.y)) { + max_size_valid = true; + + if (size.x > max_size.x) { + size.x = max_size.x; + } + if (size_limit.x > max_size.x) { + size_limit.x = max_size.x; + reset_min_first = true; + } - if (max_size.y > 0 && max_size.y > min_size.y && size.y > max_size.y) { - size.y = max_size.y; + if (size.y > max_size.y) { + size.y = max_size.y; + } + if (size_limit.y > max_size.y) { + size_limit.y = max_size.y; + reset_min_first = true; + } } if (embedder) { + size.x = MAX(size.x, 1); + size.y = MAX(size.y, 1); + embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + if (reset_min_first && wrap_controls) { + // Avoid an error if setting max_size to a value between min_size and the previous size_limit. + DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id); + } + DisplayServer::get_singleton()->window_set_size(size, window_id); + DisplayServer::get_singleton()->window_set_max_size(max_size_valid ? max_size : Size2i(), window_id); DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id); - DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); } //update the viewport @@ -953,6 +976,8 @@ void Window::set_wrap_controls(bool p_enable) { wrap_controls = p_enable; if (wrap_controls) { child_controls_changed(); + } else { + _update_window_size(); } } @@ -1516,7 +1541,7 @@ void Window::_validate_property(PropertyInfo &property) const { Transform2D Window::get_screen_transform() const { Transform2D embedder_transform = Transform2D(); if (_get_embedder()) { - embedder_transform.translate(get_position()); + embedder_transform.translate_local(get_position()); embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform; } return embedder_transform * Viewport::get_screen_transform(); diff --git a/scene/multiplayer/SCsub b/scene/multiplayer/SCsub deleted file mode 100644 index fc61250247..0000000000 --- a/scene/multiplayer/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -env.add_source_files(env.scene_sources, "*.cpp") diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 5c5b60df63..a5842106fb 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -130,18 +130,14 @@ #include "scene/main/http_request.h" #include "scene/main/instance_placeholder.h" #include "scene/main/missing_node.h" +#include "scene/main/multiplayer_api.h" #include "scene/main/resource_preloader.h" #include "scene/main/scene_tree.h" #include "scene/main/timer.h" #include "scene/main/viewport.h" #include "scene/main/window.h" -#include "scene/multiplayer/multiplayer_spawner.h" -#include "scene/multiplayer/multiplayer_synchronizer.h" -#include "scene/multiplayer/scene_cache_interface.h" -#include "scene/multiplayer/scene_replication_interface.h" -#include "scene/multiplayer/scene_rpc_interface.h" #include "scene/resources/animation_library.h" -#include "scene/resources/audio_stream_sample.h" +#include "scene/resources/audio_stream_wav.h" #include "scene/resources/bit_map.h" #include "scene/resources/bone_map.h" #include "scene/resources/box_shape_3d.h" @@ -159,6 +155,7 @@ #include "scene/resources/gradient.h" #include "scene/resources/height_map_shape_3d.h" #include "scene/resources/immediate_mesh.h" +#include "scene/resources/label_settings.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/mesh_data_tool.h" @@ -173,6 +170,7 @@ #include "scene/resources/segment_shape_2d.h" #include "scene/resources/separation_ray_shape_2d.h" #include "scene/resources/separation_ray_shape_3d.h" +#include "scene/resources/shader_include.h" #include "scene/resources/skeleton_modification_2d.h" #include "scene/resources/skeleton_modification_2d_ccdik.h" #include "scene/resources/skeleton_modification_2d_fabrik.h" @@ -246,6 +244,7 @@ #include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" #include "scene/3d/remote_transform_3d.h" +#include "scene/3d/shape_cast_3d.h" #include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_ik_3d.h" #include "scene/3d/soft_dynamic_body_3d.h" @@ -272,6 +271,9 @@ static Ref<ResourceFormatLoaderCompressedTexture3D> resource_loader_texture_3d; static Ref<ResourceFormatSaverShader> resource_saver_shader; static Ref<ResourceFormatLoaderShader> resource_loader_shader; +static Ref<ResourceFormatSaverShaderInclude> resource_saver_shader_include; +static Ref<ResourceFormatLoaderShaderInclude> resource_loader_shader_include; + void register_scene_types() { SceneStringNames::create(); @@ -300,6 +302,12 @@ void register_scene_types() { resource_loader_shader.instantiate(); ResourceLoader::add_resource_format_loader(resource_loader_shader, true); + resource_saver_shader_include.instantiate(); + ResourceSaver::add_resource_format_saver(resource_saver_shader_include, true); + + resource_loader_shader_include.instantiate(); + ResourceLoader::add_resource_format_loader(resource_loader_shader_include, true); + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(Object); @@ -311,9 +319,13 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(Viewport); GDREGISTER_CLASS(SubViewport); GDREGISTER_CLASS(ViewportTexture); + + GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer); + GDREGISTER_CLASS(MultiplayerPeerExtension); + GDREGISTER_ABSTRACT_CLASS(MultiplayerAPI); + GDREGISTER_CLASS(MultiplayerAPIExtension); + GDREGISTER_CLASS(HTTPRequest); - GDREGISTER_CLASS(MultiplayerSpawner); - GDREGISTER_CLASS(MultiplayerSynchronizer); GDREGISTER_CLASS(Timer); GDREGISTER_CLASS(CanvasLayer); GDREGISTER_CLASS(CanvasModulate); @@ -439,6 +451,7 @@ void register_scene_types() { GDREGISTER_CLASS(AnimationNodeStateMachine); GDREGISTER_CLASS(AnimationNodeStateMachinePlayback); + GDREGISTER_CLASS(AnimationNodeSync); GDREGISTER_CLASS(AnimationNodeStateMachineTransition); GDREGISTER_CLASS(AnimationNodeOutput); GDREGISTER_CLASS(AnimationNodeOneShot); @@ -510,9 +523,7 @@ void register_scene_types() { GDREGISTER_CLASS(GPUParticlesAttractorVectorField3D); GDREGISTER_CLASS(CPUParticles3D); GDREGISTER_CLASS(Position3D); - GDREGISTER_CLASS(RootMotionView); - ClassDB::set_class_enabled("RootMotionView", false); // disabled by default, enabled by editor OS::get_singleton()->yield(); // may take time to init @@ -537,6 +548,7 @@ void register_scene_types() { GDREGISTER_CLASS(CollisionShape3D); GDREGISTER_CLASS(CollisionPolygon3D); GDREGISTER_CLASS(RayCast3D); + GDREGISTER_CLASS(ShapeCast3D); GDREGISTER_CLASS(MultiMeshInstance3D); GDREGISTER_CLASS(Curve3D); @@ -567,6 +579,7 @@ void register_scene_types() { GDREGISTER_CLASS(Shader); GDREGISTER_CLASS(VisualShader); + GDREGISTER_CLASS(ShaderInclude); GDREGISTER_ABSTRACT_CLASS(VisualShaderNode); GDREGISTER_CLASS(VisualShaderNodeCustom); GDREGISTER_CLASS(VisualShaderNodeInput); @@ -772,6 +785,7 @@ void register_scene_types() { GDREGISTER_CLASS(QuadMesh); GDREGISTER_CLASS(SphereMesh); GDREGISTER_CLASS(TextMesh); + GDREGISTER_CLASS(TorusMesh); GDREGISTER_CLASS(TubeTrailMesh); GDREGISTER_CLASS(RibbonTrailMesh); GDREGISTER_CLASS(PointMesh); @@ -857,10 +871,11 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(Font); GDREGISTER_CLASS(FontFile); GDREGISTER_CLASS(FontVariation); + GDREGISTER_CLASS(SystemFont); GDREGISTER_CLASS(Curve); - GDREGISTER_CLASS(SceneReplicationConfig); + GDREGISTER_CLASS(LabelSettings); GDREGISTER_CLASS(TextLine); GDREGISTER_CLASS(TextParagraph); @@ -888,7 +903,7 @@ void register_scene_types() { GDREGISTER_CLASS(AudioStreamPlayer3D); #endif GDREGISTER_ABSTRACT_CLASS(VideoStream); - GDREGISTER_CLASS(AudioStreamSample); + GDREGISTER_CLASS(AudioStreamWAV); OS::get_singleton()->yield(); // may take time to init @@ -1075,6 +1090,9 @@ void register_scene_types() { ClassDB::add_compatibility_class("World", "World3D"); // Renamed during 4.0 alpha, added to ease transition between alphas. + ClassDB::add_compatibility_class("AudioStreamOGGVorbis", "AudioStreamOggVorbis"); + ClassDB::add_compatibility_class("AudioStreamSample", "AudioStreamWAV"); + ClassDB::add_compatibility_class("OGGPacketSequence", "OggPacketSequence"); ClassDB::add_compatibility_class("StreamCubemap", "CompressedCubemap"); ClassDB::add_compatibility_class("StreamCubemapArray", "CompressedCubemapArray"); ClassDB::add_compatibility_class("StreamTexture2D", "CompressedTexture2D"); @@ -1102,9 +1120,6 @@ void register_scene_types() { } SceneDebugger::initialize(); - SceneReplicationInterface::make_default(); - SceneRPCInterface::make_default(); - SceneCacheInterface::make_default(); } void initialize_theme() { @@ -1181,6 +1196,12 @@ void unregister_scene_types() { ResourceLoader::remove_resource_format_loader(resource_loader_shader); resource_loader_shader.unref(); + ResourceSaver::remove_resource_format_saver(resource_saver_shader_include); + resource_saver_shader_include.unref(); + + ResourceLoader::remove_resource_format_loader(resource_loader_shader_include); + resource_loader_shader_include.unref(); + // StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either #ifndef _3D_DISABLED BaseMaterial3D::finish_shaders(); diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h index f0a14387c1..dce8713976 100644 --- a/scene/register_scene_types.h +++ b/scene/register_scene_types.h @@ -36,4 +36,4 @@ void unregister_scene_types(); void initialize_theme(); -#endif +#endif // REGISTER_SCENE_TYPES_H diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 7183accc66..69b30b72b0 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1563,33 +1563,35 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const { return -1; } -void Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) { - ERR_FAIL_INDEX(p_track, tracks.size()); +int Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) { + ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; + int ret = -1; + switch (t->type) { case TYPE_POSITION_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I)); - int idx = position_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1); + ret = position_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_ROTATION_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS)); - int idx = rotation_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS), -1); + ret = rotation_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_SCALE_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I)); - int idx = scale_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1); + ret = scale_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_BLEND_SHAPE: { - ERR_FAIL_COND((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT)); - int idx = blend_shape_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT), -1); + ret = blend_shape_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_VALUE: { @@ -1599,17 +1601,17 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.time = p_time; k.transition = p_transition; k.value = p_key; - _insert(p_time, vt->values, k); + ret = _insert(p_time, vt->values, k); } break; case TYPE_METHOD: { MethodTrack *mt = static_cast<MethodTrack *>(t); - ERR_FAIL_COND(p_key.get_type() != Variant::DICTIONARY); + ERR_FAIL_COND_V(p_key.get_type() != Variant::DICTIONARY, -1); Dictionary d = p_key; - ERR_FAIL_COND(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING)); - ERR_FAIL_COND(!d.has("args") || !d["args"].is_array()); + ERR_FAIL_COND_V(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING), -1); + ERR_FAIL_COND_V(!d.has("args") || !d["args"].is_array(), -1); MethodKey k; @@ -1618,14 +1620,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.method = d["method"]; k.params = d["args"]; - _insert(p_time, mt->methods, k); + ret = _insert(p_time, mt->methods, k); } break; case TYPE_BEZIER: { BezierTrack *bt = static_cast<BezierTrack *>(t); Array arr = p_key; - ERR_FAIL_COND(arr.size() != 6); + ERR_FAIL_COND_V(arr.size() != 6, -1); TKey<BezierKey> k; k.time = p_time; @@ -1635,23 +1637,23 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.value.out_handle.x = arr[3]; k.value.out_handle.y = arr[4]; k.value.handle_mode = static_cast<HandleMode>((int)arr[5]); - _insert(p_time, bt->values, k); + ret = _insert(p_time, bt->values, k); } break; case TYPE_AUDIO: { AudioTrack *at = static_cast<AudioTrack *>(t); Dictionary k = p_key; - ERR_FAIL_COND(!k.has("start_offset")); - ERR_FAIL_COND(!k.has("end_offset")); - ERR_FAIL_COND(!k.has("stream")); + ERR_FAIL_COND_V(!k.has("start_offset"), -1); + ERR_FAIL_COND_V(!k.has("end_offset"), -1); + ERR_FAIL_COND_V(!k.has("stream"), -1); TKey<AudioKey> ak; ak.time = p_time; ak.value.start_offset = k["start_offset"]; ak.value.end_offset = k["end_offset"]; ak.value.stream = k["stream"]; - _insert(p_time, at->values, ak); + ret = _insert(p_time, at->values, ak); } break; case TYPE_ANIMATION: { @@ -1661,12 +1663,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke ak.time = p_time; ak.value = p_key; - _insert(p_time, at->values, ak); + ret = _insert(p_time, at->values, ak); } break; } emit_changed(); + + return ret; } int Animation::track_get_key_count(int p_track) const { @@ -2302,7 +2306,7 @@ Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a } Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const { - return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c); + return p_a.spherical_cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); } Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const { @@ -2363,7 +2367,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a Quaternion pa = p_pre_a; Quaternion pb = p_post_b; - return a.cubic_slerp(b, pa, pb, p_c); + return a.spherical_cubic_interpolate(b, pa, pb, p_c); } case Variant::AABB: { AABB a = p_a; diff --git a/scene/resources/animation.h b/scene/resources/animation.h index b4528ccd3a..bf9f786a0d 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -392,7 +392,7 @@ public: void track_set_enabled(int p_track, bool p_enabled); bool track_is_enabled(int p_track) const; - void track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1); + int track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1); void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition); void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); void track_set_key_time(int p_track, int p_key_idx, double p_time); @@ -488,4 +488,4 @@ VARIANT_ENUM_CAST(Animation::UpdateMode); VARIANT_ENUM_CAST(Animation::HandleMode); VARIANT_ENUM_CAST(Animation::LoopMode); -#endif +#endif // ANIMATION_H diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h index 7a69cd140a..d63807b6d7 100644 --- a/scene/resources/animation_library.h +++ b/scene/resources/animation_library.h @@ -63,4 +63,4 @@ public: AnimationLibrary(); }; -#endif // ANIMATIONLIBRARY_H +#endif // ANIMATION_LIBRARY_H diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_wav.cpp index 30c222bdff..a87c8272ea 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* audio_stream_sample.cpp */ +/* audio_stream_wav.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "audio_stream_sample.h" +#include "audio_stream_wav.h" #include "core/io/file_access.h" #include "core/io/marshalls.h" -void AudioStreamPlaybackSample::start(float p_from_pos) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { +void AudioStreamPlaybackWAV::start(float p_from_pos) { + if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) { //no seeking in IMA_ADPCM for (int i = 0; i < 2; i++) { ima_adpcm[i].step_index = 0; @@ -55,24 +55,24 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { active = true; } -void AudioStreamPlaybackSample::stop() { +void AudioStreamPlaybackWAV::stop() { active = false; } -bool AudioStreamPlaybackSample::is_playing() const { +bool AudioStreamPlaybackWAV::is_playing() const { return active; } -int AudioStreamPlaybackSample::get_loop_count() const { +int AudioStreamPlaybackWAV::get_loop_count() const { return 0; } -float AudioStreamPlaybackSample::get_playback_position() const { +float AudioStreamPlaybackWAV::get_playback_position() const { return float(offset >> MIX_FRAC_BITS) / base->mix_rate; } -void AudioStreamPlaybackSample::seek(float p_time) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { +void AudioStreamPlaybackWAV::seek(float p_time) { + if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) { return; //no seeking in ima-adpcm } @@ -87,7 +87,7 @@ void AudioStreamPlaybackSample::seek(float p_time) { } template <class Depth, bool is_stereo, bool is_ima_adpcm> -void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) { +void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) { // this function will be compiled branchless by any decent compiler int32_t final, final_r, next, next_r; @@ -124,7 +124,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds ima_adpcm[i].last_nibble++; const uint8_t *src_ptr = (const uint8_t *)base->data; - src_ptr += AudioStreamSample::DATA_PAD; + src_ptr += AudioStreamWAV::DATA_PAD; uint8_t nbb = src_ptr[(ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i]; nibble = (ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF); @@ -221,7 +221,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds } } -int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { +int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { if (!base->data || !active) { for (int i = 0; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); @@ -231,13 +231,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int int len = base->data_bytes; switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: + case AudioStreamWAV::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: + case AudioStreamWAV::FORMAT_IMA_ADPCM: len *= 2; break; } @@ -251,13 +251,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int int64_t loop_begin_fp = ((int64_t)base->loop_begin << MIX_FRAC_BITS); int64_t loop_end_fp = ((int64_t)base->loop_end << MIX_FRAC_BITS); int64_t length_fp = ((int64_t)len << MIX_FRAC_BITS); - int64_t begin_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_begin_fp : 0; - int64_t end_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_end_fp : length_fp; + int64_t begin_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_begin_fp : 0; + int64_t end_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_end_fp : length_fp; bool is_stereo = base->stereo; int32_t todo = p_frames; - if (base->loop_mode == AudioStreamSample::LOOP_BACKWARD) { + if (base->loop_mode == AudioStreamWAV::LOOP_BACKWARD) { sign = -1; } @@ -271,20 +271,20 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int //looping - AudioStreamSample::LoopMode loop_format = base->loop_mode; - AudioStreamSample::Format format = base->format; + AudioStreamWAV::LoopMode loop_format = base->loop_mode; + AudioStreamWAV::Format format = base->format; /* audio data */ uint8_t *dataptr = (uint8_t *)base->data; - const void *data = dataptr + AudioStreamSample::DATA_PAD; + const void *data = dataptr + AudioStreamWAV::DATA_PAD; AudioFrame *dst_buff = p_buffer; - if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { - if (loop_format != AudioStreamSample::LOOP_DISABLED) { + if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) { + if (loop_format != AudioStreamWAV::LOOP_DISABLED) { ima_adpcm[0].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; ima_adpcm[1].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; - loop_format = AudioStreamSample::LOOP_FORWARD; + loop_format = AudioStreamWAV::LOOP_FORWARD; } } @@ -297,9 +297,9 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int if (increment < 0) { /* going backwards */ - if (loop_format != AudioStreamSample::LOOP_DISABLED && offset < loop_begin_fp) { + if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset < loop_begin_fp) { /* loopstart reached */ - if (loop_format == AudioStreamSample::LOOP_PINGPONG) { + if (loop_format == AudioStreamWAV::LOOP_PINGPONG) { /* bounce ping pong */ offset = loop_begin_fp + (loop_begin_fp - offset); increment = -increment; @@ -317,10 +317,10 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int } } else { /* going forward */ - if (loop_format != AudioStreamSample::LOOP_DISABLED && offset >= loop_end_fp) { + if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset >= loop_end_fp) { /* loopend reached */ - if (loop_format == AudioStreamSample::LOOP_PINGPONG) { + if (loop_format == AudioStreamWAV::LOOP_PINGPONG) { /* bounce ping pong */ offset = loop_end_fp - (offset - loop_end_fp); increment = -increment; @@ -328,7 +328,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int } else { /* go to loop-begin */ - if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { + if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) { for (int i = 0; i < 2; i++) { ima_adpcm[i].step_index = ima_adpcm[i].loop_step_index; ima_adpcm[i].predictor = ima_adpcm[i].loop_predictor; @@ -366,14 +366,14 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int todo -= target; switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: { + case AudioStreamWAV::FORMAT_8_BITS: { if (is_stereo) { do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); } else { do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); } } break; - case AudioStreamSample::FORMAT_16_BITS: { + case AudioStreamWAV::FORMAT_16_BITS: { if (is_stereo) { do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); } else { @@ -381,7 +381,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int } } break; - case AudioStreamSample::FORMAT_IMA_ADPCM: { + case AudioStreamWAV::FORMAT_IMA_ADPCM: { if (is_stereo) { do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); } else { @@ -406,69 +406,73 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int return p_frames; } -AudioStreamPlaybackSample::AudioStreamPlaybackSample() {} +void AudioStreamPlaybackWAV::tag_used_streams() { + base->tag_used(get_playback_position()); +} + +AudioStreamPlaybackWAV::AudioStreamPlaybackWAV() {} ///////////////////// -void AudioStreamSample::set_format(Format p_format) { +void AudioStreamWAV::set_format(Format p_format) { format = p_format; } -AudioStreamSample::Format AudioStreamSample::get_format() const { +AudioStreamWAV::Format AudioStreamWAV::get_format() const { return format; } -void AudioStreamSample::set_loop_mode(LoopMode p_loop_mode) { +void AudioStreamWAV::set_loop_mode(LoopMode p_loop_mode) { loop_mode = p_loop_mode; } -AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const { +AudioStreamWAV::LoopMode AudioStreamWAV::get_loop_mode() const { return loop_mode; } -void AudioStreamSample::set_loop_begin(int p_frame) { +void AudioStreamWAV::set_loop_begin(int p_frame) { loop_begin = p_frame; } -int AudioStreamSample::get_loop_begin() const { +int AudioStreamWAV::get_loop_begin() const { return loop_begin; } -void AudioStreamSample::set_loop_end(int p_frame) { +void AudioStreamWAV::set_loop_end(int p_frame) { loop_end = p_frame; } -int AudioStreamSample::get_loop_end() const { +int AudioStreamWAV::get_loop_end() const { return loop_end; } -void AudioStreamSample::set_mix_rate(int p_hz) { +void AudioStreamWAV::set_mix_rate(int p_hz) { ERR_FAIL_COND(p_hz == 0); mix_rate = p_hz; } -int AudioStreamSample::get_mix_rate() const { +int AudioStreamWAV::get_mix_rate() const { return mix_rate; } -void AudioStreamSample::set_stereo(bool p_enable) { +void AudioStreamWAV::set_stereo(bool p_enable) { stereo = p_enable; } -bool AudioStreamSample::is_stereo() const { +bool AudioStreamWAV::is_stereo() const { return stereo; } -float AudioStreamSample::get_length() const { +float AudioStreamWAV::get_length() const { int len = data_bytes; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: + case AudioStreamWAV::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: + case AudioStreamWAV::FORMAT_IMA_ADPCM: len *= 2; break; } @@ -480,11 +484,11 @@ float AudioStreamSample::get_length() const { return float(len) / mix_rate; } -bool AudioStreamSample::is_monophonic() const { +bool AudioStreamWAV::is_monophonic() const { return false; } -void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { +void AudioStreamWAV::set_data(const Vector<uint8_t> &p_data) { AudioServer::get_singleton()->lock(); if (data) { memfree(data); @@ -506,7 +510,7 @@ void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { AudioServer::get_singleton()->unlock(); } -Vector<uint8_t> AudioStreamSample::get_data() const { +Vector<uint8_t> AudioStreamWAV::get_data() const { Vector<uint8_t> pv; if (data) { @@ -521,8 +525,8 @@ Vector<uint8_t> AudioStreamSample::get_data() const { return pv; } -Error AudioStreamSample::save_to_wav(const String &p_path) { - if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { +Error AudioStreamWAV::save_to_wav(const String &p_path) { + if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) { WARN_PRINT("Saving IMA_ADPC samples are not supported yet"); return ERR_UNAVAILABLE; } @@ -540,13 +544,13 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { int byte_pr_sample = 0; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: + case AudioStreamWAV::FORMAT_8_BITS: byte_pr_sample = 1; break; - case AudioStreamSample::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_16_BITS: byte_pr_sample = 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: + case AudioStreamWAV::FORMAT_IMA_ADPCM: byte_pr_sample = 4; break; } @@ -579,19 +583,19 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { Vector<uint8_t> data = get_data(); const uint8_t *read_data = data.ptr(); switch (format) { - case AudioStreamSample::FORMAT_8_BITS: + case AudioStreamWAV::FORMAT_8_BITS: for (unsigned int i = 0; i < data_bytes; i++) { uint8_t data_point = (read_data[i] + 128); file->store_8(data_point); } break; - case AudioStreamSample::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_16_BITS: for (unsigned int i = 0; i < data_bytes / 2; i++) { uint16_t data_point = decode_uint16(&read_data[i * 2]); file->store_16(data_point); } break; - case AudioStreamSample::FORMAT_IMA_ADPCM: + case AudioStreamWAV::FORMAT_IMA_ADPCM: //Unimplemented break; } @@ -599,40 +603,40 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { return OK; } -Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() { - Ref<AudioStreamPlaybackSample> sample; +Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() { + Ref<AudioStreamPlaybackWAV> sample; sample.instantiate(); - sample->base = Ref<AudioStreamSample>(this); + sample->base = Ref<AudioStreamWAV>(this); return sample; } -String AudioStreamSample::get_stream_name() const { +String AudioStreamWAV::get_stream_name() const { return ""; } -void AudioStreamSample::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data); - ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data); +void AudioStreamWAV::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data); + ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data); - ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamSample::set_format); - ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamSample::get_format); + ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamWAV::set_format); + ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamWAV::get_format); - ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamSample::set_loop_mode); - ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamSample::get_loop_mode); + ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamWAV::set_loop_mode); + ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamWAV::get_loop_mode); - ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamSample::set_loop_begin); - ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamSample::get_loop_begin); + ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamWAV::set_loop_begin); + ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamWAV::get_loop_begin); - ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamSample::set_loop_end); - ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamSample::get_loop_end); + ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamWAV::set_loop_end); + ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamWAV::get_loop_end); - ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamSample::set_mix_rate); - ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamSample::get_mix_rate); + ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamWAV::set_mix_rate); + ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamWAV::get_mix_rate); - ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo); - ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo); + ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamWAV::set_stereo); + ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamWAV::is_stereo); - ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav); + ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav); ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); @@ -652,9 +656,9 @@ void AudioStreamSample::_bind_methods() { BIND_ENUM_CONSTANT(LOOP_BACKWARD); } -AudioStreamSample::AudioStreamSample() {} +AudioStreamWAV::AudioStreamWAV() {} -AudioStreamSample::~AudioStreamSample() { +AudioStreamWAV::~AudioStreamWAV() { if (data) { memfree(data); data = nullptr; diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_wav.h index 357febc27a..d800388d96 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_wav.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* audio_stream_sample.h */ +/* audio_stream_wav.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIO_STREAM_SAMPLE_H -#define AUDIO_STREAM_SAMPLE_H +#ifndef AUDIO_STREAM_WAV_H +#define AUDIO_STREAM_WAV_H #include "servers/audio/audio_stream.h" -class AudioStreamSample; +class AudioStreamWAV; -class AudioStreamPlaybackSample : public AudioStreamPlayback { - GDCLASS(AudioStreamPlaybackSample, AudioStreamPlayback); +class AudioStreamPlaybackWAV : public AudioStreamPlayback { + GDCLASS(AudioStreamPlaybackWAV, AudioStreamPlayback); enum { MIX_FRAC_BITS = 13, MIX_FRAC_LEN = (1 << MIX_FRAC_BITS), @@ -57,8 +57,8 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback { int64_t offset = 0; int sign = 1; bool active = false; - friend class AudioStreamSample; - Ref<AudioStreamSample> base; + friend class AudioStreamWAV; + Ref<AudioStreamWAV> base; template <class Depth, bool is_stereo, bool is_ima_adpcm> void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm); @@ -75,11 +75,13 @@ public: virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; - AudioStreamPlaybackSample(); + virtual void tag_used_streams() override; + + AudioStreamPlaybackWAV(); }; -class AudioStreamSample : public AudioStream { - GDCLASS(AudioStreamSample, AudioStream); +class AudioStreamWAV : public AudioStream { + GDCLASS(AudioStreamWAV, AudioStream); RES_BASE_EXTENSION("sample") public: @@ -98,7 +100,7 @@ public: }; private: - friend class AudioStreamPlaybackSample; + friend class AudioStreamPlaybackWAV; enum { DATA_PAD = 16 //padding for interpolation @@ -144,14 +146,14 @@ public: Error save_to_wav(const String &p_path); - virtual Ref<AudioStreamPlayback> instance_playback() override; + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; - AudioStreamSample(); - ~AudioStreamSample(); + AudioStreamWAV(); + ~AudioStreamWAV(); }; -VARIANT_ENUM_CAST(AudioStreamSample::Format) -VARIANT_ENUM_CAST(AudioStreamSample::LoopMode) +VARIANT_ENUM_CAST(AudioStreamWAV::Format) +VARIANT_ENUM_CAST(AudioStreamWAV::LoopMode) -#endif // AUDIO_STREAM_SAMPLE_H +#endif // AUDIO_STREAM_WAV_H diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index ce030934fa..aff917b2d4 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -50,6 +50,14 @@ bool BoneMap::_get(const StringName &p_path, Variant &r_ret) const { return true; } +void BoneMap::_get_property_list(List<PropertyInfo> *p_list) const { + HashMap<StringName, StringName>::ConstIterator E = bone_map.begin(); + while (E) { + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_map/" + E->key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + ++E; + } +} + Ref<SkeletonProfile> BoneMap::get_profile() const { return profile; } @@ -153,6 +161,7 @@ void BoneMap::_bind_methods() { ClassDB::bind_method(D_METHOD("find_profile_bone_name", "skeleton_bone_name"), &BoneMap::find_profile_bone_name); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "profile", PROPERTY_HINT_RESOURCE_TYPE, "SkeletonProfile"), "set_profile", "get_profile"); + ADD_ARRAY("bonemap", "bonemap"); ADD_SIGNAL(MethodInfo("bone_map_updated")); ADD_SIGNAL(MethodInfo("profile_updated")); diff --git a/scene/resources/bone_map.h b/scene/resources/bone_map.h index 4b7928015d..17452dfc73 100644 --- a/scene/resources/bone_map.h +++ b/scene/resources/bone_map.h @@ -46,6 +46,7 @@ protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); virtual void _validate_property(PropertyInfo &property) const override; + void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); public: diff --git a/scene/resources/box_shape_3d.h b/scene/resources/box_shape_3d.h index 4e6db893af..3dd0bb6cb7 100644 --- a/scene/resources/box_shape_3d.h +++ b/scene/resources/box_shape_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BOX_SHAPE_H -#define BOX_SHAPE_H +#ifndef BOX_SHAPE_3D_H +#define BOX_SHAPE_3D_H #include "scene/resources/shape_3d.h" @@ -56,4 +56,4 @@ public: BoxShape3D(); }; -#endif // BOX_SHAPE_H +#endif // BOX_SHAPE_3D_H diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h index 4c039ab326..ad7f2e5b74 100644 --- a/scene/resources/capsule_shape_3d.h +++ b/scene/resources/capsule_shape_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAPSULE_SHAPE_H -#define CAPSULE_SHAPE_H +#ifndef CAPSULE_SHAPE_3D_H +#define CAPSULE_SHAPE_3D_H #include "scene/resources/shape_3d.h" @@ -55,4 +55,4 @@ public: CapsuleShape3D(); }; -#endif // CAPSULE_SHAPE_H +#endif // CAPSULE_SHAPE_3D_H diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index 0f49a0d80f..d350d753b0 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -52,4 +52,4 @@ public: ConcavePolygonShape2D(); }; -#endif +#endif // CONCAVE_POLYGON_SHAPE_2D_H diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h index a265590edd..68feacfa25 100644 --- a/scene/resources/concave_polygon_shape_3d.h +++ b/scene/resources/concave_polygon_shape_3d.h @@ -77,4 +77,4 @@ public: ConcavePolygonShape3D(); }; -#endif // CONCAVE_POLYGON_SHAPE_H +#endif // CONCAVE_POLYGON_SHAPE_3D_H diff --git a/scene/resources/convex_polygon_shape_3d.h b/scene/resources/convex_polygon_shape_3d.h index 930edb015d..5ca4d2a713 100644 --- a/scene/resources/convex_polygon_shape_3d.h +++ b/scene/resources/convex_polygon_shape_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONVEX_POLYGON_SHAPE_H -#define CONVEX_POLYGON_SHAPE_H +#ifndef CONVEX_POLYGON_SHAPE_3D_H +#define CONVEX_POLYGON_SHAPE_3D_H #include "scene/resources/shape_3d.h" @@ -52,4 +52,4 @@ public: ConvexPolygonShape3D(); }; -#endif // CONVEX_POLYGON_SHAPE_H +#endif // CONVEX_POLYGON_SHAPE_3D_H diff --git a/scene/resources/cylinder_shape_3d.h b/scene/resources/cylinder_shape_3d.h index 65427423c8..f554358044 100644 --- a/scene/resources/cylinder_shape_3d.h +++ b/scene/resources/cylinder_shape_3d.h @@ -54,4 +54,4 @@ public: CylinderShape3D(); }; -#endif // CYLINDER_SHAPE_H +#endif // CYLINDER_SHAPE_3D_H diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 520a0a04ed..fa375795c1 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -741,7 +741,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_selected_color", "Tree", control_font_pressed_color); theme->set_color("font_outline_color", "Tree", Color(1, 1, 1)); theme->set_color("guide_color", "Tree", Color(0.7, 0.7, 0.7, 0.25)); - theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); + theme->set_color("drop_position_color", "Tree", Color(1, 1, 1)); theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27)); theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27)); theme->set_color("children_hl_line_color", "Tree", Color(0.27, 0.27, 0.27)); @@ -776,7 +776,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_color", "ItemList", control_font_lower_color); theme->set_color("font_selected_color", "ItemList", control_font_pressed_color); theme->set_color("font_outline_color", "ItemList", Color(1, 1, 1)); - theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1)); + theme->set_color("guide_color", "ItemList", Color(0.7, 0.7, 0.7, 0.25)); theme->set_stylebox("selected", "ItemList", make_flat_stylebox(style_selected_color)); theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "ItemList", focus); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index f777330a07..9b070a90cc 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -39,4 +39,4 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void clear_default_theme(); -#endif +#endif // DEFAULT_THEME_H diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 854bd34d6a..d361b34da8 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1249,8 +1249,8 @@ void Environment::_bind_methods() { ADD_GROUP("SSR", "ssr_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssr_enabled"), "set_ssr_enabled", "is_ssr_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssr_max_steps", PROPERTY_HINT_RANGE, "1,512,1"), "set_ssr_max_steps", "get_ssr_max_steps"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_in", "get_ssr_fade_in"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_out", "get_ssr_fade_out"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_depth_tolerance", PROPERTY_HINT_RANGE, "0.01,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); // SSAO @@ -1277,7 +1277,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_radius", PROPERTY_HINT_RANGE, "0.01,16,0.01,or_greater"), "set_ssao_radius", "get_ssao_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_intensity", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_ssao_intensity", "get_ssao_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING), "set_ssao_power", "get_ssao_power"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssao_power", "get_ssao_power"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_detail", PROPERTY_HINT_RANGE, "0,5,0.01"), "set_ssao_detail", "get_ssao_detail"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_horizon", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_horizon", "get_ssao_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_sharpness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_sharpness", "get_ssao_sharpness"); @@ -1337,8 +1337,10 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_bounce_feedback", PROPERTY_HINT_RANGE, "0,1.99,0.01"), "set_sdfgi_bounce_feedback", "get_sdfgi_bounce_feedback"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_RANGE, "1,8,1"), "set_sdfgi_cascades", "get_sdfgi_cascades"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance"); + // Don't store the values of `sdfgi_cascade0_distance` and `sdfgi_max_distance` + // as they're derived from `sdfgi_min_cell_size`. + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater", PROPERTY_USAGE_EDITOR), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater", PROPERTY_USAGE_EDITOR), "set_sdfgi_max_distance", "get_sdfgi_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_y_scale", PROPERTY_HINT_ENUM, "50% (Compact),75% (Balanced),100% (Sparse)"), "set_sdfgi_y_scale", "get_sdfgi_y_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_energy"), "set_sdfgi_energy", "get_sdfgi_energy"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_normal_bias"), "set_sdfgi_normal_bias", "get_sdfgi_normal_bias"); @@ -1423,7 +1425,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_fog_light_energy", "get_fog_light_energy"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_scatter", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_fog_sun_scatter", "get_fog_sun_scatter"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,16,0.0001"), "set_fog_density", "get_fog_density"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater"), "set_fog_density", "get_fog_density"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater,suffix:m"), "set_fog_height", "get_fog_height"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density"); @@ -1462,7 +1464,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_anisotropy", PROPERTY_HINT_RANGE, "-0.9,0.9,0.01"), "set_volumetric_fog_anisotropy", "get_volumetric_fog_anisotropy"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_ambient_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_ambient_inject", "get_volumetric_fog_ambient_inject"); ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled"); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index b71fe8904a..385d815230 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -175,10 +175,10 @@ private: // Fog bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); + Color fog_light_color = Color(0.518, 0.553, 0.608); float fog_light_energy = 1.0; float fog_sun_scatter = 0.0; - float fog_density = 0.001; + float fog_density = 0.01; float fog_height = 0.0; float fog_height_density = 0.0; //can be negative to invert effect float fog_aerial_perspective = 0.0; @@ -194,8 +194,8 @@ private: float volumetric_fog_anisotropy = 0.2; float volumetric_fog_length = 64.0; float volumetric_fog_detail_spread = 2.0; - float volumetric_fog_gi_inject = 0.0; - float volumetric_fog_ambient_inject = false; + float volumetric_fog_gi_inject = 1.0; + float volumetric_fog_ambient_inject = 0.0; bool volumetric_fog_temporal_reproject = true; float volumetric_fog_temporal_reproject_amount = 0.9; void _update_volumetric_fog(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 6053d27ef7..619036d296 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -69,19 +69,19 @@ void Font::_bind_methods() { // Drawing string. ClassDB::bind_method(D_METHOD("set_cache_capacity", "single_line", "multi_line"), &Font::set_cache_capacity); - ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "jst_flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "brk_flags", "jst_flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "flags", "direction", "orientation"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "flags", "direction", "orientation"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_flags", "direction", "orientation"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "flags", "direction", "orientation"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); - ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "flags", "direction", "orientation"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "jst_flags", "direction", "orientation"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); + ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL)); // Drawing char. - ClassDB::bind_method(D_METHOD("get_char_size", "char"), &Font::get_char_size); - ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "modulate"), &Font::draw_char, DEFVAL(Color(1.0, 1.0, 1.0))); - ClassDB::bind_method(D_METHOD("draw_char_outline", "canvas_item", "pos", "char", "size", "modulate"), &Font::draw_char_outline, DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0))); + ClassDB::bind_method(D_METHOD("get_char_size", "char", "font_size"), &Font::get_char_size); + ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "font_size", "modulate"), &Font::draw_char, DEFVAL(Color(1.0, 1.0, 1.0))); + ClassDB::bind_method(D_METHOD("draw_char_outline", "canvas_item", "pos", "char", "font_size", "size", "modulate"), &Font::draw_char_outline, DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0))); // Helper functions. ClassDB::bind_method(D_METHOD("has_char", "char"), &Font::has_char); @@ -157,7 +157,7 @@ void Font::set_fallbacks(const TypedArray<Font> &p_fallbacks) { for (int i = 0; i < fallbacks.size(); i++) { Ref<Font> f = fallbacks[i]; if (f.is_valid()) { - f->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED); + f->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); } } _invalidate_rids(); @@ -239,7 +239,7 @@ String Font::get_font_style_name() const { return TS->font_get_style_name(_get_rid()); } -uint32_t Font::get_font_style() const { +BitField<TextServer::FontStyle> Font::get_font_style() const { return TS->font_get_style(_get_rid()); } @@ -253,15 +253,15 @@ void Font::set_cache_capacity(int p_single_line, int p_multi_line) { cache_wrap.set_capacity(p_multi_line); } -Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); } + hash = hash_djb2_one_64(p_direction, hash); + hash = hash_djb2_one_64(p_orientation, hash); Ref<TextLine> buffer; if (cache.has(hash)) { @@ -271,16 +271,22 @@ Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignmen buffer->set_direction(p_direction); buffer->set_orientation(p_orientation); buffer->add_string(p_text, Ref<Font>(this), p_font_size); + if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { + buffer->set_horizontal_alignment(p_alignment); + buffer->set_width(p_width); + buffer->set_flags(p_jst_flags); + } cache.insert(hash, buffer); } return buffer->get_size(); } -Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); + hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -293,7 +299,8 @@ Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment lines_buffer->set_orientation(p_orientation); lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size); lines_buffer->set_width(p_width); - lines_buffer->set_flags(p_flags); + lines_buffer->set_break_flags(p_brk_flags); + lines_buffer->set_justification_flags(p_jst_flags); cache_wrap.insert(hash, lines_buffer); } @@ -303,13 +310,15 @@ Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment return lines_buffer->get_size(); } -void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); } + hash = hash_djb2_one_64(p_direction, hash); + hash = hash_djb2_one_64(p_orientation, hash); Ref<TextLine> buffer; if (cache.has(hash)) { @@ -331,16 +340,19 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t buffer->set_width(p_width); buffer->set_horizontal_alignment(p_alignment); - buffer->set_flags(p_flags); + if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { + buffer->set_flags(p_jst_flags); + } buffer->draw(p_canvas_item, ofs, p_modulate); } -void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); + hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -353,7 +365,8 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S lines_buffer->set_orientation(p_orientation); lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size); lines_buffer->set_width(p_width); - lines_buffer->set_flags(p_flags); + lines_buffer->set_break_flags(p_brk_flags); + lines_buffer->set_justification_flags(p_jst_flags); cache_wrap.insert(hash, lines_buffer); } @@ -370,13 +383,15 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S lines_buffer->draw(p_canvas_item, ofs, p_modulate); } -void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); } + hash = hash_djb2_one_64(p_direction, hash); + hash = hash_djb2_one_64(p_orientation, hash); Ref<TextLine> buffer; if (cache.has(hash)) { @@ -398,16 +413,19 @@ void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const Str buffer->set_width(p_width); buffer->set_horizontal_alignment(p_alignment); - buffer->set_flags(p_flags); + if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { + buffer->set_flags(p_jst_flags); + } buffer->draw_outline(p_canvas_item, ofs, p_size, p_modulate); } -void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { +void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_flags, hash); + hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -420,7 +438,8 @@ void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, lines_buffer->set_orientation(p_orientation); lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size); lines_buffer->set_width(p_width); - lines_buffer->set_flags(p_flags); + lines_buffer->set_break_flags(p_brk_flags); + lines_buffer->set_justification_flags(p_jst_flags); cache_wrap.insert(hash, lines_buffer); } @@ -980,7 +999,7 @@ void FontFile::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range"); @@ -1332,7 +1351,7 @@ Error FontFile::load_bitmap_font(const String &p_path) { int height = 0; int ascent = 0; int outline = 0; - uint32_t st_flags = 0; + BitField<TextServer::FontStyle> st_flags = 0; String font_name; bool packed = false; @@ -1358,10 +1377,10 @@ Error FontFile::load_bitmap_font(const String &p_path) { uint8_t flags = f->get_8(); ERR_FAIL_COND_V_MSG(flags & 0x02, ERR_CANT_CREATE, RTR("Non-unicode version of BMFont is not supported.")); if (flags & (1 << 3)) { - st_flags |= TextServer::FONT_BOLD; + st_flags.set_flag(TextServer::FONT_BOLD); } if (flags & (1 << 2)) { - st_flags |= TextServer::FONT_ITALIC; + st_flags.set_flag(TextServer::FONT_ITALIC); } f->get_8(); // non-unicode charset, skip f->get_16(); // stretch_h, skip @@ -1588,12 +1607,12 @@ Error FontFile::load_bitmap_font(const String &p_path) { } if (keys.has("bold")) { if (keys["bold"].to_int()) { - st_flags |= TextServer::FONT_BOLD; + st_flags.set_flag(TextServer::FONT_BOLD); } } if (keys.has("italic")) { if (keys["italic"].to_int()) { - st_flags |= TextServer::FONT_ITALIC; + st_flags.set_flag(TextServer::FONT_ITALIC); } } if (keys.has("face")) { @@ -1840,7 +1859,7 @@ void FontFile::set_font_style_name(const String &p_name) { TS->font_set_style_name(cache[0], p_name); } -void FontFile::set_font_style(uint32_t p_style) { +void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) { _ensure_rid(0); TS->font_set_style(cache[0], p_style); } @@ -2515,7 +2534,7 @@ void FontVariation::set_base_font(const Ref<Font> &p_font) { } base_font = p_font; if (base_font.is_valid()) { - base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED); + base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); } _invalidate_rids(); notify_property_list_changed(); @@ -2546,7 +2565,7 @@ Ref<Font> FontVariation::_get_base_font_or_default() const { Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); if (f.is_valid()) { theme_font = f; - theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED); + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); } return f; } @@ -2563,7 +2582,7 @@ Ref<Font> FontVariation::_get_base_font_or_default() const { Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); if (f.is_valid()) { theme_font = f; - theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED); + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); } return f; } @@ -2573,7 +2592,7 @@ Ref<Font> FontVariation::_get_base_font_or_default() const { Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); if (f.is_valid()) { theme_font = f; - theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED); + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); } return f; } @@ -2674,3 +2693,374 @@ FontVariation::FontVariation() { FontVariation::~FontVariation() { reset_state(); } + +/*************************************************************************/ +/* SystemFont */ +/*************************************************************************/ + +void SystemFont::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased); + ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased); + + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps); + + ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &SystemFont::set_force_autohinter); + ClassDB::bind_method(D_METHOD("is_force_autohinter"), &SystemFont::is_force_autohinter); + + ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &SystemFont::set_hinting); + ClassDB::bind_method(D_METHOD("get_hinting"), &SystemFont::get_hinting); + + ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning); + ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning); + + ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling); + ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling); + + ClassDB::bind_method(D_METHOD("get_font_names"), &SystemFont::get_font_names); + ClassDB::bind_method(D_METHOD("set_font_names", "names"), &SystemFont::set_font_names); + + ClassDB::bind_method(D_METHOD("set_font_style", "style"), &SystemFont::set_font_style); + + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), "set_subpixel_positioning", "get_subpixel_positioning"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks"); +} + +void SystemFont::_update_rids() const { + Ref<Font> f = _get_base_font_or_default(); + + rids.clear(); + if (fallbacks.is_empty() && f.is_valid()) { + RID rid = _get_rid(); + if (rid.is_valid()) { + rids.push_back(rid); + } + + const TypedArray<Font> &base_fallbacks = f->get_fallbacks(); + for (int i = 0; i < base_fallbacks.size(); i++) { + _update_rids_fb(base_fallbacks[i], 0); + } + } else { + _update_rids_fb(const_cast<SystemFont *>(this), 0); + } + dirty_rids = false; +} + +void SystemFont::_update_base_font() { + if (base_font.is_valid()) { + base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids)); + base_font.unref(); + } + + face_indeces.clear(); + ftr_weight = 0; + ftr_italic = 0; + for (const String &E : names) { + if (E.is_empty()) { + continue; + } + + String path = OS::get_singleton()->get_system_font_path(E, style & TextServer::FONT_BOLD, style & TextServer::FONT_ITALIC); + if (path.is_empty()) { + continue; + } + Ref<FontFile> file; + file.instantiate(); + Error err = file->load_dynamic_font(path); + if (err != OK) { + continue; + } + + // If it's a font collection check all faces to match requested style. + for (int i = 0; i < file->get_face_count(); i++) { + file->set_face_index(0, i); + if (((file->get_font_style() & TextServer::FONT_BOLD) == (style & TextServer::FONT_BOLD)) && ((file->get_font_style() & TextServer::FONT_ITALIC) == (style & TextServer::FONT_ITALIC))) { + face_indeces.push_back(i); + } + } + if (face_indeces.is_empty()) { + face_indeces.push_back(0); + } + file->set_face_index(0, face_indeces[0]); + + // If it's a variable font, apply weight and italic coordinates to match requested style. + Dictionary ftr = file->get_supported_variation_list(); + if ((style & TextServer::FONT_BOLD) && ftr.has(TS->name_to_tag("weight"))) { + ftr_weight = 700; + } + if ((style & TextServer::FONT_ITALIC) && ftr.has(TS->name_to_tag("italic"))) { + ftr_italic = 1; + } + + // Apply font rendering settings. + file->set_antialiased(antialiased); + file->set_generate_mipmaps(mipmaps); + file->set_force_autohinter(force_autohinter); + file->set_hinting(hinting); + file->set_subpixel_positioning(subpixel_positioning); + file->set_oversampling(oversampling); + + base_font = file; + } + + if (base_font.is_valid()) { + base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); + } + + _invalidate_rids(); + notify_property_list_changed(); +} + +void SystemFont::reset_state() { + if (base_font.is_valid()) { + base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids)); + base_font.unref(); + } + + if (theme_font.is_valid()) { + theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids)); + theme_font.unref(); + } + + names.clear(); + face_indeces.clear(); + ftr_weight = 0; + ftr_italic = 0; + style = 0; + antialiased = true; + mipmaps = false; + force_autohinter = false; + hinting = TextServer::HINTING_LIGHT; + subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED; + oversampling = 0.f; + + Font::reset_state(); +} + +Ref<Font> SystemFont::_get_base_font_or_default() const { + if (theme_font.is_valid()) { + theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids)); + theme_font.unref(); + } + + if (base_font.is_valid()) { + return base_font; + } + + // Check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + List<StringName> theme_types; + Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + if (f.is_valid()) { + theme_font = f; + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); + } + return f; + } + } + } + + // Lastly, fall back on the items defined in the default Theme, if they exist. + if (Theme::get_default().is_valid()) { + List<StringName> theme_types; + Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + if (f.is_valid()) { + theme_font = f; + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); + } + return f; + } + } + + // If they don't exist, use any type to return the default/empty value. + Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); + if (f.is_valid()) { + theme_font = f; + theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); + } + return f; + } + + return Ref<Font>(); +} + +void SystemFont::set_antialiased(bool p_antialiased) { + if (antialiased != p_antialiased) { + antialiased = p_antialiased; + if (base_font.is_valid()) { + base_font->set_antialiased(antialiased); + } + emit_changed(); + } +} + +bool SystemFont::is_antialiased() const { + return antialiased; +} + +void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) { + if (mipmaps != p_generate_mipmaps) { + mipmaps = p_generate_mipmaps; + if (base_font.is_valid()) { + base_font->set_generate_mipmaps(mipmaps); + } + emit_changed(); + } +} + +bool SystemFont::get_generate_mipmaps() const { + return mipmaps; +} + +void SystemFont::set_force_autohinter(bool p_force_autohinter) { + if (force_autohinter != p_force_autohinter) { + force_autohinter = p_force_autohinter; + if (base_font.is_valid()) { + base_font->set_force_autohinter(force_autohinter); + } + emit_changed(); + } +} + +bool SystemFont::is_force_autohinter() const { + return force_autohinter; +} + +void SystemFont::set_hinting(TextServer::Hinting p_hinting) { + if (hinting != p_hinting) { + hinting = p_hinting; + if (base_font.is_valid()) { + base_font->set_hinting(hinting); + } + emit_changed(); + } +} + +TextServer::Hinting SystemFont::get_hinting() const { + return hinting; +} + +void SystemFont::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) { + if (subpixel_positioning != p_subpixel) { + subpixel_positioning = p_subpixel; + if (base_font.is_valid()) { + base_font->set_subpixel_positioning(subpixel_positioning); + } + emit_changed(); + } +} + +TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const { + return subpixel_positioning; +} + +void SystemFont::set_oversampling(real_t p_oversampling) { + if (oversampling != p_oversampling) { + oversampling = p_oversampling; + if (base_font.is_valid()) { + base_font->set_oversampling(oversampling); + } + emit_changed(); + } +} + +real_t SystemFont::get_oversampling() const { + return oversampling; +} + +void SystemFont::set_font_names(const PackedStringArray &p_names) { + if (names != p_names) { + names = p_names; + _update_base_font(); + } +} + +PackedStringArray SystemFont::get_font_names() const { + return names; +} + +void SystemFont::set_font_style(BitField<TextServer::FontStyle> p_style) { + if (style != p_style) { + style = p_style; + _update_base_font(); + } +} + +BitField<TextServer::FontStyle> SystemFont::get_font_style() const { + return style; +} + +int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const { + if (base_font.is_valid()) { + return base_font->get_spacing(p_spacing); + } else { + return 0; + } +} + +RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform) const { + Ref<Font> f = _get_base_font_or_default(); + if (f.is_valid()) { + Dictionary var = p_variation_coordinates; + if (ftr_weight > 0 && !var.has(TS->name_to_tag("weight"))) { + var[TS->name_to_tag("weight")] = ftr_weight; + } + if (ftr_italic > 0 && !var.has(TS->name_to_tag("italic"))) { + var[TS->name_to_tag("italic")] = ftr_italic; + } + + if (!face_indeces.is_empty()) { + int face_index = CLAMP(p_face_index, 0, face_indeces.size() - 1); + return f->find_variation(var, face_indeces[face_index], p_strength, p_transform); + } else { + return f->find_variation(var, 0, p_strength, p_transform); + } + } + return RID(); +} + +RID SystemFont::_get_rid() const { + Ref<Font> f = _get_base_font_or_default(); + if (f.is_valid()) { + if (!face_indeces.is_empty()) { + Dictionary var; + if (ftr_weight > 0) { + var[TS->name_to_tag("weight")] = ftr_weight; + } + if (ftr_italic > 0) { + var[TS->name_to_tag("italic")] = ftr_italic; + } + return f->find_variation(var, face_indeces[0]); + } else { + return f->_get_rid(); + } + } + return RID(); +} + +int64_t SystemFont::get_face_count() const { + return face_indeces.size(); +} + +SystemFont::SystemFont() { + /* NOP */ +} + +SystemFont::~SystemFont() { + reset_state(); +} diff --git a/scene/resources/font.h b/scene/resources/font.h index 40b223b0f5..260b4e521f 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -41,7 +41,7 @@ class TextLine; class TextParagraph; /*************************************************************************/ -/* Font */ +/* Font */ /*************************************************************************/ class Font : public Resource { @@ -91,7 +91,7 @@ public: virtual String get_font_name() const; virtual String get_font_style_name() const; - virtual uint32_t get_font_style() const; + virtual BitField<TextServer::FontStyle> get_font_style() const; virtual int get_spacing(TextServer::SpacingType p_spacing) const { return 0; }; virtual Dictionary get_opentype_features() const; @@ -99,14 +99,14 @@ public: // Drawing string. virtual void set_cache_capacity(int p_single_line, int p_multi_line); - virtual Size2 get_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - virtual Size2 get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual Size2 get_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual Size2 get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - virtual void draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; - virtual void draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual void draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; + virtual void draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const; // Drawing char. virtual Size2 get_char_size(char32_t p_char, int p_font_size = DEFAULT_FONT_SIZE) const; @@ -190,7 +190,7 @@ public: // Common properties. virtual void set_font_name(const String &p_name); virtual void set_font_style_name(const String &p_name); - virtual void set_font_style(uint32_t p_style); + virtual void set_font_style(BitField<TextServer::FontStyle> p_style); virtual void set_antialiased(bool p_antialiased); virtual bool is_antialiased() const; @@ -381,4 +381,74 @@ public: ~FontVariation(); }; -#endif /* FONT_H */ +/*************************************************************************/ +/* SystemFont */ +/*************************************************************************/ + +class SystemFont : public Font { + GDCLASS(SystemFont, Font); + + PackedStringArray names; + BitField<TextServer::FontStyle> style = 0; + + mutable Ref<Font> theme_font; + + Ref<FontFile> base_font; + Vector<int> face_indeces; + int ftr_weight = 0; + int ftr_italic = 0; + + bool antialiased = true; + bool mipmaps = false; + bool force_autohinter = false; + TextServer::Hinting hinting = TextServer::HINTING_LIGHT; + TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; + real_t oversampling = 0.f; + +protected: + static void _bind_methods(); + + virtual void _update_base_font(); + virtual void _update_rids() const override; + + virtual void reset_state() override; + +public: + virtual Ref<Font> _get_base_font_or_default() const; + + virtual void set_antialiased(bool p_antialiased); + virtual bool is_antialiased() const; + + virtual void set_generate_mipmaps(bool p_generate_mipmaps); + virtual bool get_generate_mipmaps() const; + + virtual void set_force_autohinter(bool p_force_autohinter); + virtual bool is_force_autohinter() const; + + virtual void set_hinting(TextServer::Hinting p_hinting); + virtual TextServer::Hinting get_hinting() const; + + virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel); + virtual TextServer::SubpixelPositioning get_subpixel_positioning() const; + + virtual void set_oversampling(real_t p_oversampling); + virtual real_t get_oversampling() const; + + virtual void set_font_names(const PackedStringArray &p_names); + virtual PackedStringArray get_font_names() const; + + virtual void set_font_style(BitField<TextServer::FontStyle> p_style); + virtual BitField<TextServer::FontStyle> get_font_style() const override; + + virtual int get_spacing(TextServer::SpacingType p_spacing) const override; + + virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D()) const override; + virtual RID _get_rid() const override; + + int64_t get_face_count() const override; + + SystemFont(); + ~SystemFont(); +}; + +#endif // FONT_H diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h index 2b04ead0af..e4bac15e4b 100644 --- a/scene/resources/gradient.h +++ b/scene/resources/gradient.h @@ -157,10 +157,10 @@ public: const Point &pointP3 = points[p3]; float x = (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset); - float r = Math::cubic_interpolate(pointP0.color.r, pointFirst.color.r, pointSecond.color.r, pointP3.color.r, x); - float g = Math::cubic_interpolate(pointP0.color.g, pointFirst.color.g, pointSecond.color.g, pointP3.color.g, x); - float b = Math::cubic_interpolate(pointP0.color.b, pointFirst.color.b, pointSecond.color.b, pointP3.color.b, x); - float a = Math::cubic_interpolate(pointP0.color.a, pointFirst.color.a, pointSecond.color.a, pointP3.color.a, x); + float r = Math::cubic_interpolate(pointFirst.color.r, pointSecond.color.r, pointP0.color.r, pointP3.color.r, x); + float g = Math::cubic_interpolate(pointFirst.color.g, pointSecond.color.g, pointP0.color.g, pointP3.color.g, x); + float b = Math::cubic_interpolate(pointFirst.color.b, pointSecond.color.b, pointP0.color.b, pointP3.color.b, x); + float a = Math::cubic_interpolate(pointFirst.color.a, pointSecond.color.a, pointP0.color.a, pointP3.color.a, x); return Color(r, g, b, a); } break; diff --git a/scene/resources/height_map_shape_3d.h b/scene/resources/height_map_shape_3d.h index 79d1b15674..633238030b 100644 --- a/scene/resources/height_map_shape_3d.h +++ b/scene/resources/height_map_shape_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef HEIGHT_MAP_SHAPE_H -#define HEIGHT_MAP_SHAPE_H +#ifndef HEIGHT_MAP_SHAPE_3D_H +#define HEIGHT_MAP_SHAPE_3D_H #include "scene/resources/shape_3d.h" @@ -60,4 +60,4 @@ public: HeightMapShape3D(); }; -#endif /* !HEIGHT_MAP_SHAPE_H */ +#endif // HEIGHT_MAP_SHAPE_3D_H diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h index e5f627ae8e..de10fdbfbe 100644 --- a/scene/resources/immediate_mesh.h +++ b/scene/resources/immediate_mesh.h @@ -115,4 +115,4 @@ public: ~ImmediateMesh(); }; -#endif // IMMEDIATEMESH_H +#endif // IMMEDIATE_MESH_H diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h index 8f77597a58..bf1d0301d1 100644 --- a/scene/resources/importer_mesh.h +++ b/scene/resources/importer_mesh.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_IMPORTER_MESH_H -#define SCENE_IMPORTER_MESH_H +#ifndef IMPORTER_MESH_H +#define IMPORTER_MESH_H #include "core/io/resource.h" #include "core/templates/local_vector.h" @@ -130,4 +130,5 @@ public: Ref<ArrayMesh> get_mesh(const Ref<ArrayMesh> &p_base = Ref<ArrayMesh>()); void clear(); }; -#endif // SCENE_IMPORTER_MESH_H + +#endif // IMPORTER_MESH_H diff --git a/scene/resources/label_settings.cpp b/scene/resources/label_settings.cpp new file mode 100644 index 0000000000..ef380a68f9 --- /dev/null +++ b/scene/resources/label_settings.cpp @@ -0,0 +1,187 @@ +/*************************************************************************/ +/* label_settings.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "label_settings.h" + +#include "core/core_string_names.h" + +void LabelSettings::_font_changed() { + emit_changed(); +} + +void LabelSettings::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_line_spacing", "spacing"), &LabelSettings::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &LabelSettings::get_line_spacing); + + ClassDB::bind_method(D_METHOD("set_font", "font"), &LabelSettings::set_font); + ClassDB::bind_method(D_METHOD("get_font"), &LabelSettings::get_font); + + ClassDB::bind_method(D_METHOD("set_font_size", "size"), &LabelSettings::set_font_size); + ClassDB::bind_method(D_METHOD("get_font_size"), &LabelSettings::get_font_size); + + ClassDB::bind_method(D_METHOD("set_font_color", "color"), &LabelSettings::set_font_color); + ClassDB::bind_method(D_METHOD("get_font_color"), &LabelSettings::get_font_color); + + ClassDB::bind_method(D_METHOD("set_outline_size", "size"), &LabelSettings::set_outline_size); + ClassDB::bind_method(D_METHOD("get_outline_size"), &LabelSettings::get_outline_size); + + ClassDB::bind_method(D_METHOD("set_outline_color", "color"), &LabelSettings::set_outline_color); + ClassDB::bind_method(D_METHOD("get_outline_color"), &LabelSettings::get_outline_color); + + ClassDB::bind_method(D_METHOD("set_shadow_size", "size"), &LabelSettings::set_shadow_size); + ClassDB::bind_method(D_METHOD("get_shadow_size"), &LabelSettings::get_shadow_size); + + ClassDB::bind_method(D_METHOD("set_shadow_color", "color"), &LabelSettings::set_shadow_color); + ClassDB::bind_method(D_METHOD("get_shadow_color"), &LabelSettings::get_shadow_color); + + ClassDB::bind_method(D_METHOD("set_shadow_offset", "offset"), &LabelSettings::set_shadow_offset); + ClassDB::bind_method(D_METHOD("get_shadow_offset"), &LabelSettings::get_shadow_offset); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing"); + + ADD_GROUP("Font", "font"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,1024,1,or_greater,suffix:px"), "set_font_size", "get_font_size"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "font_color"), "set_font_color", "get_font_color"); + + ADD_GROUP("Outline", "outline"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_outline_size", "get_outline_size"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_color"), "set_outline_color", "get_outline_color"); + + ADD_GROUP("Shadow", "shadow"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_shadow_size", "get_shadow_size"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_shadow_offset", "get_shadow_offset"); +} + +void LabelSettings::set_line_spacing(real_t p_spacing) { + if (line_spacing != p_spacing) { + line_spacing = p_spacing; + emit_changed(); + } +} + +real_t LabelSettings::get_line_spacing() const { + return line_spacing; +} + +void LabelSettings::set_font(const Ref<Font> &p_font) { + if (font != p_font) { + if (font.is_valid()) { + font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &LabelSettings::_font_changed)); + } + font = p_font; + if (font.is_valid()) { + font->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &LabelSettings::_font_changed), CONNECT_REFERENCE_COUNTED); + } + emit_changed(); + } +} + +Ref<Font> LabelSettings::get_font() const { + return font; +} + +void LabelSettings::set_font_size(int p_size) { + if (font_size != p_size) { + font_size = p_size; + emit_changed(); + } +} + +int LabelSettings::get_font_size() const { + return font_size; +} + +void LabelSettings::set_font_color(const Color &p_color) { + if (font_color != p_color) { + font_color = p_color; + emit_changed(); + } +} + +Color LabelSettings::get_font_color() const { + return font_color; +} + +void LabelSettings::set_outline_size(int p_size) { + if (outline_size != p_size) { + outline_size = p_size; + emit_changed(); + } +} + +int LabelSettings::get_outline_size() const { + return outline_size; +} + +void LabelSettings::set_outline_color(const Color &p_color) { + if (outline_color != p_color) { + outline_color = p_color; + emit_changed(); + } +} + +Color LabelSettings::get_outline_color() const { + return outline_color; +} + +void LabelSettings::set_shadow_size(int p_size) { + if (shadow_size != p_size) { + shadow_size = p_size; + emit_changed(); + } +} + +int LabelSettings::get_shadow_size() const { + return shadow_size; +} + +void LabelSettings::set_shadow_color(const Color &p_color) { + if (shadow_color != p_color) { + shadow_color = p_color; + emit_changed(); + } +} + +Color LabelSettings::get_shadow_color() const { + return shadow_color; +} + +void LabelSettings::set_shadow_offset(const Vector2 &p_offset) { + if (shadow_offset != p_offset) { + shadow_offset = p_offset; + emit_changed(); + } +} + +Vector2 LabelSettings::get_shadow_offset() const { + return shadow_offset; +} diff --git a/scene/resources/label_settings.h b/scene/resources/label_settings.h new file mode 100644 index 0000000000..062d499d50 --- /dev/null +++ b/scene/resources/label_settings.h @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* label_settings.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 LABEL_SETTINGS_H +#define LABEL_SETTINGS_H + +#include "core/io/resource.h" +#include "font.h" + +/*************************************************************************/ + +class LabelSettings : public Resource { + GDCLASS(LabelSettings, Resource); + + real_t line_spacing = 3; + + Ref<Font> font; + int font_size = Font::DEFAULT_FONT_SIZE; + Color font_color = Color(1, 1, 1); + + int outline_size = 0; + Color outline_color = Color(1, 1, 1); + + int shadow_size = 1; + Color shadow_color = Color(0, 0, 0, 0); + Vector2 shadow_offset = Vector2(1, 1); + + void _font_changed(); + +protected: + static void _bind_methods(); + +public: + void set_line_spacing(real_t p_spacing); + real_t get_line_spacing() const; + + void set_font(const Ref<Font> &p_font); + Ref<Font> get_font() const; + + void set_font_size(int p_size); + int get_font_size() const; + + void set_font_color(const Color &p_color); + Color get_font_color() const; + + void set_outline_size(int p_size); + int get_outline_size() const; + + void set_outline_color(const Color &p_color); + Color get_outline_color() const; + + void set_shadow_size(int p_size); + int get_shadow_size() const; + + void set_shadow_color(const Color &p_color); + Color get_shadow_color() const; + + void set_shadow_offset(const Vector2 &p_offset); + Vector2 get_shadow_offset() const; +}; + +#endif // LABEL_SETTINGS_H diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index b7a3b677f5..88bc01fb25 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -154,18 +154,18 @@ Material::~Material() { bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); + StringName pr = shader->remap_uniform(p_name); if (!pr) { String n = p_name; if (n.find("param/") == 0) { //backwards compatibility pr = n.substr(6, n.length()); } - if (n.find("shader_param/") == 0) { //backwards compatibility - pr = n.replace_first("shader_param/", ""); + if (n.find("shader_uniform/") == 0) { //backwards compatibility + pr = n.replace_first("shader_uniform/", ""); } } if (pr) { - set_shader_param(pr, p_value); + set_shader_uniform(pr, p_value); return true; } } @@ -175,14 +175,14 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); + StringName pr = shader->remap_uniform(p_name); if (!pr) { String n = p_name; if (n.find("param/") == 0) { //backwards compatibility pr = n.substr(6, n.length()); } - if (n.find("shader_param/") == 0) { //backwards compatibility - pr = n.replace_first("shader_param/", ""); + if (n.find("shader_uniform/") == 0) { //backwards compatibility + pr = n.replace_first("shader_uniform/", ""); } } @@ -202,13 +202,104 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { if (!shader.is_null()) { - shader->get_param_list(p_list); + List<PropertyInfo> list; + shader->get_shader_uniform_list(&list, true); + + HashMap<String, HashMap<String, List<PropertyInfo>>> groups; + { + HashMap<String, List<PropertyInfo>> none_subgroup; + none_subgroup.insert("<None>", List<PropertyInfo>()); + groups.insert("<None>", none_subgroup); + } + + String last_group = "<None>"; + String last_subgroup = "<None>"; + + bool is_none_group_undefined = true; + bool is_none_group = true; + + for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) { + if (E->get().usage == PROPERTY_USAGE_GROUP) { + if (!E->get().name.is_empty()) { + Vector<String> vgroup = E->get().name.split("::"); + last_group = vgroup[0]; + if (vgroup.size() > 1) { + last_subgroup = vgroup[1]; + } else { + last_subgroup = "<None>"; + } + is_none_group = false; + + if (!groups.has(last_group)) { + PropertyInfo info; + info.usage = PROPERTY_USAGE_GROUP; + info.name = last_group.capitalize(); + + List<PropertyInfo> none_subgroup; + none_subgroup.push_back(info); + + HashMap<String, List<PropertyInfo>> subgroup_map; + subgroup_map.insert("<None>", none_subgroup); + + groups.insert(last_group, subgroup_map); + } + + if (!groups[last_group].has(last_subgroup)) { + PropertyInfo info; + info.usage = PROPERTY_USAGE_SUBGROUP; + info.name = last_subgroup.capitalize(); + + List<PropertyInfo> subgroup; + subgroup.push_back(info); + + groups[last_group].insert(last_subgroup, subgroup); + } + } else { + last_group = "<None>"; + last_subgroup = "<None>"; + is_none_group = true; + } + continue; // Pass group. + } + + if (is_none_group_undefined && is_none_group) { + is_none_group_undefined = false; + + PropertyInfo info; + info.usage = PROPERTY_USAGE_GROUP; + info.name = "Shader Param"; + groups["<None>"]["<None>"].push_back(info); + } + + PropertyInfo info = E->get(); + info.name = info.name; + groups[last_group][last_subgroup].push_back(info); + } + + // Sort groups alphabetically. + List<UniformProp> props; + for (HashMap<String, HashMap<String, List<PropertyInfo>>>::Iterator group = groups.begin(); group; ++group) { + for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = group->value.begin(); subgroup; ++subgroup) { + for (List<PropertyInfo>::Element *item = subgroup->value.front(); item; item = item->next()) { + if (subgroup->key == "<None>") { + props.push_back({ group->key, item->get() }); + } else { + props.push_back({ group->key + "::" + subgroup->key, item->get() }); + } + } + } + } + props.sort_custom<UniformPropComparator>(); + + for (List<UniformProp>::Element *E = props.front(); E; E = E->next()) { + p_list->push_back(E->get().info); + } } } bool ShaderMaterial::property_can_revert(const String &p_name) { if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); + StringName pr = shader->remap_uniform(p_name); if (pr) { Variant default_value = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); Variant current_value; @@ -222,7 +313,7 @@ bool ShaderMaterial::property_can_revert(const String &p_name) { Variant ShaderMaterial::property_get_revert(const String &p_name) { Variant r_ret; if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); + StringName pr = shader->remap_uniform(p_name); if (pr) { r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); } @@ -258,7 +349,7 @@ Ref<Shader> ShaderMaterial::get_shader() const { return shader; } -void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { +void ShaderMaterial::set_shader_uniform(const StringName &p_param, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { param_cache.erase(p_param); RS::get_singleton()->material_set_param(_get_material(), p_param, Variant()); @@ -278,7 +369,7 @@ void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant & } } -Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { +Variant ShaderMaterial::get_shader_uniform(const StringName &p_param) const { if (param_cache.has(p_param)) { return param_cache[p_param]; } else { @@ -293,8 +384,8 @@ void ShaderMaterial::_shader_changed() { void ShaderMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); - ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); - ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); + ClassDB::bind_method(D_METHOD("set_shader_uniform", "param", "value"), &ShaderMaterial::set_shader_uniform); + ClassDB::bind_method(D_METHOD("get_shader_uniform", "param"), &ShaderMaterial::get_shader_uniform); ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert); ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert); @@ -303,12 +394,12 @@ void ShaderMaterial::_bind_methods() { void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { String f = p_function.operator String(); - if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + if ((f == "get_shader_uniform" || f == "set_shader_uniform") && p_idx == 0) { if (shader.is_valid()) { List<PropertyInfo> pl; - shader->get_param_list(&pl); + shader->get_shader_uniform_list(&pl); for (const PropertyInfo &E : pl) { - r_options->push_back(E.name.replace_first("shader_param/", "").quote()); + r_options->push_back(E.name.replace_first("shader_uniform/", "").quote()); } } } @@ -976,7 +1067,8 @@ void BaseMaterial3D::_update_shader() { code += " float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; code += " float layer_depth = 1.0 / num_layers;\n"; code += " float current_layer_depth = 0.0;\n"; - code += " vec2 P = view_dir.xy * heightmap_scale;\n"; + // Multiply the heightmap scale by 0.01 to improve heightmap scale usability. + code += " vec2 P = view_dir.xy * heightmap_scale * 0.01;\n"; code += " vec2 delta = P / num_layers;\n"; code += " vec2 ofs = base_uv;\n"; if (flags[FLAG_INVERT_HEIGHTMAP]) { @@ -1012,7 +1104,8 @@ void BaseMaterial3D::_update_shader() { } // Use offset limiting to improve the appearance of non-deep parallax. // This reduces the impression of depth, but avoids visible warping in the distance. - code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale;\n"; + // Multiply the heightmap scale by 0.01 to improve heightmap scale usability. + code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;\n"; } code += " base_uv=ofs;\n"; @@ -1185,38 +1278,21 @@ void BaseMaterial3D::_update_shader() { if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) { if (!RenderingServer::get_singleton()->is_low_end()) { code += " {\n"; + if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) { code += " float fade_distance = abs((VIEW_MATRIX * MODEL_MATRIX[3]).z);\n"; } else { - code += " float fade_distance=-VERTEX.z;\n"; + code += " float fade_distance = -VERTEX.z;\n"; } + // Use interleaved gradient noise, which is fast but still looks good. + code += " const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);"; + code += " float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n"; + // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance. + code += " if (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n"; + code += " discard;\n"; + code += " }\n"; - code += " float fade=clamp(smoothstep(distance_fade_min,distance_fade_max,fade_distance),0.0,1.0);\n"; - code += " int x = int(FRAGCOORD.x) % 4;\n"; - code += " int y = int(FRAGCOORD.y) % 4;\n"; - code += " int index = x + y * 4;\n"; - code += " float limit = 0.0;\n\n"; - code += " if (x < 8) {\n"; - code += " if (index == 0) limit = 0.0625;\n"; - code += " if (index == 1) limit = 0.5625;\n"; - code += " if (index == 2) limit = 0.1875;\n"; - code += " if (index == 3) limit = 0.6875;\n"; - code += " if (index == 4) limit = 0.8125;\n"; - code += " if (index == 5) limit = 0.3125;\n"; - code += " if (index == 6) limit = 0.9375;\n"; - code += " if (index == 7) limit = 0.4375;\n"; - code += " if (index == 8) limit = 0.25;\n"; - code += " if (index == 9) limit = 0.75;\n"; - code += " if (index == 10) limit = 0.125;\n"; - code += " if (index == 11) limit = 0.625;\n"; - code += " if (index == 12) limit = 1.0;\n"; - code += " if (index == 13) limit = 0.5;\n"; - code += " if (index == 14) limit = 0.875;\n"; - code += " if (index == 15) limit = 0.375;\n"; - code += " }\n\n"; - code += " if (fade < limit)\n"; - code += " discard;\n"; code += " }\n\n"; } @@ -1702,12 +1778,21 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) { } flags[p_flag] = p_enabled; - if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN || p_flag == FLAG_USE_POINT_SIZE) { + + if ( + p_flag == FLAG_USE_SHADOW_TO_OPACITY || + p_flag == FLAG_USE_TEXTURE_REPEAT || + p_flag == FLAG_SUBSURFACE_MODE_SKIN || + p_flag == FLAG_USE_POINT_SIZE || + p_flag == FLAG_UV1_USE_TRIPLANAR || + p_flag == FLAG_UV2_USE_TRIPLANAR) { notify_property_list_changed(); } + if (p_flag == FLAG_PARTICLE_TRAILS_MODE) { update_configuration_warning(); } + _queue_shader_change(); } @@ -1833,6 +1918,14 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NO_EDITOR; } + if ((property.name == "uv1_triplanar_sharpness" || property.name == "uv1_world_triplanar") && !flags[FLAG_UV1_USE_TRIPLANAR]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + + if ((property.name == "uv2_triplanar_sharpness" || property.name == "uv2_world_triplanar") && !flags[FLAG_UV2_USE_TRIPLANAR]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH); // alpha anti aliasiasing is only enabled when you can select aa @@ -2546,7 +2639,7 @@ void BaseMaterial3D::_bind_methods() { ADD_GROUP("Transparency", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); @@ -2593,7 +2686,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION); - ADD_GROUP("NormalMap", "normal_"); + ADD_GROUP("Normal Map", "normal_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL); @@ -2633,7 +2726,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "heightmap_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_HEIGHTMAP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP); - ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); + ADD_GROUP("Subsurface Scattering", "subsurf_scatter_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_SCATTERING); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN); @@ -2857,7 +2950,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : set_clearcoat(1); set_clearcoat_roughness(0.5); set_anisotropy(0); - set_heightmap_scale(0.05); + set_heightmap_scale(5.0); set_subsurface_scattering_strength(0); set_backlight(Color(0, 0, 0)); set_transmittance_color(Color(1, 1, 1, 1)); @@ -2878,7 +2971,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : set_transparency(TRANSPARENCY_DISABLED); set_alpha_antialiasing(ALPHA_ANTIALIASING_OFF); - set_alpha_scissor_threshold(0.05); + set_alpha_scissor_threshold(0.5); set_alpha_hash_scale(1.0); set_alpha_antialiasing_edge(0.3); diff --git a/scene/resources/material.h b/scene/resources/material.h index b845fd68c8..ca5b17dd07 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -84,6 +84,17 @@ class ShaderMaterial : public Material { HashMap<StringName, Variant> param_cache; + struct UniformProp { + String str; + PropertyInfo info; + }; + + struct UniformPropComparator { + bool operator()(const UniformProp &p_a, const UniformProp &p_b) const { + return p_a.str.naturalnocasecmp_to(p_b.str) < 0; + } + }; + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -104,8 +115,8 @@ public: void set_shader(const Ref<Shader> &p_shader); Ref<Shader> get_shader() const; - void set_shader_param(const StringName &p_param, const Variant &p_value); - Variant get_shader_param(const StringName &p_param) const; + void set_shader_uniform(const StringName &p_param, const Variant &p_value); + Variant get_shader_uniform(const StringName &p_param) const; virtual Shader::Mode get_shader_mode() const override; @@ -809,4 +820,4 @@ public: ////////////////////// -#endif +#endif // MATERIAL_H diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 3e7b0a2808..ec9db89794 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -260,6 +260,64 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { return triangle_mesh; } +Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>()); + + if (surface_triangle_meshes.size() != get_surface_count()) { + surface_triangle_meshes.resize(get_surface_count()); + } + + if (surface_triangle_meshes[p_surface].is_valid()) { + return surface_triangle_meshes[p_surface]; + } + + int facecount = 0; + + if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) { + return Ref<TriangleMesh>(); + } + + if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { + facecount += surface_get_array_index_len(p_surface); + } else { + facecount += surface_get_array_len(p_surface); + } + + Vector<Vector3> faces; + faces.resize(facecount); + Vector3 *facesw = faces.ptrw(); + + Array a = surface_get_arrays(p_surface); + ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); + + int vc = surface_get_array_len(p_surface); + Vector<Vector3> vertices = a[ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); + int widx = 0; + + if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { + int ic = surface_get_array_index_len(p_surface); + Vector<int> indices = a[ARRAY_INDEX]; + const int *ir = indices.ptr(); + + for (int j = 0; j < ic; j++) { + int index = ir[j]; + facesw[widx++] = vr[index]; + } + + } else { + for (int j = 0; j < vc; j++) { + facesw[widx++] = vr[j]; + } + } + + Ref<TriangleMesh> triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh->create(faces); + surface_triangle_meshes.set(p_surface, triangle_mesh); + + return triangle_mesh; +} + void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { if (debug_lines.size() > 0) { r_lines = debug_lines; @@ -320,6 +378,14 @@ Vector<Face3> Mesh::get_faces() const { return Vector<Face3>(); } +Vector<Face3> Mesh::get_surface_faces(int p_surface) const { + Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface); + if (tm.is_valid()) { + return tm->get_faces(); + } + return Vector<Face3>(); +} + Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { if (p_simplify) { ConvexDecompositionSettings settings; diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index b166d12ead..142373ce7f 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -42,6 +42,7 @@ class Mesh : public Resource { GDCLASS(Mesh, Resource); mutable Ref<TriangleMesh> triangle_mesh; //cached + mutable Vector<Ref<TriangleMesh>> surface_triangle_meshes; //cached mutable Vector<Vector3> debug_lines; Size2i lightmap_size_hint; @@ -161,7 +162,9 @@ public: virtual AABB get_aabb() const; Vector<Face3> get_faces() const; + Vector<Face3> get_surface_faces(int p_surface) const; Ref<TriangleMesh> generate_triangle_mesh() const; + Ref<TriangleMesh> generate_surface_triangle_mesh(int p_surface) const; void generate_debug_mesh_lines(Vector<Vector3> &r_lines); void generate_debug_mesh_indices(Vector<Vector3> &r_points); @@ -362,4 +365,4 @@ public: ~PlaceholderMesh(); }; -#endif +#endif // MESH_H diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index c8bfb73b2d..2d3f9d9afc 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -107,7 +107,7 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::ARRAY, name + PNAME("shapes"))); p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh")); p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("navmesh_transform"), PROPERTY_HINT_NONE, "suffix:m")); - p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER)); + p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT)); } } diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 30ada5365f..0f8cc76173 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -113,4 +113,4 @@ public: VARIANT_ENUM_CAST(MultiMesh::TransformFormat); -#endif // MULTI_MESH_H +#endif // MULTIMESH_H diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index a808ead66b..ac5493efdc 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -30,6 +30,10 @@ #include "navigation_mesh.h" +#ifdef DEBUG_ENABLED +#include "servers/navigation_server_3d.h" +#endif + void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { ERR_FAIL_COND(p_mesh.is_null()); @@ -337,6 +341,7 @@ void NavigationMesh::clear_polygons() { polygons.clear(); } +#ifndef DISABLE_DEPRECATED Ref<Mesh> NavigationMesh::get_debug_mesh() { if (debug_mesh.is_valid()) { return debug_mesh; @@ -420,6 +425,102 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { return debug_mesh; } +#endif // DISABLE_DEPRECATED + +#ifdef DEBUG_ENABLED +Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() { + if (debug_mesh.is_valid()) { + // Blocks further updates for now, code below is intended for dynamic updates e.g. when settings change. + return debug_mesh; + } + + if (!debug_mesh.is_valid()) { + debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + } else { + debug_mesh->clear_surfaces(); + } + + if (vertices.size() == 0) { + return debug_mesh; + } + + int polygon_count = get_polygon_count(); + + if (polygon_count < 1) { + // no face, no play + return debug_mesh; + } + + // build geometry face surface + Vector<Vector3> face_vertex_array; + face_vertex_array.resize(polygon_count * 3); + + for (int i = 0; i < polygon_count; i++) { + Vector<int> polygon = get_polygon(i); + + face_vertex_array.push_back(vertices[polygon[0]]); + face_vertex_array.push_back(vertices[polygon[1]]); + face_vertex_array.push_back(vertices[polygon[2]]); + } + + Array face_mesh_array; + face_mesh_array.resize(Mesh::ARRAY_MAX); + face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array; + + // if enabled add vertex colors to colorize each face individually + bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color(); + if (enabled_geometry_face_random_color) { + Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); + Color polygon_color = debug_navigation_geometry_face_color; + + Vector<Color> face_color_array; + face_color_array.resize(polygon_count * 3); + + for (int i = 0; i < polygon_count; i++) { + polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf())); + + Vector<int> polygon = get_polygon(i); + + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + face_color_array.push_back(polygon_color); + } + face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array; + } + + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); + Ref<StandardMaterial3D> debug_geometry_face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material(); + debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_face_material); + + // if enabled build geometry edge line surface + bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines(); + + if (enabled_edge_lines) { + Vector<Vector3> line_vertex_array; + line_vertex_array.resize(polygon_count * 6); + + for (int i = 0; i < polygon_count; i++) { + Vector<int> polygon = get_polygon(i); + + line_vertex_array.push_back(vertices[polygon[0]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[1]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[2]]); + line_vertex_array.push_back(vertices[polygon[0]]); + } + + Array line_mesh_array; + line_mesh_array.resize(Mesh::ARRAY_MAX); + line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array; + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array); + Ref<StandardMaterial3D> debug_geometry_edge_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material(); + debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_edge_material); + } + + return debug_mesh; +} +#endif void NavigationMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type); diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index 40b275c792..79d8962d24 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -204,7 +204,11 @@ public: Vector<int> get_polygon(int p_idx); void clear_polygons(); +#ifndef DISABLE_DEPRECATED Ref<Mesh> get_debug_mesh(); +#endif // DISABLE_DEPRECATED + + Ref<ArrayMesh> _get_debug_mesh(); NavigationMesh(); }; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 2c58aa83a9..ac67e6e5e9 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -434,10 +434,10 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { for (int j = 0; j < binds.size(); j++) { argptrs[j] = &binds[j]; } - callable = callable.bind(argptrs, binds.size()); + callable = callable.bindp(argptrs, binds.size()); } - cfrom->connect(snames[c.signal], callable, varray(), CONNECT_PERSIST | c.flags); + cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags); } //Node *s = ret_nodes[0]; @@ -892,9 +892,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String cd.signal = _nm_get_string(c.signal.get_name(), name_map); cd.flags = c.flags; cd.unbinds = unbinds; - for (int i = 0; i < c.binds.size(); i++) { // TODO: This could be removed now. - cd.binds.push_back(_vm_get_variant(c.binds[i], variant_map)); - } + for (int i = 0; i < binds.size(); i++) { cd.binds.push_back(_vm_get_variant(binds[i], variant_map)); } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 5f8001c871..8e1a1d29b6 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -249,4 +249,4 @@ public: VARIANT_ENUM_CAST(PackedScene::GenEditState) -#endif // SCENE_PRELOADER_H +#endif // PACKED_SCENE_H diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 7a49b9b515..4b2e029f47 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -98,6 +98,17 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_ring_radius = "emission_ring_radius"; shader_names->emission_ring_inner_radius = "emission_ring_inner_radius"; + shader_names->turbulence_enabled = "turbulence_enabled"; + shader_names->turbulence_noise_strength = "turbulence_noise_strength"; + shader_names->turbulence_noise_scale = "turbulence_noise_scale"; + shader_names->turbulence_noise_speed = "turbulence_noise_speed"; + shader_names->turbulence_noise_speed_random = "turbulence_noise_speed_random"; + shader_names->turbulence_influence_over_life = "turbulence_influence_over_life"; + shader_names->turbulence_influence_min = "turbulence_influence_min"; + shader_names->turbulence_influence_max = "turbulence_influence_max"; + shader_names->turbulence_initial_displacement_min = "turbulence_initial_displacement_min"; + shader_names->turbulence_initial_displacement_max = "turbulence_initial_displacement_max"; + shader_names->gravity = "gravity"; shader_names->lifetime_randomness = "lifetime_randomness"; @@ -141,7 +152,6 @@ void ParticlesMaterial::_update_shader() { shader_map[mk].users++; return; } - //must create a shader! // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). @@ -282,6 +292,77 @@ void ParticlesMaterial::_update_shader() { code += "uniform float collision_bounce;\n"; } + if (turbulence_enabled) { + code += "uniform float turbulence_noise_strength;\n"; + code += "uniform float turbulence_noise_scale;\n"; + code += "uniform float turbulence_influence_min;\n"; + code += "uniform float turbulence_influence_max;\n"; + code += "uniform float turbulence_initial_displacement_min;\n"; + code += "uniform float turbulence_initial_displacement_max;\n"; + code += "uniform float turbulence_noise_speed_random;\n"; + code += "uniform vec3 turbulence_noise_speed = vec3(1.0, 1.0, 1.0);\n"; + if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) { + code += "uniform sampler2D turbulence_influence_over_life;\n"; + } + if (turbulence_color_ramp.is_valid()) { + code += "uniform sampler2D turbulence_color_ramp;\n"; + } + code += "\n"; + + //functions for 3D noise / turbulence + code += "\n\n"; + code += "// 3D Noise with friendly permission by Inigo Quilez\n"; + code += "vec3 hash_noise( vec3 p ) {\n"; + code += " p *= mat3(vec3(127.1, 311.7, -53.7), vec3(269.5, 183.3, 77.1), vec3(-301.7, 27.3, 215.3));\n"; + code += " return 2.0 * fract(fract(p)*4375.55) -1.;\n"; + code += "}\n"; + code += "\n"; + code += "float noise( vec3 p) {\n"; + code += " vec3 i = floor(p);;\n"; + code += " vec3 f = fract(p);\n "; + code += " vec3 u = f * f * (3.0 - 2.0 * f);\n"; + code += "\n"; + code += " return 2.0*mix( mix( mix( dot( hash_noise( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ), dot( hash_noise( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),\n"; + code += " mix( dot( hash_noise( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ), dot( hash_noise( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),\n"; + code += " mix( mix( dot( hash_noise( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ), dot( hash_noise( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),\n"; + code += " mix( dot( hash_noise( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ), dot( hash_noise( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z);\n"; + code += "}\n\n"; + code += "// Curl 3D and noise_3d function with friendly permission by Isaac Cohen\n"; + code += "vec3 noise_3d(vec3 p) {\n"; + code += " float s = noise(p);\n"; + code += " float s1 = noise(vec3(p.y - 19.1, p.z + 33.4, p.x + 47.2));\n"; + code += " float s2 = noise(vec3(p.z + 74.2, p.x - 124.5, p.y + 99.4));\n"; + code += " vec3 c = vec3(s, s1, s2);\n"; + code += " return c;\n"; + code += "}\n\n"; + code += "vec3 curl_3d(vec3 p, float c) {\n"; + code += " float epsilon = 0.001 + c;\n"; + code += " vec3 dx = vec3(epsilon, 0.0, 0.0);\n"; + code += " vec3 dy = vec3(0.0, epsilon, 0.0);\n"; + code += " vec3 dz = vec3(0.0, 0.0, epsilon);\n"; + code += " vec3 x0 = noise_3d(p - dx).xyz;\n"; + code += " vec3 x1 = noise_3d(p + dx).xyz;\n"; + code += " vec3 y0 = noise_3d(p - dy).xyz;\n"; + code += " vec3 y1 = noise_3d(p + dy).xyz;\n"; + code += " vec3 z0 = noise_3d(p - dz).xyz;\n"; + code += " vec3 z1 = noise_3d(p + dz).xyz;\n"; + code += " float x = y1.z - y0.z - z1.y + z0.y;\n"; + code += " float y = z1.x - z0.x - x1.z + x0.z;\n"; + code += " float z = x1.y - x0.y - y1.x + y0.x;\n"; + code += " float divisor = 1.0 / (2.0 * epsilon);\n"; + code += " return vec3(normalize(vec3(x, y, z) * divisor));\n"; + code += "}\n"; + code += "vec3 get_noise_direction(vec3 pos, vec3 emission_pos, vec3 time_noise) {\n"; + code += " float adj_contrast = max((turbulence_noise_strength - 1.0), 0.0) * 70.0;\n"; + code += " vec3 noise_time = (vec3(TIME) * turbulence_noise_speed) + time_noise;\n"; + code += " vec3 noise_pos = (pos * turbulence_noise_scale) - emission_pos;\n"; + code += " vec3 diff = pos - emission_pos;\n"; + code += " vec3 noise_direction = curl_3d(noise_pos + noise_time - diff, adj_contrast);\n"; + code += " noise_direction = mix(0.9 * noise_direction, noise_direction, turbulence_noise_strength - 9.0);\n"; + code += " return noise_direction;\n"; + code += "}\n"; + } + //need a random function code += "\n\n"; code += "float rand_from_seed(inout uint seed) {\n"; @@ -463,8 +544,18 @@ void ParticlesMaterial::_update_shader() { break; } } - code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + // Apply noise/turbulence: initial displacement. + if (turbulence_enabled) { + if (get_turbulence_noise_speed_random() >= 0.0) { + code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n"; + } else { + code += " const vec3 time_noise = vec3(0.0);\n"; + } + code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; + code += " float turb_init_displacement = mix(turbulence_initial_displacement_min, turbulence_initial_displacement_max, rand_from_seed(alt_seed));"; + code += " TRANSFORM[3].xyz += noise_direction * turb_init_displacement;\n"; + } code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " VELOCITY.z = 0.0;\n"; @@ -483,7 +574,6 @@ void ParticlesMaterial::_update_shader() { if (color_initial_ramp.is_valid()) { code += " float color_initial_rand = rand_from_seed(alt_seed);\n"; } - code += " float pi = 3.14159;\n"; code += " float degree_to_rad = pi / 180.0;\n"; code += "\n"; @@ -570,7 +660,7 @@ void ParticlesMaterial::_update_shader() { code += " vec3 diff = pos - org;\n"; code += " force += length(diff) > 0.0 ? normalize(diff) * tex_radial_accel * mix(radial_accel_min, radial_accel_max, rand_from_seed(alt_seed)) : vec3(0.0);\n"; code += " // apply tangential acceleration;\n"; - code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed))\n;"; + code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed));\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0, 1.0)), 0.0) * tangent_accel_val : vec3(0.0);\n"; @@ -584,6 +674,41 @@ void ParticlesMaterial::_update_shader() { code += " // apply attractor forces\n"; code += " VELOCITY += force * DELTA;\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n"; + } + + // Apply noise/turbulence. + if (turbulence_enabled) { + code += " // apply turbulence\n"; + if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) { + code += " float turbulence_influence = textureLod(turbulence_influence_over_life, vec2(tv, 0.0), 0.0).r;\n"; + } else { + code += " const float turbulence_influence = 1.0;\n"; + } + code += " \n"; + if (get_turbulence_noise_speed_random() >= 0.0) { + code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n"; + } else { + code += " const vec3 time_noise = vec3(0.0);\n"; + } + code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; + // If collision happened, turbulence is no longer applied. + String extra_tab = ""; + if (collision_enabled) { + code += " if (!COLLIDED) {\n"; + extra_tab = " "; + } + code += extra_tab + " \n"; + code += extra_tab + " float vel_mag = length(VELOCITY);\n"; + code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n"; + code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + if (collision_enabled) { + code += " }"; + } + } + code += " \n"; code += " // orbit velocity\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " float orbit_amount = tex_orbit_velocity * mix(orbit_velocity_min, orbit_velocity_max, rand_from_seed(alt_seed));\n"; @@ -595,9 +720,6 @@ void ParticlesMaterial::_update_shader() { code += " }\n"; } - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n"; - } code += " float dmp = mix(damping_min, damping_max, rand_from_seed(alt_seed));\n"; code += " if (dmp * tex_damping > 0.0) {\n"; code += " float v = length(VELOCITY);\n"; @@ -701,24 +823,34 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[3] = origin;\n"; } } - //scale by scale - code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n"; - code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n"; - code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n"; - code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; - code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; code += " TRANSFORM[3].z = 0.0;\n"; } + if (collision_enabled) { code += " if (COLLIDED) {\n"; - code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n"; - code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; - code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n"; + code += " if (length(VELOCITY) > 3.0) {\n"; + code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; + code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; + code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; + code += " } else {\n"; + code += " VELOCITY = vec3(0.0);\n"; + // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral" + if (turbulence_enabled) { + code += " noise_direction = vec3(1.0, 0.0, 0.0);\n"; + } + code += " }\n"; code += " }\n"; } + + // scale by scale + code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n"; + code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n"; + code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n"; + code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; + code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { code += " int emit_count = 0;\n"; switch (sub_emitter_mode) { @@ -856,6 +988,15 @@ void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_min, p_value); } break; + case PARAM_TURB_VEL_INFLUENCE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_min, p_value); + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_min, p_value); + } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -912,6 +1053,15 @@ void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_max, p_value); } break; + case PARAM_TURB_VEL_INFLUENCE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_max, p_value); + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_max, p_value); + } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -986,6 +1136,16 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, tex_rid); } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_over_life, tex_rid); + _adjust_curve_range(p_texture, 0, 1); + } break; + case PARAM_TURB_VEL_INFLUENCE: { + // Can't happen, but silences warning + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -1151,6 +1311,54 @@ real_t ParticlesMaterial::get_emission_ring_inner_radius() const { return emission_ring_inner_radius; } +void ParticlesMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) { + turbulence_enabled = p_turbulence_enabled; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_enabled, turbulence_enabled); + _queue_shader_change(); + notify_property_list_changed(); +} + +bool ParticlesMaterial::get_turbulence_enabled() const { + return turbulence_enabled; +} + +void ParticlesMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { + turbulence_noise_strength = p_turbulence_noise_strength; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_strength, p_turbulence_noise_strength); +} + +float ParticlesMaterial::get_turbulence_noise_strength() const { + return turbulence_noise_strength; +} + +void ParticlesMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { + turbulence_noise_scale = p_turbulence_noise_scale; + float shader_turbulence_noise_scale = (pow(p_turbulence_noise_scale, 0.25) * 5.6234 / 10.0) * 4.0 - 3.0; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_scale, shader_turbulence_noise_scale); +} + +float ParticlesMaterial::get_turbulence_noise_scale() const { + return turbulence_noise_scale; +} + +void ParticlesMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { + turbulence_noise_speed_random = p_turbulence_noise_speed_random; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed_random, p_turbulence_noise_speed_random); +} + +float ParticlesMaterial::get_turbulence_noise_speed_random() const { + return turbulence_noise_speed_random; +} + +void ParticlesMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { + turbulence_noise_speed = p_turbulence_noise_speed; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed, turbulence_noise_speed); +} + +Vector3 ParticlesMaterial::get_turbulence_noise_speed() const { + return turbulence_noise_speed; +} + void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; @@ -1214,6 +1422,20 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) { property.usage = PROPERTY_USAGE_NONE; } + + if (!turbulence_enabled) { + if (property.name == "turbulence_noise_strength" || + property.name == "turbulence_noise_scale" || + property.name == "turbulence_noise_speed" || + property.name == "turbulence_noise_speed_random" || + property.name == "turbulence_influence_over_life" || + property.name == "turbulence_influence_min" || + property.name == "turbulence_influence_max" || + property.name == "turbulence_initial_displacement_min" || + property.name == "turbulence_initial_displacement_max") { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + } } void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { @@ -1365,6 +1587,21 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius); ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticlesMaterial::get_turbulence_enabled); + ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticlesMaterial::set_turbulence_enabled); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticlesMaterial::get_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticlesMaterial::set_turbulence_noise_strength); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticlesMaterial::get_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticlesMaterial::set_turbulence_noise_scale); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticlesMaterial::get_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticlesMaterial::set_turbulence_noise_speed_random); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticlesMaterial::get_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticlesMaterial::set_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); @@ -1413,7 +1650,7 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_height"), "set_emission_ring_height", "get_emission_ring_height"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius"); - ADD_GROUP("ParticleFlags", "particle_flag_"); + ADD_GROUP("Particle Flags", "particle_flag_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_disable_z"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_DISABLE_Z); @@ -1467,6 +1704,19 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_min", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_min", "get_param_min", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_max", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_max", "get_param_max", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); + + ADD_GROUP("Turbulence", "turbulence_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "turbulence_enabled"), "set_turbulence_enabled", "get_turbulence_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_strength", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_turbulence_noise_strength", "get_turbulence_noise_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_scale", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_scale", "get_turbulence_noise_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "turbulence_noise_speed"), "set_turbulence_noise_speed", "get_turbulence_noise_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_speed_random", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_speed_random", "get_turbulence_noise_speed_random"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_min", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_min", "get_param_min", PARAM_TURB_VEL_INFLUENCE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_max", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_max", "get_param_max", PARAM_TURB_VEL_INFLUENCE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_min", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_min", "get_param_min", PARAM_TURB_INIT_DISPLACEMENT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_max", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_max", "get_param_max", PARAM_TURB_INIT_DISPLACEMENT); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "turbulence_influence_over_life", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TURB_INFLUENCE_OVER_LIFE); + ADD_GROUP("Animation", "anim_"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_min", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_ANIM_SPEED); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_max", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_ANIM_SPEED); @@ -1517,6 +1767,10 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + BIND_ENUM_CONSTANT(PARAM_TURB_VEL_INFLUENCE); + BIND_ENUM_CONSTANT(PARAM_TURB_INIT_DISPLACEMENT); + BIND_ENUM_CONSTANT(PARAM_TURB_INFLUENCE_OVER_LIFE); + BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED); BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT); BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); @@ -1560,6 +1814,17 @@ ParticlesMaterial::ParticlesMaterial() : set_emission_ring_height(1); set_emission_ring_radius(1); set_emission_ring_inner_radius(0); + + set_turbulence_enabled(false); + set_turbulence_noise_speed(Vector3(0.5, 0.5, 0.5)); + set_turbulence_noise_strength(1); + set_turbulence_noise_scale(9); + set_turbulence_noise_speed_random(0); + set_param_min(PARAM_TURB_VEL_INFLUENCE, 0.1); + set_param_max(PARAM_TURB_VEL_INFLUENCE, 0.1); + set_param_min(PARAM_TURB_INIT_DISPLACEMENT, 0.0); + set_param_max(PARAM_TURB_INIT_DISPLACEMENT, 0.0); + set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index af45593f38..7fb46d6ac5 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -58,6 +58,9 @@ public: PARAM_HUE_VARIATION, PARAM_ANIM_SPEED, PARAM_ANIM_OFFSET, + PARAM_TURB_INFLUENCE_OVER_LIFE, + PARAM_TURB_VEL_INFLUENCE, + PARAM_TURB_INIT_DISPLACEMENT, PARAM_MAX }; @@ -105,9 +108,10 @@ private: uint32_t attractor_enabled : 1; uint32_t collision_enabled : 1; uint32_t collision_scale : 1; + uint32_t turbulence_enabled : 1; }; - uint32_t key = 0; + uint64_t key = 0; static uint32_t hash(const MaterialKey &p_key) { return hash_murmur3_one_32(p_key.key); @@ -152,6 +156,7 @@ private: mk.collision_enabled = collision_enabled; mk.attractor_enabled = attractor_interaction_enabled; mk.collision_scale = collision_scale; + mk.turbulence_enabled = turbulence_enabled; return mk; } @@ -216,6 +221,17 @@ private: StringName emission_ring_radius; StringName emission_ring_inner_radius; + StringName turbulence_enabled; + StringName turbulence_noise_strength; + StringName turbulence_noise_scale; + StringName turbulence_noise_speed; + StringName turbulence_noise_speed_random; + StringName turbulence_influence_over_life; + StringName turbulence_influence_min; + StringName turbulence_influence_max; + StringName turbulence_initial_displacement_min; + StringName turbulence_initial_displacement_max; + StringName gravity; StringName lifetime_randomness; @@ -243,6 +259,7 @@ private: float params_min[PARAM_MAX]; float params_max[PARAM_MAX]; + float params[PARAM_MAX]; Ref<Texture2D> tex_parameters[PARAM_MAX]; Color color; @@ -265,6 +282,13 @@ private: bool anim_loop = false; + bool turbulence_enabled; + Vector3 turbulence_noise_speed; + Ref<Texture2D> turbulence_color_ramp; + float turbulence_noise_strength = 0.0f; + float turbulence_noise_scale = 0.0f; + float turbulence_noise_speed_random = 0.0f; + Vector3 gravity; double lifetime_randomness = 0.0; @@ -340,6 +364,18 @@ public: real_t get_emission_ring_inner_radius() const; int get_emission_point_count() const; + void set_turbulence_enabled(bool p_turbulence_enabled); + void set_turbulence_noise_strength(float p_turbulence_noise_strength); + void set_turbulence_noise_scale(float p_turbulence_noise_scale); + void set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random); + void set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed); + + bool get_turbulence_enabled() const; + float get_turbulence_noise_strength() const; + float get_turbulence_noise_scale() const; + float get_turbulence_noise_speed_random() const; + Vector3 get_turbulence_noise_speed() const; + void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 68441afb1c..f038a79b8f 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -1622,6 +1622,134 @@ bool SphereMesh::get_is_hemisphere() const { SphereMesh::SphereMesh() {} /** + TorusMesh +*/ + +void TorusMesh::_create_mesh_array(Array &p_arr) const { + // set our bounding box + + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same."); + + float min_radius = inner_radius; + float max_radius = outer_radius; + + if (min_radius > max_radius) { + SWAP(min_radius, max_radius); + } + + float radius = (max_radius - min_radius) * 0.5; + + for (int i = 0; i <= rings; i++) { + int prevrow = (i - 1) * (ring_segments + 1); + int thisrow = i * (ring_segments + 1); + float inci = float(i) / rings; + float angi = inci * Math_TAU; + + Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi)); + + for (int j = 0; j <= ring_segments; j++) { + float incj = float(j) / ring_segments; + float angj = incj * Math_TAU; + + Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj)); + Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0); + + points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x)); + normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x)); + ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0); + uvs.push_back(Vector2(inci, incj)); + + if (i > 0 && j > 0) { + indices.push_back(thisrow + j - 1); + indices.push_back(prevrow + j); + indices.push_back(prevrow + j - 1); + + indices.push_back(thisrow + j - 1); + indices.push_back(thisrow + j); + indices.push_back(prevrow + j); + } + } + } + + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; +} + +void TorusMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius); + ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius); + + ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius); + ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius); + + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings); + + ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments); + ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments"); +} + +void TorusMesh::set_inner_radius(const float p_inner_radius) { + inner_radius = p_inner_radius; + _request_update(); +} + +float TorusMesh::get_inner_radius() const { + return inner_radius; +} + +void TorusMesh::set_outer_radius(const float p_outer_radius) { + outer_radius = p_outer_radius; + _request_update(); +} + +float TorusMesh::get_outer_radius() const { + return outer_radius; +} + +void TorusMesh::set_rings(const int p_rings) { + ERR_FAIL_COND(p_rings < 3); + rings = p_rings; + _request_update(); +} + +int TorusMesh::get_rings() const { + return rings; +} + +void TorusMesh::set_ring_segments(const int p_ring_segments) { + ERR_FAIL_COND(p_ring_segments < 3); + ring_segments = p_ring_segments; + _request_update(); +} + +int TorusMesh::get_ring_segments() const { + return ring_segments; +} + +TorusMesh::TorusMesh() {} + +/** PointMesh */ diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index cb93211756..64eefd2c07 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -351,6 +351,38 @@ public: }; /** + Big donut +*/ +class TorusMesh : public PrimitiveMesh { + GDCLASS(TorusMesh, PrimitiveMesh); + +private: + float inner_radius = 0.5; + float outer_radius = 1.0; + int rings = 64; + int ring_segments = 32; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const override; + +public: + void set_inner_radius(const float p_inner_radius); + float get_inner_radius() const; + + void set_outer_radius(const float p_outer_radius); + float get_outer_radius() const; + + void set_rings(const int p_rings); + int get_rings() const; + + void set_ring_segments(const int p_ring_segments); + int get_ring_segments() const; + + TorusMesh(); +}; + +/** A single point for use in particle systems */ @@ -595,4 +627,5 @@ public: }; VARIANT_ENUM_CAST(RibbonTrailMesh::Shape) -#endif + +#endif // PRIMITIVE_MESHES_H diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 66afb001fb..2b1d91e4ef 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -65,14 +65,18 @@ Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, Varia return ERR_PARSE_ERROR; } - String unique_id = token.value; + if (p_data->no_placeholders) { + r_res.unref(); + } else { + String unique_id = token.value; - if (!p_data->resource_map.has(unique_id)) { - r_err_str = "Found unique_id reference before mapping, sub-resources stored out of order in resource file"; - return ERR_PARSE_ERROR; - } + if (!p_data->resource_map.has(unique_id)) { + r_err_str = "Found unique_id reference before mapping, sub-resources stored out of order in resource file"; + return ERR_PARSE_ERROR; + } - r_res = p_data->resource_map[unique_id]; + r_res = p_data->resource_map[unique_id]; + } VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) { @@ -91,11 +95,15 @@ Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, Varia return ERR_PARSE_ERROR; } - String id = token.value; + if (p_data->no_placeholders) { + r_res.unref(); + } else { + String id = token.value; - ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR); - r_res = p_data->rev_external_resources[id]; + r_res = p_data->rev_external_resources[id]; + } VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) { @@ -1066,7 +1074,7 @@ static void bs_save_unicode_string(Ref<FileAccess> p_f, const String &p_string, p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1); } -Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_path) { +Error ResourceLoaderText::save_as_binary(const String &p_path) { if (error) { return error; } @@ -1271,7 +1279,7 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa } if (next_tag.name == "node") { - //this is a node, must save one more! + // This is a node, must save one more! if (!is_scene) { error_text += "found the 'node' tag on a resource file!"; @@ -1346,6 +1354,126 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa return OK; } +Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) { + if (error) { + return error; + } + + ignore_resource_parsing = true; + + DummyReadData dummy_read; + dummy_read.no_placeholders = true; + VariantParser::ResourceParser rp; + rp.ext_func = _parse_ext_resource_dummys; + rp.sub_func = _parse_sub_resource_dummys; + rp.userdata = &dummy_read; + + while (next_tag.name == "ext_resource") { + error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp); + + if (error) { + _printerr(); + return error; + } + } + + while (next_tag.name == "sub_resource" || next_tag.name == "resource") { + if (next_tag.name == "sub_resource") { + if (!next_tag.fields.has("type")) { + error = ERR_FILE_CORRUPT; + error_text = "Missing 'type' in external resource tag"; + _printerr(); + return error; + } + + r_classes->insert(next_tag.fields["type"]); + + } else { + r_classes->insert(next_tag.fields["res_type"]); + } + + while (true) { + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp); + + if (error) { + if (error == ERR_FILE_EOF) { + return OK; + } + + _printerr(); + return error; + } + + if (!assign.is_empty()) { + continue; + } else if (!next_tag.name.is_empty()) { + error = OK; + break; + } else { + error = ERR_FILE_CORRUPT; + error_text = "Premature end of file while parsing [sub_resource]"; + _printerr(); + return error; + } + } + } + + while (next_tag.name == "node") { + // This is a node, must save one more! + + if (!is_scene) { + error_text += "found the 'node' tag on a resource file!"; + _printerr(); + error = ERR_FILE_CORRUPT; + return error; + } + + if (!next_tag.fields.has("type")) { + error = ERR_FILE_CORRUPT; + error_text = "Missing 'type' in external resource tag"; + _printerr(); + return error; + } + + r_classes->insert(next_tag.fields["type"]); + + while (true) { + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp); + + if (error) { + if (error == ERR_FILE_MISSING_DEPENDENCIES) { + // Resource loading error, just skip it. + } else if (error != ERR_FILE_EOF) { + _printerr(); + return error; + } else { + return OK; + } + } + + if (!assign.is_empty()) { + continue; + } else if (!next_tag.name.is_empty()) { + error = OK; + break; + } else { + error = ERR_FILE_CORRUPT; + error_text = "Premature end of file while parsing [sub_resource]"; + _printerr(); + return error; + } + } + } + + return OK; +} + String ResourceLoaderText::recognize(Ref<FileAccess> p_f) { error = OK; @@ -1473,6 +1601,26 @@ bool ResourceFormatLoaderText::handles_type(const String &p_type) const { return true; } +void ResourceFormatLoaderText::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { + String ext = p_path.get_extension().to_lower(); + if (ext == "tscn") { + r_classes->insert("PackedScene"); + } + + // ...for anything else must test... + + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + if (f.is_null()) { + return; // Could not read. + } + + ResourceLoaderText loader; + loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + loader.res_path = loader.local_path; + loader.open(f); + loader.get_classes_used(r_classes); +} + String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { String ext = p_path.get_extension().to_lower(); if (ext == "tscn") { @@ -1561,7 +1709,7 @@ Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, loader.local_path = ProjectSettings::get_singleton()->localize_path(path); loader.res_path = loader.local_path; loader.open(f); - return loader.save_as_binary(f, p_dst_path); + return loader.save_as_binary(p_dst_path); } /*****************************************************************************************************/ @@ -2063,7 +2211,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso return OK; } -Error ResourceFormatSaverText::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverText::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { if (p_path.ends_with(".tscn") && !Ref<PackedScene>(p_resource).is_valid()) { return ERR_FILE_UNRECOGNIZED; } diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index 5c6a937bf2..9154bcf795 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -90,6 +90,7 @@ class ResourceLoaderText { }; struct DummyReadData { + bool no_placeholders = false; HashMap<Ref<Resource>, int> external_resources; HashMap<String, Ref<Resource>> rev_external_resources; HashMap<Ref<Resource>, int> resource_index_map; @@ -125,8 +126,9 @@ public: ResourceUID::ID get_uid(Ref<FileAccess> p_f); void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types); Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map); + Error get_classes_used(HashSet<StringName> *r_classes); - Error save_as_binary(Ref<FileAccess> p_f, const String &p_path); + Error save_as_binary(const String &p_path); ResourceLoaderText(); }; @@ -137,6 +139,8 @@ public: virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; + virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes); + virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); @@ -190,7 +194,7 @@ public: class ResourceFormatSaverText : public ResourceFormatSaver { public: static ResourceFormatSaverText *singleton; - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; diff --git a/scene/resources/separation_ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp index 0d6aee47d8..fea41061fd 100644 --- a/scene/resources/separation_ray_shape_2d.cpp +++ b/scene/resources/separation_ray_shape_2d.cpp @@ -57,7 +57,7 @@ void SeparationRayShape2D::draw(const RID &p_to_rid, const Color &p_color) { Transform2D xf; xf.rotate(target_position.angle()); - xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); + xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); Vector<Vector2> pts = { xf.xform(Vector2(arrow_size, 0)), diff --git a/scene/resources/separation_ray_shape_3d.h b/scene/resources/separation_ray_shape_3d.h index 0e750a48e6..ae08ff7887 100644 --- a/scene/resources/separation_ray_shape_3d.h +++ b/scene/resources/separation_ray_shape_3d.h @@ -28,8 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SEPARATION_RAY_SHAPE_H -#define SEPARATION_RAY_SHAPE_H +#ifndef SEPARATION_RAY_SHAPE_3D_H +#define SEPARATION_RAY_SHAPE_3D_H + #include "scene/resources/shape_3d.h" class SeparationRayShape3D : public Shape3D { @@ -53,4 +54,5 @@ public: SeparationRayShape3D(); }; -#endif // SEPARATION_RAY_SHAPE_H + +#endif // SEPARATION_RAY_SHAPE_3D_H diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index d49157b1b8..db7b03f2be 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -33,6 +33,7 @@ #include "core/io/file_access.h" #include "scene/scene_string_names.h" #include "servers/rendering/shader_language.h" +#include "servers/rendering/shader_preprocessor.h" #include "servers/rendering_server.h" #include "texture.h" @@ -40,7 +41,23 @@ Shader::Mode Shader::get_mode() const { return mode; } +void Shader::_dependency_changed() { + RenderingServer::get_singleton()->shader_set_code(shader, RenderingServer::get_singleton()->shader_get_code(shader)); + params_cache_dirty = true; + + emit_changed(); +} + +void Shader::set_path(const String &p_path, bool p_take_over) { + Resource::set_path(p_path, p_take_over); + RS::get_singleton()->shader_set_path_hint(shader, p_path); +} + void Shader::set_code(const String &p_code) { + for (Ref<ShaderInclude> E : include_dependencies) { + E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed)); + } + String type = ShaderLanguage::get_shader_type(p_code); if (type == "canvas_item") { @@ -55,7 +72,27 @@ void Shader::set_code(const String &p_code) { mode = MODE_SPATIAL; } - RenderingServer::get_singleton()->shader_set_code(shader, p_code); + code = p_code; + String pp_code = p_code; + + HashSet<Ref<ShaderInclude>> new_include_dependencies; + + { + // Preprocessor must run here and not in the server because: + // 1) Need to keep track of include dependencies at resource level + // 2) Server does not do interaction with Resource filetypes, this is a scene level feature. + ShaderPreprocessor preprocessor; + preprocessor.preprocess(p_code, pp_code, nullptr, nullptr, &new_include_dependencies); + } + + // This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower) + include_dependencies = new_include_dependencies; + + for (Ref<ShaderInclude> E : include_dependencies) { + E->connect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed)); + } + + RenderingServer::get_singleton()->shader_set_code(shader, pp_code); params_cache_dirty = true; emit_changed(); @@ -63,24 +100,28 @@ void Shader::set_code(const String &p_code) { String Shader::get_code() const { _update_shader(); - return RenderingServer::get_singleton()->shader_get_code(shader); + return code; } -void Shader::get_param_list(List<PropertyInfo> *p_params) const { +void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups) const { _update_shader(); List<PropertyInfo> local; - RenderingServer::get_singleton()->shader_get_param_list(shader, &local); + RenderingServer::get_singleton()->shader_get_shader_uniform_list(shader, &local); params_cache.clear(); params_cache_dirty = false; for (PropertyInfo &pi : local) { - if (default_textures.has(pi.name)) { //do not show default textures + bool is_group = pi.usage == PROPERTY_USAGE_GROUP || pi.usage == PROPERTY_USAGE_SUBGROUP; + if (!p_get_groups && is_group) { continue; } - String original_name = pi.name; - pi.name = "shader_param/" + pi.name; - params_cache[pi.name] = original_name; + if (!is_group) { + if (default_textures.has(pi.name)) { //do not show default textures + continue; + } + params_cache[pi.name] = pi.name; + } if (p_params) { //small little hack if (pi.type == Variant::RID) { @@ -135,8 +176,8 @@ bool Shader::is_text_shader() const { return true; } -bool Shader::has_param(const StringName &p_param) const { - return params_cache.has("shader_param/" + p_param); +bool Shader::has_uniform(const StringName &p_param) const { + return params_cache.has("shader_uniform/" + p_param); } void Shader::_update_shader() const { @@ -151,7 +192,7 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture", "index"), &Shader::set_default_texture_param, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_default_texture_param", "param", "index"), &Shader::get_default_texture_param, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); + ClassDB::bind_method(D_METHOD("has_uniform", "name"), &Shader::has_uniform); ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); @@ -210,7 +251,7 @@ String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const return ""; } -Error ResourceFormatSaverShader::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverShader::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<Shader> shader = p_resource; ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER); diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 11c9f60ce8..abc953de5f 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -35,6 +35,7 @@ #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "scene/resources/texture.h" +#include "shader_include.h" class Shader : public Resource { GDCLASS(Shader, Resource); @@ -53,6 +54,8 @@ public: private: RID shader; Mode mode = MODE_SPATIAL; + HashSet<Ref<ShaderInclude>> include_dependencies; + String code; // hack the name of performance // shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make @@ -61,6 +64,7 @@ private: mutable HashMap<StringName, StringName> params_cache; //map a shader param to a material param.. HashMap<StringName, HashMap<int, Ref<Texture2D>>> default_textures; + void _dependency_changed(); virtual void _update_shader() const; //used for visual shader protected: static void _bind_methods(); @@ -69,24 +73,26 @@ public: //void set_mode(Mode p_mode); virtual Mode get_mode() const; + virtual void set_path(const String &p_path, bool p_take_over = false) override; + void set_code(const String &p_code); String get_code() const; - void get_param_list(List<PropertyInfo> *p_params) const; - bool has_param(const StringName &p_param) const; + void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const; + bool has_uniform(const StringName &p_param) const; - void set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index = 0); - Ref<Texture2D> get_default_texture_param(const StringName &p_param, int p_index = 0) const; + void set_default_texture_param(const StringName &p_uniform, const Ref<Texture2D> &p_texture, int p_index = 0); + Ref<Texture2D> get_default_texture_param(const StringName &p_uniform, int p_index = 0) const; void get_default_texture_param_list(List<StringName> *r_textures) const; virtual bool is_text_shader() const; - _FORCE_INLINE_ StringName remap_param(const StringName &p_param) const { + _FORCE_INLINE_ StringName remap_uniform(const StringName &p_uniform) const { if (params_cache_dirty) { - get_param_list(nullptr); + get_shader_uniform_list(nullptr); } - const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_param); + const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_uniform); if (E) { return E->value; } @@ -111,7 +117,7 @@ public: class ResourceFormatSaverShader : public ResourceFormatSaver { public: - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; virtual bool recognize(const Ref<Resource> &p_resource) const; }; diff --git a/scene/resources/shader_include.cpp b/scene/resources/shader_include.cpp new file mode 100644 index 0000000000..42435fe3c7 --- /dev/null +++ b/scene/resources/shader_include.cpp @@ -0,0 +1,144 @@ +/*************************************************************************/ +/* shader_include.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "shader_include.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering/shader_preprocessor.h" + +void ShaderInclude::_dependency_changed() { + emit_changed(); +} + +void ShaderInclude::set_code(const String &p_code) { + HashSet<Ref<ShaderInclude>> new_dependencies; + code = p_code; + + for (Ref<ShaderInclude> E : dependencies) { + E->disconnect(SNAME("changed"), callable_mp(this, &ShaderInclude::_dependency_changed)); + } + + { + String pp_code; + ShaderPreprocessor preprocessor; + preprocessor.preprocess(p_code, pp_code, nullptr, nullptr, &new_dependencies); + } + + // This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower) + dependencies = new_dependencies; + + for (Ref<ShaderInclude> E : dependencies) { + E->connect(SNAME("changed"), callable_mp(this, &ShaderInclude::_dependency_changed)); + } + + emit_changed(); +} + +String ShaderInclude::get_code() const { + return code; +} + +void ShaderInclude::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_code", "code"), &ShaderInclude::set_code); + ClassDB::bind_method(D_METHOD("get_code"), &ShaderInclude::get_code); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); +} + +// ResourceFormatLoaderShaderInclude + +Ref<Resource> ResourceFormatLoaderShaderInclude::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_FILE_CANT_OPEN; + } + + Ref<ShaderInclude> shader_inc; + shader_inc.instantiate(); + + Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path); + + String str; + str.parse_utf8((const char *)buffer.ptr(), buffer.size()); + + shader_inc->set_code(str); + + if (r_error) { + *r_error = OK; + } + + return shader_inc; +} + +void ResourceFormatLoaderShaderInclude::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("gdshaderinc"); +} + +bool ResourceFormatLoaderShaderInclude::handles_type(const String &p_type) const { + return (p_type == "ShaderInclude"); +} + +String ResourceFormatLoaderShaderInclude::get_resource_type(const String &p_path) const { + String extension = p_path.get_extension().to_lower(); + if (extension == "gdshaderinc") { + return "ShaderInclude"; + } + return ""; +} + +// ResourceFormatSaverShaderInclude + +Error ResourceFormatSaverShaderInclude::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { + Ref<ShaderInclude> shader_inc = p_resource; + ERR_FAIL_COND_V(shader_inc.is_null(), ERR_INVALID_PARAMETER); + + String source = shader_inc->get_code(); + + Error error; + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &error); + + ERR_FAIL_COND_V_MSG(error, error, "Cannot save shader include '" + p_path + "'."); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + + return OK; +} + +void ResourceFormatSaverShaderInclude::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const { + const ShaderInclude *shader_inc = Object::cast_to<ShaderInclude>(*p_resource); + if (shader_inc != nullptr) { + p_extensions->push_back("gdshaderinc"); + } +} + +bool ResourceFormatSaverShaderInclude::recognize(const Ref<Resource> &p_resource) const { + return p_resource->get_class_name() == "ShaderInclude"; //only shader, not inherited +} diff --git a/scene/resources/shader_include.h b/scene/resources/shader_include.h new file mode 100644 index 0000000000..b0865e3a61 --- /dev/null +++ b/scene/resources/shader_include.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* shader_include.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 SHADER_INCLUDE_H +#define SHADER_INCLUDE_H + +#include "core/io/resource.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/templates/hash_set.h" + +class ShaderInclude : public Resource { + GDCLASS(ShaderInclude, Resource); + OBJ_SAVE_TYPE(ShaderInclude); + +private: + String code; + HashSet<Ref<ShaderInclude>> dependencies; + void _dependency_changed(); + +protected: + static void _bind_methods(); + +public: + void set_code(const String &p_text); + String get_code() const; +}; + +class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader { +public: + virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); + 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 ResourceFormatSaverShaderInclude : public ResourceFormatSaver { +public: + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); + virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; + virtual bool recognize(const Ref<Resource> &p_resource) const; +}; + +#endif // SHADER_INCLUDE_H diff --git a/scene/resources/shape_3d.h b/scene/resources/shape_3d.h index 77e79a269d..58fe723d89 100644 --- a/scene/resources/shape_3d.h +++ b/scene/resources/shape_3d.h @@ -73,4 +73,4 @@ public: ~Shape3D(); }; -#endif // SHAPE_H +#endif // SHAPE_3D_H diff --git a/scene/resources/skeleton_modification_2d.h b/scene/resources/skeleton_modification_2d.h index 3b9235ffd8..4c49119df0 100644 --- a/scene/resources/skeleton_modification_2d.h +++ b/scene/resources/skeleton_modification_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2D_H -#define SKELETONMODIFICATION2D_H +#ifndef SKELETON_MODIFICATION_2D_H +#define SKELETON_MODIFICATION_2D_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_stack_2d.h" @@ -86,4 +86,4 @@ public: SkeletonModification2D(); }; -#endif // SKELETONMODIFICATION2D_H +#endif // SKELETON_MODIFICATION_2D_H diff --git a/scene/resources/skeleton_modification_2d_ccdik.h b/scene/resources/skeleton_modification_2d_ccdik.h index 31485fa31f..e49dfca5b5 100644 --- a/scene/resources/skeleton_modification_2d_ccdik.h +++ b/scene/resources/skeleton_modification_2d_ccdik.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DCCDIK_H -#define SKELETONMODIFICATION2DCCDIK_H +#ifndef SKELETON_MODIFICATION_2D_CCDIK_H +#define SKELETON_MODIFICATION_2D_CCDIK_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -113,4 +113,4 @@ public: ~SkeletonModification2DCCDIK(); }; -#endif // SKELETONMODIFICATION2DCCDIK_H +#endif // SKELETON_MODIFICATION_2D_CCDIK_H diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h index d5077084ef..4a875d039f 100644 --- a/scene/resources/skeleton_modification_2d_fabrik.h +++ b/scene/resources/skeleton_modification_2d_fabrik.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DFABRIK_H -#define SKELETONMODIFICATION2DFABRIK_H +#ifndef SKELETON_MODIFICATION_2D_FABRIK_H +#define SKELETON_MODIFICATION_2D_FABRIK_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -105,4 +105,4 @@ public: ~SkeletonModification2DFABRIK(); }; -#endif // SKELETONMODIFICATION2DFABRIK_H +#endif // SKELETON_MODIFICATION_2D_FABRIK_H diff --git a/scene/resources/skeleton_modification_2d_jiggle.h b/scene/resources/skeleton_modification_2d_jiggle.h index a1abca6564..b9080eafa9 100644 --- a/scene/resources/skeleton_modification_2d_jiggle.h +++ b/scene/resources/skeleton_modification_2d_jiggle.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DJIGGLE_H -#define SKELETONMODIFICATION2DJIGGLE_H +#ifndef SKELETON_MODIFICATION_2D_JIGGLE_H +#define SKELETON_MODIFICATION_2D_JIGGLE_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -136,4 +136,4 @@ public: ~SkeletonModification2DJiggle(); }; -#endif // SKELETONMODIFICATION2DJIGGLE_H +#endif // SKELETON_MODIFICATION_2D_JIGGLE_H diff --git a/scene/resources/skeleton_modification_2d_lookat.h b/scene/resources/skeleton_modification_2d_lookat.h index ff91b92e7d..e4d7afa605 100644 --- a/scene/resources/skeleton_modification_2d_lookat.h +++ b/scene/resources/skeleton_modification_2d_lookat.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DLOOKAT_H -#define SKELETONMODIFICATION2DLOOKAT_H +#ifndef SKELETON_MODIFICATION_2D_LOOKAT_H +#define SKELETON_MODIFICATION_2D_LOOKAT_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -97,4 +97,4 @@ public: ~SkeletonModification2DLookAt(); }; -#endif // SKELETONMODIFICATION2DLOOKAT_H +#endif // SKELETON_MODIFICATION_2D_LOOKAT_H diff --git a/scene/resources/skeleton_modification_2d_physicalbones.h b/scene/resources/skeleton_modification_2d_physicalbones.h index 373ff666ee..55482b2cca 100644 --- a/scene/resources/skeleton_modification_2d_physicalbones.h +++ b/scene/resources/skeleton_modification_2d_physicalbones.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DPHYSICALBONES_H -#define SKELETONMODIFICATION2DPHYSICALBONES_H +#ifndef SKELETON_MODIFICATION_2D_PHYSICALBONES_H +#define SKELETON_MODIFICATION_2D_PHYSICALBONES_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -79,4 +79,4 @@ public: ~SkeletonModification2DPhysicalBones(); }; -#endif // SKELETONMODIFICATION2DPHYSICALBONES_H +#endif // SKELETON_MODIFICATION_2D_PHYSICALBONES_H diff --git a/scene/resources/skeleton_modification_2d_stackholder.h b/scene/resources/skeleton_modification_2d_stackholder.h index 99d9f6f381..4da9fcc1f6 100644 --- a/scene/resources/skeleton_modification_2d_stackholder.h +++ b/scene/resources/skeleton_modification_2d_stackholder.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DSTACKHOLDER_H -#define SKELETONMODIFICATION2DSTACKHOLDER_H +#ifndef SKELETON_MODIFICATION_2D_STACKHOLDER_H +#define SKELETON_MODIFICATION_2D_STACKHOLDER_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -61,4 +61,4 @@ public: ~SkeletonModification2DStackHolder(); }; -#endif // SKELETONMODIFICATION2DSTACKHOLDER_H +#endif // SKELETON_MODIFICATION_2D_STACKHOLDER_H diff --git a/scene/resources/skeleton_modification_2d_twoboneik.h b/scene/resources/skeleton_modification_2d_twoboneik.h index fc14d35f70..e1dbb6cfda 100644 --- a/scene/resources/skeleton_modification_2d_twoboneik.h +++ b/scene/resources/skeleton_modification_2d_twoboneik.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION2DTWOBONEIK_H -#define SKELETONMODIFICATION2DTWOBONEIK_H +#ifndef SKELETON_MODIFICATION_2D_TWOBONEIK_H +#define SKELETON_MODIFICATION_2D_TWOBONEIK_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -104,4 +104,4 @@ public: ~SkeletonModification2DTwoBoneIK(); }; -#endif // SKELETONMODIFICATION2DTWOBONEIK_H +#endif // SKELETON_MODIFICATION_2D_TWOBONEIK_H diff --git a/scene/resources/skeleton_modification_3d.h b/scene/resources/skeleton_modification_3d.h index ab736fcbd2..6daf5efcd9 100644 --- a/scene/resources/skeleton_modification_3d.h +++ b/scene/resources/skeleton_modification_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATION3D_H -#define SKELETONMODIFICATION3D_H +#ifndef SKELETON_MODIFICATION_3D_H +#define SKELETON_MODIFICATION_3D_H #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_stack_3d.h" @@ -76,4 +76,4 @@ public: SkeletonModification3D(); }; -#endif // SKELETONMODIFICATION3D_H +#endif // SKELETON_MODIFICATION_3D_H diff --git a/scene/resources/skeleton_modification_3d_ccdik.h b/scene/resources/skeleton_modification_3d_ccdik.h index 873ab8aa5a..7098794038 100644 --- a/scene/resources/skeleton_modification_3d_ccdik.h +++ b/scene/resources/skeleton_modification_3d_ccdik.h @@ -32,8 +32,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DCCDIK_H -#define SKELETONMODIFICATION3DCCDIK_H +#ifndef SKELETON_MODIFICATION_3D_CCDIK_H +#define SKELETON_MODIFICATION_3D_CCDIK_H class SkeletonModification3DCCDIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DCCDIK, SkeletonModification3D); @@ -111,4 +111,4 @@ public: ~SkeletonModification3DCCDIK(); }; -#endif //SKELETONMODIFICATION3DCCDIK_H +#endif // SKELETON_MODIFICATION_3D_CCDIK_H diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h index cc4d3a5e20..3d66bb6d99 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.h +++ b/scene/resources/skeleton_modification_3d_fabrik.h @@ -32,8 +32,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DFABRIK_H -#define SKELETONMODIFICATION3DFABRIK_H +#ifndef SKELETON_MODIFICATION_3D_FABRIK_H +#define SKELETON_MODIFICATION_3D_FABRIK_H class SkeletonModification3DFABRIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DFABRIK, SkeletonModification3D); @@ -121,4 +121,4 @@ public: ~SkeletonModification3DFABRIK(); }; -#endif //SKELETONMODIFICATION3DFABRIK_H +#endif // SKELETON_MODIFICATION_3D_FABRIK_H diff --git a/scene/resources/skeleton_modification_3d_jiggle.h b/scene/resources/skeleton_modification_3d_jiggle.h index 7ec5ed4f11..f41ffcd58d 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.h +++ b/scene/resources/skeleton_modification_3d_jiggle.h @@ -32,8 +32,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DJIGGLE_H -#define SKELETONMODIFICATION3DJIGGLE_H +#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H +#define SKELETON_MODIFICATION_3D_JIGGLE_H class SkeletonModification3DJiggle : public SkeletonModification3D { GDCLASS(SkeletonModification3DJiggle, SkeletonModification3D); @@ -135,4 +135,4 @@ public: ~SkeletonModification3DJiggle(); }; -#endif //SKELETONMODIFICATION3DJIGGLE_H +#endif // SKELETON_MODIFICATION_3D_JIGGLE_H diff --git a/scene/resources/skeleton_modification_3d_lookat.h b/scene/resources/skeleton_modification_3d_lookat.h index 9f5120a0fd..4e5714b5dc 100644 --- a/scene/resources/skeleton_modification_3d_lookat.h +++ b/scene/resources/skeleton_modification_3d_lookat.h @@ -31,8 +31,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DLOOKAT_H -#define SKELETONMODIFICATION3DLOOKAT_H +#ifndef SKELETON_MODIFICATION_3D_LOOKAT_H +#define SKELETON_MODIFICATION_3D_LOOKAT_H class SkeletonModification3DLookAt : public SkeletonModification3D { GDCLASS(SkeletonModification3DLookAt, SkeletonModification3D); @@ -86,4 +86,4 @@ public: ~SkeletonModification3DLookAt(); }; -#endif //SKELETONMODIFICATION3DLOOKAT_H +#endif // SKELETON_MODIFICATION_3D_LOOKAT_H diff --git a/scene/resources/skeleton_modification_3d_stackholder.h b/scene/resources/skeleton_modification_3d_stackholder.h index 5780d7d43f..ae22099158 100644 --- a/scene/resources/skeleton_modification_3d_stackholder.h +++ b/scene/resources/skeleton_modification_3d_stackholder.h @@ -31,8 +31,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DSTACKHOLDER_H -#define SKELETONMODIFICATION3DSTACKHOLDER_H +#ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H +#define SKELETON_MODIFICATION_3D_STACKHOLDER_H class SkeletonModification3DStackHolder : public SkeletonModification3D { GDCLASS(SkeletonModification3DStackHolder, SkeletonModification3D); @@ -56,4 +56,4 @@ public: ~SkeletonModification3DStackHolder(); }; -#endif //SKELETONMODIFICATION3DSTACKHOLDER_H +#endif // SKELETON_MODIFICATION_3D_STACKHOLDER_H diff --git a/scene/resources/skeleton_modification_3d_twoboneik.h b/scene/resources/skeleton_modification_3d_twoboneik.h index a4ddc6cee7..57e8237511 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.h +++ b/scene/resources/skeleton_modification_3d_twoboneik.h @@ -31,8 +31,8 @@ #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETONMODIFICATION3DTWOBONEIK_H -#define SKELETONMODIFICATION3DTWOBONEIK_H +#ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H +#define SKELETON_MODIFICATION_3D_TWOBONEIK_H class SkeletonModification3DTwoBoneIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DTwoBoneIK, SkeletonModification3D); @@ -115,4 +115,4 @@ public: ~SkeletonModification3DTwoBoneIK(); }; -#endif //SKELETONMODIFICATION3DTWOBONEIK_H +#endif // SKELETON_MODIFICATION_3D_TWOBONEIK_H diff --git a/scene/resources/skeleton_modification_stack_2d.h b/scene/resources/skeleton_modification_stack_2d.h index 7b5f8e0322..ceffd71368 100644 --- a/scene/resources/skeleton_modification_stack_2d.h +++ b/scene/resources/skeleton_modification_stack_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATIONSTACK2D_H -#define SKELETONMODIFICATIONSTACK2D_H +#ifndef SKELETON_MODIFICATION_STACK_2D_H +#define SKELETON_MODIFICATION_STACK_2D_H #include "scene/2d/skeleton_2d.h" #include "scene/resources/skeleton_modification_2d.h" @@ -96,4 +96,4 @@ public: SkeletonModificationStack2D(); }; -#endif // SKELETONMODIFICATION2D_H +#endif // SKELETON_MODIFICATION_STACK_2D_H diff --git a/scene/resources/skeleton_modification_stack_3d.h b/scene/resources/skeleton_modification_stack_3d.h index 2c17fba2c5..4ff1bd1e33 100644 --- a/scene/resources/skeleton_modification_stack_3d.h +++ b/scene/resources/skeleton_modification_stack_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKELETONMODIFICATIONSTACK3D_H -#define SKELETONMODIFICATIONSTACK3D_H +#ifndef SKELETON_MODIFICATION_STACK_3D_H +#define SKELETON_MODIFICATION_STACK_3D_H #include "core/templates/local_vector.h" #include "scene/3d/skeleton_3d.h" @@ -88,4 +88,4 @@ public: SkeletonModificationStack3D(); }; -#endif // SKELETONMODIFICATIONSTACK3D_H +#endif // SKELETON_MODIFICATION_STACK_3D_H diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp index 05d48f9545..bfb4bb6e2b 100644 --- a/scene/resources/skeleton_profile.cpp +++ b/scene/resources/skeleton_profile.cpp @@ -34,7 +34,7 @@ bool SkeletonProfile::_set(const StringName &p_path, const Variant &p_value) { ERR_FAIL_COND_V(is_read_only, false); String path = p_path; - if (path.begins_with("group/")) { + if (path.begins_with("groups/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); ERR_FAIL_INDEX_V(which, groups.size(), false); @@ -43,23 +43,35 @@ bool SkeletonProfile::_set(const StringName &p_path, const Variant &p_value) { set_group_name(which, p_value); } else if (what == "texture") { set_texture(which, p_value); + } else { + return false; } - return true; } - if (path.begins_with("bone/")) { + if (path.begins_with("bones/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); ERR_FAIL_INDEX_V(which, bones.size(), false); if (what == "bone_name") { set_bone_name(which, p_value); + } else if (what == "bone_parent") { + set_bone_parent(which, p_value); + } else if (what == "tail_direction") { + set_tail_direction(which, static_cast<TailDirection>((int)p_value)); + } else if (what == "bone_tail") { + set_bone_tail(which, p_value); + } else if (what == "reference_pose") { + set_reference_pose(which, p_value); } else if (what == "handle_offset") { set_handle_offset(which, p_value); } else if (what == "group") { set_group(which, p_value); + } else if (what == "require") { + set_require(which, p_value); + } else { + return false; } - return true; } return true; } @@ -67,7 +79,7 @@ bool SkeletonProfile::_set(const StringName &p_path, const Variant &p_value) { bool SkeletonProfile::_get(const StringName &p_path, Variant &r_ret) const { String path = p_path; - if (path.begins_with("group/")) { + if (path.begins_with("groups/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); ERR_FAIL_INDEX_V(which, groups.size(), false); @@ -76,34 +88,61 @@ bool SkeletonProfile::_get(const StringName &p_path, Variant &r_ret) const { r_ret = get_group_name(which); } else if (what == "texture") { r_ret = get_texture(which); + } else { + return false; } - return true; } - if (path.begins_with("bone/")) { + if (path.begins_with("bones/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); ERR_FAIL_INDEX_V(which, bones.size(), false); if (what == "bone_name") { r_ret = get_bone_name(which); + } else if (what == "bone_parent") { + r_ret = get_bone_parent(which); + } else if (what == "tail_direction") { + r_ret = get_tail_direction(which); + } else if (what == "bone_tail") { + r_ret = get_bone_tail(which); + } else if (what == "reference_pose") { + r_ret = get_reference_pose(which); } else if (what == "handle_offset") { r_ret = get_handle_offset(which); } else if (what == "group") { r_ret = get_group(which); + } else if (what == "require") { + r_ret = is_require(which); + } else { + return false; } - return true; } return true; } void SkeletonProfile::_validate_property(PropertyInfo &property) const { if (is_read_only) { - if (property.name == ("group_size") || property.name == ("bone_size")) { + if (property.name == ("group_size") || property.name == ("bone_size") || property.name == ("root_bone") || property.name == ("scale_base_bone")) { property.usage = PROPERTY_USAGE_NO_EDITOR; return; } } + + if (property.name == ("root_bone") || property.name == ("scale_base_bone")) { + String hint = ""; + for (int i = 0; i < bones.size(); i++) { + hint += i == 0 ? String(bones[i].bone_name) : "," + String(bones[i].bone_name); + } + property.hint_string = hint; + } + + PackedStringArray split = property.name.split("/"); + if (split.size() == 3 && split[0] == "bones") { + if (split[2] == "bone_tail" && get_tail_direction(split[1].to_int()) != TAIL_DIRECTION_SPECIFIC_CHILD) { + property.usage = PROPERTY_USAGE_NONE; + } + } } void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const { @@ -112,7 +151,7 @@ void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const { } String group_names = ""; for (int i = 0; i < groups.size(); i++) { - String path = "group/" + itos(i) + "/"; + String path = "groups/" + itos(i) + "/"; p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "group_name")); p_list->push_back(PropertyInfo(Variant::OBJECT, path + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); if (i > 0) { @@ -121,11 +160,42 @@ void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const { group_names = group_names + groups[i].group_name; } for (int i = 0; i < bones.size(); i++) { - String path = "bone/" + itos(i) + "/"; + String path = "bones/" + itos(i) + "/"; p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_name")); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_parent")); + p_list->push_back(PropertyInfo(Variant::INT, path + "tail_direction", PROPERTY_HINT_ENUM, "AverageChildren,SpecificChild,End")); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_tail")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, path + "reference_pose")); p_list->push_back(PropertyInfo(Variant::VECTOR2, path + "handle_offset")); p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "group", PROPERTY_HINT_ENUM, group_names)); + p_list->push_back(PropertyInfo(Variant::BOOL, path + "require")); + } + + for (PropertyInfo &E : *p_list) { + _validate_property(E); + } +} + +StringName SkeletonProfile::get_root_bone() { + return root_bone; +} + +void SkeletonProfile::set_root_bone(StringName p_bone_name) { + if (is_read_only) { + return; + } + root_bone = p_bone_name; +} + +StringName SkeletonProfile::get_scale_base_bone() { + return scale_base_bone; +} + +void SkeletonProfile::set_scale_base_bone(StringName p_bone_name) { + if (is_read_only) { + return; } + scale_base_bone = p_bone_name; } int SkeletonProfile::get_group_size() { @@ -184,6 +254,18 @@ void SkeletonProfile::set_bone_size(int p_size) { notify_property_list_changed(); } +int SkeletonProfile::find_bone(StringName p_bone_name) const { + if (p_bone_name == StringName()) { + return -1; + } + for (int i = 0; i < bones.size(); i++) { + if (bones[i].bone_name == p_bone_name) { + return i; + } + } + return -1; +} + StringName SkeletonProfile::get_bone_name(int p_bone_idx) const { ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName()); return bones[p_bone_idx].bone_name; @@ -198,6 +280,63 @@ void SkeletonProfile::set_bone_name(int p_bone_idx, const StringName p_bone_name emit_signal("profile_updated"); } +StringName SkeletonProfile::get_bone_parent(int p_bone_idx) const { + ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName()); + return bones[p_bone_idx].bone_parent; +} + +void SkeletonProfile::set_bone_parent(int p_bone_idx, const StringName p_bone_parent) { + if (is_read_only) { + return; + } + ERR_FAIL_INDEX(p_bone_idx, bones.size()); + bones.write[p_bone_idx].bone_parent = p_bone_parent; + emit_signal("profile_updated"); +} + +SkeletonProfile::TailDirection SkeletonProfile::get_tail_direction(int p_bone_idx) const { + ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), TAIL_DIRECTION_AVERAGE_CHILDREN); + return bones[p_bone_idx].tail_direction; +} + +void SkeletonProfile::set_tail_direction(int p_bone_idx, const TailDirection p_tail_direction) { + if (is_read_only) { + return; + } + ERR_FAIL_INDEX(p_bone_idx, bones.size()); + bones.write[p_bone_idx].tail_direction = p_tail_direction; + emit_signal("profile_updated"); + notify_property_list_changed(); +} + +StringName SkeletonProfile::get_bone_tail(int p_bone_idx) const { + ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName()); + return bones[p_bone_idx].bone_tail; +} + +void SkeletonProfile::set_bone_tail(int p_bone_idx, const StringName p_bone_tail) { + if (is_read_only) { + return; + } + ERR_FAIL_INDEX(p_bone_idx, bones.size()); + bones.write[p_bone_idx].bone_tail = p_bone_tail; + emit_signal("profile_updated"); +} + +Transform3D SkeletonProfile::get_reference_pose(int p_bone_idx) const { + ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), Transform3D()); + return bones[p_bone_idx].reference_pose; +} + +void SkeletonProfile::set_reference_pose(int p_bone_idx, const Transform3D p_reference_pose) { + if (is_read_only) { + return; + } + ERR_FAIL_INDEX(p_bone_idx, bones.size()); + bones.write[p_bone_idx].reference_pose = p_reference_pose; + emit_signal("profile_updated"); +} + Vector2 SkeletonProfile::get_handle_offset(int p_bone_idx) const { ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), Vector2()); return bones[p_bone_idx].handle_offset; @@ -226,6 +365,20 @@ void SkeletonProfile::set_group(int p_bone_idx, const StringName p_group) { emit_signal("profile_updated"); } +bool SkeletonProfile::is_require(int p_bone_idx) const { + ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), false); + return bones[p_bone_idx].require; +} + +void SkeletonProfile::set_require(int p_bone_idx, const bool p_require) { + if (is_read_only) { + return; + } + ERR_FAIL_INDEX(p_bone_idx, bones.size()); + bones.write[p_bone_idx].require = p_require; + emit_signal("profile_updated"); +} + bool SkeletonProfile::has_bone(StringName p_bone_name) { bool is_found = false; for (int i = 0; i < bones.size(); i++) { @@ -238,6 +391,12 @@ bool SkeletonProfile::has_bone(StringName p_bone_name) { } void SkeletonProfile::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_root_bone", "bone_name"), &SkeletonProfile::set_root_bone); + ClassDB::bind_method(D_METHOD("get_root_bone"), &SkeletonProfile::get_root_bone); + + ClassDB::bind_method(D_METHOD("set_scale_base_bone", "bone_name"), &SkeletonProfile::set_scale_base_bone); + ClassDB::bind_method(D_METHOD("get_scale_base_bone"), &SkeletonProfile::get_scale_base_bone); + ClassDB::bind_method(D_METHOD("set_group_size", "size"), &SkeletonProfile::set_group_size); ClassDB::bind_method(D_METHOD("get_group_size"), &SkeletonProfile::get_group_size); @@ -250,19 +409,40 @@ void SkeletonProfile::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bone_size", "size"), &SkeletonProfile::set_bone_size); ClassDB::bind_method(D_METHOD("get_bone_size"), &SkeletonProfile::get_bone_size); + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SkeletonProfile::find_bone); + ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &SkeletonProfile::get_bone_name); ClassDB::bind_method(D_METHOD("set_bone_name", "bone_idx", "bone_name"), &SkeletonProfile::set_bone_name); + ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &SkeletonProfile::get_bone_parent); + ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "bone_parent"), &SkeletonProfile::set_bone_parent); + + ClassDB::bind_method(D_METHOD("get_tail_direction", "bone_idx"), &SkeletonProfile::get_tail_direction); + ClassDB::bind_method(D_METHOD("set_tail_direction", "bone_idx", "tail_direction"), &SkeletonProfile::set_tail_direction); + + ClassDB::bind_method(D_METHOD("get_bone_tail", "bone_idx"), &SkeletonProfile::get_bone_tail); + ClassDB::bind_method(D_METHOD("set_bone_tail", "bone_idx", "bone_tail"), &SkeletonProfile::set_bone_tail); + + ClassDB::bind_method(D_METHOD("get_reference_pose", "bone_idx"), &SkeletonProfile::get_reference_pose); + ClassDB::bind_method(D_METHOD("set_reference_pose", "bone_idx", "bone_name"), &SkeletonProfile::set_reference_pose); + ClassDB::bind_method(D_METHOD("get_handle_offset", "bone_idx"), &SkeletonProfile::get_handle_offset); ClassDB::bind_method(D_METHOD("set_handle_offset", "bone_idx", "handle_offset"), &SkeletonProfile::set_handle_offset); ClassDB::bind_method(D_METHOD("get_group", "bone_idx"), &SkeletonProfile::get_group); ClassDB::bind_method(D_METHOD("set_group", "bone_idx", "group"), &SkeletonProfile::set_group); - ADD_PROPERTY(PropertyInfo(Variant::INT, "group_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Groups,group/"), "set_group_size", "get_group_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Bones,bone/"), "set_bone_size", "get_bone_size"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "root_bone", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_root_bone", "get_root_bone"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "scale_base_bone", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_scale_base_bone", "get_scale_base_bone"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "group_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Groups,groups/"), "set_group_size", "get_group_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Bones,bones/"), "set_bone_size", "get_bone_size"); ADD_SIGNAL(MethodInfo("profile_updated")); + + BIND_ENUM_CONSTANT(TAIL_DIRECTION_AVERAGE_CHILDREN); + BIND_ENUM_CONSTANT(TAIL_DIRECTION_SPECIFIC_CHILD); + BIND_ENUM_CONSTANT(TAIL_DIRECTION_END); } SkeletonProfile::SkeletonProfile() { @@ -274,6 +454,9 @@ SkeletonProfile::~SkeletonProfile() { SkeletonProfileHumanoid::SkeletonProfileHumanoid() { is_read_only = true; + root_bone = "Root"; + scale_base_bone = "Hips"; + groups.resize(4); groups.write[0].group_name = "Body"; @@ -284,226 +467,364 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.resize(56); bones.write[0].bone_name = "Root"; + bones.write[0].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); bones.write[0].handle_offset = Vector2(0.5, 0.91); bones.write[0].group = "Body"; bones.write[1].bone_name = "Hips"; + bones.write[1].bone_parent = "Root"; + bones.write[1].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD; + bones.write[1].bone_tail = "Spine"; + bones.write[1].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75, 0); bones.write[1].handle_offset = Vector2(0.5, 0.5); bones.write[1].group = "Body"; + bones.write[1].require = true; bones.write[2].bone_name = "Spine"; + bones.write[2].bone_parent = "Hips"; + bones.write[2].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[2].handle_offset = Vector2(0.5, 0.43); bones.write[2].group = "Body"; + bones.write[2].require = true; bones.write[3].bone_name = "Chest"; + bones.write[3].bone_parent = "Spine"; + bones.write[3].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[3].handle_offset = Vector2(0.5, 0.36); bones.write[3].group = "Body"; bones.write[4].bone_name = "UpperChest"; + bones.write[4].bone_parent = "Chest"; + bones.write[4].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[4].handle_offset = Vector2(0.5, 0.29); bones.write[4].group = "Body"; bones.write[5].bone_name = "Neck"; + bones.write[5].bone_parent = "UpperChest"; + bones.write[5].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD; + bones.write[5].bone_tail = "Head"; + bones.write[5].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[5].handle_offset = Vector2(0.5, 0.23); bones.write[5].group = "Body"; + bones.write[5].require = true; bones.write[6].bone_name = "Head"; + bones.write[6].bone_parent = "Neck"; + bones.write[6].tail_direction = TAIL_DIRECTION_END; + bones.write[6].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[6].handle_offset = Vector2(0.5, 0.18); bones.write[6].group = "Body"; + bones.write[6].require = true; bones.write[7].bone_name = "LeftEye"; + bones.write[7].bone_parent = "Head"; + bones.write[7].reference_pose = Transform3D(1, 0, 0, 0, 0, -1, 0, 1, 0, 0.05, 0.15, 0); bones.write[7].handle_offset = Vector2(0.6, 0.46); bones.write[7].group = "Face"; bones.write[8].bone_name = "RightEye"; + bones.write[8].bone_parent = "Head"; + bones.write[8].reference_pose = Transform3D(1, 0, 0, 0, 0, -1, 0, 1, 0, -0.05, 0.15, 0); bones.write[8].handle_offset = Vector2(0.37, 0.46); bones.write[8].group = "Face"; bones.write[9].bone_name = "Jaw"; + bones.write[9].bone_parent = "Head"; + bones.write[9].reference_pose = Transform3D(-1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0.05, 0.05); bones.write[9].handle_offset = Vector2(0.46, 0.75); bones.write[9].group = "Face"; bones.write[10].bone_name = "LeftShoulder"; + bones.write[10].bone_parent = "UpperChest"; + bones.write[10].reference_pose = Transform3D(0, 1, 0, 0, 0, 1, 1, 0, 0, 0.05, 0.1, 0); bones.write[10].handle_offset = Vector2(0.55, 0.235); bones.write[10].group = "Body"; + bones.write[10].require = true; bones.write[11].bone_name = "LeftUpperArm"; + bones.write[11].bone_parent = "LeftShoulder"; + bones.write[11].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.05, 0); bones.write[11].handle_offset = Vector2(0.6, 0.24); bones.write[11].group = "Body"; + bones.write[11].require = true; bones.write[12].bone_name = "LeftLowerArm"; + bones.write[12].bone_parent = "LeftUpperArm"; + bones.write[12].reference_pose = Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0.25, 0); bones.write[12].handle_offset = Vector2(0.7, 0.24); bones.write[12].group = "Body"; + bones.write[12].require = true; bones.write[13].bone_name = "LeftHand"; + bones.write[13].bone_parent = "LeftLowerArm"; + bones.write[13].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD; + bones.write[13].bone_tail = "LeftMiddleProximal"; + bones.write[13].reference_pose = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, 0, 0.25, 0); bones.write[13].handle_offset = Vector2(0.82, 0.235); bones.write[13].group = "Body"; + bones.write[13].require = true; - bones.write[14].bone_name = "LeftThumbProximal"; + bones.write[14].bone_name = "LeftThumbMetacarpal"; + bones.write[14].bone_parent = "LeftHand"; + bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0.707, 0.577, 0.408, -0.707, 0.577, 0.408, -0.025, 0, 0); bones.write[14].handle_offset = Vector2(0.4, 0.8); bones.write[14].group = "LeftHand"; - bones.write[15].bone_name = "LeftThumbIntermediate"; + bones.write[15].bone_name = "LeftThumbProximal"; + bones.write[15].bone_parent = "LeftThumbMetacarpal"; + bones.write[15].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0); bones.write[15].handle_offset = Vector2(0.3, 0.69); bones.write[15].group = "LeftHand"; bones.write[16].bone_name = "LeftThumbDistal"; + bones.write[16].bone_parent = "LeftThumbProximal"; + bones.write[16].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0); bones.write[16].handle_offset = Vector2(0.23, 0.555); bones.write[16].group = "LeftHand"; bones.write[17].bone_name = "LeftIndexProximal"; + bones.write[17].bone_parent = "LeftHand"; + bones.write[17].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.025, 0.075, 0); bones.write[17].handle_offset = Vector2(0.413, 0.52); bones.write[17].group = "LeftHand"; bones.write[18].bone_name = "LeftIndexIntermediate"; + bones.write[18].bone_parent = "LeftIndexProximal"; + bones.write[18].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[18].handle_offset = Vector2(0.403, 0.36); bones.write[18].group = "LeftHand"; bones.write[19].bone_name = "LeftIndexDistal"; + bones.write[19].bone_parent = "LeftIndexIntermediate"; + bones.write[19].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[19].handle_offset = Vector2(0.403, 0.255); bones.write[19].group = "LeftHand"; bones.write[20].bone_name = "LeftMiddleProximal"; + bones.write[20].bone_parent = "LeftHand"; + bones.write[20].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0); bones.write[20].handle_offset = Vector2(0.5, 0.51); bones.write[20].group = "LeftHand"; bones.write[21].bone_name = "LeftMiddleIntermediate"; + bones.write[21].bone_parent = "LeftMiddleProximal"; + bones.write[21].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0); bones.write[21].handle_offset = Vector2(0.5, 0.345); bones.write[21].group = "LeftHand"; bones.write[22].bone_name = "LeftMiddleDistal"; + bones.write[22].bone_parent = "LeftMiddleIntermediate"; + bones.write[22].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[22].handle_offset = Vector2(0.5, 0.22); bones.write[22].group = "LeftHand"; bones.write[23].bone_name = "LeftRingProximal"; + bones.write[23].bone_parent = "LeftHand"; + bones.write[23].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.025, 0.075, 0); bones.write[23].handle_offset = Vector2(0.586, 0.52); bones.write[23].group = "LeftHand"; bones.write[24].bone_name = "LeftRingIntermediate"; + bones.write[24].bone_parent = "LeftRingProximal"; + bones.write[24].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[24].handle_offset = Vector2(0.59, 0.36); bones.write[24].group = "LeftHand"; bones.write[25].bone_name = "LeftRingDistal"; + bones.write[25].bone_parent = "LeftRingIntermediate"; + bones.write[25].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[25].handle_offset = Vector2(0.591, 0.25); bones.write[25].group = "LeftHand"; bones.write[26].bone_name = "LeftLittleProximal"; + bones.write[26].bone_parent = "LeftHand"; + bones.write[26].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0.05, 0); bones.write[26].handle_offset = Vector2(0.663, 0.543); bones.write[26].group = "LeftHand"; bones.write[27].bone_name = "LeftLittleIntermediate"; + bones.write[27].bone_parent = "LeftLittleProximal"; + bones.write[27].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[27].handle_offset = Vector2(0.672, 0.415); bones.write[27].group = "LeftHand"; bones.write[28].bone_name = "LeftLittleDistal"; + bones.write[28].bone_parent = "LeftLittleIntermediate"; + bones.write[28].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[28].handle_offset = Vector2(0.672, 0.32); bones.write[28].group = "LeftHand"; bones.write[29].bone_name = "RightShoulder"; + bones.write[29].bone_parent = "UpperChest"; + bones.write[29].reference_pose = Transform3D(0, -1, 0, 0, 0, 1, -1, 0, 0, -0.05, 0.1, 0); bones.write[29].handle_offset = Vector2(0.45, 0.235); bones.write[29].group = "Body"; + bones.write[29].require = true; bones.write[30].bone_name = "RightUpperArm"; + bones.write[30].bone_parent = "RightShoulder"; + bones.write[30].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.05, 0); bones.write[30].handle_offset = Vector2(0.4, 0.24); bones.write[30].group = "Body"; + bones.write[30].require = true; bones.write[31].bone_name = "RightLowerArm"; + bones.write[31].bone_parent = "RightUpperArm"; + bones.write[31].reference_pose = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, 0, 0.25, 0); bones.write[31].handle_offset = Vector2(0.3, 0.24); bones.write[31].group = "Body"; + bones.write[31].require = true; bones.write[32].bone_name = "RightHand"; + bones.write[32].bone_parent = "RightLowerArm"; + bones.write[32].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD; + bones.write[32].bone_tail = "RightMiddleProximal"; + bones.write[32].reference_pose = Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0.25, 0); bones.write[32].handle_offset = Vector2(0.18, 0.235); bones.write[32].group = "Body"; + bones.write[32].require = true; - bones.write[33].bone_name = "RightThumbProximal"; + bones.write[33].bone_name = "RightThumbMetacarpal"; + bones.write[33].bone_parent = "RightHand"; + bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, -0.707, 0.577, 0.408, 0.707, 0.577, 0.408, 0.025, 0, 0); bones.write[33].handle_offset = Vector2(0.6, 0.8); bones.write[33].group = "RightHand"; - bones.write[34].bone_name = "RightThumbIntermediate"; + bones.write[34].bone_name = "RightThumbProximal"; + bones.write[34].bone_parent = "RightThumbMetacarpal"; + bones.write[34].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0); bones.write[34].handle_offset = Vector2(0.7, 0.69); bones.write[34].group = "RightHand"; bones.write[35].bone_name = "RightThumbDistal"; + bones.write[35].bone_parent = "RightThumbProximal"; + bones.write[35].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0); bones.write[35].handle_offset = Vector2(0.77, 0.555); bones.write[35].group = "RightHand"; bones.write[36].bone_name = "RightIndexProximal"; + bones.write[36].bone_parent = "RightHand"; + bones.write[36].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.025, 0.075, 0); bones.write[36].handle_offset = Vector2(0.587, 0.52); bones.write[36].group = "RightHand"; bones.write[37].bone_name = "RightIndexIntermediate"; + bones.write[37].bone_parent = "RightIndexProximal"; + bones.write[37].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[37].handle_offset = Vector2(0.597, 0.36); bones.write[37].group = "RightHand"; bones.write[38].bone_name = "RightIndexDistal"; + bones.write[38].bone_parent = "RightIndexIntermediate"; + bones.write[38].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[38].handle_offset = Vector2(0.597, 0.255); bones.write[38].group = "RightHand"; bones.write[39].bone_name = "RightMiddleProximal"; + bones.write[39].bone_parent = "RightHand"; + bones.write[39].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0); bones.write[39].handle_offset = Vector2(0.5, 0.51); bones.write[39].group = "RightHand"; bones.write[40].bone_name = "RightMiddleIntermediate"; + bones.write[40].bone_parent = "RightMiddleProximal"; + bones.write[40].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0); bones.write[40].handle_offset = Vector2(0.5, 0.345); bones.write[40].group = "RightHand"; bones.write[41].bone_name = "RightMiddleDistal"; + bones.write[41].bone_parent = "RightMiddleIntermediate"; + bones.write[41].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[41].handle_offset = Vector2(0.5, 0.22); bones.write[41].group = "RightHand"; bones.write[42].bone_name = "RightRingProximal"; + bones.write[42].bone_parent = "RightHand"; + bones.write[42].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.025, 0.075, 0); bones.write[42].handle_offset = Vector2(0.414, 0.52); bones.write[42].group = "RightHand"; bones.write[43].bone_name = "RightRingIntermediate"; + bones.write[43].bone_parent = "RightRingProximal"; + bones.write[43].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[43].handle_offset = Vector2(0.41, 0.36); bones.write[43].group = "RightHand"; bones.write[44].bone_name = "RightRingDistal"; + bones.write[44].bone_parent = "RightRingIntermediate"; + bones.write[44].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[44].handle_offset = Vector2(0.409, 0.25); bones.write[44].group = "RightHand"; bones.write[45].bone_name = "RightLittleProximal"; + bones.write[45].bone_parent = "RightHand"; + bones.write[45].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.05, 0.05, 0); bones.write[45].handle_offset = Vector2(0.337, 0.543); bones.write[45].group = "RightHand"; bones.write[46].bone_name = "RightLittleIntermediate"; + bones.write[46].bone_parent = "RightLittleProximal"; + bones.write[46].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0); bones.write[46].handle_offset = Vector2(0.328, 0.415); bones.write[46].group = "RightHand"; bones.write[47].bone_name = "RightLittleDistal"; + bones.write[47].bone_parent = "RightLittleIntermediate"; + bones.write[47].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0); bones.write[47].handle_offset = Vector2(0.328, 0.32); bones.write[47].group = "RightHand"; bones.write[48].bone_name = "LeftUpperLeg"; + bones.write[48].bone_parent = "Hips"; + bones.write[48].reference_pose = Transform3D(-1, 0, 0, 0, -1, 0, 0, 0, 1, 0.1, 0, 0); bones.write[48].handle_offset = Vector2(0.549, 0.49); bones.write[48].group = "Body"; + bones.write[48].require = true; bones.write[49].bone_name = "LeftLowerLeg"; + bones.write[49].bone_parent = "LeftUpperLeg"; + bones.write[49].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.375, 0); bones.write[49].handle_offset = Vector2(0.548, 0.683); bones.write[49].group = "Body"; + bones.write[49].require = true; bones.write[50].bone_name = "LeftFoot"; + bones.write[50].bone_parent = "LeftLowerLeg"; + bones.write[50].reference_pose = Transform3D(-1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0.375, 0); bones.write[50].handle_offset = Vector2(0.545, 0.9); bones.write[50].group = "Body"; + bones.write[50].require = true; bones.write[51].bone_name = "LeftToes"; + bones.write[51].bone_parent = "LeftFoot"; + bones.write[51].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.15, 0); bones.write[51].handle_offset = Vector2(0.545, 0.95); bones.write[51].group = "Body"; bones.write[52].bone_name = "RightUpperLeg"; + bones.write[52].bone_parent = "Hips"; + bones.write[52].reference_pose = Transform3D(-1, 0, 0, 0, -1, 0, 0, 0, 1, -0.1, 0, 0); bones.write[52].handle_offset = Vector2(0.451, 0.49); bones.write[52].group = "Body"; + bones.write[52].require = true; bones.write[53].bone_name = "RightLowerLeg"; + bones.write[53].bone_parent = "RightUpperLeg"; + bones.write[53].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.375, 0); bones.write[53].handle_offset = Vector2(0.452, 0.683); bones.write[53].group = "Body"; + bones.write[53].require = true; bones.write[54].bone_name = "RightFoot"; + bones.write[54].bone_parent = "RightLowerLeg"; + bones.write[54].reference_pose = Transform3D(-1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0.375, 0); bones.write[54].handle_offset = Vector2(0.455, 0.9); bones.write[54].group = "Body"; + bones.write[54].require = true; bones.write[55].bone_name = "RightToes"; + bones.write[55].bone_parent = "RightFoot"; + bones.write[55].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.15, 0); bones.write[55].handle_offset = Vector2(0.455, 0.95); bones.write[55].group = "Body"; } diff --git a/scene/resources/skeleton_profile.h b/scene/resources/skeleton_profile.h index 920aaa2b8d..84dfca458e 100644 --- a/scene/resources/skeleton_profile.h +++ b/scene/resources/skeleton_profile.h @@ -36,6 +36,13 @@ class SkeletonProfile : public Resource { GDCLASS(SkeletonProfile, Resource); +public: + enum TailDirection { + TAIL_DIRECTION_AVERAGE_CHILDREN, + TAIL_DIRECTION_SPECIFIC_CHILD, + TAIL_DIRECTION_END + }; + protected: // Note: SkeletonProfileHumanoid which extends SkeletonProfile exists to unify standard bone names. // That is what is_read_only is for, so don't make it public. @@ -48,10 +55,18 @@ protected: struct SkeletonProfileBone { StringName bone_name; + StringName bone_parent; + TailDirection tail_direction = TAIL_DIRECTION_AVERAGE_CHILDREN; + StringName bone_tail; + Transform3D reference_pose; Vector2 handle_offset; StringName group; + bool require = false; }; + StringName root_bone; + StringName scale_base_bone; + Vector<SkeletonProfileGroup> groups; Vector<SkeletonProfileBone> bones; @@ -62,6 +77,12 @@ protected: static void _bind_methods(); public: + StringName get_root_bone(); + void set_root_bone(StringName p_bone_name); + + StringName get_scale_base_bone(); + void set_scale_base_bone(StringName p_bone_name); + int get_group_size(); void set_group_size(int p_size); @@ -74,15 +95,32 @@ public: int get_bone_size(); void set_bone_size(int p_size); + int find_bone(const StringName p_bone_name) const; + StringName get_bone_name(int p_bone_idx) const; void set_bone_name(int p_bone_idx, const StringName p_bone_name); + StringName get_bone_parent(int p_bone_idx) const; + void set_bone_parent(int p_bone_idx, const StringName p_bone_parent); + + TailDirection get_tail_direction(int p_bone_idx) const; + void set_tail_direction(int p_bone_idx, const TailDirection p_tail_direction); + + StringName get_bone_tail(int p_bone_idx) const; + void set_bone_tail(int p_bone_idx, const StringName p_bone_tail); + + Transform3D get_reference_pose(int p_bone_idx) const; + void set_reference_pose(int p_bone_idx, const Transform3D p_reference_pose); + Vector2 get_handle_offset(int p_bone_idx) const; void set_handle_offset(int p_bone_idx, const Vector2 p_handle_offset); StringName get_group(int p_bone_idx) const; void set_group(int p_bone_idx, const StringName p_group); + bool is_require(int p_bone_idx) const; + void set_require(int p_bone_idx, const bool p_require); + bool has_bone(StringName p_bone_name); SkeletonProfile(); @@ -97,4 +135,6 @@ public: ~SkeletonProfileHumanoid(); }; +VARIANT_ENUM_CAST(SkeletonProfile::TailDirection); + #endif // SKELETON_PROFILE_H diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h index 5be8922ba4..61999af3c4 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -219,4 +219,4 @@ public: ~PhysicalSkyMaterial(); }; -#endif /* !SKY_MATERIAL_H */ +#endif // SKY_MATERIAL_H diff --git a/scene/resources/sphere_shape_3d.h b/scene/resources/sphere_shape_3d.h index 8f77378ef4..91d72e01ec 100644 --- a/scene/resources/sphere_shape_3d.h +++ b/scene/resources/sphere_shape_3d.h @@ -52,4 +52,4 @@ public: SphereShape3D(); }; -#endif // SPHERE_SHAPE_H +#endif // SPHERE_SHAPE_3D_H diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp index ba21b9fd17..55c9d7397d 100644 --- a/scene/resources/sprite_frames.cpp +++ b/scene/resources/sprite_frames.cpp @@ -96,17 +96,6 @@ void SpriteFrames::rename_animation(const StringName &p_prev, const StringName & animations[p_next] = anim; } -Vector<String> SpriteFrames::_get_animation_list() const { - Vector<String> ret; - List<StringName> al; - get_animation_list(&al); - for (const StringName &E : al) { - ret.push_back(E); - } - - return ret; -} - void SpriteFrames::get_animation_list(List<StringName> *r_animations) const { for (const KeyValue<StringName, Anim> &E : animations) { r_animations->push_back(E.key); @@ -147,31 +136,22 @@ bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { return E->value.loop; } -void SpriteFrames::_set_frames(const Array &p_frames) { - clear_all(); - HashMap<StringName, Anim>::Iterator E = animations.find(SceneStringNames::get_singleton()->_default); - ERR_FAIL_COND(!E); - - E->value.frames.resize(p_frames.size()); - for (int i = 0; i < E->value.frames.size(); i++) { - E->value.frames.write[i] = p_frames[i]; - } -} - -Array SpriteFrames::_get_frames() const { - return Array(); -} - Array SpriteFrames::_get_animations() const { Array anims; - for (const KeyValue<StringName, Anim> &E : animations) { + + List<StringName> sorted_names; + get_animation_list(&sorted_names); + sorted_names.sort_custom<StringName::AlphCompare>(); + + for (const StringName &name : sorted_names) { + const Anim &anim = animations[name]; Dictionary d; - d["name"] = E.key; - d["speed"] = E.value.speed; - d["loop"] = E.value.loop; + d["name"] = name; + d["speed"] = anim.speed; + d["loop"] = anim.loop; Array frames; - for (int i = 0; i < E.value.frames.size(); i++) { - frames.push_back(E.value.frames[i]); + for (int i = 0; i < anim.frames.size(); i++) { + frames.push_back(anim.frames[i]); } d["frames"] = frames; anims.push_back(d); @@ -225,15 +205,12 @@ void SpriteFrames::_bind_methods() { ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear); ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all); - ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames); - ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_frames", "_get_frames"); //compatibility + // `animations` property is for serialization. ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); } SpriteFrames::SpriteFrames() { diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h index e32ccc1336..87d84b70c0 100644 --- a/scene/resources/sprite_frames.h +++ b/scene/resources/sprite_frames.h @@ -44,14 +44,9 @@ class SpriteFrames : public Resource { HashMap<StringName, Anim> animations; - Array _get_frames() const; - void _set_frames(const Array &p_frames); - Array _get_animations() const; void _set_animations(const Array &p_animations); - Vector<String> _get_animation_list() const; - protected: static void _bind_methods(); diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 3b3654775f..9f4f69d3ba 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -264,4 +264,4 @@ public: ~StyleBoxLine(); }; -#endif +#endif // STYLE_BOX_H diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 2d399ca3bf..6735d6623f 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -207,4 +207,4 @@ public: VARIANT_ENUM_CAST(SurfaceTool::CustomFormat) VARIANT_ENUM_CAST(SurfaceTool::SkinWeightCount) -#endif +#endif // SURFACE_TOOL_H diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h index 1243a9dbf7..69131ffbee 100644 --- a/scene/resources/syntax_highlighter.h +++ b/scene/resources/syntax_highlighter.h @@ -142,4 +142,4 @@ public: Color get_member_variable_color() const; }; -#endif +#endif // SYNTAX_HIGHLIGHTER_H diff --git a/scene/resources/text_file.h b/scene/resources/text_file.h index 0c8cf855f0..168e4f5879 100644 --- a/scene/resources/text_file.h +++ b/scene/resources/text_file.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEXTFILE_H -#define TEXTFILE_H +#ifndef TEXT_FILE_H +#define TEXT_FILE_H #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" @@ -51,4 +51,4 @@ public: Error load_text(const String &p_path); }; -#endif // TEXTFILE_H +#endif // TEXT_FILE_H diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp index f32b7feb4b..823d742d72 100644 --- a/scene/resources/text_line.cpp +++ b/scene/resources/text_line.cpp @@ -74,7 +74,7 @@ void TextLine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextLine::set_flags); ClassDB::bind_method(D_METHOD("get_flags"), &TextLine::get_flags); - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab"), "set_flags", "get_flags"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justification,Word Justification,Trim Edge Spaces After Justification,Justify Only After Last Tab,Constrain Ellipsis"), "set_flags", "get_flags"); ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &TextLine::set_text_overrun_behavior); ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &TextLine::get_text_overrun_behavior); @@ -106,24 +106,24 @@ void TextLine::_shape() { TS->shaped_text_tab_align(rid, tab_stops); } - uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM; + BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { switch (overrun_behavior) { case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_WORD: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); break; case TextServer::OVERRUN_TRIM_CHAR: - overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); break; case TextServer::OVERRUN_NO_TRIMMING: break; @@ -131,7 +131,7 @@ void TextLine::_shape() { if (alignment == HORIZONTAL_ALIGNMENT_FILL) { TS->shaped_text_fit_to_width(rid, width, flags); - overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE; + overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); TS->shaped_text_overrun_trim_to_width(rid, width, overrun_flags); } else { TS->shaped_text_overrun_trim_to_width(rid, width, overrun_flags); @@ -241,14 +241,14 @@ void TextLine::tab_align(const Vector<float> &p_tab_stops) { dirty = true; } -void TextLine::set_flags(uint16_t p_flags) { +void TextLine::set_flags(BitField<TextServer::JustificationFlag> p_flags) { if (flags != p_flags) { flags = p_flags; dirty = true; } } -uint16_t TextLine::get_flags() const { +BitField<TextServer::JustificationFlag> TextLine::get_flags() const { return flags; } diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h index 2d1548d079..e70e82cf2b 100644 --- a/scene/resources/text_line.h +++ b/scene/resources/text_line.h @@ -45,7 +45,7 @@ private: bool dirty = true; float width = -1.0; - uint16_t flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; + BitField<TextServer::JustificationFlag> flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_TRIM_ELLIPSIS; @@ -84,8 +84,8 @@ public: void tab_align(const Vector<float> &p_tab_stops); - void set_flags(uint16_t p_flags); - uint16_t get_flags() const; + void set_flags(BitField<TextServer::JustificationFlag> p_flags); + BitField<TextServer::JustificationFlag> get_flags() const; void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior); TextServer::OverrunBehavior get_text_overrun_behavior() const; diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index c8b9e895fc..43d3f329fa 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -74,10 +74,15 @@ void TextParagraph::_bind_methods() { ClassDB::bind_method(D_METHOD("tab_align", "tab_stops"), &TextParagraph::tab_align); - ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextParagraph::set_flags); - ClassDB::bind_method(D_METHOD("get_flags"), &TextParagraph::get_flags); + ClassDB::bind_method(D_METHOD("set_break_flags", "flags"), &TextParagraph::set_break_flags); + ClassDB::bind_method(D_METHOD("get_break_flags"), &TextParagraph::get_break_flags); - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab,Break Mandatory,Break Words,Break Graphemes"), "set_flags", "get_flags"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive"), "set_break_flags", "get_break_flags"); + + ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags); + ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification,Word Justification,Trim Edge Spaces After Justification,Justify Only After Last Tab,Constrain Ellipsis"), "set_justification_flags", "get_justification_flags"); ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &TextParagraph::set_text_overrun_behavior); ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &TextParagraph::get_text_overrun_behavior); @@ -154,7 +159,7 @@ void TextParagraph::_shape_lines() { if (h_offset > 0) { // Dropcap, flow around. - PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags); + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, brk_flags); for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x; @@ -172,7 +177,7 @@ void TextParagraph::_shape_lines() { } } // Use fixed for the rest of lines. - PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags); + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, brk_flags); for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); if (!tab_stops.is_empty()) { @@ -181,43 +186,43 @@ void TextParagraph::_shape_lines() { lines_rid.push_back(line); } - uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM; + BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { switch (overrun_behavior) { case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_ELLIPSIS: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); break; case TextServer::OVERRUN_TRIM_WORD: - overrun_flags |= TextServer::OVERRUN_TRIM; - overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); break; case TextServer::OVERRUN_TRIM_CHAR: - overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); break; case TextServer::OVERRUN_NO_TRIMMING: break; } } - bool autowrap_enabled = ((flags & TextServer::BREAK_WORD_BOUND) == TextServer::BREAK_WORD_BOUND) || ((flags & TextServer::BREAK_GRAPHEME_BOUND) == TextServer::BREAK_GRAPHEME_BOUND); + bool autowrap_enabled = brk_flags.has_flag(TextServer::BREAK_WORD_BOUND) || brk_flags.has_flag(TextServer::BREAK_GRAPHEME_BOUND); // Fill after min_size calculation. if (autowrap_enabled) { int visible_lines = (max_lines_visible >= 0) ? MIN(max_lines_visible, (int)lines_rid.size()) : (int)lines_rid.size(); bool lines_hidden = visible_lines > 0 && visible_lines < (int)lines_rid.size(); if (lines_hidden) { - overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS; + overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); } if (alignment == HORIZONTAL_ALIGNMENT_FILL) { for (int i = 0; i < (int)lines_rid.size(); i++) { if (i < visible_lines - 1 || (int)lines_rid.size() == 1) { - TS->shaped_text_fit_to_width(lines_rid[i], width, flags); + TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags); } else if (i == (visible_lines - 1)) { TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); } @@ -231,10 +236,10 @@ void TextParagraph::_shape_lines() { // Autowrap disabled. for (int i = 0; i < (int)lines_rid.size(); i++) { if (alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(lines_rid[i], width, flags); - overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE; + TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags); + overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); - TS->shaped_text_fit_to_width(lines_rid[i], width, flags | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); + TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); } else { TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); } @@ -420,17 +425,30 @@ void TextParagraph::tab_align(const Vector<float> &p_tab_stops) { lines_dirty = true; } -void TextParagraph::set_flags(uint16_t p_flags) { +void TextParagraph::set_justification_flags(BitField<TextServer::JustificationFlag> p_flags) { + _THREAD_SAFE_METHOD_ + + if (jst_flags != p_flags) { + jst_flags = p_flags; + lines_dirty = true; + } +} + +BitField<TextServer::JustificationFlag> TextParagraph::get_justification_flags() const { + return jst_flags; +} + +void TextParagraph::set_break_flags(BitField<TextServer::LineBreakFlag> p_flags) { _THREAD_SAFE_METHOD_ - if (flags != p_flags) { - flags = p_flags; + if (brk_flags != p_flags) { + brk_flags = p_flags; lines_dirty = true; } } -uint16_t TextParagraph::get_flags() const { - return flags; +BitField<TextServer::LineBreakFlag> TextParagraph::get_break_flags() const { + return brk_flags; } void TextParagraph::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) { diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index f161cb5b8c..0fe82b4364 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -54,7 +54,8 @@ private: float width = -1.0; int max_lines_visible = -1; - uint16_t flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; + BitField<TextServer::LineBreakFlag> brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND; + BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING; HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; @@ -102,8 +103,11 @@ public: void tab_align(const Vector<float> &p_tab_stops); - void set_flags(uint16_t p_flags); - uint16_t get_flags() const; + void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags); + BitField<TextServer::JustificationFlag> get_justification_flags() const; + + void set_break_flags(BitField<TextServer::LineBreakFlag> p_flags); + BitField<TextServer::LineBreakFlag> get_break_flags() const; void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior); TextServer::OverrunBehavior get_text_overrun_behavior() const; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 8c175e9ced..05ed9238b8 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -300,8 +300,8 @@ bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { return true; } -void ImageTexture::set_size_override(const Size2 &p_size) { - Size2 s = p_size; +void ImageTexture::set_size_override(const Size2i &p_size) { + Size2i s = p_size; if (s.x != 0) { w = s.x; } @@ -323,6 +323,7 @@ void ImageTexture::_bind_methods() { ClassDB::bind_static_method("ImageTexture", D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image); ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); + ClassDB::bind_method(D_METHOD("set_image", "image"), &ImageTexture::set_image); ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update); ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override); } @@ -2008,7 +2009,7 @@ void CurveXYZTexture::set_curve_x(Ref<Curve> p_curve) { } _curve_x = p_curve; if (_curve_x.is_valid()) { - _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); + _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED); } _update(); } @@ -2021,7 +2022,7 @@ void CurveXYZTexture::set_curve_y(Ref<Curve> p_curve) { } _curve_y = p_curve; if (_curve_y.is_valid()) { - _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); + _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED); } _update(); } @@ -2034,7 +2035,7 @@ void CurveXYZTexture::set_curve_z(Ref<Curve> p_curve) { } _curve_z = p_curve; if (_curve_z.is_valid()) { - _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); + _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED); } _update(); } @@ -2157,7 +2158,7 @@ void GradientTexture1D::_bind_methods() { ClassDB::bind_method(D_METHOD("_update"), &GradientTexture1D::_update); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_gradient", "get_gradient"); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,16384,suffix:px"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr"); } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 5973643034..36b193c5d4 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -130,7 +130,7 @@ public: bool is_pixel_opaque(int p_x, int p_y) const override; - void set_size_override(const Size2 &p_size); + void set_size_override(const Size2i &p_size); virtual void set_path(const String &p_path, bool p_take_over = false) override; @@ -1106,4 +1106,4 @@ public: PlaceholderTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} }; -#endif +#endif // TEXTURE_H diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 39b77568cf..3f6eec8497 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -295,7 +295,7 @@ void Theme::set_default_font(const Ref<Font> &p_default_font) { default_font = p_default_font; if (default_font.is_valid()) { - default_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED); + default_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED); } _emit_theme_changed(); @@ -341,7 +341,7 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_theme_type, c icon_map[p_theme_type][p_name] = p_icon; if (p_icon.is_valid()) { - icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED); + icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED); } _emit_theme_changed(!existing); @@ -451,7 +451,7 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_theme_typ style_map[p_theme_type][p_name] = p_style; if (p_style.is_valid()) { - style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED); + style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED); } _emit_theme_changed(!existing); @@ -561,7 +561,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, c font_map[p_theme_type][p_name] = p_font; if (p_font.is_valid()) { - font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED); + font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED); } _emit_theme_changed(!existing); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 87d7d2fdea..a2aca5e61f 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -256,4 +256,4 @@ public: VARIANT_ENUM_CAST(Theme::DataType); -#endif +#endif // THEME_H diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 05483db1e4..b0b9f1228f 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -1048,13 +1048,13 @@ int TileSet::get_custom_data_layer_by_name(String p_value) const { } } -void TileSet::set_custom_data_name(int p_layer_id, String p_value) { +void TileSet::set_custom_data_layer_name(int p_layer_id, String p_value) { ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size()); // Exit if another property has the same name. if (!p_value.is_empty()) { for (int other_layer_id = 0; other_layer_id < get_custom_data_layers_count(); other_layer_id++) { - if (other_layer_id != p_layer_id && get_custom_data_name(other_layer_id) == p_value) { + if (other_layer_id != p_layer_id && get_custom_data_layer_name(other_layer_id) == p_value) { ERR_FAIL_MSG(vformat("There is already a custom property named %s", p_value)); } } @@ -1070,12 +1070,12 @@ void TileSet::set_custom_data_name(int p_layer_id, String p_value) { emit_changed(); } -String TileSet::get_custom_data_name(int p_layer_id) const { +String TileSet::get_custom_data_layer_name(int p_layer_id) const { ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), ""); return custom_data_layers[p_layer_id].name; } -void TileSet::set_custom_data_type(int p_layer_id, Variant::Type p_value) { +void TileSet::set_custom_data_layer_type(int p_layer_id, Variant::Type p_value) { ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size()); custom_data_layers.write[p_layer_id].type = p_value; @@ -1086,7 +1086,7 @@ void TileSet::set_custom_data_type(int p_layer_id, Variant::Type p_value) { emit_changed(); } -Variant::Type TileSet::get_custom_data_type(int p_layer_id) const { +Variant::Type TileSet::get_custom_data_layer_type(int p_layer_id) const { ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), Variant::NIL); return custom_data_layers[p_layer_id].type; } @@ -1801,9 +1801,9 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) { if (counts[terrain_set][terrain].count > 0) { // Get the best tile. Ref<Texture2D> texture = counts[terrain_set][terrain].texture; - Rect2 region = counts[terrain_set][terrain].region; + Rect2i region = counts[terrain_set][terrain].region; image->create(region.size.x, region.size.y, false, Image::FORMAT_RGBA8); - image->blit_rect(texture->get_image(), region, Point2()); + image->blit_rect(texture->get_image(), region, Point2i()); image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST); } else { image->create(1, 1, false, Image::FORMAT_RGBA8); @@ -2467,9 +2467,42 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_peering_bit_polygon(Vector } void TileSet::reset_state() { + // Rendering occlusion_layers.clear(); + tile_lines_mesh.instantiate(); + tile_filled_mesh.instantiate(); + tile_meshes_dirty = true; + + // Physics physics_layers.clear(); + + // Terrains + terrain_sets.clear(); + terrain_meshes.clear(); + terrain_peering_bits_meshes.clear(); + per_terrain_pattern_tiles.clear(); + terrains_cache_dirty = true; + + // Navigation + navigation_layers.clear(); + custom_data_layers.clear(); + custom_data_layers_by_name.clear(); + + // Proxies + source_level_proxies.clear(); + coords_level_proxies.clear(); + alternative_level_proxies.clear(); + +#ifndef DISABLE_DEPRECATED + for (const KeyValue<int, CompatibilityTileData *> &E : compatibility_data) { + memdelete(E.value); + } + compatibility_data.clear(); +#endif // DISABLE_DEPRECATED + while (!source_ids.is_empty()) { + remove_source(source_ids[0]); + } } const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1); @@ -3003,14 +3036,14 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { while (index >= custom_data_layers.size()) { add_custom_data_layer(); } - set_custom_data_name(index, p_value); + set_custom_data_layer_name(index, p_value); return true; } else if (components[1] == "type") { ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false); while (index >= custom_data_layers.size()) { add_custom_data_layer(); } - set_custom_data_type(index, Variant::Type(int(p_value))); + set_custom_data_layer_type(index, Variant::Type(int(p_value))); return true; } } else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_int()) { @@ -3132,10 +3165,10 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { return false; } if (components[1] == "name") { - r_ret = get_custom_data_name(index); + r_ret = get_custom_data_layer_name(index); return true; } else if (components[1] == "type") { - r_ret = get_custom_data_type(index); + r_ret = get_custom_data_layer_type(index); return true; } } else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_int()) { @@ -3358,6 +3391,11 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("add_custom_data_layer", "to_position"), &TileSet::add_custom_data_layer, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("move_custom_data_layer", "layer_index", "to_position"), &TileSet::move_custom_data_layer); ClassDB::bind_method(D_METHOD("remove_custom_data_layer", "layer_index"), &TileSet::remove_custom_data_layer); + ClassDB::bind_method(D_METHOD("get_custom_data_layer_by_name", "layer_name"), &TileSet::get_custom_data_layer_by_name); + ClassDB::bind_method(D_METHOD("set_custom_data_layer_name", "layer_index", "layer_name"), &TileSet::set_custom_data_layer_name); + ClassDB::bind_method(D_METHOD("get_custom_data_layer_name", "layer_index"), &TileSet::get_custom_data_layer_name); + ClassDB::bind_method(D_METHOD("set_custom_data_layer_type", "layer_index", "layer_type"), &TileSet::set_custom_data_layer_type); + ClassDB::bind_method(D_METHOD("get_custom_data_layer_type", "layer_index"), &TileSet::get_custom_data_layer_type); // Tile proxies ClassDB::bind_method(D_METHOD("set_source_level_tile_proxy", "source_from", "source_to"), &TileSet::set_source_level_tile_proxy); @@ -3457,6 +3495,10 @@ void TileSetSource::set_tile_set(const TileSet *p_tile_set) { tile_set = p_tile_set; } +void TileSetSource::reset_state() { + tile_set = nullptr; +}; + void TileSetSource::_bind_methods() { // Base tiles ClassDB::bind_method(D_METHOD("get_tiles_count"), &TileSetSource::get_tiles_count); @@ -3640,12 +3682,17 @@ void TileSetAtlasSource::remove_custom_data_layer(int p_index) { } void TileSetAtlasSource::reset_state() { - // Reset all TileData. + tile_set = nullptr; + for (KeyValue<Vector2i, TileAlternativesData> &E_tile : tiles) { - for (KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) { - E_alternative.value->reset_state(); + for (const KeyValue<int, TileData *> &E_tile_data : E_tile.value.alternatives) { + memdelete(E_tile_data.value); } } + _coords_mapping_cache.clear(); + tiles.clear(); + tiles_ids.clear(); + _queue_update_padded_texture(); } void TileSetAtlasSource::set_texture(Ref<Texture2D> p_texture) { @@ -3927,7 +3974,7 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { tile_property_list.push_back(property_info); // animation_frames_count. - tile_property_list.push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NETWORK)); + tile_property_list.push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); // animation_frame_*. bool store_durations = tiles[E_tile.key].animation_frames_durations.size() >= 2; @@ -4805,14 +4852,14 @@ void TileData::notify_tile_data_properties_should_change() { // Convert custom data to the new type. custom_data.resize(tile_set->get_custom_data_layers_count()); for (int i = 0; i < custom_data.size(); i++) { - if (custom_data[i].get_type() != tile_set->get_custom_data_type(i)) { + if (custom_data[i].get_type() != tile_set->get_custom_data_layer_type(i)) { Variant new_val; Callable::CallError error; - if (Variant::can_convert(custom_data[i].get_type(), tile_set->get_custom_data_type(i))) { + if (Variant::can_convert(custom_data[i].get_type(), tile_set->get_custom_data_layer_type(i))) { const Variant *args[] = { &custom_data[i] }; - Variant::construct(tile_set->get_custom_data_type(i), new_val, args, 1, error); + Variant::construct(tile_set->get_custom_data_layer_type(i), new_val, args, 1, error); } else { - Variant::construct(tile_set->get_custom_data_type(i), new_val, nullptr, 0, error); + Variant::construct(tile_set->get_custom_data_layer_type(i), new_val, nullptr, 0, error); } custom_data.write[i] = new_val; } @@ -4975,13 +5022,6 @@ void TileData::remove_custom_data_layer(int p_index) { custom_data.remove_at(p_index); } -void TileData::reset_state() { - occluders.clear(); - physics.clear(); - navigation.clear(); - custom_data.clear(); -} - void TileData::set_allow_transform(bool p_allow_transform) { allow_transform = p_allow_transform; } @@ -5626,7 +5666,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { Variant default_val; Callable::CallError error; Variant::construct(custom_data[i].get_type(), default_val, nullptr, 0, error); - property_info = PropertyInfo(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + property_info = PropertyInfo(tile_set->get_custom_data_layer_type(i), vformat("custom_data_%d", i), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); if (custom_data[i] == default_val) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 7368d2bd87..6ea3889fce 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -479,10 +479,10 @@ public: void move_custom_data_layer(int p_from_index, int p_to_pos); void remove_custom_data_layer(int p_index); int get_custom_data_layer_by_name(String p_value) const; - void set_custom_data_name(int p_layer_id, String p_value); - String get_custom_data_name(int p_layer_id) const; - void set_custom_data_type(int p_layer_id, Variant::Type p_value); - Variant::Type get_custom_data_type(int p_layer_id) const; + void set_custom_data_layer_name(int p_layer_id, String p_value); + String get_custom_data_layer_name(int p_layer_id) const; + void set_custom_data_layer_type(int p_layer_id, Variant::Type p_value); + Variant::Type get_custom_data_layer_type(int p_layer_id) const; // Tiles proxies. void set_source_level_tile_proxy(int p_source_from, int p_source_to); @@ -569,7 +569,7 @@ public: virtual void add_custom_data_layer(int p_index){}; virtual void move_custom_data_layer(int p_from_index, int p_to_pos){}; virtual void remove_custom_data_layer(int p_index){}; - virtual void reset_state() override{}; + virtual void reset_state() override; // Tiles. virtual int get_tiles_count() const = 0; @@ -847,7 +847,6 @@ public: void add_custom_data_layer(int p_index); void move_custom_data_layer(int p_from_index, int p_to_pos); void remove_custom_data_layer(int p_index); - void reset_state(); void set_allow_transform(bool p_allow_transform); bool is_allowing_transform() const; diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 3e154d539b..35686b293c 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -72,7 +72,7 @@ class VideoStream : public Resource { public: virtual void set_audio_track(int p_track) = 0; - virtual Ref<VideoStreamPlayback> instance_playback() = 0; + virtual Ref<VideoStreamPlayback> instantiate_playback() = 0; }; -#endif +#endif // VIDEO_STREAM_H diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index b8eac6de00..a67716d52b 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -30,6 +30,7 @@ #include "visual_shader.h" +#include "core/templates/rb_map.h" #include "core/templates/vmap.h" #include "servers/rendering/shader_types.h" #include "visual_shader_nodes.h" @@ -966,6 +967,12 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from ERR_FAIL_COND(!g->nodes.has(p_to_node)); ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count()); + for (const Connection &E : g->connections) { + if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) { + return; + } + } + Connection c; c.from_node = p_from_node; c.from_port = p_from_port; @@ -2640,6 +2647,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" }, // Node3D, Fragment { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, @@ -2668,6 +2679,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" }, // Node3D, Light { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, @@ -3189,18 +3204,18 @@ VisualShaderNodeInput::VisualShaderNodeInput() { ////////////// UniformRef -List<VisualShaderNodeUniformRef::Uniform> uniforms; +RBMap<RID, List<VisualShaderNodeUniformRef::Uniform>> uniforms; -void VisualShaderNodeUniformRef::add_uniform(const String &p_name, UniformType p_type) { - uniforms.push_back({ p_name, p_type }); +void VisualShaderNodeUniformRef::add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type) { + uniforms[p_shader_rid].push_back({ p_name, p_type }); } -void VisualShaderNodeUniformRef::clear_uniforms() { - uniforms.clear(); +void VisualShaderNodeUniformRef::clear_uniforms(RID p_shader_rid) { + uniforms[p_shader_rid].clear(); } -bool VisualShaderNodeUniformRef::has_uniform(const String &p_name) { - for (const VisualShaderNodeUniformRef::Uniform &E : uniforms) { +bool VisualShaderNodeUniformRef::has_uniform(RID p_shader_rid, const String &p_name) { + for (const VisualShaderNodeUniformRef::Uniform &E : uniforms[p_shader_rid]) { if (E.name == p_name) { return true; } @@ -3313,14 +3328,24 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const { return ""; } +void VisualShaderNodeUniformRef::set_shader_rid(const RID &p_shader_rid) { + shader_rid = p_shader_rid; +} + void VisualShaderNodeUniformRef::set_uniform_name(const String &p_name) { uniform_name = p_name; + if (shader_rid.is_valid()) { + update_uniform_type(); + } + emit_changed(); +} + +void VisualShaderNodeUniformRef::update_uniform_type() { if (uniform_name != "[None]") { uniform_type = get_uniform_type_by_name(uniform_name); } else { uniform_type = UniformType::UNIFORM_TYPE_FLOAT; } - emit_changed(); } String VisualShaderNodeUniformRef::get_uniform_name() const { @@ -3328,35 +3353,45 @@ String VisualShaderNodeUniformRef::get_uniform_name() const { } int VisualShaderNodeUniformRef::get_uniforms_count() const { - return uniforms.size(); + ERR_FAIL_COND_V(!shader_rid.is_valid(), 0); + + return uniforms[shader_rid].size(); } String VisualShaderNodeUniformRef::get_uniform_name_by_index(int p_idx) const { - if (p_idx >= 0 && p_idx < uniforms.size()) { - return uniforms[p_idx].name; + ERR_FAIL_COND_V(!shader_rid.is_valid(), String()); + + if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) { + return uniforms[shader_rid][p_idx].name; } return ""; } VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_name(const String &p_name) const { - for (int i = 0; i < uniforms.size(); i++) { - if (uniforms[i].name == p_name) { - return uniforms[i].type; + ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT); + + for (int i = 0; i < uniforms[shader_rid].size(); i++) { + if (uniforms[shader_rid][i].name == p_name) { + return uniforms[shader_rid][i].type; } } return UniformType::UNIFORM_TYPE_FLOAT; } VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_index(int p_idx) const { - if (p_idx >= 0 && p_idx < uniforms.size()) { - return uniforms[p_idx].type; + ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT); + + if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) { + return uniforms[shader_rid][p_idx].type; } return UniformType::UNIFORM_TYPE_FLOAT; } VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_by_index(int p_idx) const { - if (p_idx >= 0 && p_idx < uniforms.size()) { - switch (uniforms[p_idx].type) { + ERR_FAIL_COND_V(!shader_rid.is_valid(), PORT_TYPE_SCALAR); + + if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) { + switch (uniforms[shader_rid][p_idx].type) { case UniformType::UNIFORM_TYPE_FLOAT: return PORT_TYPE_SCALAR; case UniformType::UNIFORM_TYPE_INT: @@ -3724,7 +3759,7 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T } return vformat(RTR("This uniform type does not support the '%s' qualifier."), qualifier_str); } else if (qualifier == Qualifier::QUAL_GLOBAL) { - RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(uniform_name); + RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(uniform_name); if (gvt == RS::GLOBAL_VAR_TYPE_MAX) { return vformat(RTR("Global uniform '%s' does not exist.\nCreate it in the Project Settings."), uniform_name); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index afd84e49cc..7ca4e5fc4a 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -561,6 +561,7 @@ public: }; private: + RID shader_rid; String uniform_name = "[None]"; UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT; @@ -568,9 +569,9 @@ protected: static void _bind_methods(); public: - static void add_uniform(const String &p_name, UniformType p_type); - static void clear_uniforms(); - static bool has_uniform(const String &p_name); + static void add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type); + static void clear_uniforms(RID p_shader_rid); + static bool has_uniform(RID p_shader_rid, const String &p_name); public: virtual String get_caption() const override; @@ -583,9 +584,13 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + void set_shader_rid(const RID &p_shader); + void set_uniform_name(const String &p_name); String get_uniform_name() const; + void update_uniform_type(); + void _set_uniform_type(int p_uniform_type); int _get_uniform_type() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b8667f07fe..b422d298b2 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -1901,13 +1901,7 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; case OP_REFLECT: - if (op_type == OP_TYPE_VECTOR_2D) { // Not supported. - code += "vec2(0.0);\n"; - } else if (op_type == OP_TYPE_VECTOR_4D) { // Not supported. - code += "vec4(0.0);\n"; - } else { - code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; - } + code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; @@ -1967,7 +1961,7 @@ String VisualShaderNodeVectorOp::get_warning(Shader::Mode p_mode, VisualShader:: bool invalid_type = false; if (op_type == OP_TYPE_VECTOR_2D || op_type == OP_TYPE_VECTOR_4D) { - if (op == OP_CROSS || op == OP_REFLECT) { + if (op == OP_CROSS) { invalid_type = true; } } @@ -4006,14 +4000,6 @@ int VisualShaderNodeVectorRefract::get_input_port_count() const { return 3; } -VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input_port_type(int p_port) const { - if (p_port == 2) { - return PORT_TYPE_SCALAR; - } - - return PORT_TYPE_VECTOR_3D; -} - String VisualShaderNodeVectorRefract::get_input_port_name(int p_port) const { switch (p_port) { case 0: @@ -4030,10 +4016,6 @@ int VisualShaderNodeVectorRefract::get_output_port_count() const { return 1; } -VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR_3D; -} - String VisualShaderNodeVectorRefract::get_output_port_name(int p_port) const { return ""; } @@ -4042,6 +4024,31 @@ String VisualShaderNodeVectorRefract::generate_code(Shader::Mode p_mode, VisualS return " " + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } +void VisualShaderNodeVectorRefract::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_4D: { + set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); + set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() { set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); @@ -5581,12 +5588,16 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty case VisualShaderNodeTextureUniform::TYPE_DATA: if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) { type_code = "hint_default_black"; + } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) { + type_code = "hint_default_transparent"; } break; case VisualShaderNodeTextureUniform::TYPE_COLOR: type_code = "source_color"; if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) { type_code += ", hint_default_black"; + } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) { + type_code += ", hint_default_transparent"; } break; case VisualShaderNodeTextureUniform::TYPE_NORMAL_MAP: @@ -5812,7 +5823,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureUniform::get_texture_repeat); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black"), "set_color_default", "get_color_default"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black,Transparent"), "set_color_default", "get_color_default"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Default,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Default,Enabled,Disabled"), "set_texture_repeat", "get_texture_repeat"); @@ -5824,6 +5835,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() { BIND_ENUM_CONSTANT(COLOR_DEFAULT_WHITE); BIND_ENUM_CONSTANT(COLOR_DEFAULT_BLACK); + BIND_ENUM_CONSTANT(COLOR_DEFAULT_TRANSPARENT); BIND_ENUM_CONSTANT(COLOR_DEFAULT_MAX); BIND_ENUM_CONSTANT(FILTER_DEFAULT); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 1eb7b7240f..ffcb41072d 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1564,21 +1564,20 @@ public: /// REFRACT /////////////////////////////////////// -class VisualShaderNodeVectorRefract : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorRefract, VisualShaderNode); +class VisualShaderNodeVectorRefract : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorRefract, VisualShaderNodeVectorBase); 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 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; + virtual void set_op_type(OpType p_op_type) override; VisualShaderNodeVectorRefract(); }; @@ -2131,6 +2130,7 @@ public: enum ColorDefault { COLOR_DEFAULT_WHITE, COLOR_DEFAULT_BLACK, + COLOR_DEFAULT_TRANSPARENT, COLOR_DEFAULT_MAX, }; diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 05a059373b..64acb6d18f 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -352,4 +352,4 @@ public: VARIANT_ENUM_CAST(VisualShaderNodeParticleEmit::EmitFlags) -#endif +#endif // VISUAL_SHADER_PARTICLE_NODES_H diff --git a/scene/resources/world_boundary_shape_3d.h b/scene/resources/world_boundary_shape_3d.h index 5378bc52c7..5c34767106 100644 --- a/scene/resources/world_boundary_shape_3d.h +++ b/scene/resources/world_boundary_shape_3d.h @@ -53,4 +53,5 @@ public: WorldBoundaryShape3D(); }; -#endif // WORLD_BOUNDARY_SHAPE_H + +#endif // WORLD_BOUNDARY_SHAPE_3D_H diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 232a8d5e1f..8f47e64d8b 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -85,4 +85,4 @@ public: ~AudioDriverDummy() {} }; -#endif +#endif // AUDIO_DRIVER_DUMMY_H diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h index 3a0578679d..653d04595e 100644 --- a/servers/audio/audio_effect.h +++ b/servers/audio/audio_effect.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECT_H -#define AUDIOEFFECT_H +#ifndef AUDIO_EFFECT_H +#define AUDIO_EFFECT_H #include "core/io/resource.h" #include "core/math/audio_frame.h" @@ -62,4 +62,4 @@ public: AudioEffect(); }; -#endif // AUDIOEFFECT_H +#endif // AUDIO_EFFECT_H diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 5d9a9e61dc..80485845c9 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -83,6 +83,10 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra return 0; } +void AudioStreamPlayback::tag_used_streams() { + GDVIRTUAL_CALL(_tag_used_streams); +} + void AudioStreamPlayback::_bind_methods() { GDVIRTUAL_BIND(_start, "from_pos") GDVIRTUAL_BIND(_stop) @@ -91,6 +95,7 @@ void AudioStreamPlayback::_bind_methods() { GDVIRTUAL_BIND(_get_playback_position) GDVIRTUAL_BIND(_seek, "position") GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames"); + GDVIRTUAL_BIND(_tag_used_streams); } ////////////////////////////// @@ -187,9 +192,9 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, //////////////////////////////// -Ref<AudioStreamPlayback> AudioStream::instance_playback() { +Ref<AudioStreamPlayback> AudioStream::instantiate_playback() { Ref<AudioStreamPlayback> ret; - if (GDVIRTUAL_CALL(_instance_playback, ret)) { + if (GDVIRTUAL_CALL(_instantiate_playback, ret)) { return ret; } ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!"); @@ -218,19 +223,74 @@ bool AudioStream::is_monophonic() const { return true; } +double AudioStream::get_bpm() const { + double ret = 0; + if (GDVIRTUAL_CALL(_get_bpm, ret)) { + return ret; + } + return 0; +} + +bool AudioStream::has_loop() const { + bool ret = 0; + if (GDVIRTUAL_CALL(_has_loop, ret)) { + return ret; + } + return 0; +} + +int AudioStream::get_bar_beats() const { + int ret = 0; + if (GDVIRTUAL_CALL(_get_bar_beats, ret)) { + return ret; + } + return 0; +} + +int AudioStream::get_beat_count() const { + int ret = 0; + if (GDVIRTUAL_CALL(_get_beat_count, ret)) { + return ret; + } + return 0; +} + +void AudioStream::tag_used(float p_offset) { + if (tagged_frame != AudioServer::get_singleton()->get_mixed_frames()) { + offset_count = 0; + tagged_frame = AudioServer::get_singleton()->get_mixed_frames(); + } + if (offset_count < MAX_TAGGED_OFFSETS) { + tagged_offsets[offset_count++] = p_offset; + } +} + +uint64_t AudioStream::get_tagged_frame() const { + return tagged_frame; +} +uint32_t AudioStream::get_tagged_frame_count() const { + return offset_count; +} +float AudioStream::get_tagged_frame_offset(int p_index) const { + ERR_FAIL_INDEX_V(p_index, MAX_TAGGED_OFFSETS, 0); + return tagged_offsets[p_index]; +} + void AudioStream::_bind_methods() { ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length); ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic); - ClassDB::bind_method(D_METHOD("instance_playback"), &AudioStream::instance_playback); - GDVIRTUAL_BIND(_instance_playback); + ClassDB::bind_method(D_METHOD("instantiate_playback"), &AudioStream::instantiate_playback); + GDVIRTUAL_BIND(_instantiate_playback); GDVIRTUAL_BIND(_get_stream_name); GDVIRTUAL_BIND(_get_length); GDVIRTUAL_BIND(_is_monophonic); + GDVIRTUAL_BIND(_get_bpm) + GDVIRTUAL_BIND(_get_beat_count) } //////////////////////////////// -Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamMicrophone::instantiate_playback() { Ref<AudioStreamPlaybackMicrophone> playback; playback.instantiate(); @@ -363,6 +423,10 @@ void AudioStreamPlaybackMicrophone::seek(float p_time) { // Can't seek a microphone input } +void AudioStreamPlaybackMicrophone::tag_used_streams() { + microphone->tag_used(0); +} + AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() { microphone->playbacks.erase(this); stop(); @@ -490,7 +554,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() { for (PoolEntry &entry : local_pool) { cumulative_weight += entry.weight; if (cumulative_weight > chosen_cumulative_weight) { - playback->playback = entry.stream->instance_playback(); + playback->playback = entry.stream->instantiate_playback(); last_playback = entry.stream; break; } @@ -498,7 +562,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() { if (playback->playback.is_null()) { // This indicates a floating point error. Take the last element. last_playback = local_pool[local_pool.size() - 1].stream; - playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback(); + playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback(); } return playback; } @@ -532,14 +596,14 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_no_repeats() { cumulative_weight += entry.weight; if (cumulative_weight > chosen_cumulative_weight) { last_playback = entry.stream; - playback->playback = entry.stream->instance_playback(); + playback->playback = entry.stream->instantiate_playback(); break; } } if (playback->playback.is_null()) { // This indicates a floating point error. Take the last element. last_playback = local_pool[local_pool.size() - 1].stream; - playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback(); + playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback(); } return playback; } @@ -568,7 +632,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() { for (Ref<AudioStream> &entry : local_pool) { if (found_last_stream) { last_playback = entry; - playback->playback = entry->instance_playback(); + playback->playback = entry->instantiate_playback(); break; } if (entry == last_playback) { @@ -578,12 +642,12 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() { if (playback->playback.is_null()) { // Wrap around last_playback = local_pool[0]; - playback->playback = local_pool.write[0]->instance_playback(); + playback->playback = local_pool.write[0]->instantiate_playback(); } return playback; } -Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamRandomizer::instantiate_playback() { switch (playback_mode) { case PLAYBACK_RANDOM: return instance_playback_random(); @@ -696,7 +760,7 @@ void AudioStreamRandomizer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "streams_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_streams_count", "get_streams_count"); ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_mode", PROPERTY_HINT_ENUM, "Random (Avoid Repeats),Random,Sequential"), "set_playback_mode", "get_playback_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0.01,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db"); BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS); BIND_ENUM_CONSTANT(PLAYBACK_RANDOM); @@ -762,6 +826,14 @@ void AudioStreamPlaybackRandomizer::seek(float p_time) { } } +void AudioStreamPlaybackRandomizer::tag_used_streams() { + Ref<AudioStreamPlayback> p = playing; // Thread safety + if (p.is_valid()) { + p->tag_used_streams(); + } + randomizer->tag_used(0); +} + int AudioStreamPlaybackRandomizer::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { if (playing.is_valid()) { return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames); diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index bf200e7ecf..7c4577977d 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -40,6 +40,8 @@ #include "core/object/script_language.h" #include "core/variant/native_ptr.h" +class AudioStream; + class AudioStreamPlayback : public RefCounted { GDCLASS(AudioStreamPlayback, RefCounted); @@ -52,6 +54,7 @@ protected: GDVIRTUAL0RC(float, _get_playback_position) GDVIRTUAL1(_seek, float) GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int) + GDVIRTUAL0(_tag_used_streams) public: virtual void start(float p_from_pos = 0.0); virtual void stop(); @@ -62,6 +65,8 @@ public: virtual float get_playback_position() const; virtual void seek(float p_time); + virtual void tag_used_streams(); + virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); }; @@ -72,7 +77,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback { FP_BITS = 16, //fixed point used for resampling FP_LEN = (1 << FP_BITS), FP_MASK = FP_LEN - 1, - INTERNAL_BUFFER_LEN = 256, + INTERNAL_BUFFER_LEN = 128, // 128 warrants 3ms positional jitter at much at 44100hz CUBIC_INTERP_HISTORY = 4 }; @@ -101,20 +106,42 @@ class AudioStream : public Resource { GDCLASS(AudioStream, Resource); OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged. + enum { + MAX_TAGGED_OFFSETS = 8 + }; + + uint64_t tagged_frame = 0; + uint64_t offset_count = 0; + float tagged_offsets[MAX_TAGGED_OFFSETS]; + protected: static void _bind_methods(); - GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback) + GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instantiate_playback) GDVIRTUAL0RC(String, _get_stream_name) GDVIRTUAL0RC(float, _get_length) GDVIRTUAL0RC(bool, _is_monophonic) + GDVIRTUAL0RC(double, _get_bpm) + GDVIRTUAL0RC(bool, _has_loop) + GDVIRTUAL0RC(int, _get_bar_beats) + GDVIRTUAL0RC(int, _get_beat_count) public: - virtual Ref<AudioStreamPlayback> instance_playback(); + virtual Ref<AudioStreamPlayback> instantiate_playback(); virtual String get_stream_name() const; + virtual double get_bpm() const; + virtual bool has_loop() const; + virtual int get_bar_beats() const; + virtual int get_beat_count() const; + virtual float get_length() const; virtual bool is_monophonic() const; + + void tag_used(float p_offset); + uint64_t get_tagged_frame() const; + uint32_t get_tagged_frame_count() const; + float get_tagged_frame_offset(int p_index) const; }; // Microphone @@ -131,7 +158,7 @@ protected: static void _bind_methods(); public: - virtual Ref<AudioStreamPlayback> instance_playback() override; + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; virtual float get_length() const override; //if supported, otherwise return 0 @@ -153,6 +180,7 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled { protected: virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override; virtual float get_stream_sampling_rate() override; + virtual float get_playback_position() const override; public: virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; @@ -163,9 +191,10 @@ public: virtual int get_loop_count() const override; //times it looped - virtual float get_playback_position() const override; virtual void seek(float p_time) override; + virtual void tag_used_streams() override; + ~AudioStreamPlaybackMicrophone(); AudioStreamPlaybackMicrophone(); }; @@ -233,7 +262,7 @@ public: void set_playback_mode(PlaybackMode p_playback_mode); PlaybackMode get_playback_mode() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; virtual float get_length() const override; //if supported, otherwise return 0 @@ -265,6 +294,8 @@ public: virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; + virtual void tag_used_streams() override; + ~AudioStreamPlaybackRandomizer(); }; diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h index bd0fcaa94d..fd424cbe9a 100644 --- a/servers/audio/effects/audio_effect_amplify.h +++ b/servers/audio/effects/audio_effect_amplify.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTAMPLIFY_H -#define AUDIOEFFECTAMPLIFY_H +#ifndef AUDIO_EFFECT_AMPLIFY_H +#define AUDIO_EFFECT_AMPLIFY_H #include "servers/audio/audio_effect.h" @@ -63,4 +63,4 @@ public: AudioEffectAmplify(); }; -#endif // AUDIOEFFECTAMPLIFY_H +#endif // AUDIO_EFFECT_AMPLIFY_H diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h index 19035222c5..72b495f7f9 100644 --- a/servers/audio/effects/audio_effect_chorus.h +++ b/servers/audio/effects/audio_effect_chorus.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTCHORUS_H -#define AUDIOEFFECTCHORUS_H +#ifndef AUDIO_EFFECT_CHORUS_H +#define AUDIO_EFFECT_CHORUS_H #include "servers/audio/audio_effect.h" @@ -133,4 +133,4 @@ public: AudioEffectChorus(); }; -#endif // AUDIOEFFECTCHORUS_H +#endif // AUDIO_EFFECT_CHORUS_H diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h index 53c448e5db..998bd3c978 100644 --- a/servers/audio/effects/audio_effect_compressor.h +++ b/servers/audio/effects/audio_effect_compressor.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTCOMPRESSOR_H -#define AUDIOEFFECTCOMPRESSOR_H +#ifndef AUDIO_EFFECT_COMPRESSOR_H +#define AUDIO_EFFECT_COMPRESSOR_H #include "servers/audio/audio_effect.h" @@ -91,4 +91,4 @@ public: AudioEffectCompressor(); }; -#endif // AUDIOEFFECTCOMPRESSOR_H +#endif // AUDIO_EFFECT_COMPRESSOR_H diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h index 5cc6d72c99..137a4e7dbe 100644 --- a/servers/audio/effects/audio_effect_delay.h +++ b/servers/audio/effects/audio_effect_delay.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTDELAY_H -#define AUDIOEFFECTDELAY_H +#ifndef AUDIO_EFFECT_DELAY_H +#define AUDIO_EFFECT_DELAY_H #include "servers/audio/audio_effect.h" @@ -131,4 +131,4 @@ public: AudioEffectDelay(); }; -#endif // AUDIOEFFECTDELAY_H +#endif // AUDIO_EFFECT_DELAY_H diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h index 487babbdda..c845a0e53c 100644 --- a/servers/audio/effects/audio_effect_distortion.h +++ b/servers/audio/effects/audio_effect_distortion.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTDISTORTION_H -#define AUDIOEFFECTDISTORTION_H +#ifndef AUDIO_EFFECT_DISTORTION_H +#define AUDIO_EFFECT_DISTORTION_H #include "servers/audio/audio_effect.h" @@ -90,4 +90,4 @@ public: VARIANT_ENUM_CAST(AudioEffectDistortion::Mode) -#endif // AUDIOEFFECTDISTORTION_H +#endif // AUDIO_EFFECT_DISTORTION_H diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index b7c373479a..500abd3a6f 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_effect_eq.h" + #include "servers/audio_server.h" void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h index 9b0560223f..b80fb7c73c 100644 --- a/servers/audio/effects/audio_effect_eq.h +++ b/servers/audio/effects/audio_effect_eq.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTEQ_H -#define AUDIOEFFECTEQ_H +#ifndef AUDIO_EFFECT_EQ_H +#define AUDIO_EFFECT_EQ_H #include "servers/audio/audio_effect.h" -#include "servers/audio/effects/eq.h" +#include "servers/audio/effects/eq_filter.h" class AudioEffectEQ; @@ -98,4 +98,4 @@ public: AudioEffectEQ(EQ::PRESET_21_BANDS) {} }; -#endif // AUDIOEFFECTEQ_H +#endif // AUDIO_EFFECT_EQ_H diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h index d5d58ddaa3..a40af2f13c 100644 --- a/servers/audio/effects/audio_effect_filter.h +++ b/servers/audio/effects/audio_effect_filter.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTFILTER_H -#define AUDIOEFFECTFILTER_H +#ifndef AUDIO_EFFECT_FILTER_H +#define AUDIO_EFFECT_FILTER_H #include "servers/audio/audio_effect.h" #include "servers/audio/audio_filter_sw.h" @@ -167,4 +167,4 @@ public: AudioEffectFilter(AudioFilterSW::HIGHSHELF) {} }; -#endif // AUDIOEFFECTFILTER_H +#endif // AUDIO_EFFECT_FILTER_H diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h index d05c9902af..3eca71a926 100644 --- a/servers/audio/effects/audio_effect_panner.h +++ b/servers/audio/effects/audio_effect_panner.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTPANNER_H -#define AUDIOEFFECTPANNER_H +#ifndef AUDIO_EFFECT_PANNER_H +#define AUDIO_EFFECT_PANNER_H #include "servers/audio/audio_effect.h" @@ -61,4 +61,4 @@ public: AudioEffectPanner(); }; -#endif // AUDIOEFFECTPANNER_H +#endif // AUDIO_EFFECT_PANNER_H diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index a6553e1431..fff6dbc32a 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -199,16 +199,16 @@ bool AudioEffectRecord::is_recording_active() const { return recording_active; } -void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) { +void AudioEffectRecord::set_format(AudioStreamWAV::Format p_format) { format = p_format; } -AudioStreamSample::Format AudioEffectRecord::get_format() const { +AudioStreamWAV::Format AudioEffectRecord::get_format() const { return format; } -Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { - AudioStreamSample::Format dst_format = format; +Ref<AudioStreamWAV> AudioEffectRecord::get_recording() const { + AudioStreamWAV::Format dst_format = format; bool stereo = true; //forcing mono is not implemented Vector<uint8_t> dst_data; @@ -216,7 +216,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { ERR_FAIL_COND_V(current_instance.is_null(), nullptr); ERR_FAIL_COND_V(current_instance->recording_data.size() == 0, nullptr); - if (dst_format == AudioStreamSample::FORMAT_8_BITS) { + if (dst_format == AudioStreamWAV::FORMAT_8_BITS) { int data_size = current_instance->recording_data.size(); dst_data.resize(data_size); uint8_t *w = dst_data.ptrw(); @@ -225,7 +225,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127); w[i] = v; } - } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) { + } else if (dst_format == AudioStreamWAV::FORMAT_16_BITS) { int data_size = current_instance->recording_data.size(); dst_data.resize(data_size * 2); uint8_t *w = dst_data.ptrw(); @@ -234,7 +234,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767); encode_uint16(v, &w[i * 2]); } - } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) { + } else if (dst_format == AudioStreamWAV::FORMAT_IMA_ADPCM) { //byte interleave Vector<float> left; Vector<float> right; @@ -273,12 +273,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { ERR_PRINT("Format not implemented."); } - Ref<AudioStreamSample> sample; + Ref<AudioStreamWAV> sample; sample.instantiate(); sample->set_data(dst_data); sample->set_format(dst_format); sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate()); - sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED); + sample->set_loop_mode(AudioStreamWAV::LOOP_DISABLED); sample->set_loop_begin(0); sample->set_loop_end(0); sample->set_stereo(stereo); @@ -297,6 +297,6 @@ void AudioEffectRecord::_bind_methods() { } AudioEffectRecord::AudioEffectRecord() { - format = AudioStreamSample::FORMAT_16_BITS; + format = AudioStreamWAV::FORMAT_16_BITS; recording_active = false; } diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h index 8a6247e27a..e89d8adbde 100644 --- a/servers/audio/effects/audio_effect_record.h +++ b/servers/audio/effects/audio_effect_record.h @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTRECORD_H -#define AUDIOEFFECTRECORD_H +#ifndef AUDIO_EFFECT_RECORD_H +#define AUDIO_EFFECT_RECORD_H #include "core/io/file_access.h" #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/os/thread.h" -#include "scene/resources/audio_stream_sample.h" +#include "scene/resources/audio_stream_wav.h" #include "servers/audio/audio_effect.h" #include "servers/audio_server.h" @@ -85,7 +85,7 @@ class AudioEffectRecord : public AudioEffect { bool recording_active; Ref<AudioEffectRecordInstance> current_instance; - AudioStreamSample::Format format; + AudioStreamWAV::Format format; void ensure_thread_stopped(); @@ -96,11 +96,11 @@ public: Ref<AudioEffectInstance> instantiate() override; void set_recording_active(bool p_record); bool is_recording_active() const; - void set_format(AudioStreamSample::Format p_format); - AudioStreamSample::Format get_format() const; - Ref<AudioStreamSample> get_recording() const; + void set_format(AudioStreamWAV::Format p_format); + AudioStreamWAV::Format get_format() const; + Ref<AudioStreamWAV> get_recording() const; AudioEffectRecord(); }; -#endif // AUDIOEFFECTRECORD_H +#endif // AUDIO_EFFECT_RECORD_H diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h index 90694c5492..a2c1fc5ea5 100644 --- a/servers/audio/effects/audio_effect_reverb.h +++ b/servers/audio/effects/audio_effect_reverb.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOEFFECTREVERB_H -#define AUDIOEFFECTREVERB_H +#ifndef AUDIO_EFFECT_REVERB_H +#define AUDIO_EFFECT_REVERB_H #include "servers/audio/audio_effect.h" -#include "servers/audio/effects/reverb.h" +#include "servers/audio/effects/reverb_filter.h" class AudioEffectReverb; @@ -94,4 +94,4 @@ public: AudioEffectReverb(); }; -#endif // AUDIOEFFECTREVERB_H +#endif // AUDIO_EFFECT_REVERB_H diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp index 46de1692e4..6365dacc80 100644 --- a/servers/audio/effects/audio_stream_generator.cpp +++ b/servers/audio/effects/audio_stream_generator.cpp @@ -46,7 +46,7 @@ float AudioStreamGenerator::get_buffer_length() const { return buffer_len; } -Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamGenerator::instantiate_playback() { Ref<AudioStreamGeneratorPlayback> playback; playback.instantiate(); playback->generator = this; @@ -196,6 +196,10 @@ void AudioStreamGeneratorPlayback::seek(float p_time) { //no seek possible } +void AudioStreamGeneratorPlayback::tag_used_streams() { + generator->tag_used(0); +} + void AudioStreamGeneratorPlayback::_bind_methods() { ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame); ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer); diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h index 2ce4b95fcf..a0bed0fda5 100644 --- a/servers/audio/effects/audio_stream_generator.h +++ b/servers/audio/effects/audio_stream_generator.h @@ -50,7 +50,7 @@ public: void set_buffer_length(float p_seconds); float get_buffer_length() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; virtual float get_length() const override; @@ -89,8 +89,11 @@ public: int get_frames_available() const; int get_skips() const; + virtual void tag_used_streams() override; + void clear_buffer(); AudioStreamGeneratorPlayback(); }; + #endif // AUDIO_STREAM_GENERATOR_H diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq_filter.cpp index 2123284b3b..6807e81cc4 100644 --- a/servers/audio/effects/eq.cpp +++ b/servers/audio/effects/eq_filter.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* eq.cpp */ +/* eq_filter.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -// Author: reduzio@gmail.com (C) 2006 +#include "eq_filter.h" -#include "eq.h" #include "core/error/error_macros.h" #include "core/math/math_funcs.h" + #include <math.h> #define POW2(v) ((v) * (v)) diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq_filter.h index d6293bf875..9dcad4dcea 100644 --- a/servers/audio/effects/eq.h +++ b/servers/audio/effects/eq_filter.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* eq.h */ +/* eq_filter.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb_filter.cpp index adfd648514..0363706714 100644 --- a/servers/audio/effects/reverb.cpp +++ b/servers/audio/effects/reverb_filter.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* reverb.cpp */ +/* reverb_filter.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "reverb.h" +#include "reverb_filter.h" #include "core/math/math_funcs.h" diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb_filter.h index c9602c5b5a..fe846fe2e7 100644 --- a/servers/audio/effects/reverb.h +++ b/servers/audio/effects/reverb_filter.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* reverb.h */ +/* reverb_filter.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REVERB_H -#define REVERB_H +#ifndef REVERB_FILTER_H +#define REVERB_FILTER_H #include "core/math/audio_frame.h" #include "core/os/memory.h" @@ -119,4 +119,4 @@ public: ~Reverb(); }; -#endif // REVERB_H +#endif // REVERB_FILTER_H diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 8ec3e469d3..9052f8e05e 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -39,7 +39,7 @@ #include "core/os/os.h" #include "core/string/string_name.h" #include "core/templates/pair.h" -#include "scene/resources/audio_stream_sample.h" +#include "scene/resources/audio_stream_wav.h" #include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" @@ -350,6 +350,10 @@ void AudioServer::_mix_step() { // Mix the audio stream unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size); + if (tag_used_audio_streams && playback->stream_playback->is_playing()) { + playback->stream_playback->tag_used_streams(); + } + if (mixed_frames != buffer_size) { // We know we have at least the size of our lookahead buffer for fade-out purposes. @@ -1312,6 +1316,10 @@ uint64_t AudioServer::get_mix_count() const { return mix_count; } +uint64_t AudioServer::get_mixed_frames() const { + return mix_frames; +} + void AudioServer::notify_listener_changed() { for (CallbackItem *ci : listener_changed_callback_list) { ci->callback(ci->userdata); @@ -1653,6 +1661,10 @@ void AudioServer::capture_set_device(const String &p_name) { AudioDriver::get_singleton()->capture_set_device(p_name); } +void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) { + tag_used_audio_streams = p_enable; +} + void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count); ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count); @@ -1719,6 +1731,8 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout); ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout); + ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device"); diff --git a/servers/audio_server.h b/servers/audio_server.h index 18e173ff0b..5613267909 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -43,7 +43,7 @@ class AudioDriverDummy; class AudioStream; -class AudioStreamSample; +class AudioStreamWAV; class AudioStreamPlayback; class AudioDriver { @@ -187,6 +187,8 @@ private: float playback_speed_scale = 1.0f; + bool tag_used_audio_streams = false; + struct Bus { StringName name; bool solo = false; @@ -380,6 +382,7 @@ public: bool is_playback_paused(Ref<AudioStreamPlayback> p_playback); uint64_t get_mix_count() const; + uint64_t get_mixed_frames() const; void notify_listener_changed(); @@ -424,6 +427,8 @@ public: String capture_get_device(); void capture_set_device(const String &p_name); + void set_enable_tagging_used_audio_streams(bool p_enable); + AudioServer(); virtual ~AudioServer(); }; diff --git a/servers/debugger/servers_debugger.h b/servers/debugger/servers_debugger.h index f949c436e7..be0e64fbc0 100644 --- a/servers/debugger/servers_debugger.h +++ b/servers/debugger/servers_debugger.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SERVER_DEBUGGER_H -#define SERVER_DEBUGGER_H +#ifndef SERVERS_DEBUGGER_H +#define SERVERS_DEBUGGER_H #include "core/debugger/debugger_marshalls.h" diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 59f88844e9..4e7db7d0a5 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -278,7 +278,7 @@ void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id Variant args[1]; args[0] = p_id; const Variant *argp[] = { &args[0] }; - utterance_callback[p_event].call_deferred(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession. + utterance_callback[p_event].call_deferredp(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession. } } break; case DisplayServer::TTS_UTTERANCE_BOUNDARY: { @@ -287,7 +287,7 @@ void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id args[0] = p_pos; args[1] = p_id; const Variant *argp[] = { &args[0], &args[1] }; - utterance_callback[p_event].call_deferred(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession. + utterance_callback[p_event].call_deferredp(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession. } } break; default: @@ -400,7 +400,7 @@ String DisplayServer::ime_get_text() const { ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server."); } -void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) { +void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) { WARN_PRINT("Virtual keyboard not supported by this display server."); } @@ -494,11 +494,11 @@ int64_t DisplayServer::window_get_native_handle(HandleType p_handle_type, Window } void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { - WARN_PRINT("Changing the VSync mode is not supported by this display server."); + WARN_PRINT("Changing the V-Sync mode is not supported by this display server."); } DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const { - WARN_PRINT("Changing the VSync mode is not supported by this display server."); + WARN_PRINT("Changing the V-Sync mode is not supported by this display server."); return VSyncMode::VSYNC_ENABLED; } @@ -660,7 +660,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); - ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "type", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(KEYBOARD_TYPE_DEFAULT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide); ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height); @@ -732,6 +732,15 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(SCREEN_SENSOR_PORTRAIT); BIND_ENUM_CONSTANT(SCREEN_SENSOR); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL); + BIND_ENUM_CONSTANT(CURSOR_ARROW); BIND_ENUM_CONSTANT(CURSOR_IBEAM); BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND); diff --git a/servers/display_server.h b/servers/display_server.h index 7a15df2f92..8632b53f7b 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -382,7 +382,18 @@ public: virtual Point2i ime_get_selection() const; virtual String ime_get_text() const; - virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + }; + + virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void virtual_keyboard_hide(); // returns height of the currently shown virtual keyboard (0 if keyboard is hidden) @@ -467,6 +478,7 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation) VARIANT_ENUM_CAST(DisplayServer::WindowMode) VARIANT_ENUM_CAST(DisplayServer::WindowFlags) VARIANT_ENUM_CAST(DisplayServer::HandleType) +VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType); VARIANT_ENUM_CAST(DisplayServer::CursorShape) VARIANT_ENUM_CAST(DisplayServer::VSyncMode) VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent) diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index 663af1ae6c..c4b4a00eaf 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -545,4 +545,4 @@ public: ~PhysicsServer3DExtension(); }; -#endif // PHYSICSSERVER3DEXTENSION_H +#endif // PHYSICS_SERVER_3D_EXTENSION_H diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp index 9f96b8cfda..40b2b2539e 100644 --- a/servers/movie_writer/movie_writer.cpp +++ b/servers/movie_writer/movie_writer.cpp @@ -30,6 +30,9 @@ #include "movie_writer.h" #include "core/config/project_settings.h" +#include "core/io/dir_access.h" +#include "core/os/time.h" +#include "servers/display_server.h" MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS]; uint32_t MovieWriter::writer_count = 0; @@ -101,6 +104,7 @@ void MovieWriter::get_supported_extensions(List<String> *r_extensions) const { } void MovieWriter::begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) { + project_name = GLOBAL_GET("application/config/name"); mix_rate = get_audio_mix_rate(); AudioDriverDummy::get_dummy_singleton()->set_mix_rate(mix_rate); AudioDriverDummy::get_dummy_singleton()->set_speaker_mode(AudioDriver::SpeakerMode(get_audio_speaker_mode())); @@ -162,10 +166,47 @@ void MovieWriter::set_extensions_hint() { } void MovieWriter::add_frame(const Ref<Image> &p_image) { + const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps; + const String movie_time = vformat("%s:%s:%s", + String::num(movie_time_seconds / 3600).pad_zeros(2), + String::num((movie_time_seconds % 3600) / 60).pad_zeros(2), + String::num(movie_time_seconds % 60).pad_zeros(2)); + +#ifdef DEBUG_ENABLED + DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s (DEBUG)", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name)); +#else + DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name)); +#endif + AudioDriverDummy::get_dummy_singleton()->mix_audio(mix_rate / fps, audio_mix_buffer.ptr()); write_frame(p_image, audio_mix_buffer.ptr()); } void MovieWriter::end() { write_end(); + + // Print a report with various statistics. + print_line("----------------"); + String movie_path = Engine::get_singleton()->get_write_movie_path(); + if (movie_path.is_relative_path()) { + // Print absolute path to make finding the file easier, + // and to make it clickable in terminal emulators that support this. + movie_path = ProjectSettings::get_singleton()->globalize_path("res://").plus_file(movie_path); + } + print_line(vformat("Done recording movie at path: %s", movie_path)); + + const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps; + const String movie_time = vformat("%s:%s:%s", + String::num(movie_time_seconds / 3600).pad_zeros(2), + String::num((movie_time_seconds % 3600) / 60).pad_zeros(2), + String::num(movie_time_seconds % 60).pad_zeros(2)); + + const int real_time_seconds = Time::get_singleton()->get_ticks_msec() / 1000; + const String real_time = vformat("%s:%s:%s", + String::num(real_time_seconds / 3600).pad_zeros(2), + String::num((real_time_seconds % 3600) / 60).pad_zeros(2), + String::num(real_time_seconds % 60).pad_zeros(2)); + + print_line(vformat("%d frames at %d FPS (movie length: %s), recorded in %s (%d%% of real-time speed).", Engine::get_singleton()->get_frames_drawn(), fps, movie_time, real_time, (float(movie_time_seconds) / real_time_seconds) * 100)); + print_line("----------------"); } diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h index 1ec6e93052..7877a60715 100644 --- a/servers/movie_writer/movie_writer.h +++ b/servers/movie_writer/movie_writer.h @@ -42,6 +42,8 @@ class MovieWriter : public Object { uint64_t mix_rate = 0; uint32_t audio_channels = 0; + String project_name; + LocalVector<int32_t> audio_mix_buffer; enum { diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 6c48c4a8de..52855c5931 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -30,6 +30,10 @@ #include "navigation_server_3d.h" +#ifdef DEBUG_ENABLED +#include "core/config/project_settings.h" +#endif // DEBUG_ENABLED + NavigationServer3D *NavigationServer3D::singleton = nullptr; void NavigationServer3D::_bind_methods() { @@ -92,6 +96,8 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process); ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map"))); + + ADD_SIGNAL(MethodInfo("navigation_debug_changed")); } const NavigationServer3D *NavigationServer3D::get_singleton() { @@ -105,6 +111,19 @@ NavigationServer3D *NavigationServer3D::get_singleton_mut() { NavigationServer3D::NavigationServer3D() { ERR_FAIL_COND(singleton != nullptr); singleton = this; + +#ifdef DEBUG_ENABLED + debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0)); + debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0)); + debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4)); + debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0)); + debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4)); + debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true); + debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true); + debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true); + debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true); + debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true); +#endif // DEBUG_ENABLED } NavigationServer3D::~NavigationServer3D() { @@ -121,3 +140,241 @@ NavigationServer3D *NavigationServer3DManager::new_default_server() { ERR_FAIL_COND_V(create_callback == nullptr, nullptr); return create_callback(); } + +#ifdef DEBUG_ENABLED +void NavigationServer3D::_emit_navigation_debug_changed_signal() { + if (debug_dirty) { + debug_dirty = false; + emit_signal(SNAME("navigation_debug_changed")); + } +} +#endif // DEBUG_ENABLED + +#ifdef DEBUG_ENABLED +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_material() { + if (debug_navigation_geometry_face_material.is_valid()) { + return debug_navigation_geometry_face_material; + } + + bool enabled_geometry_face_random_color = get_debug_navigation_enable_geometry_face_random_color(); + + Color debug_navigation_geometry_face_color = get_debug_navigation_geometry_face_color(); + + Ref<StandardMaterial3D> face_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + face_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + face_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + face_material->set_albedo(debug_navigation_geometry_face_color); + if (enabled_geometry_face_random_color) { + face_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + face_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } + + debug_navigation_geometry_face_material = face_material; + + return debug_navigation_geometry_face_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_material() { + if (debug_navigation_geometry_edge_material.is_valid()) { + return debug_navigation_geometry_edge_material; + } + + bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray(); + + Color debug_navigation_geometry_edge_color = get_debug_navigation_geometry_edge_color(); + + Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_material->set_albedo(debug_navigation_geometry_edge_color); + if (enabled_edge_lines_xray) { + line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + + debug_navigation_geometry_edge_material = line_material; + + return debug_navigation_geometry_edge_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_disabled_material() { + if (debug_navigation_geometry_face_disabled_material.is_valid()) { + return debug_navigation_geometry_face_disabled_material; + } + + Color debug_navigation_geometry_face_disabled_color = get_debug_navigation_geometry_face_disabled_color(); + + Ref<StandardMaterial3D> face_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + face_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + face_disabled_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + face_disabled_material->set_albedo(debug_navigation_geometry_face_disabled_color); + + debug_navigation_geometry_face_disabled_material = face_disabled_material; + + return debug_navigation_geometry_face_disabled_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_disabled_material() { + if (debug_navigation_geometry_edge_disabled_material.is_valid()) { + return debug_navigation_geometry_edge_disabled_material; + } + + bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray(); + + Color debug_navigation_geometry_edge_disabled_color = get_debug_navigation_geometry_edge_disabled_color(); + + Ref<StandardMaterial3D> line_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_disabled_material->set_albedo(debug_navigation_geometry_edge_disabled_color); + if (enabled_edge_lines_xray) { + line_disabled_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + + debug_navigation_geometry_edge_disabled_material = line_disabled_material; + + return debug_navigation_geometry_edge_disabled_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_edge_connections_material() { + if (debug_navigation_edge_connections_material.is_valid()) { + return debug_navigation_edge_connections_material; + } + + bool enabled_edge_connections_xray = get_debug_navigation_enable_edge_connections_xray(); + + Color debug_navigation_edge_connection_color = get_debug_navigation_edge_connection_color(); + + Ref<StandardMaterial3D> edge_connections_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + edge_connections_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + edge_connections_material->set_albedo(debug_navigation_edge_connection_color); + if (enabled_edge_connections_xray) { + edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + edge_connections_material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2); + + debug_navigation_edge_connections_material = edge_connections_material; + + return debug_navigation_edge_connections_material; +} + +void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) { + debug_navigation_edge_connection_color = p_color; + if (debug_navigation_edge_connections_material.is_valid()) { + debug_navigation_edge_connections_material->set_albedo(debug_navigation_edge_connection_color); + } +} + +Color NavigationServer3D::get_debug_navigation_edge_connection_color() const { + return debug_navigation_edge_connection_color; +} + +void NavigationServer3D::set_debug_navigation_geometry_edge_color(const Color &p_color) { + debug_navigation_geometry_edge_color = p_color; + if (debug_navigation_geometry_edge_material.is_valid()) { + debug_navigation_geometry_edge_material->set_albedo(debug_navigation_geometry_edge_color); + } +} + +Color NavigationServer3D::get_debug_navigation_geometry_edge_color() const { + return debug_navigation_geometry_edge_color; +} + +void NavigationServer3D::set_debug_navigation_geometry_face_color(const Color &p_color) { + debug_navigation_geometry_face_color = p_color; + if (debug_navigation_geometry_face_material.is_valid()) { + debug_navigation_geometry_face_material->set_albedo(debug_navigation_geometry_face_color); + } +} + +Color NavigationServer3D::get_debug_navigation_geometry_face_color() const { + return debug_navigation_geometry_face_color; +} + +void NavigationServer3D::set_debug_navigation_geometry_edge_disabled_color(const Color &p_color) { + debug_navigation_geometry_edge_disabled_color = p_color; + if (debug_navigation_geometry_edge_disabled_material.is_valid()) { + debug_navigation_geometry_edge_disabled_material->set_albedo(debug_navigation_geometry_edge_disabled_color); + } +} + +Color NavigationServer3D::get_debug_navigation_geometry_edge_disabled_color() const { + return debug_navigation_geometry_edge_disabled_color; +} + +void NavigationServer3D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) { + debug_navigation_geometry_face_disabled_color = p_color; + if (debug_navigation_geometry_face_disabled_material.is_valid()) { + debug_navigation_geometry_face_disabled_material->set_albedo(debug_navigation_geometry_face_disabled_color); + } +} + +Color NavigationServer3D::get_debug_navigation_geometry_face_disabled_color() const { + return debug_navigation_geometry_face_disabled_color; +} + +void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) { + debug_navigation_enable_edge_connections = p_value; + debug_dirty = true; + call_deferred("_emit_navigation_debug_changed_signal"); +} + +bool NavigationServer3D::get_debug_navigation_enable_edge_connections() const { + return debug_navigation_enable_edge_connections; +} + +void NavigationServer3D::set_debug_navigation_enable_edge_connections_xray(const bool p_value) { + debug_navigation_enable_edge_connections_xray = p_value; + if (debug_navigation_edge_connections_material.is_valid()) { + debug_navigation_edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_connections_xray); + } +} + +bool NavigationServer3D::get_debug_navigation_enable_edge_connections_xray() const { + return debug_navigation_enable_edge_connections_xray; +} + +void NavigationServer3D::set_debug_navigation_enable_edge_lines(const bool p_value) { + debug_navigation_enable_edge_lines = p_value; + debug_dirty = true; + call_deferred("_emit_navigation_debug_changed_signal"); +} + +bool NavigationServer3D::get_debug_navigation_enable_edge_lines() const { + return debug_navigation_enable_edge_lines; +} + +void NavigationServer3D::set_debug_navigation_enable_edge_lines_xray(const bool p_value) { + debug_navigation_enable_edge_lines_xray = p_value; + if (debug_navigation_geometry_edge_material.is_valid()) { + debug_navigation_geometry_edge_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_lines_xray); + } +} + +bool NavigationServer3D::get_debug_navigation_enable_edge_lines_xray() const { + return debug_navigation_enable_edge_lines_xray; +} + +void NavigationServer3D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) { + debug_navigation_enable_geometry_face_random_color = p_value; + debug_dirty = true; + call_deferred("_emit_navigation_debug_changed_signal"); +} + +bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color() const { + return debug_navigation_enable_geometry_face_random_color; +} + +void NavigationServer3D::set_debug_enabled(bool p_enabled) { + if (debug_enabled != p_enabled) { + debug_dirty = true; + } + + debug_enabled = p_enabled; + + if (debug_dirty) { + call_deferred("_emit_navigation_debug_changed_signal"); + } +} + +bool NavigationServer3D::get_debug_enabled() const { + return debug_enabled; +} +#endif // DEBUG_ENABLED diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index cf91596604..f24c0117d1 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -207,6 +207,68 @@ public: NavigationServer3D(); virtual ~NavigationServer3D(); + +#ifdef DEBUG_ENABLED + bool debug_enabled = false; + bool debug_dirty = true; + void _emit_navigation_debug_changed_signal(); + + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; + + Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0); + Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0); + Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4); + Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0); + Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4); + bool debug_navigation_enable_edge_connections = true; + bool debug_navigation_enable_edge_connections_xray = true; + bool debug_navigation_enable_edge_lines = true; + bool debug_navigation_enable_edge_lines_xray = true; + bool debug_navigation_enable_geometry_face_random_color = true; + + Ref<StandardMaterial3D> debug_navigation_geometry_edge_material; + Ref<StandardMaterial3D> debug_navigation_geometry_face_material; + Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material; + Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material; + Ref<StandardMaterial3D> debug_navigation_edge_connections_material; + + void set_debug_navigation_edge_connection_color(const Color &p_color); + Color get_debug_navigation_edge_connection_color() const; + + void set_debug_navigation_geometry_edge_color(const Color &p_color); + Color get_debug_navigation_geometry_edge_color() const; + + void set_debug_navigation_geometry_face_color(const Color &p_color); + Color get_debug_navigation_geometry_face_color() const; + + void set_debug_navigation_geometry_edge_disabled_color(const Color &p_color); + Color get_debug_navigation_geometry_edge_disabled_color() const; + + void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); + Color get_debug_navigation_geometry_face_disabled_color() const; + + void set_debug_navigation_enable_edge_connections(const bool p_value); + bool get_debug_navigation_enable_edge_connections() const; + + void set_debug_navigation_enable_edge_connections_xray(const bool p_value); + bool get_debug_navigation_enable_edge_connections_xray() const; + + void set_debug_navigation_enable_edge_lines(const bool p_value); + bool get_debug_navigation_enable_edge_lines() const; + + void set_debug_navigation_enable_edge_lines_xray(const bool p_value); + bool get_debug_navigation_enable_edge_lines_xray() const; + + void set_debug_navigation_enable_geometry_face_random_color(const bool p_value); + bool get_debug_navigation_enable_geometry_face_random_color() const; + + Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material(); + Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material(); + Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material(); + Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material(); + Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material(); +#endif // DEBUG_ENABLED }; typedef NavigationServer3D *(*NavigationServer3DCallback)(); diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 11208f2d5b..af90f96438 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -247,7 +247,11 @@ void GodotArea2D::call_queries() { Callable::CallError ce; Variant ret; - monitor_callback.call((const Variant **)resptr, 5, ret, ce); + monitor_callback.callp((const Variant **)resptr, 5, ret, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce)); + } } } else { monitored_bodies.clear(); @@ -285,7 +289,11 @@ void GodotArea2D::call_queries() { Callable::CallError ce; Variant ret; - area_monitor_callback.call((const Variant **)resptr, 5, ret, ce); + area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce)); + } } } else { monitored_areas.clear(); diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 6873504f70..268beb1a55 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -683,10 +683,10 @@ void GodotBody2D::call_queries() { Callable::CallError ce; Variant rv; if (fi_callback_data->udata.get_type() != Variant::NIL) { - fi_callback_data->callable.call(vp, 2, rv, ce); + fi_callback_data->callable.callp(vp, 2, rv, ce); } else { - fi_callback_data->callable.call(vp, 1, rv, ce); + fi_callback_data->callable.callp(vp, 1, rv, ce); } } } diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 551fd9329f..0603458acd 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -239,7 +239,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) { /* SETUP CONSTRAINTS / PROCESS COLLISIONS */ uint32_t total_contraint_count = all_constraints.size(); - work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics2DConstraintSetup")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); @@ -258,7 +259,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) { // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); + group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics2DConstraintSolveIslands")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); @@ -297,10 +299,7 @@ GodotStep2D::GodotStep2D() { body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); constraint_islands.reserve(ISLAND_COUNT_RESERVE); all_constraints.reserve(CONSTRAINT_COUNT_RESERVE); - - work_pool.init(); } GodotStep2D::~GodotStep2D() { - work_pool.finish(); } diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h index 9a6d8caf9b..9f8fdd6ce3 100644 --- a/servers/physics_2d/godot_step_2d.h +++ b/servers/physics_2d/godot_step_2d.h @@ -33,8 +33,8 @@ #include "godot_space_2d.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" -#include "core/templates/thread_work_pool.h" class GodotStep2D { uint64_t _step = 1; @@ -42,8 +42,6 @@ class GodotStep2D { int iterations = 0; real_t delta = 0.0; - ThreadWorkPool work_pool; - LocalVector<LocalVector<GodotBody2D *>> body_islands; LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands; LocalVector<GodotConstraint2D *> all_constraints; diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h index 01a47f222e..309af76561 100644 --- a/servers/physics_3d/gjk_epa.h +++ b/servers/physics_3d/gjk_epa.h @@ -37,4 +37,4 @@ bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0); bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B); -#endif +#endif // GJK_EPA_H diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index e2ad765d62..9765d0bf58 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -276,7 +276,11 @@ void GodotArea3D::call_queries() { Callable::CallError ce; Variant ret; - monitor_callback.call((const Variant **)resptr, 5, ret, ce); + monitor_callback.callp((const Variant **)resptr, 5, ret, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT_ONCE("Error calling monitor callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce)); + } } } else { monitored_bodies.clear(); @@ -314,7 +318,11 @@ void GodotArea3D::call_queries() { Callable::CallError ce; Variant ret; - area_monitor_callback.call((const Variant **)resptr, 5, ret, ce); + area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT_ONCE("Error calling area monitor callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce)); + } } } else { monitored_areas.clear(); diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index ad97533f44..4c89106839 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -766,7 +766,7 @@ void GodotBody3D::call_queries() { Callable::CallError ce; int argc = (fi_callback_data->udata.get_type() == Variant::NIL) ? 1 : 2; Variant rv; - fi_callback_data->callable.call(vp, argc, rv, ce); + fi_callback_data->callable.callp(vp, argc, rv, ce); } } diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h index 3eb7aa4c9e..46c5ec3254 100644 --- a/servers/physics_3d/godot_collision_solver_3d_sat.h +++ b/servers/physics_3d/godot_collision_solver_3d_sat.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_COLLISION_SOLVER_SAT_H -#define GODOT_COLLISION_SOLVER_SAT_H +#ifndef GODOT_COLLISION_SOLVER_3D_SAT_H +#define GODOT_COLLISION_SOLVER_3D_SAT_H #include "godot_collision_solver_3d.h" bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0); -#endif // GODOT_COLLISION_SOLVER_SAT_H +#endif // GODOT_COLLISION_SOLVER_3D_SAT_H diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 99656d01a0..f384c829a4 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -343,7 +343,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) { /* SETUP CONSTRAINTS / PROCESS COLLISIONS */ uint32_t total_contraint_count = all_constraints.size(); - work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics3DConstraintSetup")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); @@ -362,7 +363,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) { // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); + group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics3DConstraintSolveIslands")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); @@ -409,10 +411,7 @@ GodotStep3D::GodotStep3D() { body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); constraint_islands.reserve(ISLAND_COUNT_RESERVE); all_constraints.reserve(CONSTRAINT_COUNT_RESERVE); - - work_pool.init(); } GodotStep3D::~GodotStep3D() { - work_pool.finish(); } diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h index 6d975b0dd3..189487757f 100644 --- a/servers/physics_3d/godot_step_3d.h +++ b/servers/physics_3d/godot_step_3d.h @@ -33,8 +33,8 @@ #include "godot_space_3d.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" -#include "core/templates/thread_work_pool.h" class GodotStep3D { uint64_t _step = 1; @@ -42,8 +42,6 @@ class GodotStep3D { int iterations = 0; real_t delta = 0.0; - ThreadWorkPool work_pool; - LocalVector<LocalVector<GodotBody3D *>> body_islands; LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands; LocalVector<GodotConstraint3D *> all_constraints; diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 41aae36785..26768e300c 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -147,6 +147,16 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// +Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) { + Ref<PhysicsRayQueryParameters2D> params; + params.instantiate(); + params->set_from(p_from); + params->set_to(p_to); + params->set_collision_mask(p_mask); + params->set_exclude(p_exclude); + return params; +} + void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { @@ -165,6 +175,8 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { } void PhysicsRayQueryParameters2D::_bind_methods() { + ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>())); + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from); ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 7a821c64e6..6d95c591c2 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -605,6 +605,7 @@ protected: static void _bind_methods(); public: + static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude); const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; } void set_from(const Vector2 &p_from) { parameters.from = p_from; } diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index a606d055f7..f25db22e66 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -184,6 +184,8 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const { } void PhysicsRayQueryParameters3D::_bind_methods() { + ClassDB::bind_static_method("PhysicsRayQueryParameters3D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters3D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>())); + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from); ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from); @@ -220,6 +222,16 @@ void PhysicsRayQueryParameters3D::_bind_methods() { /////////////////////////////////////////////////////// +Ref<PhysicsRayQueryParameters3D> PhysicsRayQueryParameters3D::create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) { + Ref<PhysicsRayQueryParameters3D> params; + params.instantiate(); + params->set_from(p_from); + params->set_to(p_to); + params->set_collision_mask(p_mask); + params->set_exclude(p_exclude); + return params; +} + void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 86a41d96ef..837073409a 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -816,6 +816,7 @@ protected: static void _bind_methods(); public: + static Ref<PhysicsRayQueryParameters3D> create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude); const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; } void set_from(const Vector3 &p_from) { parameters.from = p_from; } diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h index 8a2be90507..623f94b95f 100644 --- a/servers/rendering/dummy/environment/fog.h +++ b/servers/rendering/dummy/environment/fog.h @@ -52,4 +52,4 @@ public: } // namespace RendererDummy -#endif // !FOG_DUMMY_H +#endif // FOG_DUMMY_H diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h index 9c7647c2de..76d34cd14e 100644 --- a/servers/rendering/dummy/environment/gi.h +++ b/servers/rendering/dummy/environment/gi.h @@ -79,4 +79,4 @@ public: } // namespace RendererDummy -#endif // !GI_DUMMY_H +#endif // GI_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h index 194b5b5cfe..64c4cf5024 100644 --- a/servers/rendering/dummy/rasterizer_canvas_dummy.h +++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h @@ -60,4 +60,4 @@ public: ~RasterizerCanvasDummy() {} }; -#endif // !RASTERIZER_CANVAS_DUMMY_H +#endif // RASTERIZER_CANVAS_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index e6d2b93f99..be98770b90 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -35,33 +35,10 @@ class RasterizerSceneDummy : public RendererSceneRender { public: - GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} + RenderGeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } + void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {} uint32_t geometry_instance_get_pair_mask() override { return 0; } - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} /* SHADOW ATLAS API */ @@ -92,49 +69,24 @@ public: /* ENVIRONMENT API */ - RID environment_allocate() override { return RID(); } - void environment_initialize(RID p_rid) override {} - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} - void environment_set_sky(RID p_env, RID p_sky) override {} - void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} - void environment_set_bg_color(RID p_env, const Color &p_color) override {} - void environment_set_bg_energy(RID p_env, float p_energy) override {} - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} void environment_glow_set_use_high_quality(bool p_enable) override {} - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} void environment_set_volumetric_fog_filter_active(bool p_enable) override {} Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - bool is_environment(RID p_env) const override { return false; } - RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } - int environment_get_canvas_max_layer(RID p_env) const override { return 0; } - RID camera_effects_allocate() override { return RID(); } void camera_effects_initialize(RID p_rid) override {} void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} @@ -143,13 +95,13 @@ public: void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} - void shadows_quality_set(RS::ShadowQuality p_quality) override {} - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} + void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {} + void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {} RID light_instance_create(RID p_light) override { return RID(); } void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} + void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} void light_instance_mark_visible(RID p_light_instance) override {} RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } @@ -179,20 +131,20 @@ public: RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} bool voxel_gi_needs_update(RID p_probe) const override { return false; } - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override {} void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} + void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {} void set_scene_pass(uint64_t p_pass) override {} void set_time(double p_time, double p_step) override {} void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {} + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {} void gi_set_use_half_resolution(bool p_enable) override {} void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} @@ -203,7 +155,14 @@ public: TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } - bool free(RID p_rid) override { return false; } + bool free(RID p_rid) override { + if (is_environment(p_rid)) { + environment_free(p_rid); + return true; + } else { + return false; + } + } void update() override {} void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} @@ -214,4 +173,4 @@ public: ~RasterizerSceneDummy() {} }; -#endif // !RASTERIZER_SCENE_DUMMY_H +#endif // RASTERIZER_SCENE_DUMMY_H diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index b0100a5fe7..0c0ea61df5 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -132,4 +132,4 @@ public: } // namespace RendererDummy -#endif // !LIGHT_STORAGE_DUMMY_H +#endif // LIGHT_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h index d4809f81e3..e25a2ac3a9 100644 --- a/servers/rendering/dummy/storage/material_storage.h +++ b/servers/rendering/dummy/storage/material_storage.h @@ -38,23 +38,23 @@ namespace RendererDummy { class MaterialStorage : public RendererMaterialStorage { public: - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {} - virtual void global_variable_remove(const StringName &p_name) override {} - virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); } + virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override {} + virtual void global_shader_uniform_remove(const StringName &p_name) override {} + virtual Vector<StringName> global_shader_uniform_get_list() const override { return Vector<StringName>(); } - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {} - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {} - virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); } - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override {} + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override {} + virtual Variant global_shader_uniform_get(const StringName &p_name) const override { return Variant(); } + virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } - virtual void global_variables_load_settings(bool p_load_textures = true) override {} - virtual void global_variables_clear() override {} + virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override {} + virtual void global_shader_uniforms_clear() override {} - virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; } - virtual void global_variables_instance_free(RID p_instance) override {} - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} + virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override { return 0; } + virtual void global_shader_uniforms_instance_free(RID p_instance) override {} + virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} /* SHADER API */ @@ -63,8 +63,10 @@ public: virtual void shader_free(RID p_rid) override{}; virtual void shader_set_code(RID p_shader, const String &p_code) override {} + virtual void shader_set_path_hint(RID p_shader, const String &p_code) override {} + virtual String shader_get_code(RID p_shader) const override { return ""; } - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} + virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } @@ -87,10 +89,10 @@ public: virtual bool material_is_animated(RID p_material) override { return false; } virtual bool material_casts_shadows(RID p_material) override { return false; } - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} + virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override {} virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {} }; } // namespace RendererDummy -#endif // !MATERIAL_STORAGE_DUMMY_H +#endif // MATERIAL_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 78b19d721d..aab5145982 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -37,17 +37,44 @@ namespace RendererDummy { class MeshStorage : public RendererMeshStorage { +private: + struct DummyMesh : public RID { + Vector<RS::SurfaceData> surfaces; + int blend_shape_count; + RS::BlendShapeMode blend_shape_mode; + PackedFloat32Array blend_shape_values; + }; + + mutable RID_Owner<DummyMesh> mesh_owner; + public: /* MESH API */ - virtual RID mesh_allocate() override { return RID(); } - virtual void mesh_initialize(RID p_rid) override {} + virtual RID mesh_allocate() override { + return mesh_owner.allocate_rid(); + } + + virtual void mesh_initialize(RID p_rid) override { + mesh_owner.initialize_rid(p_rid, DummyMesh()); + } virtual void mesh_free(RID p_rid) override {} virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!m); + m->surfaces.push_back(RS::SurfaceData()); + RS::SurfaceData *s = &m->surfaces.write[m->surfaces.size() - 1]; + s->format = p_surface.format; + s->primitive = p_surface.primitive; + s->vertex_data = p_surface.vertex_data; + s->attribute_data = p_surface.attribute_data; + s->vertex_count = p_surface.vertex_count; + s->index_data = p_surface.index_data; + s->index_count = p_surface.index_count; + } virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } @@ -61,8 +88,19 @@ public: virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } - virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; } + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!m, RS::SurfaceData()); + RS::SurfaceData s = m->surfaces[p_surface]; + return s; + } + + virtual int mesh_get_surface_count(RID p_mesh) const override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!m, 0); + print_line(m->surfaces.size()); + return m->surfaces.size(); + } virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } @@ -131,4 +169,4 @@ public: } // namespace RendererDummy -#endif // !MESH_STORAGE_DUMMY_H +#endif // MESH_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h index f614b41c4c..7cee55922d 100644 --- a/servers/rendering/dummy/storage/particles_storage.h +++ b/servers/rendering/dummy/storage/particles_storage.h @@ -123,4 +123,4 @@ public: } // namespace RendererDummy -#endif // !PARTICLES_STORAGE_DUMMY_H +#endif // PARTICLES_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index fe10f6489c..73b1284558 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -169,8 +169,11 @@ public: virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {} virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); } virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {} + + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{}; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{}; }; } // namespace RendererDummy -#endif // !TEXTURE_STORAGE_DUMMY_H +#endif // TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h index f090309e88..b94f678c75 100644 --- a/servers/rendering/dummy/storage/utilities.h +++ b/servers/rendering/dummy/storage/utilities.h @@ -95,4 +95,4 @@ public: } // namespace RendererDummy -#endif // !UTILITIES_DUMMY_H +#endif // UTILITIES_DUMMY_H diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h index ac50da0fc0..c55021e1a1 100644 --- a/servers/rendering/environment/renderer_fog.h +++ b/servers/rendering/environment/renderer_fog.h @@ -50,4 +50,4 @@ public: virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0; }; -#endif // !RENDERER_FOG_H +#endif // RENDERER_FOG_H diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h index 4f93bb8675..70d2bb3a9c 100644 --- a/servers/rendering/environment/renderer_gi.h +++ b/servers/rendering/environment/renderer_gi.h @@ -78,4 +78,4 @@ public: virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0; }; -#endif // !RENDERER_GI_H +#endif // RENDERER_GI_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index dea68ac61c..86e5e4802b 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -605,9 +605,13 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, } if (p_antialiased) { - float border_size = 2.0; - if (p_width < border_size) { - border_size = p_width; + // Use the same antialiasing feather size as StyleBoxFlat's default + // (but doubled, as it's specified for both sides here). + // This value is empirically determined to provide good antialiasing quality + // while not making lines appear too soft. + float border_size = 1.25f; + if (p_width < 1.0f) { + border_size *= p_width; } Vector2 dir2 = diff.normalized(); @@ -774,9 +778,13 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point Color *colors_ptr = colors.ptrw(); if (p_antialiased) { - float border_size = 2.0; - if (p_width < border_size) { - border_size = p_width; + // Use the same antialiasing feather size as StyleBoxFlat's default + // (but doubled, as it's specified for both sides here). + // This value is empirically determined to provide good antialiasing quality + // while not making lines appear too soft. + float border_size = 1.25f; + if (p_width < 1.0f) { + border_size *= p_width; } Color color2 = Color(1, 1, 1, 0); @@ -1906,11 +1914,11 @@ void RendererCanvasCull::update_visibility_notifiers() { if (!visibility_notifier->enter_callable.is_null()) { if (RSG::threaded) { - visibility_notifier->enter_callable.call_deferred(nullptr, 0); + visibility_notifier->enter_callable.call_deferredp(nullptr, 0); } else { Callable::CallError ce; Variant ret; - visibility_notifier->enter_callable.call(nullptr, 0, ret, ce); + visibility_notifier->enter_callable.callp(nullptr, 0, ret, ce); } } } else { @@ -1919,11 +1927,11 @@ void RendererCanvasCull::update_visibility_notifiers() { if (!visibility_notifier->exit_callable.is_null()) { if (RSG::threaded) { - visibility_notifier->exit_callable.call_deferred(nullptr, 0); + visibility_notifier->exit_callable.call_deferredp(nullptr, 0); } else { Callable::CallError ce; Variant ret; - visibility_notifier->exit_callable.call(nullptr, 0, ret, ce); + visibility_notifier->exit_callable.callp(nullptr, 0, ret, ce); } } } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 48d0598c9f..e8c54310c9 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_CANVAS_CULL_H -#define RENDERING_SERVER_CANVAS_CULL_H +#ifndef RENDERER_CANVAS_CULL_H +#define RENDERER_CANVAS_CULL_H #include "core/templates/paged_allocator.h" #include "renderer_compositor.h" @@ -317,4 +317,4 @@ public: ~RendererCanvasCull(); }; -#endif // RENDERING_SERVER_CANVAS_CULL_H +#endif // RENDERER_CANVAS_CULL_H diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp index f93fdd500a..623f0c647b 100644 --- a/servers/rendering/renderer_canvas_render.cpp +++ b/servers/rendering/renderer_canvas_render.cpp @@ -131,6 +131,6 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const { RendererCanvasRender::Item::CommandMesh::~CommandMesh() { if (mesh_instance.is_valid()) { - RSG::mesh_storage->mesh_free(mesh_instance); + RSG::mesh_storage->mesh_instance_free(mesh_instance); } } diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 52b2f82089..11a7d34291 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERINGSERVERCANVASRENDER_H -#define RENDERINGSERVERCANVASRENDER_H +#ifndef RENDERER_CANVAS_RENDER_H +#define RENDERER_CANVAS_RENDER_H #include "servers/rendering_server.h" @@ -77,7 +77,7 @@ public: Rect2 rect_cache; Transform2D xform_cache; float radius_cache; //used for shadow far plane - //CameraMatrix shadow_matrix_cache; + //Projection shadow_matrix_cache; Transform2D light_shader_xform; //Vector2 light_shader_pos; @@ -520,4 +520,4 @@ public: virtual ~RendererCanvasRender() {} }; -#endif // RENDERINGSERVERCANVASRENDER_H +#endif // RENDERER_CANVAS_RENDER_H diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index b331ec2c1d..80e71a0df3 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" #include "core/string/print_string.h" +#include "servers/xr_server.h" RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; bool RendererCompositor::low_end = false; @@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const { } RendererCompositor::RendererCompositor() { - xr_enabled = GLOBAL_GET("xr/shaders/enabled"); + if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) { + xr_enabled = GLOBAL_GET("xr/shaders/enabled"); + } else { + xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON; + } } RendererCanvasRender *RendererCanvasRender::singleton = nullptr; diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index a67eb25736..4cfded8460 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_COMPOSITOR_H -#define RENDERING_SERVER_COMPOSITOR_H +#ifndef RENDERER_COMPOSITOR_H +#define RENDERER_COMPOSITOR_H #include "servers/rendering/environment/renderer_fog.h" #include "servers/rendering/environment/renderer_gi.h" @@ -109,4 +109,4 @@ public: virtual ~RendererCompositor() {} }; -#endif // RASTERIZER_H +#endif // RENDERER_COMPOSITOR_H diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp new file mode 100644 index 0000000000..675659f4c8 --- /dev/null +++ b/servers/rendering/renderer_geometry_instance.cpp @@ -0,0 +1,138 @@ +/*************************************************************************/ +/* renderer_geometry_instance.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "servers/rendering/renderer_geometry_instance.h" + +void RenderGeometryInstanceBase::set_skeleton(RID p_skeleton) { + data->skeleton = p_skeleton; + + _mark_dirty(); + data->dirty_dependencies = true; +} + +void RenderGeometryInstanceBase::set_material_override(RID p_override) { + data->material_override = p_override; + + _mark_dirty(); + data->dirty_dependencies = true; +} + +void RenderGeometryInstanceBase::set_material_overlay(RID p_overlay) { + data->material_overlay = p_overlay; + + _mark_dirty(); + data->dirty_dependencies = true; +} + +void RenderGeometryInstanceBase::set_surface_materials(const Vector<RID> &p_materials) { + data->surface_materials = p_materials; + + _mark_dirty(); + data->dirty_dependencies = true; +} + +void RenderGeometryInstanceBase::set_mesh_instance(RID p_mesh_instance) { + mesh_instance = p_mesh_instance; + + _mark_dirty(); +} + +void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { + transform = p_transform; + mirror = p_transform.basis.determinant() < 0; + data->aabb = p_aabb; + transformed_aabb = p_transformed_aabb; + + Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); + // handle non uniform scale here + + float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); + float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); + non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; + + lod_model_scale = max_scale; +} + +void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) { + lod_bias = p_lod_bias; +} + +void RenderGeometryInstanceBase::set_layer_mask(uint32_t p_layer_mask) { + layer_mask = p_layer_mask; +} + +void RenderGeometryInstanceBase::set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { + fade_near = p_enable_near; + fade_near_begin = p_near_begin; + fade_near_end = p_near_end; + fade_far = p_enable_far; + fade_far_begin = p_far_begin; + fade_far_end = p_far_end; +} + +void RenderGeometryInstanceBase::set_parent_fade_alpha(float p_alpha) { + parent_fade_alpha = p_alpha; +} + +void RenderGeometryInstanceBase::set_transparency(float p_transparency) { + force_alpha = CLAMP(1.0 - p_transparency, 0, 1); +} + +void RenderGeometryInstanceBase::set_use_baked_light(bool p_enable) { + data->use_baked_light = p_enable; + + _mark_dirty(); +} + +void RenderGeometryInstanceBase::set_use_dynamic_gi(bool p_enable) { + data->use_dynamic_gi = p_enable; + + _mark_dirty(); +} + +void RenderGeometryInstanceBase::set_instance_shader_uniforms_offset(int32_t p_offset) { + shader_uniforms_offset = p_offset; + + _mark_dirty(); +} + +void RenderGeometryInstanceBase::set_cast_double_sided_shadows(bool p_enable) { + data->cast_double_sided_shadows = p_enable; + + _mark_dirty(); +} + +Transform3D RenderGeometryInstanceBase::get_transform() { + return transform; +} + +AABB RenderGeometryInstanceBase::get_aabb() { + return data->aabb; +} diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h new file mode 100644 index 0000000000..fecb9878c2 --- /dev/null +++ b/servers/rendering/renderer_geometry_instance.h @@ -0,0 +1,150 @@ +/*************************************************************************/ +/* renderer_geometry_instance.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 RENDERER_GEOMETRY_INSTANCE_H +#define RENDERER_GEOMETRY_INSTANCE_H + +#include "core/math/rect2.h" +#include "core/math/transform_3d.h" +#include "core/math/vector3.h" +#include "core/templates/rid.h" +#include "storage/utilities.h" + +// API definition for our RenderGeometryInstance class so we can expose this through GDExternal in the near future +class RenderGeometryInstance { +public: + virtual ~RenderGeometryInstance() {} + + virtual void _mark_dirty() = 0; + + virtual void set_skeleton(RID p_skeleton) = 0; + virtual void set_material_override(RID p_override) = 0; + virtual void set_material_overlay(RID p_overlay) = 0; + virtual void set_surface_materials(const Vector<RID> &p_materials) = 0; + virtual void set_mesh_instance(RID p_mesh_instance) = 0; + virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0; + virtual void set_lod_bias(float p_lod_bias) = 0; + virtual void set_layer_mask(uint32_t p_layer_mask) = 0; + virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0; + virtual void set_parent_fade_alpha(float p_alpha) = 0; + virtual void set_transparency(float p_transparency) = 0; + virtual void set_use_baked_light(bool p_enable) = 0; + virtual void set_use_dynamic_gi(bool p_enable) = 0; + virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0; + virtual void set_lightmap_capture(const Color *p_sh9) = 0; + virtual void set_instance_shader_uniforms_offset(int32_t p_offset) = 0; + virtual void set_cast_double_sided_shadows(bool p_enable) = 0; + + virtual Transform3D get_transform() = 0; + virtual AABB get_aabb() = 0; + + virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) = 0; + virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0; + virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0; + virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0; + + virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) = 0; +}; + +// Base implementation of RenderGeometryInstance shared by internal renderers. +class RenderGeometryInstanceBase : public RenderGeometryInstance { +public: + // setup + uint32_t base_flags = 0; + uint32_t flags_cache = 0; + + // used during rendering + float depth = 0; + + RID mesh_instance; + + Transform3D transform; + bool mirror = false; // move into data? + AABB transformed_aabb; //needed for LOD + bool non_uniform_scale = false; + float lod_model_scale = 1.0; + float lod_bias = 0.0; + + uint32_t layer_mask = 1; + + bool fade_near = false; + float fade_near_begin = 0; + float fade_near_end = 0; + bool fade_far = false; + float fade_far_begin = 0; + float fade_far_end = 0; + + float parent_fade_alpha = 1.0; + float force_alpha = 1.0; + + int32_t shader_uniforms_offset = -1; + + struct Data { + //data used less often goes into regular heap + RID base; + RS::InstanceType base_type; + + RID skeleton; + Vector<RID> surface_materials; + RID material_override; + RID material_overlay; + AABB aabb; + + bool use_baked_light = false; + bool use_dynamic_gi = false; + bool cast_double_sided_shadows = false; + bool dirty_dependencies = false; + + DependencyTracker dependency_tracker; + }; + + Data *data = nullptr; + + virtual void set_skeleton(RID p_skeleton) override; + virtual void set_material_override(RID p_override) override; + virtual void set_material_overlay(RID p_overlay) override; + virtual void set_surface_materials(const Vector<RID> &p_materials) override; + virtual void set_mesh_instance(RID p_mesh_instance) override; + virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; + virtual void set_lod_bias(float p_lod_bias) override; + virtual void set_layer_mask(uint32_t p_layer_mask) override; + virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; + virtual void set_parent_fade_alpha(float p_alpha) override; + virtual void set_transparency(float p_transparency) override; + virtual void set_use_baked_light(bool p_enable) override; + virtual void set_use_dynamic_gi(bool p_enable) override; + virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override; + virtual void set_cast_double_sided_shadows(bool p_enable) override; + + virtual Transform3D get_transform() override; + virtual AABB get_aabb() override; +}; + +#endif // RENDERER_GEOMETRY_INSTANCE_H diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 228933d618..1bb45cbcc1 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID } } -void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) { +void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) { view_xform = p_view_transform.affine_inverse(); projection = p_cam_projection; z_near = projection.get_z_near(); @@ -385,7 +385,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa adjusted_projection.adjust_perspective_znear(0.0001); } - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); projection = correction * projection; adjusted_projection = correction * adjusted_projection; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 74ca530ff6..17ca1986c6 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -168,8 +168,8 @@ private: uint32_t render_element_max = 0; Transform3D view_xform; - CameraMatrix adjusted_projection; - CameraMatrix projection; + Projection adjusted_projection; + Projection projection; float z_far = 0; float z_near = 0; bool orthogonal = false; @@ -220,7 +220,7 @@ private: public: void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer); - void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y); + void begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y); _FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) { if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) { @@ -375,4 +375,4 @@ public: ~ClusterBuilderRD(); }; -#endif // CLUSTER_BUILDER_H +#endif // CLUSTER_BUILDER_RD_H diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h index d7b736119c..30b33be168 100644 --- a/servers/rendering/renderer_rd/effects/bokeh_dof.h +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h @@ -117,4 +117,4 @@ public: } // namespace RendererRD -#endif // !BOKEH_DOF_RD_H +#endif // BOKEH_DOF_RD_H diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index c30e8ed58f..5507483cee 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -100,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { { Vector<String> copy_modes; - copy_modes.push_back("\n"); - copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); - copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); - copy_modes.push_back("\n#define MULTIVIEW\n"); - copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n"); // COPY_TO_FB_COPY + copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2 + copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH copy_to_fb.shader.initialize(copy_modes); @@ -249,6 +249,56 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { roughness.raster_pipeline.clear(); } } + + { + Vector<String> specular_modes; + specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD + specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR + specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD + specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR + + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW + + specular_merge.shader.initialize(specular_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false); + } + + specular_merge.shader_version = specular_merge.shader.version_create(); + + //use additive + + RD::PipelineColorBlendState::Attachment ba; + ba.enable_blend = true; + ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE; + ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + ba.color_blend_op = RD::BLEND_OP_ADD; + ba.alpha_blend_op = RD::BLEND_OP_ADD; + + RD::PipelineColorBlendState blend_additive; + blend_additive.attachments.push_back(ba); + + for (int i = 0; i < SPECULAR_MERGE_MAX; i++) { + if (specular_merge.shader.is_variant_enabled(i)) { + RD::PipelineColorBlendState blend_state; + if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) { + blend_state = blend_additive; + } else { + blend_state = RD::PipelineColorBlendState::create_disabled(); + } + specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } + } + } } CopyEffects::~CopyEffects() { @@ -264,6 +314,8 @@ CopyEffects::~CopyEffects() { roughness.compute_shader.version_free(roughness.shader_version); } + specular_merge.shader.version_free(specular_merge.shader_version); + RD::get_singleton()->free(filter.coefficient_buffer); if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { @@ -1083,3 +1135,57 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f RD::get_singleton()->draw_list_draw(draw_list, true); RD::get_singleton()->draw_list_end(); } + +void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::get_singleton()->draw_command_begin_label("Merge specular"); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>()); + + int mode; + if (p_reflection.is_valid()) { + if (p_base.is_valid()) { + mode = SPECULAR_MERGE_SSR; + } else { + mode = SPECULAR_MERGE_ADDITIVE_SSR; + } + } else { + if (p_base.is_valid()) { + mode = SPECULAR_MERGE_ADD; + } else { + mode = SPECULAR_MERGE_ADDITIVE_ADD; + } + } + + if (p_view_count > 1) { + mode += SPECULAR_MERGE_ADD_MULTIVIEW; + } + + RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + + if (p_base.is_valid()) { + RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2); + } + + RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0); + + if (p_reflection.is_valid()) { + RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1); + } + + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + RD::get_singleton()->draw_command_end_label(); +} diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index 882b446964..d25555eee5 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COPY_RD_H -#define COPY_RD_H +#ifndef COPY_EFFECTS_RD_H +#define COPY_EFFECTS_RD_H #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h" @@ -42,6 +42,7 @@ #include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" @@ -274,6 +275,33 @@ private: PipelineCacheRD raster_pipeline; } roughness; + // Merge specular + + enum SpecularMergeMode { + SPECULAR_MERGE_ADD, + SPECULAR_MERGE_SSR, + SPECULAR_MERGE_ADDITIVE_ADD, + SPECULAR_MERGE_ADDITIVE_SSR, + + SPECULAR_MERGE_ADD_MULTIVIEW, + SPECULAR_MERGE_SSR_MULTIVIEW, + SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, + SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, + + SPECULAR_MERGE_MAX + }; + + /* Specular merge must be done using raster, rather than compute + * because it must continue the existing color buffer + */ + + struct SpecularMerge { + SpecularMergeShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[SPECULAR_MERGE_MAX]; + + } specular_merge; + static CopyEffects *singleton; public: @@ -309,8 +337,10 @@ public: void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); + + void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count); }; } // namespace RendererRD -#endif // !COPY_RD_H +#endif // COPY_EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h index d4b24a610f..2a4cd06827 100644 --- a/servers/rendering/renderer_rd/effects/resolve.h +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -71,4 +71,4 @@ public: } // namespace RendererRD -#endif // !RESOLVE_RD_H +#endif // RESOLVE_RD_H diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp new file mode 100644 index 0000000000..0f896a8aa7 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -0,0 +1,1715 @@ +/*************************************************************************/ +/* ss_effects.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "ss_effects.h" + +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +SSEffects *SSEffects::singleton = nullptr; + +static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } +} + +SSEffects::SSEffects() { + singleton = this; + + { + // Initialize depth buffer for screen space effects + Vector<String> downsampler_modes; + downsampler_modes.push_back("\n"); + downsampler_modes.push_back("\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n"); + downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS"); + + ss_effects.downsample_shader.initialize(downsampler_modes); + + ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create(); + + for (int i = 0; i < SS_EFFECTS_MAX; i++) { + ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i)); + } + + ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants)); + SSEffectsGatherConstants gather_constants; + + const int sub_pass_count = 5; + for (int pass = 0; pass < 4; pass++) { + for (int subPass = 0; subPass < sub_pass_count; subPass++) { + int a = pass; + int b = subPass; + + int spmap[5]{ 0, 1, 4, 3, 2 }; + b = spmap[subPass]; + + float ca, sa; + float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; + + ca = Math::cos(angle0); + sa = Math::sin(angle0); + + float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f; + + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca; + } + } + + RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants); + } + + // Initialize Screen Space Indirect Lighting (SSIL) + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n"); + ssil_modes.push_back("\n#define SSIL_BASE\n"); + ssil_modes.push_back("\n#define ADAPTIVE\n"); + + ssil.gather_shader.initialize(ssil_modes); + + ssil.gather_shader_version = ssil.gather_shader.version_create(); + + for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i)); + } + ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms)); + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define GENERATE_MAP\n"); + ssil_modes.push_back("\n#define PROCESS_MAPA\n"); + ssil_modes.push_back("\n#define PROCESS_MAPB\n"); + + ssil.importance_map_shader.initialize(ssil_modes); + + ssil.importance_map_shader_version = ssil.importance_map_shader.version_create(); + + for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP)); + } + ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero); + RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter"); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(ssil.importance_map_load_counter); + uniforms.push_back(u); + } + ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2); + RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set"); + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define MODE_NON_SMART\n"); + ssil_modes.push_back("\n#define MODE_SMART\n"); + ssil_modes.push_back("\n#define MODE_WIDE\n"); + + ssil.blur_shader.initialize(ssil_modes); + + ssil.blur_shader_version = ssil.blur_shader.version_create(); + for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS)); + } + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define MODE_NON_SMART\n"); + ssil_modes.push_back("\n#define MODE_SMART\n"); + ssil_modes.push_back("\n#define MODE_HALF\n"); + + ssil.interleave_shader.initialize(ssil_modes); + + ssil.interleave_shader_version = ssil.interleave_shader.version_create(); + for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE)); + } + } + + { + // Initialize Screen Space Ambient Occlusion (SSAO) + + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.max_lod = 4; + + uint32_t pipeline = 0; + { + Vector<String> ssao_modes; + + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define SSAO_BASE\n"); + ssao_modes.push_back("\n#define ADAPTIVE\n"); + + ssao.gather_shader.initialize(ssao_modes); + + ssao.gather_shader_version = ssao.gather_shader.version_create(); + + for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i)); + pipeline++; + } + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define GENERATE_MAP\n"); + ssao_modes.push_back("\n#define PROCESS_MAPA\n"); + ssao_modes.push_back("\n#define PROCESS_MAPB\n"); + + ssao.importance_map_shader.initialize(ssao_modes); + + ssao.importance_map_shader_version = ssao.importance_map_shader.version_create(); + + for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP)); + + pipeline++; + } + + ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero); + RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter"); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); + RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set"); + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_WIDE\n"); + + ssao.blur_shader.initialize(ssao_modes); + + ssao.blur_shader_version = ssao.blur_shader.version_create(); + + for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); + + pipeline++; + } + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_HALF\n"); + + ssao.interleave_shader.initialize(ssao_modes); + + ssao.interleave_shader_version = ssao.interleave_shader.version_create(); + for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE)); + RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i)); + pipeline++; + } + } + + ERR_FAIL_COND(pipeline != SSAO_MAX); + + ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler); + } + + { + // Screen Space Reflections + + Vector<RD::PipelineSpecializationConstant> specialization_constants; + + { + RD::PipelineSpecializationConstant sc; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX + sc.bool_value = false; + specialization_constants.push_back(sc); + } + + { + Vector<String> ssr_scale_modes; + ssr_scale_modes.push_back("\n"); + + ssr_scale.shader.initialize(ssr_scale_modes); + ssr_scale.shader_version = ssr_scale.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants); + } + } + + { + Vector<String> ssr_modes; + ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL + ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH + + ssr.shader.initialize(ssr_modes); + ssr.shader_version = ssr.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { + ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants); + } + } + } + + { + Vector<String> ssr_filter_modes; + ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL + ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL + + ssr_filter.shader.initialize(ssr_filter_modes); + ssr_filter.shader_version = ssr_filter.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { + ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants); + } + } + } + } +} + +SSEffects::~SSEffects() { + { + // Cleanup SS Reflections + ssr.shader.version_free(ssr.shader_version); + ssr_filter.shader.version_free(ssr_filter.shader_version); + ssr_scale.shader.version_free(ssr_scale.shader_version); + + if (ssr.ubo.is_valid()) { + RD::get_singleton()->free(ssr.ubo); + } + } + + { + // Cleanup SS downsampler + ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); + + RD::get_singleton()->free(ss_effects.mirror_sampler); + RD::get_singleton()->free(ss_effects.gather_constants_buffer); + } + + { + // Cleanup SSIL + ssil.blur_shader.version_free(ssil.blur_shader_version); + ssil.gather_shader.version_free(ssil.gather_shader_version); + ssil.interleave_shader.version_free(ssil.interleave_shader_version); + ssil.importance_map_shader.version_free(ssil.importance_map_shader_version); + + RD::get_singleton()->free(ssil.importance_map_load_counter); + RD::get_singleton()->free(ssil.projection_uniform_buffer); + } + + { + // Cleanup SSAO + ssao.blur_shader.version_free(ssao.blur_shader_version); + ssao.gather_shader.version_free(ssao.gather_shader_version); + ssao.interleave_shader.version_free(ssao.interleave_shader_version); + ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); + + RD::get_singleton()->free(ssao.importance_map_load_counter); + } + + singleton = nullptr; +} + +/* SS Downsampler */ + +void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // Downsample and deinterleave the depth buffer for SSAO and SSIL + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + int downsample_mode = SS_EFFECTS_DOWNSAMPLE; + bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM; + + if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF; + } else if (use_mips) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP; + } + + bool use_half_size = false; + bool use_full_mips = false; + + if (p_ssao_half_size && p_ssil_half_size) { + downsample_mode++; + use_half_size = true; + } else if (p_ssao_half_size != p_ssil_half_size) { + if (use_mips) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS; + use_full_mips = true; + } else { + // Only need the first two mipmaps, but the cost to generate the next two is trivial + // TODO investigate the benefit of a shader version to generate only 2 mips + downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP; + use_mips = true; + } + } + + int depth_index = use_half_size ? 1 : 0; + + RD::get_singleton()->draw_command_begin_label("Downsample Depth"); + if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_depth_mipmaps[depth_index + 1]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_depth_mipmaps[depth_index + 2]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.append_id(p_depth_mipmaps[depth_index + 3]); + uniforms.push_back(u); + } + if (use_full_mips) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.append_id(p_depth_mipmaps[4]); + uniforms.push_back(u); + } + ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); + } + + float depth_linearize_mul = -p_projection.matrix[3][2]; + float depth_linearize_add = p_projection.matrix[2][2]; + if (depth_linearize_mul * depth_linearize_add < 0) { + depth_linearize_add = -depth_linearize_add; + } + + ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal(); + ss_effects.downsample_push_constant.z_near = depth_linearize_mul; + ss_effects.downsample_push_constant.z_far = depth_linearize_add; + if (ss_effects.downsample_push_constant.orthogonal) { + ss_effects.downsample_push_constant.z_near = p_projection.get_z_near(); + ss_effects.downsample_push_constant.z_far = p_projection.get_z_far(); + } + ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x; + ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y; + ss_effects.downsample_push_constant.radius_sq = 1.0; + + RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer })); + RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1); + if (use_mips) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant)); + + Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1))); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); + + ss_effects.used_full_mips_last_frame = use_full_mips; + ss_effects.used_half_size_last_frame = use_half_size; +} + +/* SSIL */ + +void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); + } + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3); + + RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0); + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] })); + RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] })); + + ssil.gather_push_constant.pass_coord_offset[0] = i % 2; + ssil.gather_push_constant.pass_coord_offset[1] = i / 2; + ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; + ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; + ssil.gather_push_constant.pass = i; + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2); + RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant)); + + Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); + } + RD::get_singleton()->compute_list_add_barrier(p_compute_list); +} + +void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) { + if (p_ssil_buffers.half_size != p_settings.half_size) { + ssil_free(p_ssil_buffers); + } + + if (p_settings.half_size) { + p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; + p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8; + p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8; + } else { + p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2; + p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2; + p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; + } + + if (p_ssil_buffers.ssil_final.is_null()) { + { + p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = p_settings.full_screen_size.x; + tf.height = p_settings.full_screen_size.y; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture"); + RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1); + if (p_ssil_buffers.last_frame.is_null()) { + tf.mipmaps = 6; + p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance"); + RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1); + for (uint32_t i = 0; i < 6; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i); + p_ssil_buffers.last_frame_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " "); + } + } + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0); + p_ssil_buffers.deinterleaved_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0); + p_ssil_buffers.pong_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0); + p_ssil_buffers.edges_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_ssil_buffers.half_buffer_width; + tf.height = p_ssil_buffers.half_buffer_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map"); + p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong"); + } + p_ssil_buffers.half_size = p_settings.half_size; + } +} + +void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting"); + //Store projection info before starting the compute list + SSILProjectionUniforms projection_uniforms; + store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix); + + RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms); + + memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant)); + + RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + { + RD::get_singleton()->draw_command_begin_label("Gather Samples"); + ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; + ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; + + ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; + float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; + ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; + ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; + ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; + ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; + ssil.gather_push_constant.z_near = p_projection.get_z_near(); + ssil.gather_push_constant.z_far = p_projection.get_z_far(); + ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); + + ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; + ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; + + ssil.gather_push_constant.radius = p_settings.radius; + float radius_near_limit = (p_settings.radius * 1.2f); + if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) { + radius_near_limit *= 1.50f; + + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + ssil.gather_push_constant.radius *= 0.8f; + } + } + radius_near_limit /= tan_half_fov_y; + ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI; + ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); + ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; + ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; + ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius; + ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection; + + ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255); + ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; + + ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1); + ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; + + if (p_ssil_buffers.projection_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_mipmap_sampler); + u.append_id(p_ssil_buffers.last_frame); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 1; + u.append_id(ssil.projection_uniform_buffer); + uniforms.push_back(u); + } + p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); + } + + if (p_ssil_buffers.gather_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_sampler); + u.append_id(p_ssil_buffers.depth_texture_view); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_normal_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(ss_effects.gather_constants_buffer); + uniforms.push_back(u); + } + p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); + } + + if (p_ssil_buffers.importance_map_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_ssil_buffers.pong); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.append_id(default_sampler); + u.append_id(p_ssil_buffers.importance_map[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(ssil.importance_map_load_counter); + uniforms.push_back(u); + } + p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); + } + + if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) { + RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); + ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI; + //base pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]); + gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + + //generate importance map + RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // process Importance Map A + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] })); + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // process Importance Map B + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->draw_command_end_label(); // Importance Map + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]); + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]); + } + + gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + RD::get_singleton()->draw_command_end_label(); //Gather + } + + { + RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); + ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; + ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + + int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; + + shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0); + + for (int pass = 0; pass < blur_passes; pass++) { + int blur_pipeline = SSIL_BLUR_PASS; + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { + blur_pipeline = SSIL_BLUR_PASS_SMART; + if (pass < blur_passes - 2) { + blur_pipeline = SSIL_BLUR_PASS_WIDE; + } + } + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]); + if (pass % 2 == 0) { + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + } else { + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + } + + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1); + } else { + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + } else { + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + } + + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1); + } + + RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant)); + + int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)); + int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1); + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + } + } + + RD::get_singleton()->draw_command_end_label(); // Blur + } + + { + RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); + ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; + ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); + + int interleave_pipeline = SSIL_INTERLEAVE_HALF; + if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) { + interleave_pipeline = SSIL_INTERLEAVE; + } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { + interleave_pipeline = SSIL_INTERLEAVE_SMART; + } + + shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]); + + RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0); + + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { + RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1); + } else { + RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1); + } + + RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); // Interleave + } + + RD::get_singleton()->draw_command_end_label(); // SSIL + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); + + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier +} + +void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) { + if (p_ssil_buffers.ssil_final.is_valid()) { + RD::get_singleton()->free(p_ssil_buffers.ssil_final); + RD::get_singleton()->free(p_ssil_buffers.deinterleaved); + RD::get_singleton()->free(p_ssil_buffers.pong); + RD::get_singleton()->free(p_ssil_buffers.edges); + RD::get_singleton()->free(p_ssil_buffers.importance_map[0]); + RD::get_singleton()->free(p_ssil_buffers.importance_map[1]); + RD::get_singleton()->free(p_ssil_buffers.last_frame); + + p_ssil_buffers.ssil_final = RID(); + p_ssil_buffers.deinterleaved = RID(); + p_ssil_buffers.pong = RID(); + p_ssil_buffers.edges = RID(); + p_ssil_buffers.deinterleaved_slices.clear(); + p_ssil_buffers.pong_slices.clear(); + p_ssil_buffers.edges_slices.clear(); + p_ssil_buffers.importance_map[0] = RID(); + p_ssil_buffers.importance_map[1] = RID(); + p_ssil_buffers.last_frame = RID(); + p_ssil_buffers.last_frame_slices.clear(); + + p_ssil_buffers.gather_uniform_set = RID(); + p_ssil_buffers.importance_map_uniform_set = RID(); + p_ssil_buffers.projection_uniform_set = RID(); + } +} + +/* SSAO */ + +void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0); + } + + RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); // + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] })); + + ssao.gather_push_constant.pass_coord_offset[0] = i % 2; + ssao.gather_push_constant.pass_coord_offset[1] = i / 2; + ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; + ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; + ssao.gather_push_constant.pass = i; + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2); + RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + + Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); + } + RD::get_singleton()->compute_list_add_barrier(p_compute_list); +} + +void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) { + if (p_ssao_buffers.half_size != p_settings.half_size) { + ssao_free(p_ssao_buffers); + } + + if (p_settings.half_size) { + p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; + p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8; + p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8; + } else { + p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2; + p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2; + p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; + } + + if (p_ssao_buffers.ao_deinterleaved.is_null()) { + { + p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0); + p_ssao_buffers.ao_deinterleaved_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0); + p_ssao_buffers.ao_pong_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong"); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map"); + p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong"); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_settings.full_screen_size.x; + tf.height = p_settings.full_screen_size.y; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final"); + } + p_ssao_buffers.half_size = p_settings.half_size; + } +} + +void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant)); + /* FIRST PASS */ + + RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion"); + /* SECOND PASS */ + // Sample SSAO + { + RD::get_singleton()->draw_command_begin_label("Gather Samples"); + ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; + ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; + + ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; + float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; + ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; + ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; + ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; + ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; + ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); + + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; + + ssao.gather_push_constant.radius = p_settings.radius; + float radius_near_limit = (p_settings.radius * 1.2f); + if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) { + radius_near_limit *= 1.50f; + + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + ssao.gather_push_constant.radius *= 0.8f; + } + } + radius_near_limit /= tan_half_fov_y; + ssao.gather_push_constant.intensity = p_settings.intensity; + ssao.gather_push_constant.shadow_power = p_settings.power; + ssao.gather_push_constant.shadow_clamp = 0.98; + ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); + ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; + ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon; + ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; + ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; + + ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255); + ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; + + ssao.gather_push_constant.detail_intensity = p_settings.detail; + ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1); + ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; + + if (p_ssao_buffers.gather_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_sampler); + u.append_id(p_ssao_buffers.depth_texture_view); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_normal_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(ss_effects.gather_constants_buffer); + uniforms.push_back(u); + } + p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0); + RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set"); + } + + if (p_ssao_buffers.importance_map_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_ssao_buffers.ao_pong); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.append_id(default_sampler); + u.append_id(p_ssao_buffers.importance_map[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set"); + } + + if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) { + RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); + ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + ssao.importance_map_push_constant.intensity = p_settings.intensity; + ssao.importance_map_push_constant.power = p_settings.power; + + //base pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); + gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID()); + + //generate importance map + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); + + RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0); + + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //process importance map A + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); + + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); + + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //process Importance Map B + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); + + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]); + RD::get_singleton()->draw_command_end_label(); // Importance Map + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); + } + + gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set); + RD::get_singleton()->draw_command_end_label(); // Gather SSAO + } + + // /* THIRD PASS */ + // // Blur + // + { + RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); + ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; + ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + + int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; + + shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0); + + for (int pass = 0; pass < blur_passes; pass++) { + int blur_pipeline = SSAO_BLUR_PASS; + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + blur_pipeline = SSAO_BLUR_PASS_SMART; + if (pass < blur_passes - 2) { + blur_pipeline = SSAO_BLUR_PASS_WIDE; + } else { + blur_pipeline = SSAO_BLUR_PASS_SMART; + } + } + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); + if (pass % 2 == 0) { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + } else { + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + } + + RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1); + } else { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + } else { + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + } + + RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); + } + + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + } + RD::get_singleton()->draw_command_end_label(); // Blur + } + + /* FOURTH PASS */ + // Interleave buffers + // back to full size + { + RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); + ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; + ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); + + shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0); + + int interleave_pipeline = SSAO_INTERLEAVE_HALF; + if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) { + interleave_pipeline = SSAO_INTERLEAVE; + } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { + interleave_pipeline = SSAO_INTERLEAVE_SMART; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); + + RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0); + + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + } else { + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); // Interleave + } + RD::get_singleton()->draw_command_end_label(); //SSAO + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer + + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier +} + +void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) { + if (p_ssao_buffers.ao_final.is_valid()) { + RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved); + RD::get_singleton()->free(p_ssao_buffers.ao_pong); + RD::get_singleton()->free(p_ssao_buffers.ao_final); + + RD::get_singleton()->free(p_ssao_buffers.importance_map[0]); + RD::get_singleton()->free(p_ssao_buffers.importance_map[1]); + + p_ssao_buffers.ao_deinterleaved = RID(); + p_ssao_buffers.ao_pong = RID(); + p_ssao_buffers.ao_final = RID(); + p_ssao_buffers.importance_map[0] = RID(); + p_ssao_buffers.importance_map[1] = RID(); + p_ssao_buffers.ao_deinterleaved_slices.clear(); + p_ssao_buffers.ao_pong_slices.clear(); + + p_ssao_buffers.gather_uniform_set = RID(); + p_ssao_buffers.importance_map_uniform_set = RID(); + } +} + +/* Screen Space Reflection */ + +void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count) { + // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view. + + if (p_ssr_buffers.depth_scaled.is_null()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + + p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled"); + + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + + p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled"); + } + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0"); + p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1"); + } + + if (p_ssr_buffers.intermediate.is_null()) { + RD::TextureFormat tf; + tf.format = p_color_format; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate"); + + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = p_view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } + + p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output"); + + for (uint32_t v = 0; v < p_view_count; v++) { + p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0); + } + } +} + +void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + { + // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders + ScreenSpaceReflectionSceneData scene_data; + + if (ssr.ubo.is_null()) { + ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData)); + } + + for (uint32_t v = 0; v < p_view_count; v++) { + store_camera(p_projections[v], scene_data.projection[v]); + store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]); + scene_data.eye_offset[v][0] = p_eye_offsets[v].x; + scene_data.eye_offset[v][1] = p_eye_offsets[v].y; + scene_data.eye_offset[v][2] = p_eye_offsets[v].z; + scene_data.eye_offset[v][3] = 0.0; + } + + RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + } + + uint32_t pipeline_specialization = 0; + if (p_view_count > 1) { + pipeline_specialization |= SSR_MULTIVIEW; + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + for (uint32_t v = 0; v < p_view_count; v++) { + RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v)); + + { //scale color and depth to half + RD::get_singleton()->draw_command_begin_label("SSR Scale"); + + ScreenSpaceReflectionScalePushConstant push_constant; + push_constant.view_index = v; + push_constant.camera_z_far = p_projections[v].get_z_far(); + push_constant.camera_z_near = p_projections[v].get_z_near(); + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.filter = false; //enabling causes arctifacts + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + + RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]); + + RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0); + + RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] })); + RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2); + + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->draw_command_end_label(); + } + + { + RD::get_singleton()->draw_command_begin_label("SSR main"); + + ScreenSpaceReflectionPushConstant push_constant; + push_constant.view_index = v; + push_constant.camera_z_far = p_projections[v].get_z_far(); + push_constant.camera_z_near = p_projections[v].get_z_near(); + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + push_constant.curve_fade_in = p_fade_in; + push_constant.distance_fade = p_fade_out; + push_constant.num_steps = p_max_steps; + push_constant.depth_tolerance = p_tolerance; + push_constant.use_half_res = true; + push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255); + push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255); + push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255); + push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); + + ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL; + RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]); + + RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0); + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1); + } else { + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1); + } + + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2); + + RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->draw_command_end_label(); + } + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + RD::get_singleton()->draw_command_begin_label("SSR filter"); + //blur + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + ScreenSpaceReflectionFilterPushConstant push_constant; + push_constant.view_index = v; + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); + push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + push_constant.vertical = 0; + if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { + push_constant.steps = p_max_steps / 3; + push_constant.increment = 3; + } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { + push_constant.steps = p_max_steps / 2; + push_constant.increment = 2; + } else { + push_constant.steps = p_max_steps; + push_constant.increment = 1; + } + + push_constant.screen_size[0] = p_screen_size.width; + push_constant.screen_size[1] = p_screen_size.height; + + // Horizontal pass + + SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL; + + RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]); + + RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0); + + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2); + + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // Vertical pass + + mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL; + shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]); + + push_constant.vertical = 1; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + if (v != p_view_count - 1) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + RD::get_singleton()->draw_command_end_label(); + } + + RD::get_singleton()->draw_command_end_label(); + } + + RD::get_singleton()->compute_list_end(); +} + +void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + p_ssr_buffers.output_slices[v] = RID(); + } + + if (p_ssr_buffers.output.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.output); + p_ssr_buffers.output = RID(); + } + + if (p_ssr_buffers.intermediate.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.intermediate); + p_ssr_buffers.intermediate = RID(); + } + + if (p_ssr_buffers.blur_radius[0].is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]); + RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]); + p_ssr_buffers.blur_radius[0] = RID(); + p_ssr_buffers.blur_radius[1] = RID(); + } + + if (p_ssr_buffers.depth_scaled.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.depth_scaled); + p_ssr_buffers.depth_scaled = RID(); + RD::get_singleton()->free(p_ssr_buffers.normal_scaled); + p_ssr_buffers.normal_scaled = RID(); + } +} diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h new file mode 100644 index 0000000000..c31271ffd2 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -0,0 +1,508 @@ +/*************************************************************************/ +/* ss_effects.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 SS_EFFECTS_RD_H +#define SS_EFFECTS_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" +#include "servers/rendering_server.h" + +namespace RendererRD { + +class SSEffects { +private: + static SSEffects *singleton; + +public: + static SSEffects *get_singleton() { return singleton; } + + SSEffects(); + ~SSEffects(); + + /* SS Downsampler */ + + void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection); + + /* SSIL */ + + struct SSILRenderBuffers { + bool half_size = false; + int buffer_width; + int buffer_height; + int half_buffer_width; + int half_buffer_height; + + RID ssil_final; + RID deinterleaved; + Vector<RID> deinterleaved_slices; + RID pong; + Vector<RID> pong_slices; + RID edges; + Vector<RID> edges_slices; + RID importance_map[2]; + RID depth_texture_view; + + RID last_frame; + Vector<RID> last_frame_slices; + + RID gather_uniform_set; + RID importance_map_uniform_set; + RID projection_uniform_set; + }; + + struct SSILSettings { + float radius = 1.0; + float intensity = 2.0; + float sharpness = 0.98; + float normal_rejection = 1.0; + + RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM; + bool half_size = true; + float adaptive_target = 0.5; + int blur_passes = 4; + float fadeout_from = 50.0; + float fadeout_to = 300.0; + + Size2i full_screen_size = Size2i(); + }; + + void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth); + void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings); + void ssil_free(SSILRenderBuffers &p_ssil_buffers); + + /* SSAO */ + + struct SSAORenderBuffers { + bool half_size = false; + int buffer_width; + int buffer_height; + int half_buffer_width; + int half_buffer_height; + + RID ao_deinterleaved; + Vector<RID> ao_deinterleaved_slices; + RID ao_pong; + Vector<RID> ao_pong_slices; + RID ao_final; + RID importance_map[2]; + RID depth_texture_view; + + RID gather_uniform_set; + RID importance_map_uniform_set; + }; + + struct SSAOSettings { + float radius = 1.0; + float intensity = 2.0; + float power = 1.5; + float detail = 0.5; + float horizon = 0.06; + float sharpness = 0.98; + + RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM; + bool half_size = false; + float adaptive_target = 0.5; + int blur_passes = 2; + float fadeout_from = 50.0; + float fadeout_to = 300.0; + + Size2i full_screen_size = Size2i(); + }; + + void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth); + void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings); + void ssao_free(SSAORenderBuffers &p_ssao_buffers); + + /* Screen Space Reflection */ + + struct SSRRenderBuffers { + RID normal_scaled; + RID depth_scaled; + RID blur_radius[2]; + RID intermediate; + RID output; + RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + }; + + void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count); + void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets); + void ssr_free(SSRRenderBuffers &p_ssr_buffers); + +private: + /* SS Downsampler */ + + struct SSEffectsDownsamplePushConstant { + float pixel_size[2]; + float z_far; + float z_near; + uint32_t orthogonal; + float radius_sq; + uint32_t pad[2]; + }; + + enum SSEffectsMode { + SS_EFFECTS_DOWNSAMPLE, + SS_EFFECTS_DOWNSAMPLE_HALF_RES, + SS_EFFECTS_DOWNSAMPLE_MIPMAP, + SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES, + SS_EFFECTS_DOWNSAMPLE_HALF, + SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF, + SS_EFFECTS_DOWNSAMPLE_FULL_MIPS, + SS_EFFECTS_MAX + }; + + struct SSEffectsGatherConstants { + float rotation_matrices[80]; //5 vec4s * 4 + }; + + struct SSEffectsShader { + SSEffectsDownsamplePushConstant downsample_push_constant; + SsEffectsDownsampleShaderRD downsample_shader; + RID downsample_shader_version; + RID downsample_uniform_set; + bool used_half_size_last_frame = false; + bool used_mips_last_frame = false; + bool used_full_mips_last_frame = false; + + RID gather_constants_buffer; + + RID mirror_sampler; + + RID pipelines[SS_EFFECTS_MAX]; + } ss_effects; + + /* SSIL */ + + enum SSILMode { + SSIL_GATHER, + SSIL_GATHER_BASE, + SSIL_GATHER_ADAPTIVE, + SSIL_GENERATE_IMPORTANCE_MAP, + SSIL_PROCESS_IMPORTANCE_MAPA, + SSIL_PROCESS_IMPORTANCE_MAPB, + SSIL_BLUR_PASS, + SSIL_BLUR_PASS_SMART, + SSIL_BLUR_PASS_WIDE, + SSIL_INTERLEAVE, + SSIL_INTERLEAVE_SMART, + SSIL_INTERLEAVE_HALF, + SSIL_MAX + }; + + struct SSILGatherPushConstant { + int32_t screen_size[2]; + int pass; + int quality; + + float half_screen_pixel_size[2]; + float half_screen_pixel_size_x025[2]; + + float NDC_to_view_mul[2]; + float NDC_to_view_add[2]; + + float pad2[2]; + float z_near; + float z_far; + + float radius; + float intensity; + int size_multiplier; + int pad; + + float fade_out_mul; + float fade_out_add; + float normal_rejection_amount; + float inv_radius_near_limit; + + uint32_t is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + int32_t pass_coord_offset[2]; + float pass_uv_offset[2]; + }; + + struct SSILImportanceMapPushConstant { + float half_screen_pixel_size[2]; + float intensity; + float pad; + }; + + struct SSILBlurPushConstant { + float edge_sharpness; + float pad; + float half_screen_pixel_size[2]; + }; + + struct SSILInterleavePushConstant { + float inv_sharpness; + uint32_t size_modifier; + float pixel_size[2]; + }; + + struct SSILProjectionUniforms { + float inv_last_frame_projection_matrix[16]; + }; + + struct SSIL { + SSILGatherPushConstant gather_push_constant; + SsilShaderRD gather_shader; + RID gather_shader_version; + RID projection_uniform_buffer; + + SSILImportanceMapPushConstant importance_map_push_constant; + SsilImportanceMapShaderRD importance_map_shader; + RID importance_map_shader_version; + RID importance_map_load_counter; + RID counter_uniform_set; + + SSILBlurPushConstant blur_push_constant; + SsilBlurShaderRD blur_shader; + RID blur_shader_version; + + SSILInterleavePushConstant interleave_push_constant; + SsilInterleaveShaderRD interleave_shader; + RID interleave_shader_version; + + RID pipelines[SSIL_MAX]; + } ssil; + + void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); + + /* SSAO */ + + enum SSAOMode { + SSAO_GATHER, + SSAO_GATHER_BASE, + SSAO_GATHER_ADAPTIVE, + SSAO_GENERATE_IMPORTANCE_MAP, + SSAO_PROCESS_IMPORTANCE_MAPA, + SSAO_PROCESS_IMPORTANCE_MAPB, + SSAO_BLUR_PASS, + SSAO_BLUR_PASS_SMART, + SSAO_BLUR_PASS_WIDE, + SSAO_INTERLEAVE, + SSAO_INTERLEAVE_SMART, + SSAO_INTERLEAVE_HALF, + SSAO_MAX + }; + + struct SSAOGatherPushConstant { + int32_t screen_size[2]; + int pass; + int quality; + + float half_screen_pixel_size[2]; + int size_multiplier; + float detail_intensity; + + float NDC_to_view_mul[2]; + float NDC_to_view_add[2]; + + float pad[2]; + float half_screen_pixel_size_x025[2]; + + float radius; + float intensity; + float shadow_power; + float shadow_clamp; + + float fade_out_mul; + float fade_out_add; + float horizon_angle_threshold; + float inv_radius_near_limit; + + uint32_t is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + int32_t pass_coord_offset[2]; + float pass_uv_offset[2]; + }; + + struct SSAOImportanceMapPushConstant { + float half_screen_pixel_size[2]; + float intensity; + float power; + }; + + struct SSAOBlurPushConstant { + float edge_sharpness; + float pad; + float half_screen_pixel_size[2]; + }; + + struct SSAOInterleavePushConstant { + float inv_sharpness; + uint32_t size_modifier; + float pixel_size[2]; + }; + + struct SSAO { + SSAOGatherPushConstant gather_push_constant; + SsaoShaderRD gather_shader; + RID gather_shader_version; + + SSAOImportanceMapPushConstant importance_map_push_constant; + SsaoImportanceMapShaderRD importance_map_shader; + RID importance_map_shader_version; + RID importance_map_load_counter; + RID counter_uniform_set; + + SSAOBlurPushConstant blur_push_constant; + SsaoBlurShaderRD blur_shader; + RID blur_shader_version; + + SSAOInterleavePushConstant interleave_push_constant; + SsaoInterleaveShaderRD interleave_shader; + RID interleave_shader_version; + + RID pipelines[SSAO_MAX]; + } ssao; + + void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); + + /* Screen Space Reflection */ + + enum SSRShaderSpecializations { + SSR_MULTIVIEW = 1 << 0, + SSR_VARIATIONS = 2, + }; + + struct ScreenSpaceReflectionSceneData { + float projection[2][16]; + float inv_projection[2][16]; + float eye_offset[2][4]; + }; + + // SSR Scale + + struct ScreenSpaceReflectionScalePushConstant { + int32_t screen_size[2]; + float camera_z_near; + float camera_z_far; + + uint32_t orthogonal; + uint32_t filter; + uint32_t view_index; + uint32_t pad1; + }; + + struct ScreenSpaceReflectionScale { + ScreenSpaceReflectionScaleShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS]; + } ssr_scale; + + // SSR main + + enum ScreenSpaceReflectionMode { + SCREEN_SPACE_REFLECTION_NORMAL, + SCREEN_SPACE_REFLECTION_ROUGH, + SCREEN_SPACE_REFLECTION_MAX, + }; + + struct ScreenSpaceReflectionPushConstant { + float proj_info[4]; // 16 - 16 + + int32_t screen_size[2]; // 8 - 24 + float camera_z_near; // 4 - 28 + float camera_z_far; // 4 - 32 + + int32_t num_steps; // 4 - 36 + float depth_tolerance; // 4 - 40 + float distance_fade; // 4 - 44 + float curve_fade_in; // 4 - 48 + + uint32_t orthogonal; // 4 - 52 + float filter_mipmap_levels; // 4 - 56 + uint32_t use_half_res; // 4 - 60 + uint8_t metallic_mask[4]; // 4 - 64 + + uint32_t view_index; // 4 - 68 + uint32_t pad[3]; // 12 - 80 + + // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now + }; + + struct ScreenSpaceReflection { + ScreenSpaceReflectionShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX]; + + RID ubo; + } ssr; + + // SSR Filter + + struct ScreenSpaceReflectionFilterPushConstant { + float proj_info[4]; // 16 - 16 + + uint32_t orthogonal; // 4 - 20 + float edge_tolerance; // 4 - 24 + int32_t increment; // 4 - 28 + uint32_t view_index; // 4 - 32 + + int32_t screen_size[2]; // 8 - 40 + uint32_t vertical; // 4 - 44 + uint32_t steps; // 4 - 48 + }; + + enum SSRReflectionMode { + SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL, + SCREEN_SPACE_REFLECTION_FILTER_VERTICAL, + SCREEN_SPACE_REFLECTION_FILTER_MAX, + }; + + struct ScreenSpaceReflectionFilter { + ScreenSpaceReflectionFilterShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX]; + } ssr_filter; +}; + +} // namespace RendererRD + +#endif // SS_EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h index a90849dbeb..05db4a0cbe 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.h +++ b/servers/rendering/renderer_rd/effects/tone_mapper.h @@ -149,4 +149,4 @@ public: } // namespace RendererRD -#endif // !TONE_MAPPER_RD_H +#endif // TONE_MAPPER_RD_H diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp new file mode 100644 index 0000000000..68cfd43d90 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -0,0 +1,174 @@ +/*************************************************************************/ +/* vrs.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "vrs.h" +#include "../renderer_compositor_rd.h" +#include "../storage_rd/texture_storage.h" +#include "../uniform_set_cache_rd.h" +#include "servers/xr_server.h" + +using namespace RendererRD; + +VRS::VRS() { + { + Vector<String> vrs_modes; + vrs_modes.push_back("\n"); // VRS_DEFAULT + vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW + + vrs_shader.shader.initialize(vrs_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false); + } + + vrs_shader.shader_version = vrs_shader.shader.version_create(); + + //use additive + + for (int i = 0; i < VRS_MAX; i++) { + if (vrs_shader.shader.is_variant_enabled(i)) { + vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + vrs_shader.pipelines[i].clear(); + } + } + } +} + +VRS::~VRS() { + vrs_shader.shader.version_free(vrs_shader.shader_version); +} + +void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT; + + RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>()); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) { + // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm + + // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we + // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating + // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size + // of the VRS buffer to supply. + Size2i texel_size = Size2i(16, 16); + + RD::TextureFormat tf; + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + } + tf.format = RD::DATA_FORMAT_R8_UINT; + tf.width = p_base_width / texel_size.x; + if (p_base_width % texel_size.x != 0) { + tf.width++; + } + tf.height = p_base_height / texel_size.y; + if (p_base_height % texel_size.y != 0) { + tf.height++; + } + tf.array_layers = p_view_count; // create a layer for every view + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.samples = RD::TEXTURE_SAMPLES_1; + + p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control + Vector<RID> fb; + fb.push_back(p_vrs_texture); + + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + + Vector<RD::FramebufferPass> passes; + passes.push_back(pass); + + p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count); +} + +void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { + TextureStorage *texture_storage = TextureStorage::get_singleton(); + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target); + + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + RD::get_singleton()->draw_command_begin_label("VRS Setup"); + + // TODO figure out if image has changed since it was last copied so we can save some resources.. + + if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) { + RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target); + if (vrs_texture.is_valid()) { + RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture); + int layers = texture_storage->texture_get_layers(vrs_texture); + if (rd_texture.is_valid()) { + // Copy into our density buffer + copy_vrs(rd_texture, p_vrs_fb, layers > 1); + } + } + } else if (vrs_mode == RS::VIEWPORT_VRS_XR) { + Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface(); + if (interface.is_valid()) { + RID vrs_texture = interface->get_vrs_texture(); + if (vrs_texture.is_valid()) { + RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture); + int layers = texture_storage->texture_get_layers(vrs_texture); + + if (rd_texture.is_valid()) { + // Copy into our density buffer + copy_vrs(rd_texture, p_vrs_fb, layers > 1); + } + } + } + } + + RD::get_singleton()->draw_command_end_label(); + } +} diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h new file mode 100644 index 0000000000..dd15df615e --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* vrs.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 VRS_RD_H +#define VRS_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class VRS { +private: + enum VRSMode { + VRS_DEFAULT, + VRS_MULTIVIEW, + VRS_MAX, + }; + + /* we have no push constant here (yet) + struct VRSPushConstant { + + }; + */ + + struct VRSShader { + // VRSPushConstant push_constant; + VrsShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[VRS_MAX]; + } vrs_shader; + +public: + VRS(); + ~VRS(); + + void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false); + + void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb); + void update_vrs_texture(RID p_vrs_fb, RID p_render_target); +}; + +} // namespace RendererRD + +#endif // VRS_RD_H diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index d45ddbc392..8d59b24f3f 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -41,14 +41,6 @@ bool EffectsRD::get_prefer_raster_effects() { return prefer_raster_effects; } -static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } -} - RID EffectsRD::_get_uniform_set_from_image(RID p_image) { if (image_to_uniform_set_cache.has(p_image)) { RID uniform_set = image_to_uniform_set_cache[p_image]; @@ -86,7 +78,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, specular_merge.shader.version_get_shader(specular_merge.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -116,105 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m return uniform_set; } -RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) { - TextureSamplerPair tsp; - tsp.texture = p_texture; - tsp.sampler = p_sampler; - - if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) { - RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(p_sampler); - u.append_id(p_texture); - uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0); - - texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set; - - return uniform_set; -} - -RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) { - TexturePair tp; - tp.texture1 = p_texture1; - tp.texture2 = p_texture2; - - if (texture_pair_to_compute_uniform_set_cache.has(tp)) { - RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.append_id(p_texture1); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.append_id(p_texture2); - uniforms.push_back(u); - } - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1); - - texture_pair_to_compute_uniform_set_cache[tp] = uniform_set; - - return uniform_set; -} - -RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) { - TexturePair tp; - tp.texture1 = p_texture1; - tp.texture2 = p_texture2; - - if (image_pair_to_compute_uniform_set_cache.has(tp)) { - RID uniform_set = image_pair_to_compute_uniform_set_cache[tp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_texture1); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_texture2); - uniforms.push_back(u); - } - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3); - - image_pair_to_compute_uniform_set_cache[tp] = uniform_set; - - return uniform_set; -} - void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) { memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant)); @@ -281,126 +174,7 @@ void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity RD::get_singleton()->compute_list_end(); } -void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - { //scale color and depth to half - ssr_scale.push_constant.camera_z_far = p_camera.get_z_far(); - ssr_scale.push_constant.camera_z_near = p_camera.get_z_near(); - ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr_scale.push_constant.filter = false; //enabling causes arctifacts - ssr_scale.push_constant.screen_size[0] = p_screen_size.x; - ssr_scale.push_constant.screen_size[1] = p_screen_size.y; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - - { - ssr.push_constant.camera_z_far = p_camera.get_z_far(); - ssr.push_constant.camera_z_near = p_camera.get_z_near(); - ssr.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr.push_constant.screen_size[0] = p_screen_size.x; - ssr.push_constant.screen_size[1] = p_screen_size.y; - ssr.push_constant.curve_fade_in = p_fade_in; - ssr.push_constant.distance_fade = p_fade_out; - ssr.push_constant.num_steps = p_max_steps; - ssr.push_constant.depth_tolerance = p_tolerance; - ssr.push_constant.use_half_res = true; - ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]); - ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]); - ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0]; - ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1]; - ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255); - ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255); - ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255); - ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); - store_camera(p_camera, ssr.push_constant.projection); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant)); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0); - - if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - } - - if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - //blur - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); - ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]); - ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]); - ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0]; - ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1]; - ssr_filter.push_constant.vertical = 0; - if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { - ssr_filter.push_constant.steps = p_max_steps / 3; - ssr_filter.push_constant.increment = 3; - } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { - ssr_filter.push_constant.steps = p_max_steps / 2; - ssr_filter.push_constant.increment = 2; - } else { - ssr_filter.push_constant.steps = p_max_steps; - ssr_filter.push_constant.increment = 1; - } - - ssr_filter.push_constant.screen_size[0] = p_screen_size.width; - ssr_filter.push_constant.screen_size[1] = p_screen_size.height; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3); - - ssr_filter.push_constant.vertical = 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { +void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); Plane p = p_camera.xform4(Plane(1, 0, -1, 1)); @@ -443,36 +217,6 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept } } -void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>()); - - if (p_reflection.is_valid()) { - if (p_base.is_valid()) { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2); - } else { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - } - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1); - - } else { - if (p_base.is_valid()) { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2); - } else { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - } - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0); - } - - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer."); @@ -546,674 +290,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_ } } -void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) { - // Downsample and deinterleave the depth buffer for SSAO and SSIL - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE; - bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM; - - if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF; - } else if (use_mips) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP; - } - - bool use_half_size = false; - bool use_full_mips = false; - - if (p_ssao_half_size && p_ssil_half_size) { - downsample_pipeline++; - use_half_size = true; - } else if (p_ssao_half_size != p_ssil_half_size) { - if (use_mips) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS; - use_full_mips = true; - } else { - // Only need the first two mipmaps, but the cost to generate the next two is trivial - // TODO investigate the benefit of a shader version to generate only 2 mips - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP; - use_mips = true; - } - } - - int depth_index = use_half_size ? 1 : 0; - - RD::get_singleton()->draw_command_begin_label("Downsample Depth"); - if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_depth_mipmaps[depth_index + 1]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_depth_mipmaps[depth_index + 2]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 2; - u.append_id(p_depth_mipmaps[depth_index + 3]); - uniforms.push_back(u); - } - if (use_full_mips) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.append_id(p_depth_mipmaps[4]); - uniforms.push_back(u); - } - ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); - } - - float depth_linearize_mul = -p_projection.matrix[3][2]; - float depth_linearize_add = p_projection.matrix[2][2]; - if (depth_linearize_mul * depth_linearize_add < 0) { - depth_linearize_add = -depth_linearize_add; - } - - ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal(); - ss_effects.downsample_push_constant.z_near = depth_linearize_mul; - ss_effects.downsample_push_constant.z_far = depth_linearize_add; - if (ss_effects.downsample_push_constant.orthogonal) { - ss_effects.downsample_push_constant.z_near = p_projection.get_z_near(); - ss_effects.downsample_push_constant.z_far = p_projection.get_z_far(); - } - ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x; - ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y; - ss_effects.downsample_push_constant.radius_sq = 1.0; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1); - if (use_mips) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2); - } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant)); - - Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1))); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); - - ss_effects.used_full_mips_last_frame = use_full_mips; - ss_effects.used_half_size_last_frame = use_half_size; -} - -void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - ssao.gather_push_constant.pass_coord_offset[0] = i % 2; - ssao.gather_push_constant.pass_coord_offset[1] = i / 2; - ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; - ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; - ssao.gather_push_constant.pass = i; - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2); - RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); - - Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); - } - RD::get_singleton()->compute_list_add_barrier(p_compute_list); -} - -void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) { - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant)); - /* FIRST PASS */ - - RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion"); - /* SECOND PASS */ - // Sample SSAO - { - RD::get_singleton()->draw_command_begin_label("Gather Samples"); - ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; - ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - - ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; - float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; - ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; - ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; - ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; - ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; - ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - - ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; - - ssao.gather_push_constant.radius = p_settings.radius; - float radius_near_limit = (p_settings.radius * 1.2f); - if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) { - radius_near_limit *= 1.50f; - - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - ssao.gather_push_constant.radius *= 0.8f; - } - } - radius_near_limit /= tan_half_fov_y; - ssao.gather_push_constant.intensity = p_settings.intensity; - ssao.gather_push_constant.shadow_power = p_settings.power; - ssao.gather_push_constant.shadow_clamp = 0.98; - ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); - ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; - ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon; - ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; - ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; - - ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255); - ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; - - ssao.gather_push_constant.detail_intensity = p_settings.detail; - ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1); - ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_depth_mipmaps_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ao_pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_importance_map); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssao.importance_map_load_counter); - uniforms.push_back(u); - } - r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); - } - - if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) { - RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); - ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - ssao.importance_map_push_constant.intensity = p_settings.intensity; - ssao.importance_map_push_constant.power = p_settings.power; - //base pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); - gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID()); - //generate importance map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - //process importance map A - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - //process Importance Map B - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]); - RD::get_singleton()->draw_command_end_label(); // Importance Map - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); - } - - gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set); - RD::get_singleton()->draw_command_end_label(); // Gather SSAO - } - - // /* THIRD PASS */ - // // Blur - // - { - RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); - ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; - ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - - int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; - - for (int pass = 0; pass < blur_passes; pass++) { - int blur_pipeline = SSAO_BLUR_PASS; - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { - blur_pipeline = SSAO_BLUR_PASS_SMART; - if (pass < blur_passes - 2) { - blur_pipeline = SSAO_BLUR_PASS_WIDE; - } else { - blur_pipeline = SSAO_BLUR_PASS_SMART; - } - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); - if (pass % 2 == 0) { - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1); - } else { - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1); - } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); - - Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); - } - - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - } - RD::get_singleton()->draw_command_end_label(); // Blur - } - - /* FOURTH PASS */ - // Interleave buffers - // back to full size - { - RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); - ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; - ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; - ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; - ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); - - int interleave_pipeline = SSAO_INTERLEAVE_HALF; - if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) { - interleave_pipeline = SSAO_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { - interleave_pipeline = SSAO_INTERLEAVE_SMART; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0); - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); // Interleave - } - RD::get_singleton()->draw_command_end_label(); //SSAO - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer - - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier -} - -void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3); - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - ssil.gather_push_constant.pass_coord_offset[0] = i % 2; - ssil.gather_push_constant.pass_coord_offset[1] = i / 2; - ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; - ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; - ssil.gather_push_constant.pass = i; - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2); - RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant)); - - Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); - } - RD::get_singleton()->compute_list_add_barrier(p_compute_list); -} - -void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) { - RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting"); - //Store projection info before starting the compute list - SSILProjectionUniforms projection_uniforms; - store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix); - - RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms); - - memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant)); - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - { - RD::get_singleton()->draw_command_begin_label("Gather Samples"); - ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; - ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - - ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; - float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; - ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; - ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; - ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; - ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; - ssil.gather_push_constant.z_near = p_projection.get_z_near(); - ssil.gather_push_constant.z_far = p_projection.get_z_far(); - ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - - ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; - - ssil.gather_push_constant.radius = p_settings.radius; - float radius_near_limit = (p_settings.radius * 1.2f); - if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) { - radius_near_limit *= 1.50f; - - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - ssil.gather_push_constant.radius *= 0.8f; - } - } - radius_near_limit /= tan_half_fov_y; - ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI; - ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); - ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; - ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; - ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius; - ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection; - - ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255); - ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; - - ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1); - ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_mipmap_sampler); - u.append_id(p_diffuse); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.append_id(ssil.projection_uniform_buffer); - uniforms.push_back(u); - } - r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_depth_mipmaps_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ssil_pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_importance_map); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssil.importance_map_load_counter); - uniforms.push_back(u); - } - r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); - } - - if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) { - RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); - ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI; - //base pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]); - gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set); - //generate importance map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - // process Importance Map A - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - // process Importance Map B - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->draw_command_end_label(); // Importance Map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]); - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]); - } - - gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set); - RD::get_singleton()->draw_command_end_label(); //Gather - } - - { - RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); - ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; - ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - - int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; - - for (int pass = 0; pass < blur_passes; pass++) { - int blur_pipeline = SSIL_BLUR_PASS; - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { - blur_pipeline = SSIL_BLUR_PASS_SMART; - if (pass < blur_passes - 2) { - blur_pipeline = SSIL_BLUR_PASS_WIDE; - } - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]); - if (pass % 2 == 0) { - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1); - } else { - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant)); - - int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)); - int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1); - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - } - } - - RD::get_singleton()->draw_command_end_label(); // Blur - } - - { - RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); - ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; - ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; - ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; - ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); - - int interleave_pipeline = SSIL_INTERLEAVE_HALF; - if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) { - interleave_pipeline = SSIL_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { - interleave_pipeline = SSIL_INTERLEAVE_SMART; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0); - - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); // Interleave - } - - RD::get_singleton()->draw_command_end_label(); // SSIL - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); - - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier -} - void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { roughness_limiter.push_constant.screen_size[0] = p_size.x; roughness_limiter.push_constant.screen_size[1] = p_size.y; @@ -1304,12 +380,12 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { { Vector<String> FSR_upscale_modes; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though. FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); #else // Everyone else can use normal mode when available. - if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) { + if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); } else { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); @@ -1358,154 +434,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } if (!prefer_raster_effects) { - { - // Initialize depth buffer for screen space effects - Vector<String> downsampler_modes; - downsampler_modes.push_back("\n"); - downsampler_modes.push_back("\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n"); - downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS"); - - ss_effects.downsample_shader.initialize(downsampler_modes); - - ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create(); - - for (int i = 0; i < SS_EFFECTS_MAX; i++) { - ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i)); - } - - ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants)); - SSEffectsGatherConstants gather_constants; - - const int sub_pass_count = 5; - for (int pass = 0; pass < 4; pass++) { - for (int subPass = 0; subPass < sub_pass_count; subPass++) { - int a = pass; - int b = subPass; - - int spmap[5]{ 0, 1, 4, 3, 2 }; - b = spmap[subPass]; - - float ca, sa; - float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; - - ca = Math::cos(angle0); - sa = Math::sin(angle0); - - float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f; - - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca; - } - } - - RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants); - } - - { - // Initialize ssao - - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.max_lod = 4; - - ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler); - - uint32_t pipeline = 0; - { - Vector<String> ssao_modes; - - ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define SSAO_BASE\n"); - ssao_modes.push_back("\n#define ADAPTIVE\n"); - - ssao.gather_shader.initialize(ssao_modes); - - ssao.gather_shader_version = ssao.gather_shader.version_create(); - - for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i)); - pipeline++; - } - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define GENERATE_MAP\n"); - ssao_modes.push_back("\n#define PROCESS_MAPA\n"); - ssao_modes.push_back("\n#define PROCESS_MAPB\n"); - - ssao.importance_map_shader.initialize(ssao_modes); - - ssao.importance_map_shader_version = ssao.importance_map_shader.version_create(); - - for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP)); - - pipeline++; - } - ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero); - RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter"); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(ssao.importance_map_load_counter); - uniforms.push_back(u); - } - ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); - RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set"); - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MODE_NON_SMART\n"); - ssao_modes.push_back("\n#define MODE_SMART\n"); - ssao_modes.push_back("\n#define MODE_WIDE\n"); - - ssao.blur_shader.initialize(ssao_modes); - - ssao.blur_shader_version = ssao.blur_shader.version_create(); - - for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); - - pipeline++; - } - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MODE_NON_SMART\n"); - ssao_modes.push_back("\n#define MODE_SMART\n"); - ssao_modes.push_back("\n#define MODE_HALF\n"); - - ssao.interleave_shader.initialize(ssao_modes); - - ssao.interleave_shader_version = ssao.interleave_shader.version_create(); - for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE)); - RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i)); - pipeline++; - } - } - - ERR_FAIL_COND(pipeline != SSAO_MAX); - } - } - - if (!prefer_raster_effects) { // Initialize roughness limiter Vector<String> shader_modes; shader_modes.push_back(""); @@ -1518,81 +446,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } if (!prefer_raster_effects) { - Vector<String> specular_modes; - specular_modes.push_back("\n#define MODE_MERGE\n"); - specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); - specular_modes.push_back("\n"); - specular_modes.push_back("\n#define MODE_SSR\n"); - - specular_merge.shader.initialize(specular_modes); - - specular_merge.shader_version = specular_merge.shader.version_create(); - - //use additive - - RD::PipelineColorBlendState::Attachment ba; - ba.enable_blend = true; - ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE; - ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - ba.color_blend_op = RD::BLEND_OP_ADD; - ba.alpha_blend_op = RD::BLEND_OP_ADD; - - RD::PipelineColorBlendState blend_additive; - blend_additive.attachments.push_back(ba); - - for (int i = 0; i < SPECULAR_MERGE_MAX; i++) { - RD::PipelineColorBlendState blend_state; - if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) { - blend_state = blend_additive; - } else { - blend_state = RD::PipelineColorBlendState::create_disabled(); - } - specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); - } - } - - if (!prefer_raster_effects) { - { - Vector<String> ssr_modes; - ssr_modes.push_back("\n"); - ssr_modes.push_back("\n#define MODE_ROUGH\n"); - - ssr.shader.initialize(ssr_modes); - - ssr.shader_version = ssr.shader.version_create(); - - for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { - ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i)); - } - } - - { - Vector<String> ssr_filter_modes; - ssr_filter_modes.push_back("\n"); - ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); - - ssr_filter.shader.initialize(ssr_filter_modes); - - ssr_filter.shader_version = ssr_filter.shader.version_create(); - - for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { - ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i)); - } - } - - { - Vector<String> ssr_scale_modes; - ssr_scale_modes.push_back("\n"); - - ssr_scale.shader.initialize(ssr_scale_modes); - - ssr_scale.shader_version = ssr_scale.shader.version_create(); - - ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0)); - } - { Vector<String> sss_modes; sss_modes.push_back("\n#define USE_11_SAMPLES\n"); @@ -1607,79 +460,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); } } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n"); - ssil_modes.push_back("\n#define SSIL_BASE\n"); - ssil_modes.push_back("\n#define ADAPTIVE\n"); - - ssil.gather_shader.initialize(ssil_modes); - - ssil.gather_shader_version = ssil.gather_shader.version_create(); - - for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i)); - } - ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms)); - } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define GENERATE_MAP\n"); - ssil_modes.push_back("\n#define PROCESS_MAPA\n"); - ssil_modes.push_back("\n#define PROCESS_MAPB\n"); - - ssil.importance_map_shader.initialize(ssil_modes); - - ssil.importance_map_shader_version = ssil.importance_map_shader.version_create(); - - for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP)); - } - ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero); - RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter"); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(ssil.importance_map_load_counter); - uniforms.push_back(u); - } - ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2); - RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set"); - } - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define MODE_NON_SMART\n"); - ssil_modes.push_back("\n#define MODE_SMART\n"); - ssil_modes.push_back("\n#define MODE_WIDE\n"); - - ssil.blur_shader.initialize(ssil_modes); - - ssil.blur_shader_version = ssil.blur_shader.version_create(); - for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS)); - } - } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define MODE_NON_SMART\n"); - ssil_modes.push_back("\n#define MODE_SMART\n"); - ssil_modes.push_back("\n#define MODE_HALF\n"); - - ssil.interleave_shader.initialize(ssil_modes); - - ssil.interleave_shader_version = ssil.interleave_shader.version_create(); - for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE)); - } - } } { @@ -1751,27 +531,8 @@ EffectsRD::~EffectsRD() { luminance_reduce.shader.version_free(luminance_reduce.shader_version); } if (!prefer_raster_effects) { - specular_merge.shader.version_free(specular_merge.shader_version); - ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); - ssao.blur_shader.version_free(ssao.blur_shader_version); - ssao.gather_shader.version_free(ssao.gather_shader_version); - ssao.interleave_shader.version_free(ssao.interleave_shader_version); - ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); - ssil.blur_shader.version_free(ssil.blur_shader_version); - ssil.gather_shader.version_free(ssil.gather_shader_version); - ssil.interleave_shader.version_free(ssil.interleave_shader_version); - ssil.importance_map_shader.version_free(ssil.importance_map_shader_version); roughness_limiter.shader.version_free(roughness_limiter.shader_version); - ssr.shader.version_free(ssr.shader_version); - ssr_filter.shader.version_free(ssr_filter.shader_version); - ssr_scale.shader.version_free(ssr_scale.shader_version); sss.shader.version_free(sss.shader_version); - - RD::get_singleton()->free(ss_effects.mirror_sampler); - RD::get_singleton()->free(ss_effects.gather_constants_buffer); - RD::get_singleton()->free(ssao.importance_map_load_counter); - RD::get_singleton()->free(ssil.importance_map_load_counter); - RD::get_singleton()->free(ssil.projection_uniform_buffer); } sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 76627a8d7d..94cd26fae9 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -31,26 +31,13 @@ #ifndef EFFECTS_RD_H #define EFFECTS_RD_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" @@ -142,231 +129,6 @@ private: PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX]; } luminance_reduce_raster; - struct SSEffectsDownsamplePushConstant { - float pixel_size[2]; - float z_far; - float z_near; - uint32_t orthogonal; - float radius_sq; - uint32_t pad[2]; - }; - - enum SSEffectsMode { - SS_EFFECTS_DOWNSAMPLE, - SS_EFFECTS_DOWNSAMPLE_HALF_RES, - SS_EFFECTS_DOWNSAMPLE_MIPMAP, - SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES, - SS_EFFECTS_DOWNSAMPLE_HALF, - SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF, - SS_EFFECTS_DOWNSAMPLE_FULL_MIPS, - SS_EFFECTS_MAX - }; - - struct SSEffectsGatherConstants { - float rotation_matrices[80]; //5 vec4s * 4 - }; - - struct SSEffects { - SSEffectsDownsamplePushConstant downsample_push_constant; - SsEffectsDownsampleShaderRD downsample_shader; - RID downsample_shader_version; - RID downsample_uniform_set; - bool used_half_size_last_frame = false; - bool used_mips_last_frame = false; - bool used_full_mips_last_frame = false; - - RID gather_constants_buffer; - - RID mirror_sampler; - - RID pipelines[SS_EFFECTS_MAX]; - } ss_effects; - - enum SSAOMode { - SSAO_GATHER, - SSAO_GATHER_BASE, - SSAO_GATHER_ADAPTIVE, - SSAO_GENERATE_IMPORTANCE_MAP, - SSAO_PROCESS_IMPORTANCE_MAPA, - SSAO_PROCESS_IMPORTANCE_MAPB, - SSAO_BLUR_PASS, - SSAO_BLUR_PASS_SMART, - SSAO_BLUR_PASS_WIDE, - SSAO_INTERLEAVE, - SSAO_INTERLEAVE_SMART, - SSAO_INTERLEAVE_HALF, - SSAO_MAX - }; - - struct SSAOGatherPushConstant { - int32_t screen_size[2]; - int pass; - int quality; - - float half_screen_pixel_size[2]; - int size_multiplier; - float detail_intensity; - - float NDC_to_view_mul[2]; - float NDC_to_view_add[2]; - - float pad[2]; - float half_screen_pixel_size_x025[2]; - - float radius; - float intensity; - float shadow_power; - float shadow_clamp; - - float fade_out_mul; - float fade_out_add; - float horizon_angle_threshold; - float inv_radius_near_limit; - - uint32_t is_orthogonal; - float neg_inv_radius; - float load_counter_avg_div; - float adaptive_sample_limit; - - int32_t pass_coord_offset[2]; - float pass_uv_offset[2]; - }; - - struct SSAOImportanceMapPushConstant { - float half_screen_pixel_size[2]; - float intensity; - float power; - }; - - struct SSAOBlurPushConstant { - float edge_sharpness; - float pad; - float half_screen_pixel_size[2]; - }; - - struct SSAOInterleavePushConstant { - float inv_sharpness; - uint32_t size_modifier; - float pixel_size[2]; - }; - - struct SSAO { - SSAOGatherPushConstant gather_push_constant; - SsaoShaderRD gather_shader; - RID gather_shader_version; - - SSAOImportanceMapPushConstant importance_map_push_constant; - SsaoImportanceMapShaderRD importance_map_shader; - RID importance_map_shader_version; - RID importance_map_load_counter; - RID counter_uniform_set; - - SSAOBlurPushConstant blur_push_constant; - SsaoBlurShaderRD blur_shader; - RID blur_shader_version; - - SSAOInterleavePushConstant interleave_push_constant; - SsaoInterleaveShaderRD interleave_shader; - RID interleave_shader_version; - - RID pipelines[SSAO_MAX]; - } ssao; - - enum SSILMode { - SSIL_GATHER, - SSIL_GATHER_BASE, - SSIL_GATHER_ADAPTIVE, - SSIL_GENERATE_IMPORTANCE_MAP, - SSIL_PROCESS_IMPORTANCE_MAPA, - SSIL_PROCESS_IMPORTANCE_MAPB, - SSIL_BLUR_PASS, - SSIL_BLUR_PASS_SMART, - SSIL_BLUR_PASS_WIDE, - SSIL_INTERLEAVE, - SSIL_INTERLEAVE_SMART, - SSIL_INTERLEAVE_HALF, - SSIL_MAX - }; - - struct SSILGatherPushConstant { - int32_t screen_size[2]; - int pass; - int quality; - - float half_screen_pixel_size[2]; - float half_screen_pixel_size_x025[2]; - - float NDC_to_view_mul[2]; - float NDC_to_view_add[2]; - - float pad2[2]; - float z_near; - float z_far; - - float radius; - float intensity; - int size_multiplier; - int pad; - - float fade_out_mul; - float fade_out_add; - float normal_rejection_amount; - float inv_radius_near_limit; - - uint32_t is_orthogonal; - float neg_inv_radius; - float load_counter_avg_div; - float adaptive_sample_limit; - - int32_t pass_coord_offset[2]; - float pass_uv_offset[2]; - }; - - struct SSILImportanceMapPushConstant { - float half_screen_pixel_size[2]; - float intensity; - float pad; - }; - - struct SSILBlurPushConstant { - float edge_sharpness; - float pad; - float half_screen_pixel_size[2]; - }; - - struct SSILInterleavePushConstant { - float inv_sharpness; - uint32_t size_modifier; - float pixel_size[2]; - }; - - struct SSILProjectionUniforms { - float inv_last_frame_projection_matrix[16]; - }; - - struct SSIL { - SSILGatherPushConstant gather_push_constant; - SsilShaderRD gather_shader; - RID gather_shader_version; - RID projection_uniform_buffer; - - SSILImportanceMapPushConstant importance_map_push_constant; - SsilImportanceMapShaderRD importance_map_shader; - RID importance_map_shader_version; - RID importance_map_load_counter; - RID counter_uniform_set; - - SSILBlurPushConstant blur_push_constant; - SsilBlurShaderRD blur_shader; - RID blur_shader_version; - - SSILInterleavePushConstant interleave_push_constant; - SsilInterleaveShaderRD interleave_shader; - RID interleave_shader_version; - - RID pipelines[SSIL_MAX]; - } ssil; - struct RoughnessLimiterPushConstant { int32_t screen_size[2]; float curve; @@ -381,101 +143,6 @@ private: } roughness_limiter; - enum SpecularMergeMode { - SPECULAR_MERGE_ADD, - SPECULAR_MERGE_SSR, - SPECULAR_MERGE_ADDITIVE_ADD, - SPECULAR_MERGE_ADDITIVE_SSR, - SPECULAR_MERGE_MAX - }; - - /* Specular merge must be done using raster, rather than compute - * because it must continue the existing color buffer - */ - - struct SpecularMerge { - SpecularMergeShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[SPECULAR_MERGE_MAX]; - - } specular_merge; - - enum ScreenSpaceReflectionMode { - SCREEN_SPACE_REFLECTION_NORMAL, - SCREEN_SPACE_REFLECTION_ROUGH, - SCREEN_SPACE_REFLECTION_MAX, - }; - - struct ScreenSpaceReflectionPushConstant { - float proj_info[4]; - - int32_t screen_size[2]; - float camera_z_near; - float camera_z_far; - - int32_t num_steps; - float depth_tolerance; - float distance_fade; - float curve_fade_in; - - uint32_t orthogonal; - float filter_mipmap_levels; - uint32_t use_half_res; - uint8_t metallic_mask[4]; - - float projection[16]; - }; - - struct ScreenSpaceReflection { - ScreenSpaceReflectionPushConstant push_constant; - ScreenSpaceReflectionShaderRD shader; - RID shader_version; - RID pipelines[SCREEN_SPACE_REFLECTION_MAX]; - - } ssr; - - struct ScreenSpaceReflectionFilterPushConstant { - float proj_info[4]; - - uint32_t orthogonal; - float edge_tolerance; - int32_t increment; - uint32_t pad; - - int32_t screen_size[2]; - uint32_t vertical; - uint32_t steps; - }; - enum { - SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL, - SCREEN_SPACE_REFLECTION_FILTER_VERTICAL, - SCREEN_SPACE_REFLECTION_FILTER_MAX, - }; - - struct ScreenSpaceReflectionFilter { - ScreenSpaceReflectionFilterPushConstant push_constant; - ScreenSpaceReflectionFilterShaderRD shader; - RID shader_version; - RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX]; - } ssr_filter; - - struct ScreenSpaceReflectionScalePushConstant { - int32_t screen_size[2]; - float camera_z_near; - float camera_z_far; - - uint32_t orthogonal; - uint32_t filter; - uint32_t pad[2]; - }; - - struct ScreenSpaceReflectionScale { - ScreenSpaceReflectionScalePushConstant push_constant; - ScreenSpaceReflectionScaleShaderRD shader; - RID shader_version; - RID pipeline; - } ssr_scale; - struct SubSurfaceScatteringPushConstant { int32_t screen_size[2]; float camera_z_far; @@ -559,9 +226,6 @@ private: RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); - RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler); - RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false); - RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2); public: bool get_prefer_raster_effects(); @@ -572,57 +236,9 @@ public: void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); - struct SSAOSettings { - float radius = 1.0; - float intensity = 2.0; - float power = 1.5; - float detail = 0.5; - float horizon = 0.06; - float sharpness = 0.98; - - RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM; - bool half_size = false; - float adaptive_target = 0.5; - int blur_passes = 2; - float fadeout_from = 50.0; - float fadeout_to = 300.0; - - Size2i full_screen_size = Size2i(); - Size2i half_screen_size = Size2i(); - Size2i quarter_screen_size = Size2i(); - }; - - struct SSILSettings { - float radius = 1.0; - float intensity = 2.0; - float sharpness = 0.98; - float normal_rejection = 1.0; - - RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM; - bool half_size = true; - float adaptive_target = 0.5; - int blur_passes = 4; - float fadeout_from = 50.0; - float fadeout_to = 300.0; - - Size2i full_screen_size = Size2i(); - Size2i half_screen_size = Size2i(); - Size2i quarter_screen_size = Size2i(); - }; - - void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection); - - void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); - void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set); - - void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); - void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set); - void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); - void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); - void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); - void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); void sort_buffer(RID p_uniform_set, int p_size); @@ -630,4 +246,4 @@ public: ~EffectsRD(); }; -#endif // !RASTERIZER_EFFECTS_RD_H +#endif // EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 2a6c96480e..58f4c855a4 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -30,6 +30,11 @@ #include "fog.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/rendering_server_default.h" + using namespace RendererRD; Fog *Fog::singleton = nullptr; @@ -126,3 +131,1075 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { ERR_FAIL_COND_V(!fog_volume, Vector3()); return fog_volume->extents; } + +//////////////////////////////////////////////////////////////////////////////// +// Fog material + +bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + uniform_set_updated = true; + + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); +} + +Fog::FogMaterialData::~FogMaterialData() { + free_parameters_uniform_set(uniform_set); +} + +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { + FogShaderData *shader_data = memnew(FogShaderData); + return shader_data; +} + +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { + return Fog::get_singleton()->_create_fog_shader_func(); +}; + +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { + FogMaterialData *material_data = memnew(FogMaterialData); + material_data->shader_data = p_shader; + //update will happen later anyway so do nothing. + return material_data; +} + +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { + return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); +}; + +//////////////////////////////////////////////////////////////////////////////// +// FOG VOLUMES INSTANCE + +RID Fog::fog_volume_instance_create(RID p_fog_volume) { + FogVolumeInstance fvi; + fvi.volume = p_fog_volume; + return fog_volume_instance_owner.make_rid(fvi); +} + +void Fog::fog_instance_free(RID p_rid) { + fog_volume_instance_owner.free(p_rid); +} + +//////////////////////////////////////////////////////////////////////////////// +// Volumetric Fog Shader + +void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + { + // Initialize local fog shader + Vector<String> volumetric_fog_modes; + volumetric_fog_modes.push_back(""); + volumetric_fog.shader.initialize(volumetric_fog_modes); + + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs); + volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); + } + + { + ShaderCompiler::DefaultIdentifierActions actions; + + actions.renames["TIME"] = "scene_params.time"; + actions.renames["PI"] = _MKSTR(Math_PI); + actions.renames["TAU"] = _MKSTR(Math_TAU); + actions.renames["E"] = _MKSTR(Math_E); + actions.renames["WORLD_POSITION"] = "world.xyz"; + actions.renames["OBJECT_POSITION"] = "params.position"; + actions.renames["UVW"] = "uvw"; + actions.renames["EXTENTS"] = "params.extents"; + actions.renames["ALBEDO"] = "albedo"; + actions.renames["DENSITY"] = "density"; + actions.renames["EMISSION"] = "emission"; + actions.renames["SDF"] = "sdf"; + + actions.usage_defines["SDF"] = "#define SDF_USED\n"; + actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n"; + actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n"; + actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n"; + + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL; + actions.base_uniform_string = "material."; + + actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; + actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; + actions.global_buffer_array_variable = "global_variables.data"; + + volumetric_fog.compiler.initialize(actions); + } + + { + // default material and shader for fog shader + volumetric_fog.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(volumetric_fog.default_shader); + material_storage->shader_set_code(volumetric_fog.default_shader, R"( +// Default fog shader. + +shader_type fog; + +void fog() { +DENSITY = 1.0; +ALBEDO = vec3(1.0); +} +)"); + volumetric_fog.default_material = material_storage->material_allocate(); + material_storage->material_initialize(volumetric_fog.default_material); + material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); + + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); + volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); + + Vector<RD::Uniform> uniforms; + + { + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); + ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); + uniforms.push_back(u); + } + + volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); + } + { + String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n"; + defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n"; + if (p_is_using_radiance_cubemap_array) { + defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; + } + Vector<String> volumetric_fog_modes; + volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); + volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); + volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); + volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); + volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); + + volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); + volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); + for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { + volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i)); + } + volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO)); + } +} + +void Fog::free_fog_shader() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); + RD::get_singleton()->free(volumetric_fog.volume_ubo); + RD::get_singleton()->free(volumetric_fog.params_ubo); + material_storage->shader_free(volumetric_fog.default_shader); + material_storage->material_free(volumetric_fog.default_material); +} + +void Fog::FogShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + +void Fog::FogShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + + if (code.is_empty()) { + return; //just invalid, but no error + } + + ShaderCompiler::GeneratedCode gen_code; + ShaderCompiler::IdentifierActions actions; + actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE; + + uses_time = false; + + actions.usage_flag_pointers["TIME"] = &uses_time; + + actions.uniforms = &uniforms; + + Fog *fog_singleton = Fog::get_singleton(); + + Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); + ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); + + if (version.is_null()) { + version = fog_singleton->volumetric_fog.shader.version_create(); + } + + fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); + ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0)); + + valid = true; +} + +void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { + if (!p_texture.is_valid()) { + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } + } else { + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = HashMap<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; + } +} + +void Fog::FogShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { + RBMap<int, StringName> order; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; + } else { + order[E.value.order] = E.key; + } + } + + String last_group; + for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; + p_param_list->push_back(pi); + } +} + +void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererMaterialStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); + p_param_list->push_back(p); + } +} + +bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool Fog::FogShaderData::is_animated() const { + return false; +} + +bool Fog::FogShaderData::casts_shadows() const { + return false; +} + +Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); + } + return Variant(); +} + +RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { + Fog *fog_singleton = Fog::get_singleton(); + + return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version); +} + +Fog::FogShaderData::~FogShaderData() { + Fog *fog_singleton = Fog::get_singleton(); + ERR_FAIL_COND(!fog_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + fog_singleton->volumetric_fog.shader.version_free(version); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Volumetric Fog + +Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { + width = fog_size.x; + height = fog_size.y; + depth = fog_size.z; + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = fog_size.x; + tf.height = fog_size.y; + tf.depth = fog_size.z; + tf.texture_type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map"); + + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + + prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map"); + RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(fog_map, "Fog map"); + +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + Vector<uint8_t> dm; + dm.resize(fog_size.x * fog_size.y * fog_size.z * 4); + dm.fill(0); + + density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(density_map, "Fog density map"); + light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(light_map, "Fog light map"); + emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map"); +#else + tf.format = RD::DATA_FORMAT_R32_UINT; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(density_map, "Fog density map"); + RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + light_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(light_map, "Fog light map"); + RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map"); + RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); +#endif + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.append_id(fog_map); + uniforms.push_back(u); + } + + sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG); +} + +Fog::VolumetricFog::~VolumetricFog() { + RD::get_singleton()->free(prev_light_density_map); + RD::get_singleton()->free(light_density_map); + RD::get_singleton()->free(fog_map); + RD::get_singleton()->free(density_map); + RD::get_singleton()->free(light_map); + RD::get_singleton()->free(emissive_map); + + if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) { + RD::get_singleton()->free(fog_uniform_set); + } + if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) { + RD::get_singleton()->free(process_uniform_set_density); + } + if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) { + RD::get_singleton()->free(process_uniform_set); + } + if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) { + RD::get_singleton()->free(process_uniform_set2); + } + if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) { + RD::get_singleton()->free(sdfgi_uniform_set); + } + if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) { + RD::get_singleton()->free(sky_uniform_set); + } +} + +Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) { + Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point); + view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera + Vector3 fog_position = Vector3(0, 0, 0); + + view_position.y = -view_position.y; + fog_position.z = -view_position.z / fog_end; + fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5; + fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5; + fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread)); + fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5); + + fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x); + fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y); + fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z); + + return Vector3i(fog_position); +} + +void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + + RENDER_TIMESTAMP("> Volumetric Fog"); + RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); + + if (p_fog_volumes.size() > 0) { + RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); + + RENDER_TIMESTAMP("Render FogVolumes"); + + VolumetricFogShader::VolumeUBO params; + + Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); + Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); + float z_near = p_cam_projection.get_z_near(); + float z_far = p_cam_projection.get_z_far(); + float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); + + Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); + Vector2 fog_near_size; + if (p_cam_projection.is_orthogonal()) { + fog_near_size = fog_far_size; + } else { + fog_near_size = Vector2(); + } + + params.fog_frustum_size_begin[0] = fog_near_size.x; + params.fog_frustum_size_begin[1] = fog_near_size.y; + + params.fog_frustum_size_end[0] = fog_far_size.x; + params.fog_frustum_size_end[1] = fog_far_size.y; + + params.fog_frustum_end = fog_end; + params.z_near = z_near; + params.z_far = z_far; + params.time = p_settings.time; + + params.fog_volume_size[0] = p_settings.vfog->width; + params.fog_volume_size[1] = p_settings.vfog->height; + params.fog_volume_size[2] = p_settings.vfog->depth; + + params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); + params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; + params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env); + + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); + RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); + + RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + + if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 1; + u.append_id(p_settings.vfog->emissive_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(volumetric_fog.volume_ubo); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 3; + u.append_id(p_settings.vfog->density_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 4; + u.append_id(p_settings.vfog->light_map); + uniforms.push_back(u); + } + + p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + bool any_uses_time = false; + + for (int i = 0; i < (int)p_fog_volumes.size(); i++) { + FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); + ERR_FAIL_COND(!fog_volume_instance); + RID fog_volume = fog_volume_instance->volume; + + RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); + + FogMaterialData *material = nullptr; + + if (fog_material.is_valid()) { + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); + if (!material || !material->shader_data->valid) { + material = nullptr; + } + } + + if (!material) { + fog_material = volumetric_fog.default_material; + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); + } + + ERR_FAIL_COND(!material); + + FogShaderData *shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + any_uses_time |= shader_data->uses_time; + + Vector3i min = Vector3i(); + Vector3i max = Vector3i(); + Vector3i kernel_size = Vector3i(); + + Vector3 position = fog_volume_instance->transform.get_origin(); + RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); + Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); + + if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { + // Local fog volume. + Vector3i points[8]; + Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); + + min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1); + max = Vector3i(1, 1, 1); + + for (int j = 0; j < 8; j++) { + min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z)); + max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z)); + } + + kernel_size = max - min; + } else { + // Volume type global runs on all cells + extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + min = Vector3i(0, 0, 0); + kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth)); + } + + if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { + continue; + } + + VolumetricFogShader::FogPushConstant push_constant; + push_constant.position[0] = position.x; + push_constant.position[1] = position.y; + push_constant.position[2] = position.z; + push_constant.extents[0] = extents.x; + push_constant.extents[1] = extents.y; + push_constant.extents[2] = extents.z; + push_constant.corner[0] = min.x; + push_constant.corner[1] = min.y; + push_constant.corner[2] = min.z; + push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); + RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant)); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); + if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); + } + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); + } + if (any_uses_time || RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { + RenderingServerDefault::redraw_request(); + } + + RD::get_singleton()->draw_command_end_label(); + + RD::get_singleton()->compute_list_end(); + } + + if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) { + //re create uniform set if needed + Vector<RD::Uniform> uniforms; + Vector<RD::Uniform> copy_uniforms; + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + if (p_settings.shadow_atlas_depth.is_null()) { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); + } else { + u.append_id(p_settings.shadow_atlas_depth); + } + + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + if (p_settings.directional_shadow_depth.is_valid()) { + u.append_id(p_settings.directional_shadow_depth); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); + } + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 3; + u.append_id(p_settings.omni_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 4; + u.append_id(p_settings.spot_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 5; + u.append_id(p_settings.directional_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 6; + u.append_id(p_settings.cluster_builder->get_cluster_buffer()); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 7; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.append_id(p_settings.vfog->light_density_map); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.append_id(p_settings.vfog->fog_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.append_id(p_settings.vfog->prev_light_density_map); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 10; + u.append_id(p_settings.shadow_sampler); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 11; + u.append_id(p_settings.voxel_gl_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 12; + for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { + u.append_id(p_settings.rbgi->voxel_gi_textures[i]); + } + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 13; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 14; + u.append_id(volumetric_fog.params_ubo); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 15; + u.append_id(p_settings.vfog->prev_light_density_map); + uniforms.push_back(u); + } + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 16; + u.append_id(p_settings.vfog->density_map); + uniforms.push_back(u); + } + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 17; + u.append_id(p_settings.vfog->light_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 18; + u.append_id(p_settings.vfog->emissive_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 19; + RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID(); + u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); + uniforms.push_back(u); + } + + p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); + + p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + + RID aux7 = uniforms.write[7].get_id(0); + RID aux8 = uniforms.write[8].get_id(0); + + uniforms.write[7].set_id(0, aux8); + uniforms.write[8].set_id(0, aux7); + + p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + + uniforms.remove_at(8); + uniforms.write[7].set_id(0, aux7); + p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); + } + + bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr); + + if (using_sdfgi) { + if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.append_id(p_settings.gi->sdfgi_ubo); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.append_id(p_settings.sdfgi->ambient_texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.append_id(p_settings.sdfgi->occlusion_texture); + uniforms.push_back(u); + } + + p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); + } + } + + p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); + p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + + VolumetricFogShader::ParamsUBO params; + + Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); + Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); + float z_near = p_cam_projection.get_z_near(); + float z_far = p_cam_projection.get_z_far(); + float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); + + Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); + Vector2 fog_near_size; + if (p_cam_projection.is_orthogonal()) { + fog_near_size = fog_far_size; + } else { + fog_near_size = Vector2(); + } + + params.fog_frustum_size_begin[0] = fog_near_size.x; + params.fog_frustum_size_begin[1] = fog_near_size.y; + + params.fog_frustum_size_end[0] = fog_far_size.x; + params.fog_frustum_size_end[1] = fog_far_size.y; + + params.ambient_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_ambient_inject(p_settings.env) * RendererSceneRenderRD::get_singleton()->environment_get_ambient_light_energy(p_settings.env); + params.z_far = z_far; + + params.fog_frustum_end = fog_end; + + Color ambient_color = RendererSceneRenderRD::get_singleton()->environment_get_ambient_light(p_settings.env).srgb_to_linear(); + params.ambient_color[0] = ambient_color.r; + params.ambient_color[1] = ambient_color.g; + params.ambient_color[2] = ambient_color.b; + params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env); + + params.fog_volume_size[0] = p_settings.vfog->width; + params.fog_volume_size[1] = p_settings.vfog->height; + params.fog_volume_size[2] = p_settings.vfog->depth; + + params.directional_light_count = p_directional_light_count; + + Color emission = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission(p_settings.env).srgb_to_linear(); + params.base_emission[0] = emission.r * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); + params.base_emission[1] = emission.g * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); + params.base_emission[2] = emission.b * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); + params.base_density = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_density(p_settings.env); + + Color base_scattering = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_scattering(p_settings.env).srgb_to_linear(); + params.base_scattering[0] = base_scattering.r; + params.base_scattering[1] = base_scattering.g; + params.base_scattering[2] = base_scattering.b; + params.phase_g = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_anisotropy(p_settings.env); + + params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + params.gi_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env); + + params.cam_rotation[0] = p_cam_transform.basis[0][0]; + params.cam_rotation[1] = p_cam_transform.basis[1][0]; + params.cam_rotation[2] = p_cam_transform.basis[2][0]; + params.cam_rotation[3] = 0; + params.cam_rotation[4] = p_cam_transform.basis[0][1]; + params.cam_rotation[5] = p_cam_transform.basis[1][1]; + params.cam_rotation[6] = p_cam_transform.basis[2][1]; + params.cam_rotation[7] = 0; + params.cam_rotation[8] = p_cam_transform.basis[0][2]; + params.cam_rotation[9] = p_cam_transform.basis[1][2]; + params.cam_rotation[10] = p_cam_transform.basis[2][2]; + params.cam_rotation[11] = 0; + params.filter_axis = 0; + params.max_voxel_gi_instances = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.001 ? p_voxel_gi_count : 0; + params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; + + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); + + params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); + params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env); + + { + uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size(); + params.cluster_shift = get_shift_from_power_of_2(cluster_size); + + uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1; + uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1; + params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32; + params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); + params.cluster_width = cluster_screen_width; + + params.screen_size[0] = p_settings.rb_size.x; + params.screen_size[1] = p_settings.rb_size.y; + } + + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_settings.env); + sky_transform = sky_transform.inverse() * p_cam_transform.basis; + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); + + RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); + + RENDER_TIMESTAMP("Render Fog"); + RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0); + + if (using_sdfgi) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1); + } + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // Copy fog to history buffer + if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + RD::get_singleton()->draw_command_end_label(); + + if (p_settings.volumetric_fog_filter_active) { + RD::get_singleton()->draw_command_begin_label("Filter Fog"); + + RENDER_TIMESTAMP("Filter Fog"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + + RD::get_singleton()->compute_list_end(); + //need restart for buffer update + + params.filter_axis = 1; + RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); + + compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); + } + + RENDER_TIMESTAMP("Integrate Fog"); + RD::get_singleton()->draw_command_begin_label("Integrate Fog"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1); + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); + + RENDER_TIMESTAMP("< Volumetric Fog"); + RD::get_singleton()->draw_command_end_label(); + RD::get_singleton()->draw_command_end_label(); +} diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 55a01c3616..171f9f3b88 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -34,12 +34,18 @@ #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" #include "servers/rendering/environment/renderer_fog.h" +#include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/environment/gi.h" +#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h" #include "servers/rendering/storage/utilities.h" namespace RendererRD { class Fog : public RendererFog { public: + /* FOG VOLUMES */ + struct FogVolume { RID material; Vector3 extents = Vector3(1, 1, 1); @@ -49,10 +55,179 @@ public: Dependency dependency; }; + struct FogVolumeInstance { + RID volume; + Transform3D transform; + bool active = false; + }; + private: static Fog *singleton; mutable RID_Owner<FogVolume, true> fog_volume_owner; + mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner; + + /* Volumetric Fog */ + struct VolumetricFogShader { + enum FogSet { + FOG_SET_BASE, + FOG_SET_UNIFORMS, + FOG_SET_MATERIAL, + FOG_SET_MAX, + }; + + struct FogPushConstant { + float position[3]; + float pad; + + float extents[3]; + float pad2; + + int32_t corner[3]; + uint32_t shape; + + float transform[16]; + }; + + struct VolumeUBO { + float fog_frustum_size_begin[2]; + float fog_frustum_size_end[2]; + + float fog_frustum_end; + float z_near; + float z_far; + float time; + + int32_t fog_volume_size[3]; + uint32_t directional_light_count; + + uint32_t use_temporal_reprojection; + uint32_t temporal_frame; + float detail_spread; + float temporal_blend; + + float to_prev_view[16]; + float transform[16]; + }; + + ShaderCompiler compiler; + VolumetricFogShaderRD shader; + RID volume_ubo; + + RID default_shader; + RID default_material; + RID default_shader_rd; + + RID base_uniform_set; + + RID params_ubo; + + enum { + VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY, + VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI, + VOLUMETRIC_FOG_PROCESS_SHADER_FILTER, + VOLUMETRIC_FOG_PROCESS_SHADER_FOG, + VOLUMETRIC_FOG_PROCESS_SHADER_COPY, + VOLUMETRIC_FOG_PROCESS_SHADER_MAX, + }; + + struct ParamsUBO { + float fog_frustum_size_begin[2]; + float fog_frustum_size_end[2]; + + float fog_frustum_end; + float ambient_inject; + float z_far; + uint32_t filter_axis; + + float ambient_color[3]; + float sky_contribution; + + int32_t fog_volume_size[3]; + uint32_t directional_light_count; + + float base_emission[3]; + float base_density; + + float base_scattering[3]; + float phase_g; + + float detail_spread; + float gi_inject; + uint32_t max_voxel_gi_instances; + uint32_t cluster_type_size; + + float screen_size[2]; + uint32_t cluster_shift; + uint32_t cluster_width; + + uint32_t max_cluster_element_count_div_32; + uint32_t use_temporal_reprojection; + uint32_t temporal_frame; + float temporal_blend; + + float cam_rotation[12]; + float to_prev_view[16]; + float radiance_inverse_xform[12]; + }; + + VolumetricFogProcessShaderRD process_shader; + + RID process_shader_version; + RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX]; + + } volumetric_fog; + + Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); + + struct FogShaderData : public RendererRD::MaterialStorage::ShaderData { + bool valid = false; + RID version; + + RID pipeline; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size = 0; + + String path; + String code; + HashMap<StringName, HashMap<int, RID>> default_texture_params; + + bool uses_time = false; + + virtual void set_path_hint(const String &p_hint); + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + virtual RS::ShaderNativeSourceCode get_native_source_code() const; + + FogShaderData() {} + virtual ~FogShaderData(); + }; + + struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData { + FogShaderData *shader_data = nullptr; + RID uniform_set; + bool uniform_set_updated; + + virtual void set_render_priority(int p_priority) {} + virtual void set_next_pass(RID p_pass) {} + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~FogMaterialData(); + }; + + RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs(); + + RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); public: static Fog *get_singleton() { return singleton; } @@ -76,8 +251,78 @@ public: RID fog_volume_get_material(RID p_fog_volume) const; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; Vector3 fog_volume_get_extents(RID p_fog_volume) const; + + /* FOG VOLUMES INSTANCE */ + + FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); }; + bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; + + RID fog_volume_instance_create(RID p_fog_volume); + void fog_instance_free(RID p_rid); + + /* Volumetric FOG */ + struct VolumetricFog { + enum { + MAX_TEMPORAL_FRAMES = 16 + }; + + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; + + float length; + float spread; + + RID light_density_map; + RID prev_light_density_map; + RID fog_map; + RID density_map; + RID light_map; + RID emissive_map; + + RID fog_uniform_set; + RID copy_uniform_set; + RID process_uniform_set_density; + RID process_uniform_set; + RID process_uniform_set2; + RID sdfgi_uniform_set; + RID sky_uniform_set; + + int last_shadow_filter = -1; + + VolumetricFog(const Vector3i &fog_size, RID p_sky_shader); + ~VolumetricFog(); + }; + + void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array); + void free_fog_shader(); + + struct VolumetricFogSettings { + Vector2i rb_size; + double time; + bool is_using_radiance_cubemap_array; + uint32_t max_cluster_elements; + bool volumetric_fog_filter_active; + RID shadow_sampler; + RID voxel_gl_buffer; + RID shadow_atlas_depth; + RID omni_light_buffer; + RID spot_light_buffer; + RID directional_shadow_depth; + RID directional_light_buffer; + + // Objects related to our render buffer + VolumetricFog *vfog; + ClusterBuilderRD *cluster_builder; + GI *gi; + GI::SDFGI *sdfgi; + GI::RenderBuffersGI *rbgi; + RID env; + SkyRD *sky; + }; + void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); }; } // namespace RendererRD -#endif // !FOG_RD_H +#endif // FOG_RD_H diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index a749e7d5bc..feafcc42c9 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -109,6 +109,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo Vector<Vector<uint8_t>> s; s.push_back(p_distance_field); voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); } #if 0 { @@ -122,6 +123,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); } RID shared_tex; { @@ -372,15 +374,15 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) { //////////////////////////////////////////////////////////////////////////////// // SDFGI -void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) { +void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); gi = p_gi; - num_cascades = p_env->sdfgi_cascades; - min_cell_size = p_env->sdfgi_min_cell_size; - uses_occlusion = p_env->sdfgi_use_occlusion; - y_scale_mode = p_env->sdfgi_y_scale; + num_cascades = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_cascades(p_env); + min_cell_size = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_min_cell_size(p_env); + uses_occlusion = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_use_occlusion(p_env); + y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env); static const float y_scale[3] = { 2.0, 1.5, 1.0 }; y_mult = y_scale[y_scale_mode]; cascades.resize(num_cascades); @@ -402,29 +404,38 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world RD::TextureFormat tf_render = tf_sdf; tf_render.format = RD::DATA_FORMAT_R16_UINT; render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo"); tf_render.format = RD::DATA_FORMAT_R32_UINT; render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission"); render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso"); tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize for (int i = 0; i < 8; i++) { render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i)); } tf_render.format = RD::DATA_FORMAT_R32_UINT; render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing"); tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT; render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0"); render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1"); tf_render.width /= 2; tf_render.height /= 2; tf_render.depth /= 2; render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0"); render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1"); } RD::TextureFormat tf_occlusion = tf_sdf; @@ -465,7 +476,9 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D; lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll"); lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll"); { //octahedral lightprobes @@ -479,6 +492,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world //lightprobe texture is an octahedral texture lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data"); RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data); @@ -492,11 +506,13 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; //lightprobe texture is an octahedral texture ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView()); + RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture"); } cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES); occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView()); + RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data"); { RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16; @@ -509,11 +525,15 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world /* 3D Textures */ cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture"); cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data"); cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture"); cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture"); { RD::TextureView tv; @@ -540,9 +560,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world /* Probe History */ cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work /* Buffers */ @@ -712,7 +734,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -788,7 +810,8 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world uniforms.push_back(u); } - cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0); + cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0); + cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0); } //preprocess initialize uniform set @@ -955,7 +978,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -968,7 +991,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -981,7 +1004,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -994,7 +1017,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1078,11 +1101,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 0); } - bounce_feedback = p_env->sdfgi_bounce_feedback; - energy = p_env->sdfgi_energy; - normal_bias = p_env->sdfgi_normal_bias; - probe_bias = p_env->sdfgi_probe_bias; - reads_sky = p_env->sdfgi_read_sky_light; + bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env); + energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env); + normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env); + probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env); + reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env); } void GI::SDFGI::erase() { @@ -1140,12 +1163,12 @@ void GI::SDFGI::erase() { } } -void GI::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) { - bounce_feedback = p_env->sdfgi_bounce_feedback; - energy = p_env->sdfgi_energy; - normal_bias = p_env->sdfgi_normal_bias; - probe_bias = p_env->sdfgi_probe_bias; - reads_sky = p_env->sdfgi_read_sky_light; +void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) { + bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env); + energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env); + normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env); + probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env); + reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env); int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2; @@ -1237,7 +1260,7 @@ void GI::SDFGI::update_light() { } cascades[i].all_dynamic_lights_dirty = false; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0); } @@ -1245,7 +1268,7 @@ void GI::SDFGI::update_light() { RD::get_singleton()->draw_command_end_label(); } -void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) { +void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes"); SDFGIShader::IntegratePushConstant push_constant; @@ -1261,29 +1284,29 @@ void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSk push_constant.ray_bias = probe_bias; push_constant.image_size[0] = probe_axis_count * probe_axis_count; push_constant.image_size[1] = probe_axis_count; - push_constant.store_ambient_texture = p_env->volumetric_fog_enabled; + push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env); RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set; push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED; push_constant.y_mult = y_mult; - if (reads_sky && p_env) { - push_constant.sky_energy = p_env->bg_energy; + if (reads_sky && p_env.is_valid()) { + push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); - if (p_env->background == RS::ENV_BG_CLEAR_COLOR) { + if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) { push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear(); push_constant.sky_color[0] = c.r; push_constant.sky_color[1] = c.g; push_constant.sky_color[2] = c.b; - } else if (p_env->background == RS::ENV_BG_COLOR) { + } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) { push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; - Color c = p_env->bg_color; + Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env); push_constant.sky_color[0] = c.r; push_constant.sky_color[1] = c.g; push_constant.sky_color[2] = c.b; - } else if (p_env->background == RS::ENV_BG_SKY) { + } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) { if (p_sky && p_sky->radiance.is_valid()) { if (integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(integrate_sky_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -1459,7 +1482,7 @@ void GI::SDFGI::update_cascades() { RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE); } -void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { +void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); @@ -1475,7 +1498,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1488,7 +1511,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1501,7 +1524,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1514,7 +1537,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1568,34 +1591,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti push_constant.max_cascades = cascades.size(); push_constant.screen_size[0] = p_width; push_constant.screen_size[1] = p_height; - push_constant.probe_axis_size = probe_axis_count; - push_constant.use_occlusion = uses_occlusion; push_constant.y_mult = y_mult; push_constant.z_near = -p_projections[v].get_z_near(); - push_constant.cam_transform[0] = p_transform.basis.rows[0][0]; - push_constant.cam_transform[1] = p_transform.basis.rows[1][0]; - push_constant.cam_transform[2] = p_transform.basis.rows[2][0]; - push_constant.cam_transform[3] = 0; - push_constant.cam_transform[4] = p_transform.basis.rows[0][1]; - push_constant.cam_transform[5] = p_transform.basis.rows[1][1]; - push_constant.cam_transform[6] = p_transform.basis.rows[2][1]; - push_constant.cam_transform[7] = 0; - push_constant.cam_transform[8] = p_transform.basis.rows[0][2]; - push_constant.cam_transform[9] = p_transform.basis.rows[1][2]; - push_constant.cam_transform[10] = p_transform.basis.rows[2][2]; - push_constant.cam_transform[11] = 0; - push_constant.cam_transform[12] = p_transform.origin.x; - push_constant.cam_transform[13] = p_transform.origin.y; - push_constant.cam_transform[14] = p_transform.origin.z; - push_constant.cam_transform[15] = 1; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i]; + } + } + push_constant.cam_origin[0] = p_transform.origin[0]; + push_constant.cam_origin[1] = p_transform.origin[1]; + push_constant.cam_origin[2] = p_transform.origin[2]; // need to properly unproject for asymmetric projection matrices in stereo.. - CameraMatrix inv_projection = p_projections[v].inverse(); + Projection inv_projection = p_projections[v].inverse(); for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j]; + for (int j = 0; j < 3; j++) { + push_constant.inv_projection[j][i] = inv_projection.matrix[i][j]; } } @@ -1609,7 +1622,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1); } -void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); // setup scene data @@ -1924,7 +1937,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } } -void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { //print_line("rendering region " + itos(p_region)); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... @@ -2391,7 +2404,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co dl_push_constant.cascade = p_cascade_indices[i]; if (dl_push_constant.light_count > 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0); } @@ -2405,7 +2418,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co //////////////////////////////////////////////////////////////////////////////// // VoxelGIInstance -void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); uint32_t data_version = gi->voxel_gi_get_data_version(probe); @@ -2444,6 +2457,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture"); RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1); @@ -2573,6 +2587,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture"); if (dynamic_maps.size() == 0) { // Render depth for first one. @@ -2580,6 +2595,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth"); } //just use depth as-is @@ -2587,13 +2603,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth"); if (dynamic_maps.size() == 0) { dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo"); dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal"); dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM"); Vector<RID> fb; fb.push_back(dmap.albedo); @@ -2921,10 +2941,10 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID //this could probably be better parallelized in compute.. for (int i = 0; i < (int)p_dynamic_objects.size(); i++) { - RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i]; + RenderGeometryInstance *instance = p_dynamic_objects[i]; //transform aabb to voxel_gi - AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance)); + AABB aabb = (to_probe_xform * instance->get_transform()).xform(instance->get_aabb()); //this needs to wrap to grid resolution to avoid jitter //also extend margin a bit just in case @@ -2985,7 +3005,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0); bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0); - CameraMatrix cm; + Projection cm; cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); if (p_scene_render->cull_argument.size() == 0) { @@ -3110,14 +3130,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID last_probe_version = gi->voxel_gi_get_version(probe); } -void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); if (mipmaps.size() == 0) { return; } - CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse()); + Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse()); int level = 0; Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); @@ -3203,7 +3223,7 @@ GI::~GI() { singleton = nullptr; } -void GI::init(RendererSceneSkyRD *p_sky) { +void GI::init(SkyRD *p_sky) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3322,7 +3342,11 @@ void GI::init(RendererSceneSkyRD *p_sky) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + if (p_sky->sky_use_cubemap_array) { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + } uniforms.push_back(u); } { @@ -3342,37 +3366,40 @@ void GI::init(RendererSceneSkyRD *p_sky) { //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; Vector<String> gi_modes; + gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_VOXEL_GI - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); // MODE_HALF_RES_SDFGI - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_COMBINED - - gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_VOXEL_GI_MULTIVIEW - gi_modes.push_back("\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_SDFGI_MULTIVIEW - gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_COMBINED_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_VOXEL_GI_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_SDFGI_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_COMBINED_MULTIVIEW shader.initialize(gi_modes, defines); + shader_version = shader.version_create(); + + Vector<RD::PipelineSpecializationConstant> specialization_constants; + + { + RD::PipelineSpecializationConstant sc; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES + sc.bool_value = false; + specialization_constants.push_back(sc); + + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX + sc.bool_value = false; + specialization_constants.push_back(sc); - if (!RendererCompositorRD::singleton->is_xr_enabled()) { - shader.set_variant_enabled(MODE_VOXEL_GI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_SDFGI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_COMBINED_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_VOXEL_GI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_SDFGI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_COMBINED_MULTIVIEW, false); + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS + sc.bool_value = false; + specialization_constants.push_back(sc); } - shader_version = shader.version_create(); - for (int i = 0; i < MODE_MAX; i++) { - if (shader.is_variant_enabled(i)) { - pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i)); - } else { - pipelines[i] = RID(); + for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false; + specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false; + specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false; + for (int i = 0; i < MODE_MAX; i++) { + pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants); } } @@ -3440,7 +3467,7 @@ void GI::free() { } } -GI::SDFGI *GI::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { +GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { SDFGI *sdfgi = memnew(SDFGI); sdfgi->create(p_env, p_world_position, p_requested_history_size, this); @@ -3513,7 +3540,7 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra } if (texture == RID()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->rbgi.voxel_gi_textures[i]) { @@ -3564,25 +3591,17 @@ void GI::RenderBuffersGI::free() { } if (ambient_buffer.is_valid()) { - if (view_count == 1) { - // Only one view? then these are copies of our main buffers. - ambient_view[0] = RID(); - reflection_view[0] = RID(); - } else { - // Multiple views? free our slices. - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(ambient_view[v]); - RD::get_singleton()->free(reflection_view[v]); - ambient_view[v] = RID(); - reflection_view[v] = RID(); - } - } - - // Now we can free our buffers. RD::get_singleton()->free(ambient_buffer); RD::get_singleton()->free(reflection_buffer); ambient_buffer = RID(); reflection_buffer = RID(); + + // these are automatically freed when we free the textures, so just reset.. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + ambient_slice[v] = RID(); + reflection_slice[v] = RID(); + } + view_count = 0; } @@ -3592,7 +3611,7 @@ void GI::RenderBuffersGI::free() { } } -void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3606,14 +3625,13 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { // Free our old buffer if applicable if (rb->rbgi.ambient_buffer.is_valid()) { - if (rb->rbgi.view_count > 1) { - for (uint32_t v = 0; v < rb->rbgi.view_count; v++) { - RD::get_singleton()->free(rb->rbgi.ambient_view[v]); - RD::get_singleton()->free(rb->rbgi.reflection_view[v]); - } - } RD::get_singleton()->free(rb->rbgi.ambient_buffer); RD::get_singleton()->free(rb->rbgi.reflection_buffer); + + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + rb->rbgi.ambient_slice[v] = RID(); + rb->rbgi.reflection_slice[v] = RID(); + } } // Remember the view count we're using @@ -3637,18 +3655,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v } tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); rb->rbgi.using_half_size_gi = half_resolution; if (p_view_count == 1) { - // Just one view? Copy our buffers - rb->rbgi.ambient_view[0] = rb->rbgi.ambient_buffer; - rb->rbgi.reflection_view[0] = rb->rbgi.reflection_buffer; + // Just copy, we don't need to create slices + rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; + rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; } else { - // More then one view? Create slices for each view for (uint32_t v = 0; v < p_view_count; v++) { - rb->rbgi.ambient_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); - rb->rbgi.reflection_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); + rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); + rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); } } } @@ -3681,29 +3700,45 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v // Now compute the contents of our buffers. RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); - for (uint32_t v = 0; v < p_view_count; v++) { - // Render each eye seperately. - // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. + // Render each eye separately. + // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. - // setup our push constant + // setup our push constant - PushConstant push_constant; + PushConstant push_constant; - push_constant.view_index = v; - push_constant.orthogonal = p_projections[v].is_orthogonal(); - push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); - push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; + push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); + push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; + + // these should be the same for all views + push_constant.orthogonal = p_projections[0].is_orthogonal(); + push_constant.z_near = p_projections[0].get_z_near(); + push_constant.z_far = p_projections[0].get_z_far(); - push_constant.z_near = p_projections[v].get_z_near(); - push_constant.z_far = p_projections[v].get_z_far(); + // these are only used if we have 1 view, else we use the projections in our scene data + push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; - push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[v].matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[v].matrix[1][1]); - push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; - push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + bool use_sdfgi = rb->sdfgi != nullptr; + bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; - bool use_sdfgi = rb->sdfgi != nullptr; - bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; + uint32_t pipeline_specialization = 0; + if (rb->rbgi.using_half_size_gi) { + pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES; + } + if (p_view_count > 1) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX; + } + if (p_vrs_slices[0].is_valid()) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS; + } + + Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); + + for (uint32_t v = 0; v < p_view_count; v++) { + push_constant.view_index = v; // setup our uniform set if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { @@ -3716,7 +3751,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3729,7 +3764,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3742,7 +3777,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3755,7 +3790,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3767,7 +3802,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi) { u.append_id(rb->sdfgi->occlusion_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3790,7 +3825,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(rb->rbgi.ambient_view[v]); + u.append_id(rb->rbgi.ambient_slice[v]); uniforms.push_back(u); } @@ -3798,7 +3833,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.append_id(rb->rbgi.reflection_view[v]); + u.append_id(rb->rbgi.reflection_slice[v]); uniforms.push_back(u); } @@ -3809,7 +3844,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->sdfgi) { u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3824,14 +3859,14 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 13; - u.append_id(p_normal_roughness_views[v]); + u.append_id(p_normal_roughness_slices[v]); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } @@ -3865,27 +3900,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v u.append_id(rb->rbgi.scene_data_ubo); uniforms.push_back(u); } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 19; + RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); + u.append_id(buffer); + uniforms.push_back(u); + } rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); } - Mode mode; - - if (p_view_count > 1) { - if (rb->rbgi.using_half_size_gi) { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_HALF_RES_SDFGI_MULTIVIEW : MODE_HALF_RES_VOXEL_GI_MULTIVIEW); - } else { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_SDFGI_MULTIVIEW : MODE_VOXEL_GI_MULTIVIEW); - } - } else { - if (rb->rbgi.using_half_size_gi) { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI); - } else { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); - } - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); @@ -3923,14 +3950,14 @@ bool GI::voxel_gi_needs_update(RID p_probe) const { return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } -void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); } -void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi); ERR_FAIL_COND(!voxel_gi); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 294b8d3cfd..304df1605b 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -35,8 +35,7 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/environment/renderer_gi.h" #include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" +#include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h" @@ -79,9 +78,9 @@ public: float energy = 1.0; float bias = 1.4; float normal_bias = 0.0; - float propagation = 0.7; + float propagation = 0.5; bool interior = false; - bool use_two_bounces = false; + bool use_two_bounces = true; uint32_t version = 1; uint32_t data_version = 1; @@ -233,16 +232,13 @@ private: uint32_t max_cascades; int32_t screen_size[2]; - uint32_t use_occlusion; float y_mult; - uint32_t probe_axis_size; float z_near; - float reserved1; - float reserved2; - float cam_transform[16]; - float inv_projection[16]; + float inv_projection[3][4]; + float cam_basis[3][3]; + float cam_origin[3]; }; SdfgiDebugShaderRD debug; @@ -471,8 +467,8 @@ public: Transform3D transform; - void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; @@ -541,7 +537,8 @@ public: Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all. RID sdf_store_uniform_set; - RID sdf_direct_light_uniform_set; + RID sdf_direct_light_static_uniform_set; + RID sdf_direct_light_dynamic_uniform_set; RID scroll_uniform_set; RID scroll_occlusion_uniform_set; RID integrate_uniform_set; @@ -613,20 +610,20 @@ public: int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically RID integrate_sky_uniform_set; - void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); + void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); void erase(); - void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position); + void update(RID p_env, const Vector3 &p_world_position); void update_light(); - void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky); + void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky); void store_probes(); int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const; void update_cascades(); - void debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); - void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); + void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); - void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); + void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); }; @@ -660,13 +657,13 @@ public: /* GI buffers */ RID ambient_buffer; + RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; RID reflection_buffer; - RID ambient_view[RendererSceneRender::MAX_RENDER_VIEWS]; - RID reflection_view[RendererSceneRender::MAX_RENDER_VIEWS]; - RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; bool using_half_size_gi = false; uint32_t view_count = 1; + RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; RID scene_data_ubo; void free(); @@ -729,63 +726,60 @@ public: }; struct PushConstant { - uint32_t view_index; uint32_t max_voxel_gi_instances; uint32_t high_quality_vct; uint32_t orthogonal; + uint32_t view_index; float proj_info[4]; float z_near; float z_far; - float pad1; float pad2; + float pad3; }; RID sdfgi_ubo; + enum Mode { MODE_VOXEL_GI, MODE_SDFGI, MODE_COMBINED, - MODE_HALF_RES_VOXEL_GI, - MODE_HALF_RES_SDFGI, - MODE_HALF_RES_COMBINED, - - MODE_VOXEL_GI_MULTIVIEW, - MODE_SDFGI_MULTIVIEW, - MODE_COMBINED_MULTIVIEW, - MODE_HALF_RES_VOXEL_GI_MULTIVIEW, - MODE_HALF_RES_SDFGI_MULTIVIEW, - MODE_HALF_RES_COMBINED_MULTIVIEW, - MODE_MAX }; + enum ShaderSpecializations { + SHADER_SPECIALIZATION_HALF_RES = 1 << 0, + SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1, + SHADER_SPECIALIZATION_USE_VRS = 1 << 2, + SHADER_SPECIALIZATION_VARIATIONS = 8, + }; + RID default_voxel_gi_buffer; bool half_resolution = false; GiShaderRD shader; RID shader_version; - RID pipelines[MODE_MAX]; + RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX]; GI(); ~GI(); - void init(RendererSceneSkyRD *p_sky); + void init(RendererRD::SkyRD *p_sky); void free(); - SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); + SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); + void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); RID voxel_gi_instance_create(RID p_base); void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); bool voxel_gi_needs_update(RID p_probe) const; - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; } // namespace RendererRD -#endif /* !GI_RD_H */ +#endif // GI_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 73175d3cf3..6433a39863 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_sky_rd.cpp */ +/* sky.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,27 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_scene_sky_rd.h" +#include "sky.h" #include "core/config/project_settings.h" #include "core/math/math_defs.h" -#include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" +using namespace RendererRD; + //////////////////////////////////////////////////////////////////////////////// // SKY SHADER -void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { +void SkyRD::SkyShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + +void SkyRD::SkyShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -141,7 +147,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -158,7 +164,7 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa } } -void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SkyRD::SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -172,15 +178,29 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par order[E.value.order] = E.key; } } - + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); } } -void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { +void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; @@ -195,7 +215,7 @@ void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMat } } -bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { +bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -203,15 +223,15 @@ bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_par return uniforms[p_param].texture_order >= 0; } -bool RendererSceneSkyRD::SkyShaderData::is_animated() const { +bool SkyRD::SkyShaderData::is_animated() const { return false; } -bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const { +bool SkyRD::SkyShaderData::casts_shadows() const { return false; } -Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -220,13 +240,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam return Variant(); } -RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const { +RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version); } -RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { +SkyRD::SkyShaderData::~SkyShaderData() { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone @@ -238,7 +258,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { //////////////////////////////////////////////////////////////////////////////// // Sky material -bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -246,7 +266,7 @@ bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<String return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); } -RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() { +SkyRD::SkyMaterialData::~SkyMaterialData() { free_parameters_uniform_set(uniform_set); } @@ -268,7 +288,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { +void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { SkyPushConstant sky_push_constant; memset(&sky_push_constant, 0, sizeof(SkyPushConstant)); @@ -319,7 +339,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_ //////////////////////////////////////////////////////////////////////////////// // ReflectionData -void RendererSceneSkyRD::ReflectionData::clear_reflection_data() { +void SkyRD::ReflectionData::clear_reflection_data() { layers.clear(); radiance_base_cubemap = RID(); if (downsampled_radiance_cubemap.is_valid()) { @@ -330,7 +350,7 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() { coefficient_buffer = RID(); } -void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { +void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { //recreate radiance and all data int mipmaps = p_mipmaps; @@ -399,21 +419,22 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, 1, RD::TEXTURE_SLICE_CUBEMAP); RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap"); + RD::TextureFormat tf; tf.format = p_texture_format; - tf.width = 64; // Always 64x64 - tf.height = 64; + tf.width = p_low_quality ? 64 : p_size >> 1; // Always 64x64 when using REALTIME. + tf.height = p_low_quality ? 64 : p_size >> 1; tf.texture_type = RD::TEXTURE_TYPE_CUBE; tf.array_layers = 6; - tf.mipmaps = 7; + tf.mipmaps = p_low_quality ? 7 : mipmaps - 1; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap"); { - uint32_t mmw = 64; - uint32_t mmh = 64; - downsampled_layer.mipmaps.resize(7); + uint32_t mmw = tf.width; + uint32_t mmh = tf.height; + downsampled_layer.mipmaps.resize(tf.mipmaps); for (int j = 0; j < downsampled_layer.mipmaps.size(); j++) { ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j]; mm.size.width = mmw; @@ -438,7 +459,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int } } -void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { +void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -496,7 +517,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_us } } -void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { +void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -565,7 +586,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(boo RD::get_singleton()->draw_command_end_label(); // Filter radiance } -void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { +void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -590,9 +611,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, } //////////////////////////////////////////////////////////////////////////////// -// RendererSceneSkyRD::Sky +// SkyRD::Sky -void RendererSceneSkyRD::Sky::free() { +void SkyRD::Sky::free() { if (radiance.is_valid()) { RD::get_singleton()->free(radiance); radiance = RID(); @@ -620,7 +641,7 @@ void RendererSceneSkyRD::Sky::free() { } } -RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { +RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { @@ -634,7 +655,7 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_ if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -650,9 +671,9 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_ } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -669,9 +690,9 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_ } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -681,7 +702,7 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_ return texture_uniform_sets[p_version]; } -bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) { +bool SkyRD::Sky::set_radiance_size(int p_radiance_size) { ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false); if (radiance_size == p_radiance_size) { return false; @@ -702,7 +723,7 @@ bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) { return true; } -bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) { +bool SkyRD::Sky::set_mode(RS::SkyMode p_mode) { if (mode == p_mode) { return false; } @@ -723,7 +744,7 @@ bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) { return true; } -bool RendererSceneSkyRD::Sky::set_material(RID p_material) { +bool SkyRD::Sky::set_material(RID p_material) { if (material == p_material) { return false; } @@ -732,7 +753,7 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) { return true; } -Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { +Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { if (radiance.is_valid()) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); @@ -766,37 +787,37 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes } //////////////////////////////////////////////////////////////////////////////// -// RendererSceneSkyRD +// SkyRD -RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; -RendererSceneSkyRD::RendererSceneSkyRD() { +SkyRD::SkyRD() { roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections"); } -void RendererSceneSkyRD::init() { +void SkyRD::init() { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -834,8 +855,8 @@ void RendererSceneSkyRD::init() { } // register our shader funds - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -891,7 +912,7 @@ void RendererSceneSkyRD::init() { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; sky_shader.compiler.initialize(actions); } @@ -916,7 +937,7 @@ void sky() { material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -949,7 +970,7 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); uniforms.push_back(u); } @@ -978,7 +999,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -1012,21 +1033,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } @@ -1051,15 +1072,15 @@ void sky() { } } -void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) { +void SkyRD::set_texture_format(RD::DataFormat p_texture_format) { texture_format = p_texture_format; } -RendererSceneSkyRD::~RendererSceneSkyRD() { +SkyRD::~SkyRD() { // cleanup anything created in init... RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.shader.version_free(md->shader_data->version); RD::get_singleton()->free(sky_scene_state.directional_light_buffer); RD::get_singleton()->free(sky_scene_state.uniform_buffer); @@ -1085,23 +1106,23 @@ RendererSceneSkyRD::~RendererSceneSkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); SkyMaterialData *material = nullptr; - Sky *sky = get_sky(p_env->sky); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); RID sky_material; SkyShaderData *shader_data = nullptr; if (sky) { - sky_material = sky_get_material(p_env->sky); + sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1109,7 +1130,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1284,32 +1305,32 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b } sky_scene_state.ubo.z_far = p_projection.get_z_far(); - sky_scene_state.ubo.fog_enabled = p_env->fog_enabled; - sky_scene_state.ubo.fog_density = p_env->fog_density; - sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective; - Color fog_color = p_env->fog_light_color.srgb_to_linear(); - float fog_energy = p_env->fog_light_energy; + sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env); + sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env); + sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env); + Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_env).srgb_to_linear(); + float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_env); sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - sky_scene_state.ubo.fog_sun_scatter = p_env->fog_sun_scatter; + sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env); RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } -void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); - Sky *sky = get_sky(p_env->sky); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); ERR_FAIL_COND(!sky); - RID sky_material = sky_get_material(p_env->sky); + RID sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1317,7 +1338,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1326,7 +1347,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM ERR_FAIL_COND(!shader_data); - float multiplier = p_env->bg_energy; + float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY; RS::SkyMode sky_mode = sky->mode; @@ -1371,9 +1392,9 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM Vector3(0, -1, 0) }; - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, 0.01, 10.0); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); cm = correction * cm; @@ -1466,26 +1487,26 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM } } -void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { +void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); ERR_FAIL_COND(p_view_count == 0); ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(p_env->sky); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env); if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) { ERR_FAIL_COND(!sky); - sky_material = sky_get_material(p_env->sky); + sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1493,13 +1514,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1508,16 +1529,16 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont ERR_FAIL_COND(!shader_data); - Basis sky_transform = p_env->sky_orientation; + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); - float multiplier = p_env->bg_energy; - float custom_fov = p_env->sky_custom_fov; + float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); + float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1573,23 +1594,23 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont RD::get_singleton()->draw_list_end(); } -void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); ERR_FAIL_COND(p_view_count == 0); ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(p_env->sky); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); ERR_FAIL_COND(!sky); SkyMaterialData *material = nullptr; RID sky_material; - sky_material = sky_get_material(p_env->sky); + sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1597,7 +1618,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1606,16 +1627,16 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u ERR_FAIL_COND(!shader_data); - Basis sky_transform = p_env->sky_orientation; + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); - float multiplier = p_env->bg_energy; - float custom_fov = p_env->sky_custom_fov; + float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); + float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1658,26 +1679,26 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u } } -void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); ERR_FAIL_COND(p_view_count == 0); ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(p_env->sky); + Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env); if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) { ERR_FAIL_COND(!sky); - sky_material = sky_get_material(p_env->sky); + sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1685,13 +1706,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1700,16 +1721,16 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme ERR_FAIL_COND(!shader_data); - Basis sky_transform = p_env->sky_orientation; + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); - float multiplier = p_env->bg_energy; - float custom_fov = p_env->sky_custom_fov; + float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); + float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1737,7 +1758,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); } -void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) { +void SkyRD::invalidate_sky(Sky *p_sky) { if (!p_sky->dirty) { p_sky->dirty = true; p_sky->dirty_list = dirty_sky_list; @@ -1745,7 +1766,7 @@ void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) { } } -void RendererSceneSkyRD::update_dirty_skys() { +void SkyRD::update_dirty_skys() { Sky *sky = dirty_sky_list; while (sky) { @@ -1849,26 +1870,26 @@ void RendererSceneSkyRD::update_dirty_skys() { dirty_sky_list = nullptr; } -RID RendererSceneSkyRD::sky_get_material(RID p_sky) const { +RID SkyRD::sky_get_material(RID p_sky) const { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, RID()); return sky->material; } -RID RendererSceneSkyRD::allocate_sky_rid() { +RID SkyRD::allocate_sky_rid() { return sky_owner.allocate_rid(); } -void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) { +void SkyRD::initialize_sky_rid(RID p_rid) { sky_owner.initialize_rid(p_rid, Sky()); } -RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const { +SkyRD::Sky *SkyRD::get_sky(RID p_sky) const { return sky_owner.get_or_null(p_sky); } -void RendererSceneSkyRD::free_sky(RID p_sky) { +void SkyRD::free_sky(RID p_sky) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1876,7 +1897,7 @@ void RendererSceneSkyRD::free_sky(RID p_sky) { sky_owner.free(p_sky); } -void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { +void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1885,7 +1906,7 @@ void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { } } -void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { +void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1894,7 +1915,7 @@ void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { } } -void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) { +void SkyRD::sky_set_material(RID p_sky, RID p_material) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1903,7 +1924,7 @@ void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) { } } -Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { +Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, Ref<Image>()); @@ -1912,7 +1933,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); } -RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const { +RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, RID()); diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/environment/sky.h index a8ee406abc..080165c112 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_sky_rd.h */ +/* sky.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_SKY_RD_H -#define RENDERING_SERVER_SCENE_SKY_RD_H +#ifndef SKY_RD_H +#define SKY_RD_H #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -44,7 +43,9 @@ // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound class RendererSceneRenderRD; -class RendererSceneSkyRD { +namespace RendererRD { + +class SkyRD { public: enum SkySet { SKY_SET_UNIFORMS, @@ -106,7 +107,7 @@ private: // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; - struct SkyShaderData : public RendererRD::ShaderData { + struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData { bool valid = false; RID version; @@ -128,8 +129,9 @@ private: bool uses_light = false; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_hint); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -141,7 +143,7 @@ private: virtual ~SkyShaderData(); }; - void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); + void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); public: struct SkySceneState { @@ -229,7 +231,7 @@ public: RID default_shader_rd; } sky_shader; - struct SkyMaterialData : public RendererRD::MaterialData { + struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData { SkyShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -283,22 +285,22 @@ public: mutable RID_Owner<Sky, true> sky_owner; int roughness_layers; - RendererRD::ShaderData *_create_sky_shader_func(); - static RendererRD::ShaderData *_create_sky_shader_funcs(); + RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs(); - RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); + RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); - RendererSceneSkyRD(); + SkyRD(); void init(); void set_texture_format(RD::DataFormat p_texture_format); - ~RendererSceneSkyRD(); + ~SkyRD(); - void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); - void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer - void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer + void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); void invalidate_sky(Sky *p_sky); void update_dirty_skys(); @@ -317,4 +319,6 @@ public: RID sky_get_radiance_texture_rd(RID p_sky) const; }; -#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */ +} // namespace RendererRD + +#endif // SKY_RD_H diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index f759fa3aa5..8754e90647 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -66,6 +66,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() } specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + specular_views[0] = specular; + } else { + for (uint32_t v = 0; v < view_count; v++) { + specular_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular, v, 0); + } + } if (msaa == RS::VIEWPORT_MSAA_DISABLED) { { @@ -80,6 +87,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + specular_msaa_views[0] = specular_msaa; + } else { + for (uint32_t v = 0; v < view_count; v++) { + specular_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular_msaa, v, 0); + } + } + { Vector<RID> fb; fb.push_back(specular_msaa); @@ -171,29 +186,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() } void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { + // note, slices are freed automatically when the parent texture is freed so we just clear them. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + color_views[v] = RID(); + depth_views[v] = RID(); + specular_views[v] = RID(); + specular_msaa_views[v] = RID(); + color_msaa_views[v] = RID(); + depth_msaa_views[v] = RID(); + normal_roughness_views[v] = RID(); + normal_roughness_msaa_views[v] = RID(); + voxelgi_views[v] = RID(); + voxelgi_msaa_views[v] = RID(); + vrs_views[v] = RID(); + } + if (voxelgi_buffer != RID()) { RD::get_singleton()->free(voxelgi_buffer); voxelgi_buffer = RID(); - if (view_count == 1) { - voxelgi_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(voxelgi_views[v]); - voxelgi_views[v] = RID(); - } - } - if (voxelgi_buffer_msaa.is_valid()) { - if (view_count == 1) { - voxelgi_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(voxelgi_msaa_views[v]); - voxelgi_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(voxelgi_buffer_msaa); voxelgi_buffer_msaa = RID(); } @@ -202,35 +214,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } if (color_msaa.is_valid()) { - if (view_count == 1) { - color_views[0] = RID(); - color_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(color_views[v]); - RD::get_singleton()->free(color_msaa_views[v]); - color_views[v] = RID(); - color_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(color_msaa); color_msaa = RID(); } if (depth_msaa.is_valid()) { - if (view_count == 1) { - depth_views[0] = RID(); - depth_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(depth_views[v]); - RD::get_singleton()->free(depth_msaa_views[v]); - depth_views[v] = RID(); - depth_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(depth_msaa); depth_msaa = RID(); } @@ -245,33 +233,17 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } color = RID(); + color_only_fb = RID(); depth = RID(); depth_fb = RID(); color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations if (normal_roughness_buffer.is_valid()) { - if (view_count == 1) { - normal_roughness_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(normal_roughness_views[v]); - normal_roughness_views[v] = RID(); - } - } - RD::get_singleton()->free(normal_roughness_buffer); normal_roughness_buffer = RID(); if (normal_roughness_buffer_msaa.is_valid()) { - if (view_count == 1) { - normal_roughness_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(normal_roughness_msaa_views[v]); - normal_roughness_msaa_views[v] = RID(); - } - } RD::get_singleton()->free(normal_roughness_buffer_msaa); normal_roughness_buffer_msaa = RID(); } @@ -294,11 +266,12 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } } -void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) { +void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; use_taa = p_use_taa; + vrs = p_vrs_texture; width = p_width; height = p_height; @@ -307,11 +280,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c color = p_color_buffer; depth = p_depth_buffer; + if (vrs.is_valid()) { + if (view_count == 1) { + // just reuse + vrs_views[0] = vrs; + } else { + // create slices + for (uint32_t v = 0; v < view_count; v++) { + vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0); + } + } + } + if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { { Vector<RID> fb; fb.push_back(p_color_buffer); fb.push_back(depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -371,6 +359,9 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c Vector<RID> fb; fb.push_back(color_msaa); fb.push_back(depth_msaa); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -409,6 +400,10 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb( fb.push_back(use_msaa ? depth_msaa : depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); color_framebuffers[p_color_pass_flags] = framebuffer; @@ -780,7 +775,7 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { uint32_t render_total = p_params->element_count; - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t render_from = p_thread * render_total / total_threads; uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); @@ -792,9 +787,10 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded @@ -805,12 +801,12 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p } void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { - //CameraMatrix projection = p_render_data->cam_projection; + //Projection projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); correction.add_jitter_offset(p_render_data->taa_jitter); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); @@ -927,7 +923,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.use_ambient_cubemap = false; } else { float energy = environment_get_ambient_light_energy(p_render_data->environment); - Color color = environment_get_ambient_light_color(p_render_data->environment); + Color color = environment_get_ambient_light(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; @@ -949,16 +945,16 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.use_reflection_cubemap = false; } - scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment); - scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment); uint32_t ss_flags = 0; if (p_opaque_render_buffers) { - ss_flags |= environment_is_ssao_enabled(p_render_data->environment) ? 1 : 0; - ss_flags |= environment_is_ssil_enabled(p_render_data->environment) ? 2 : 0; + ss_flags |= environment_get_ssao_enabled(p_render_data->environment) ? 1 : 0; + ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? 2 : 0; } scene_state.ubo.ss_effects_flags = ss_flags; - scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment); + scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); @@ -1000,10 +996,10 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO)); - CameraMatrix prev_correction; + Projection prev_correction; prev_correction.set_depth_correction(true); prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter); - CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection; + Projection prev_projection = prev_correction * p_render_data->prev_cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix); @@ -1080,7 +1076,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i instance_data.flags = inst->flags_cache; instance_data.gi_offset = inst->gi_offset_cache; instance_data.layer_mask = inst->layer_mask; - instance_data.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset); + instance_data.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset); instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x; instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y; instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x; @@ -1414,7 +1410,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (p_render_data->render_buffers.is_valid()) { render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); } - RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; //first of all, make a new render pass @@ -1439,7 +1434,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sdfgi = false; bool using_voxelgi = false; bool reverse_cull = false; - bool using_ssil = p_render_data->environment.is_valid() && environment_is_ssil_enabled(p_render_data->environment); + bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); if (render_buffer) { screen_size.x = render_buffer->width; @@ -1453,21 +1448,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co using_voxelgi = true; } - if (!p_render_data->environment.is_valid() && using_voxelgi) { + if (p_render_data->environment.is_null() && using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; - } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { - if (environment_is_sdfgi_enabled(p_render_data->environment)) { + } else if (p_render_data->environment.is_valid() && (environment_get_ssr_enabled(p_render_data->environment) || environment_get_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { + if (environment_get_sdfgi_enabled(p_render_data->environment)) { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi using_sdfgi = true; } else { depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } - if (environment_is_ssr_enabled(p_render_data->environment)) { + if (environment_get_ssr_enabled(p_render_data->environment)) { using_separate_specular = true; using_ssr = true; color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; } - } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { + } else if (p_render_data->environment.is_valid() && (environment_get_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } @@ -1508,7 +1503,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors - env = nullptr; } reverse_cull = true; // for some reason our views are inverted @@ -1560,7 +1554,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) { + if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1570,7 +1564,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) { + if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1593,18 +1587,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - CameraMatrix projection = p_render_data->cam_projection; + Projection projection = p_render_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); - RID sky_rid = env->sky; + RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(env, projection, p_render_data->cam_transform, time); + sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -1620,7 +1614,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); - bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_is_ssao_enabled(p_render_data->environment); + bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); bool continue_depth = false; if (depth_pre_pass) { //depth pre pass @@ -1673,8 +1667,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co continue_depth = !finish_depth; } - RID null_rids[2]; - _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : null_rids, render_buffer ? render_buffer->voxelgi_buffer : RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); @@ -1724,9 +1718,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - CameraMatrix dc; + Projection dc; dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); + Projection cm = (dc * p_render_data->cam_projection) * Projection(p_render_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { @@ -1741,11 +1735,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - CameraMatrix dc; + Projection dc; dc.set_depth_correction(true); - CameraMatrix cms[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection cms[RendererSceneRender::MAX_RENDER_VIEWS]; for (uint32_t v = 0; v < p_render_data->view_count; v++) { - cms[v] = (dc * p_render_data->view_projection[v]) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); + cms[v] = (dc * p_render_data->view_projection[v]) * Projection(p_render_data->cam_transform.affine_inverse()); } _debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth); } @@ -1756,12 +1750,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Draw Sky"); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; - sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time); + Projection projection = correction * p_render_data->cam_projection; + sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time); } else { - sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); + sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); } RD::get_singleton()->draw_command_end_label(); } @@ -1771,9 +1765,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co for (uint32_t v = 0; v < render_buffer->view_count; v++) { RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); } - // TODO mame this do multiview if (using_separate_specular) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa_views[v], render_buffer->specular_views[v]); + } } } @@ -1794,12 +1789,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_ssr) { RENDER_TIMESTAMP("Screen-Space Reflections"); RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections"); - _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_views, render_buffer->specular, render_buffer->specular_views, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->view_projection, p_render_data->view_eye_offset, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - RendererCompositorRD::singleton->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); + copy_effects->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID(), p_render_data->view_count); } } @@ -1876,7 +1871,7 @@ void RenderForwardClustered::_render_shadow_begin() { scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { +void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -1966,7 +1961,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -2005,7 +2000,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); @@ -2054,7 +2049,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering UV2"); RD::get_singleton()->draw_command_begin_label("Render UV2"); @@ -2124,7 +2119,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { +void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { RENDER_TIMESTAMP("Render SDFGI"); RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel"); @@ -2270,15 +2265,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() { case RS::DECAL_FILTER_NEAREST: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; - case RS::DECAL_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } break; case RS::DECAL_FILTER_LINEAR: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::DECAL_FILTER_NEAREST_MIPMAPS: { + sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { + sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; @@ -2297,15 +2295,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() { case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; - case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { + sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { + sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; @@ -2386,7 +2387,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); uniforms.push_back(u); } @@ -2438,7 +2439,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -2455,7 +2456,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2469,7 +2470,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); } u.append_id(texture); uniforms.push_back(u); @@ -2481,7 +2482,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } uniforms.push_back(u); } @@ -2490,7 +2491,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); @@ -2508,7 +2509,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); @@ -2538,7 +2539,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2547,7 +2548,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2557,7 +2558,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); u.append_id(texture); uniforms.push_back(u); } @@ -2567,7 +2568,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2577,7 +2578,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2587,7 +2588,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2599,7 +2600,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); } else { - t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.append_id(t); uniforms.push_back(u); @@ -2611,7 +2612,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2630,10 +2631,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); if (vfog.is_null()) { - vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(vfog); uniforms.push_back(u); @@ -2643,7 +2644,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2667,12 +2668,16 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]); + RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY]; + if (instance_buffer == RID()) { + instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used + } + u.append_id(instance_buffer); uniforms.push_back(u); } { // No radiance texture. - RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2682,7 +2687,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No reflection atlas. - RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2695,7 +2700,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2705,7 +2710,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2716,7 +2721,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { u.append_id(default_tex); } @@ -2730,7 +2735,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.append_id(default_tex); } @@ -2795,24 +2800,23 @@ RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_bu RenderForwardClustered *RenderForwardClustered::singleton = nullptr; -void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - if (ginstance->dirty_list_element.in_list()) { +void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() { + if (dirty_list_element.in_list()) { return; } //clear surface caches - GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; + GeometryInstanceSurfaceDataCache *surf = surface_caches; while (surf) { GeometryInstanceSurfaceDataCache *next = surf->next; - geometry_instance_surface_alloc.free(surf); + RenderForwardClustered::get_singleton()->geometry_instance_surface_alloc.free(surf); surf = next; } - ginstance->surface_caches = nullptr; + surface_caches = nullptr; - geometry_instance_dirty_list.add(&ginstance->dirty_list_element); + RenderForwardClustered::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element); } void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { @@ -2866,7 +2870,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); @@ -2927,7 +2931,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain( while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } @@ -2947,7 +2951,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw SceneShaderForwardClustered::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2958,7 +2962,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2969,7 +2973,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); @@ -2980,7 +2984,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw } } -void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); @@ -3139,7 +3143,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D case Dependency::DEPENDENCY_CHANGED_PARTICLES: case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); @@ -3153,10 +3157,10 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D } } void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { - static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } -RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) { +RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) { RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); @@ -3169,155 +3173,47 @@ RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed; ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted; - _geometry_instance_mark_dirty(ginstance); + ginstance->_mark_dirty(); return ginstance; } -void RenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->skeleton = p_skeleton; - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} -void RenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_override = p_override; - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} -void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_overlay = p_overlay; - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} -void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->surface_materials = p_materials; - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} -void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->mesh_instance = p_mesh_instance; - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); +void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) { uint64_t frame = RSG::rasterizer->get_frame_number(); - if (frame != ginstance->prev_transform_change_frame) { - ginstance->prev_transform = ginstance->transform; - ginstance->prev_transform_change_frame = frame; - ginstance->prev_transform_dirty = true; + if (frame != prev_transform_change_frame) { + prev_transform = transform; + prev_transform_change_frame = frame; + prev_transform_dirty = true; } - ginstance->transform = p_transform; - ginstance->mirror = p_transform.basis.determinant() < 0; - ginstance->data->aabb = p_aabb; - ginstance->transformed_aabb = p_transformed_aabb; - - Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); - // handle non uniform scale here - - float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); - float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); - ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; - - ginstance->lod_model_scale = max_scale; -} -void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lod_bias = p_lod_bias; -} -void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->fade_near = p_enable_near; - ginstance->fade_near_begin = p_near_begin; - ginstance->fade_near_end = p_near_end; - ginstance->fade_far = p_enable_far; - ginstance->fade_far_begin = p_far_begin; - ginstance->fade_far_end = p_far_end; + RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabbb); } -void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->parent_fade_alpha = p_alpha; -} +void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { + lightmap_instance = p_lightmap_instance; + lightmap_uv_scale = p_lightmap_uv_scale; + lightmap_slice_index = p_lightmap_slice_index; -void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1); + _mark_dirty(); } -void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_baked_light = p_enable; - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_dynamic_gi = p_enable; - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lightmap_instance = p_lightmap_instance; - ginstance->lightmap_uv_scale = p_lightmap_uv_scale; - ginstance->lightmap_slice_index = p_lightmap_slice_index; - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); +void RenderForwardClustered::GeometryInstanceForwardClustered::set_lightmap_capture(const Color *p_sh9) { if (p_sh9) { - if (ginstance->lightmap_sh == nullptr) { - ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc(); + if (lightmap_sh == nullptr) { + lightmap_sh = RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.alloc(); } - memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9); + memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9); } else { - if (ginstance->lightmap_sh != nullptr) { - geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); - ginstance->lightmap_sh = nullptr; + if (lightmap_sh != nullptr) { + RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh); + lightmap_sh = nullptr; } } - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->shader_parameters_offset = p_offset; - _geometry_instance_mark_dirty(ginstance); -} -void RenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->data->cast_double_sided_shadows = p_enable; - _geometry_instance_mark_dirty(ginstance); + _mark_dirty(); } -void RenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->layer_mask = p_layer_mask; -} - -void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) { +void RenderForwardClustered::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (ginstance->lightmap_sh != nullptr) { @@ -3336,47 +3232,25 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() { return (1 << RS::INSTANCE_VOXEL_GI); } -void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { -} -void RenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { -} -void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { -} - -Transform3D RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance); - ERR_FAIL_COND_V(!ginstance, Transform3D()); - return ginstance->transform; -} - -AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance); - ERR_FAIL_COND_V(!ginstance, AABB()); - return ginstance->data->aabb; -} -void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); +void RenderForwardClustered::GeometryInstanceForwardClustered::pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { if (p_voxel_gi_instance_count > 0) { - ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0]; + voxel_gi_instances[0] = p_voxel_gi_instances[0]; } else { - ginstance->voxel_gi_instances[0] = RID(); + voxel_gi_instances[0] = RID(); } if (p_voxel_gi_instance_count > 1) { - ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1]; + voxel_gi_instances[1] = p_voxel_gi_instances[1]; } else { - ginstance->voxel_gi_instances[1] = RID(); + voxel_gi_instances[1] = RID(); } } -void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { - GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->using_projectors = p_projector; - ginstance->using_softshadows = p_softshadow; - _geometry_instance_mark_dirty(ginstance); +void RenderForwardClustered::GeometryInstanceForwardClustered::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) { + using_projectors = p_projector; + using_softshadows = p_softshadow; + _mark_dirty(); } void RenderForwardClustered::_update_shader_quality_settings() { @@ -3407,12 +3281,18 @@ void RenderForwardClustered::_update_shader_quality_settings() { sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; sc.constant_id = SPEC_CONSTANT_DECAL_FILTER; - sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; + sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || + decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || + decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC || + decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER; - sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; + sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 9e1f1b9954..7e71406af8 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H -#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H +#ifndef RENDER_FORWARD_CLUSTERED_H +#define RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/effects/resolve.h" @@ -107,26 +107,32 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID depth_normal_roughness_voxelgi_fb; RID color_only_fb; RID specular_only_fb; + + RID vrs; + int width, height; HashMap<uint32_t, RID> color_framebuffers; // for multiview - uint32_t view_count; + uint32_t view_count = 1; RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this + RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID render_sdfgi_uniform_set; void ensure_specular(); void ensure_voxelgi(); void ensure_velocity(); void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); RID get_color_pass_fb(uint32_t p_color_pass_flags); ~RenderBufferDataForwardClustered(); @@ -421,7 +427,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; struct GeometryInstanceData; - struct GeometryInstanceForwardClustered; + class GeometryInstanceForwardClustered; struct GeometryInstanceLightmapSH { Color sh[9]; @@ -481,73 +487,48 @@ class RenderForwardClustered : public RendererSceneRenderRD { GeometryInstanceForwardClustered *owner = nullptr; }; - struct GeometryInstanceForwardClustered : public GeometryInstance { + class GeometryInstanceForwardClustered : public RenderGeometryInstanceBase { + public: + // lightmap + RID lightmap_instance; + Rect2 lightmap_uv_scale; + uint32_t lightmap_slice_index; + GeometryInstanceLightmapSH *lightmap_sh = nullptr; + //used during rendering - bool mirror = false; - bool non_uniform_scale = false; - float lod_bias = 0.0; - float lod_model_scale = 1.0; - AABB transformed_aabb; //needed for LOD - float depth = 0; + uint32_t gi_offset_cache = 0; - uint32_t flags_cache = 0; bool store_transform_cache = true; - int32_t shader_parameters_offset = -1; - uint32_t lightmap_slice_index; - Rect2 lightmap_uv_scale; - uint32_t layer_mask = 1; RID transforms_uniform_set; uint32_t instance_count = 0; uint32_t trail_steps = 1; - RID mesh_instance; bool can_sdfgi = false; bool using_projectors = false; bool using_softshadows = false; - bool fade_near = false; - float fade_near_begin = 0; - float fade_near_end = 0; - bool fade_far = false; - float fade_far_begin = 0; - float fade_far_end = 0; - float force_alpha = 1.0; - float parent_fade_alpha = 1.0; //used during setup - uint32_t base_flags = 0; uint64_t prev_transform_change_frame = 0xFFFFFFFF; bool prev_transform_dirty = true; - Transform3D transform; Transform3D prev_transform; RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE]; - RID lightmap_instance; - GeometryInstanceLightmapSH *lightmap_sh = nullptr; GeometryInstanceSurfaceDataCache *surface_caches = nullptr; SelfList<GeometryInstanceForwardClustered> dirty_list_element; - struct Data { - //data used less often goes into regular heap - RID base; - RS::InstanceType base_type; - - RID skeleton; - Vector<RID> surface_materials; - RID material_override; - RID material_overlay; - AABB aabb; + GeometryInstanceForwardClustered() : + dirty_list_element(this) {} - bool use_dynamic_gi = false; - bool use_baked_light = true; - bool cast_double_sided_shadows = false; - bool mirror = false; - bool dirty_dependencies = false; + virtual void _mark_dirty() override; - DependencyTracker dependency_tracker; - }; + virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override; + virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; + virtual void set_lightmap_capture(const Color *p_sh9) override; - Data *data = nullptr; + virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override {} + virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override; - GeometryInstanceForwardClustered() : - dirty_list_element(this) {} + virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override; }; static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); @@ -562,8 +543,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); - void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); - void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance); void _update_dirty_geometry_instances(); /* Render List */ @@ -634,52 +614,27 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; public: + static RenderForwardClustered *get_singleton() { return singleton; } + _FORCE_INLINE_ virtual void update_uniform_sets() override { base_uniform_set_updated = true; _update_render_base_uniform_set(); } - virtual GeometryInstance *geometry_instance_create(RID p_base) override; - virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; - virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; - virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override; - virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override; - virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; - virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; - virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override; - virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override; - virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; - virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override; - virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override; - virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override; - virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override; - virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; - virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override; - virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override; - virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override; - - virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override; - virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override; - - virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override; + virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override; + virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; virtual uint32_t geometry_instance_get_pair_mask() override; - virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override; - virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; - virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override; - virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override; - - virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override; virtual bool free(RID p_rid) override; @@ -687,4 +642,5 @@ public: ~RenderForwardClustered(); }; } // namespace RendererSceneRenderImplementation -#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H + +#endif // RENDER_FORWARD_CLUSTERED_H diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 1951bfe915..556db086b2 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -37,6 +37,10 @@ using namespace RendererSceneRenderImplementation; +void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { //compile @@ -388,7 +392,7 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St } } -void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -403,7 +407,22 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -469,7 +488,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() { } } -RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *SceneShaderForwardClustered::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -493,7 +512,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -591,8 +610,8 @@ void SceneShaderForwardClustered::init(const String p_defines) { valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS); - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -663,7 +682,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; - actions.renames["FOG"] = "custom_fog"; + actions.renames["FOG"] = "fog"; actions.renames["RADIANCE"] = "custom_radiance"; actions.renames["IRRADIANCE"] = "custom_irradiance"; actions.renames["BONE_INDICES"] = "bone_attrib"; @@ -674,6 +693,11 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["CUSTOM3"] = "custom3_attrib"; actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz"; + actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; + actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz"; + actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; @@ -769,7 +793,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs"; compiler.initialize(actions); @@ -798,7 +822,7 @@ void fragment() { material_storage->material_initialize(default_material); material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); @@ -826,7 +850,7 @@ void fragment() { material_storage->material_initialize(overdraw_material); material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 1cfe723174..fa9ebde1b2 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RSSR_SCENE_SHADER_FC_H -#define RSSR_SCENE_SHADER_FC_H +#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H +#define SCENE_SHADER_FORWARD_CLUSTERED_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" @@ -93,7 +93,7 @@ public: SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3, }; - struct ShaderData : public RendererRD::ShaderData { + struct ShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -180,8 +180,9 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -197,12 +198,12 @@ public: SelfList<ShaderData>::List shader_list; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererRD::MaterialData { + struct MaterialData : public RendererRD::MaterialStorage::MaterialData { ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; @@ -215,8 +216,8 @@ public: virtual ~MaterialData(); }; - RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } @@ -251,4 +252,5 @@ public: }; } // namespace RendererSceneRenderImplementation -#endif // !RSSR_SCENE_SHADER_FM_H + +#endif // SCENE_SHADER_FORWARD_CLUSTERED_H diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index e1855ddb36..ffd47cc163 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -87,10 +87,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() { } } -void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) { +void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; + vrs = p_vrs_texture; Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer); @@ -108,6 +109,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(p_color_buffer); // 0 - color buffer fb.push_back(depth); // 1 - depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -116,6 +120,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); @@ -131,12 +138,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 2 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // 2/3 - target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); blit_pass.input_attachments.push_back(0); - passes.push_back(blit_pass); + passes.push_back(blit_pass); // this doesn't need VRS color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); } else { @@ -179,6 +187,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(color_msaa); // 0 - msaa color buffer fb.push_back(depth_msaa); // 1 - msaa depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -187,18 +198,22 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); // - add sky pass - fb.push_back(color); // 2 - color buffer + int color_buffer_id = fb.size(); + fb.push_back(color); // color buffer passes.push_back(pass); // without resolve for our 3 + 4 subpass config { // but with resolve for our 2 subpass config Vector<RD::FramebufferPass> two_passes; two_passes.push_back(pass); // opaque subpass without resolve - pass.resolve_attachments.push_back(2); + pass.resolve_attachments.push_back(color_buffer_id); two_passes.push_back(pass); // sky subpass with resolve color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count); @@ -217,10 +232,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 3 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(3); - blit_pass.input_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); + blit_pass.input_attachments.push_back(color_buffer_id); passes.push_back(blit_pass); color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); @@ -321,7 +337,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -338,7 +354,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -352,7 +368,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); } u.append_id(texture); uniforms.push_back(u); @@ -364,7 +380,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } uniforms.push_back(u); } @@ -375,7 +391,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); @@ -396,7 +412,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.resize(MAX_VOXEL_GI_INSTANCESS); - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (i < (int)p_voxel_gi_instances.size()) { RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); @@ -427,7 +443,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -436,7 +452,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -481,7 +497,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (p_render_data->render_buffers.is_valid()) { render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); } - RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); RENDER_TIMESTAMP("Setup 3D Scene"); @@ -524,7 +539,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) { // can't do blit subpass using_subpass_post_process = false; - } else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) { + } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || environment_get_auto_exposure(p_render_data->environment) || camera_effects_uses_dof(p_render_data->camera_effects))) { // can't do blit subpass using_subpass_post_process = false; } @@ -554,7 +569,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors - env = nullptr; } reverse_cull = true; @@ -596,7 +610,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.g *= bg_energy; clear_color.b *= bg_energy; /* - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -608,7 +622,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.g *= bg_energy; clear_color.b *= bg_energy; /* - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -632,18 +646,18 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - CameraMatrix projection = p_render_data->cam_projection; + Projection projection = p_render_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); - RID sky_rid = env->sky; + RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); + sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -664,19 +678,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; - sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time); + Projection projection = correction * p_render_data->cam_projection; + sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time); } else { - sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); + sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); } RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } - RID null_rids[2]; - _pre_opaque_render(p_render_data, false, false, false, null_rids, RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids); uint32_t spec_constant_base_flags = 0; @@ -691,7 +705,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS; } - if (!is_environment(p_render_data->environment) || environment_is_fog_enabled(p_render_data->environment)) { + if (!is_environment(p_render_data->environment) || environment_get_fog_enabled(p_render_data->environment)) { spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; } } @@ -742,9 +756,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderList")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { //single threaded RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); @@ -760,12 +777,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; - sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); + Projection projection = correction * p_render_data->cam_projection; + sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); } else { - sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); + sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); } RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass @@ -806,10 +823,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr()); render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass(); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { //single threaded RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); @@ -843,9 +862,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); } else { //single threaded @@ -884,7 +905,7 @@ void RenderForwardMobile::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { +void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -978,7 +999,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { /* */ -void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); @@ -1024,7 +1045,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering UV2"); RD::get_singleton()->draw_command_begin_label("Render UV2"); @@ -1091,11 +1112,11 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { +void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { // we don't do GI in low end.. } -void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -1193,15 +1214,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() { case RS::DECAL_FILTER_NEAREST: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; - case RS::DECAL_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } break; case RS::DECAL_FILTER_LINEAR: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::DECAL_FILTER_NEAREST_MIPMAPS: { + sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { + sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; @@ -1220,15 +1244,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() { case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; - case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { + sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; + case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { + sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; @@ -1309,7 +1336,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 14; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); uniforms.push_back(u); } @@ -1527,11 +1554,11 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, // This populates our UBO with main scene data that is pushed into set 1 - //CameraMatrix projection = p_render_data->cam_projection; + //Projection projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); @@ -1640,7 +1667,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.use_ambient_cubemap = false; } else { float energy = environment_get_ambient_light_energy(p_render_data->environment); - Color color = environment_get_ambient_light_color(p_render_data->environment); + Color color = environment_get_ambient_light(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; @@ -1662,11 +1689,11 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.use_reflection_cubemap = false; } - scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment); - scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment); - scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment); + scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_get_ssao_enabled(p_render_data->environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment); - scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment); + scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); @@ -1755,7 +1782,7 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list, void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { uint32_t render_total = p_params->element_count; - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t render_from = p_thread * render_total / total_threads; uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); @@ -1767,9 +1794,11 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, p_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded @@ -1874,7 +1903,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr push_constant.flags = inst->flags_cache; push_constant.gi_offset = inst->gi_offset_cache; push_constant.layer_mask = inst->layer_mask; - push_constant.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset); + push_constant.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset); if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { // abuse lightmap_uv_scale[0] here, should not be needed here @@ -2031,7 +2060,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr /* Geometry instance */ -RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) { +RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) { RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); @@ -2041,165 +2070,36 @@ RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_cr ginstance->data->base = p_base; ginstance->data->base_type = type; - _geometry_instance_mark_dirty(ginstance); + ginstance->_mark_dirty(); return ginstance; } -void RenderForwardMobile::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->skeleton = p_skeleton; +void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { + lightmap_instance = p_lightmap_instance; + lightmap_uv_scale = p_lightmap_uv_scale; + lightmap_slice_index = p_lightmap_slice_index; - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; + _mark_dirty(); } -void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_override = p_override; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_overlay = p_overlay; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->surface_materials = p_materials; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RenderForwardMobile::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->mesh_instance = p_mesh_instance; - - _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->transform = p_transform; - ginstance->mirror = p_transform.basis.determinant() < 0; - ginstance->data->aabb = p_aabb; - ginstance->transformed_aabb = p_transformed_aabb; - - Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); - // handle non uniform scale here - - float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); - float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); - ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; - - ginstance->lod_model_scale = max_scale; -} - -void RenderForwardMobile::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->layer_mask = p_layer_mask; -} - -void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lod_bias = p_lod_bias; -} - -void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { -} - -void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) { -} - -void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) { -} - -void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_baked_light = p_enable; - - _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { - // !BAS! do we support this in mobile? - // GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - // ERR_FAIL_COND(!ginstance); - // ginstance->data->use_dynamic_gi = p_enable; - // _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lightmap_instance = p_lightmap_instance; - ginstance->lightmap_uv_scale = p_lightmap_uv_scale; - ginstance->lightmap_slice_index = p_lightmap_slice_index; - _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); +void RenderForwardMobile::GeometryInstanceForwardMobile::set_lightmap_capture(const Color *p_sh9) { if (p_sh9) { - if (ginstance->lightmap_sh == nullptr) { - ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc(); + if (lightmap_sh == nullptr) { + lightmap_sh = RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.alloc(); } - memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9); + memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9); } else { - if (ginstance->lightmap_sh != nullptr) { - geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); - ginstance->lightmap_sh = nullptr; + if (lightmap_sh != nullptr) { + RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh); + lightmap_sh = nullptr; } } - _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->shader_parameters_offset = p_offset; - _geometry_instance_mark_dirty(ginstance); -} - -void RenderForwardMobile::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->data->cast_double_sided_shadows = p_enable; - _geometry_instance_mark_dirty(ginstance); -} - -Transform3D RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance); - ERR_FAIL_COND_V(!ginstance, Transform3D()); - return ginstance->transform; -} - -AABB RenderForwardMobile::geometry_instance_get_aabb(GeometryInstance *p_instance) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance); - ERR_FAIL_COND_V(!ginstance, AABB()); - return ginstance->data->aabb; + _mark_dirty(); } -void RenderForwardMobile::geometry_instance_free(GeometryInstance *p_geometry_instance) { +void RenderForwardMobile::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (ginstance->lightmap_sh != nullptr) { @@ -2219,26 +2119,23 @@ uint32_t RenderForwardMobile::geometry_instance_get_pair_mask() { return ((1 << RS::INSTANCE_LIGHT) + (1 << RS::INSTANCE_REFLECTION_PROBE) + (1 << RS::INSTANCE_DECAL)); } -void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->omni_light_count = 0; - ginstance->spot_light_count = 0; +void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) { + omni_light_count = 0; + spot_light_count = 0; for (uint32_t i = 0; i < p_light_instance_count; i++) { - RS::LightType type = light_instance_get_type(p_light_instances[i]); + RS::LightType type = RenderForwardMobile::get_singleton()->light_instance_get_type(p_light_instances[i]); switch (type) { case RS::LIGHT_OMNI: { - if (ginstance->omni_light_count < (uint32_t)MAX_RDL_CULL) { - ginstance->omni_lights[ginstance->omni_light_count] = light_instance_get_forward_id(p_light_instances[i]); - ginstance->omni_light_count++; + if (omni_light_count < (uint32_t)MAX_RDL_CULL) { + omni_lights[omni_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + omni_light_count++; } } break; case RS::LIGHT_SPOT: { - if (ginstance->spot_light_count < (uint32_t)MAX_RDL_CULL) { - ginstance->spot_lights[ginstance->spot_light_count] = light_instance_get_forward_id(p_light_instances[i]); - ginstance->spot_light_count++; + if (spot_light_count < (uint32_t)MAX_RDL_CULL) { + spot_lights[spot_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + spot_light_count++; } } break; default: @@ -2247,56 +2144,42 @@ void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstanc } } -void RenderForwardMobile::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL; - for (uint32_t i = 0; i < ginstance->reflection_probe_count; i++) { - ginstance->reflection_probes[i] = reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); +void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { + reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL; + for (uint32_t i = 0; i < reflection_probe_count; i++) { + reflection_probes[i] = RenderForwardMobile::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); } } -void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL; - for (uint32_t i = 0; i < ginstance->decals_count; i++) { - ginstance->decals[i] = decal_instance_get_forward_id(p_decal_instances[i]); +void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) { + decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL; + for (uint32_t i = 0; i < decals_count; i++) { + decals[i] = RenderForwardMobile::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]); } } -void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { - // We do not have this here! +void RenderForwardMobile::GeometryInstanceForwardMobile::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) { + use_projector = p_projector; + use_soft_shadow = p_softshadow; } -void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - - ginstance->use_projector = p_projector; - ginstance->use_soft_shadow = p_softshadow; -} - -void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { - GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - if (ginstance->dirty_list_element.in_list()) { +void RenderForwardMobile::GeometryInstanceForwardMobile::_mark_dirty() { + if (dirty_list_element.in_list()) { return; } //clear surface caches - GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; + GeometryInstanceSurfaceDataCache *surf = surface_caches; while (surf) { GeometryInstanceSurfaceDataCache *next = surf->next; - geometry_instance_surface_alloc.free(surf); + RenderForwardMobile::get_singleton()->geometry_instance_surface_alloc.free(surf); surf = next; } - ginstance->surface_caches = nullptr; + surface_caches = nullptr; - geometry_instance_dirty_list.add(&ginstance->dirty_list_element); + RenderForwardMobile::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element); } void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { @@ -2350,7 +2233,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); @@ -2409,7 +2292,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(Geo while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } @@ -2429,7 +2312,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward SceneShaderForwardMobile::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2440,7 +2323,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2451,7 +2334,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); @@ -2462,7 +2345,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward } } -void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); @@ -2616,7 +2499,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe case Dependency::DEPENDENCY_CHANGED_PARTICLES: case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata); @@ -2630,7 +2513,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe } } void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { - static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } /* misc */ @@ -2681,12 +2564,18 @@ void RenderForwardMobile::_update_shader_quality_settings() { sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS; - sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; + sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || + decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || + decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC || + decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS; - sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; + sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC || + light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 473a58045c..4a7112eb81 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H -#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H +#ifndef RENDER_FORWARD_MOBILE_H +#define RENDER_FORWARD_MOBILE_H #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h" @@ -131,12 +131,14 @@ protected: RID depth_msaa; // RID normal_roughness_buffer_msaa; + RID vrs; + RID color_fbs[FB_CONFIG_MAX]; int width, height; uint32_t view_count; void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); ~RenderBufferDataForwardMobile(); }; @@ -158,7 +160,7 @@ protected: // PASS_MODE_SDF, }; - struct GeometryInstanceForwardMobile; + class GeometryInstanceForwardMobile; struct GeometryInstanceSurfaceDataCache; struct RenderElementInfo; @@ -210,14 +212,14 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; uint64_t lightmap_texture_array_version = 0xFFFFFFFF; @@ -516,14 +518,8 @@ protected: GeometryInstanceForwardMobile *owner = nullptr; }; - // !BAS! GeometryInstanceForwardClustered and GeometryInstanceForwardMobile will likely have a lot of overlap - // may need to think about making this its own class like GeometryInstanceRD? - - struct GeometryInstanceForwardMobile : public GeometryInstance { - // setup - uint32_t base_flags = 0; - uint32_t flags_cache = 0; - + class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase { + public: // this structure maps to our push constant in our shader and is populated right before our draw call struct PushConstant { float transform[16]; @@ -541,28 +537,18 @@ protected: // PushConstant push_constant; // we populate this from our instance data //used during rendering - uint32_t layer_mask = 1; RID transforms_uniform_set; - float depth = 0; - bool mirror = false; bool use_projector = false; bool use_soft_shadow = false; - Transform3D transform; bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform - bool non_uniform_scale = false; - AABB transformed_aabb; //needed for LOD - float lod_bias = 0.0; - float lod_model_scale = 1.0; - int32_t shader_parameters_offset = -1; uint32_t instance_count = 0; uint32_t trail_steps = 1; - RID mesh_instance; // lightmap uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap - uint32_t lightmap_slice_index; - Rect2 lightmap_uv_scale; RID lightmap_instance; + Rect2 lightmap_uv_scale; + uint32_t lightmap_slice_index; GeometryInstanceLightmapSH *lightmap_sh = nullptr; // culled light info @@ -580,30 +566,20 @@ protected: // do we use this? SelfList<GeometryInstanceForwardMobile> dirty_list_element; - struct Data { - //data used less often goes into regular heap - RID base; - RS::InstanceType base_type; - - RID skeleton; - Vector<RID> surface_materials; - RID material_override; - RID material_overlay; - AABB aabb; - - bool use_baked_light = true; - bool cast_double_sided_shadows = false; - // bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct + GeometryInstanceForwardMobile() : + dirty_list_element(this) {} - bool dirty_dependencies = false; + virtual void _mark_dirty() override; - DependencyTracker dependency_tracker; - }; + virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; + virtual void set_lightmap_capture(const Color *p_sh9) override; - Data *data = nullptr; + virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override; + virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; + virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override; + virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - GeometryInstanceForwardMobile() : - dirty_list_element(this) {} + virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override; }; _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); @@ -611,6 +587,8 @@ protected: void _update_shader_quality_settings() override; public: + static RenderForwardMobile *get_singleton() { return singleton; } + virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override; static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); @@ -625,41 +603,13 @@ public: void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); - void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); - void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance); void _update_dirty_geometry_instances(); - virtual GeometryInstance *geometry_instance_create(RID p_base) override; - virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; - virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; - virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override; - virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override; - virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; - virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; - virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override; - virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override; - virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; - virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override; - virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override; - virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override; - virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override; - virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; - virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override; - virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override; - virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override; - - virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override; - virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override; - - virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override; + virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override; + virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; virtual uint32_t geometry_instance_get_pair_mask() override; - virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override; - virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; - virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override; - virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override; - - virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override; virtual bool free(RID p_rid) override; @@ -672,4 +622,5 @@ public: ~RenderForwardMobile(); }; } // namespace RendererSceneRenderImplementation -#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H + +#endif // RENDER_FORWARD_MOBILE_H diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index dd00dc2bf9..01b54607bc 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -39,6 +39,10 @@ using namespace RendererSceneRenderImplementation; /* ShaderData */ +void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { //compile @@ -345,7 +349,7 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin } } -void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -360,7 +364,22 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_ } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -426,7 +445,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() { } } -RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -450,7 +469,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -493,8 +512,8 @@ void SceneShaderForwardMobile::init(const String p_defines) { } } - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -565,7 +584,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; - actions.renames["FOG"] = "custom_fog"; + actions.renames["FOG"] = "fog"; actions.renames["RADIANCE"] = "custom_radiance"; actions.renames["IRRADIANCE"] = "custom_irradiance"; actions.renames["BONE_INDICES"] = "bone_attrib"; @@ -576,6 +595,11 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["CUSTOM3"] = "custom3_attrib"; actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz"; + actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; + actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz"; + actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; @@ -666,7 +690,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture @@ -697,7 +721,7 @@ void fragment() { material_storage->material_initialize(default_material); material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_material_shader_ptr = md->shader_data; @@ -724,7 +748,7 @@ void fragment() { material_storage->material_initialize(overdraw_material); material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 88c2143b09..e208334547 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RSSR_SCENE_SHADER_FM_H -#define RSSR_SCENE_SHADER_FM_H +#ifndef SCENE_SHADER_FORWARD_MOBILE_H +#define SCENE_SHADER_FORWARD_MOBILE_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h" @@ -55,7 +55,7 @@ public: SHADER_VERSION_MAX }; - struct ShaderData : public RendererRD::ShaderData { + struct ShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -139,8 +139,10 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -155,12 +157,12 @@ public: virtual ~ShaderData(); }; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererRD::MaterialData { + struct MaterialData : public RendererRD::MaterialStorage::MaterialData { ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; @@ -175,8 +177,8 @@ public: SelfList<ShaderData>::List shader_list; - RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } @@ -210,4 +212,5 @@ public: }; } // namespace RendererSceneRenderImplementation -#endif // !RSSR_SCENE_SHADER_FM_H + +#endif // SCENE_SHADER_FORWARD_MOBILE_H diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp index ddf1d1bd00..9baa86a32d 100644 --- a/servers/rendering/renderer_thread_pool.cpp +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_thread_pool.cpp */ +/* framebuffer_cache_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,37 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_thread_pool.h" +#include "framebuffer_cache_rd.h" -RendererThreadPool *RendererThreadPool::singleton = nullptr; +FramebufferCacheRD *FramebufferCacheRD::singleton = nullptr; -RendererThreadPool::RendererThreadPool() { +void FramebufferCacheRD::_invalidate(Cache *p_cache) { + if (p_cache->prev) { + p_cache->prev->next = p_cache->next; + } else { + // At beginning of table + uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE; + hash_table[table_idx] = p_cache->next; + } + + if (p_cache->next) { + p_cache->next->prev = p_cache->prev; + } + + cache_allocator.free(p_cache); + cache_instances_used--; +} +void FramebufferCacheRD::_framebuffer_invalidation_callback(void *p_userdata) { + singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata)); +} + +FramebufferCacheRD::FramebufferCacheRD() { + ERR_FAIL_COND(singleton != nullptr); singleton = this; - thread_work_pool.init(); } -RendererThreadPool::~RendererThreadPool() { - thread_work_pool.finish(); +FramebufferCacheRD::~FramebufferCacheRD() { + if (cache_instances_used > 0) { + ERR_PRINT("At exit: " + itos(cache_instances_used) + " framebuffer cache instance(s) still in use."); + } } diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h new file mode 100644 index 0000000000..f360e0fc6b --- /dev/null +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h @@ -0,0 +1,310 @@ +/*************************************************************************/ +/* framebuffer_cache_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 FRAMEBUFFER_CACHE_RD_H +#define FRAMEBUFFER_CACHE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/paged_allocator.h" +#include "servers/rendering/rendering_device.h" + +class FramebufferCacheRD : public Object { + GDCLASS(FramebufferCacheRD, Object) + + struct Cache { + Cache *prev = nullptr; + Cache *next = nullptr; + uint32_t hash = 0; + RID cache; + LocalVector<RID> textures; + LocalVector<RD::FramebufferPass> passes; + uint32_t views = 0; + }; + + PagedAllocator<Cache> cache_allocator; + + enum { + HASH_TABLE_SIZE = 16381 // Prime + }; + + Cache *hash_table[HASH_TABLE_SIZE] = {}; + + static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) { + h = hash_murmur3_one_32(p.depth_attachment, h); + h = hash_murmur3_one_32(p.vrs_attachment, h); + + h = hash_murmur3_one_32(p.color_attachments.size(), h); + for (int i = 0; i < p.color_attachments.size(); i++) { + h = hash_murmur3_one_32(p.color_attachments[i], h); + } + + h = hash_murmur3_one_32(p.resolve_attachments.size(), h); + for (int i = 0; i < p.resolve_attachments.size(); i++) { + h = hash_murmur3_one_32(p.resolve_attachments[i], h); + } + + h = hash_murmur3_one_32(p.preserve_attachments.size(), h); + for (int i = 0; i < p.preserve_attachments.size(); i++) { + h = hash_murmur3_one_32(p.preserve_attachments[i], h); + } + + return h; + } + + static _FORCE_INLINE_ bool _compare_pass(const RD::FramebufferPass &a, const RD::FramebufferPass &b) { + if (a.depth_attachment != b.depth_attachment) { + return false; + } + + if (a.vrs_attachment != b.vrs_attachment) { + return false; + } + + if (a.color_attachments.size() != b.color_attachments.size()) { + return false; + } + + for (int i = 0; i < a.color_attachments.size(); i++) { + if (a.color_attachments[i] != b.color_attachments[i]) { + return false; + } + } + + if (a.resolve_attachments.size() != b.resolve_attachments.size()) { + return false; + } + + for (int i = 0; i < a.resolve_attachments.size(); i++) { + if (a.resolve_attachments[i] != b.resolve_attachments[i]) { + return false; + } + } + + if (a.preserve_attachments.size() != b.preserve_attachments.size()) { + return false; + } + + for (int i = 0; i < a.preserve_attachments.size(); i++) { + if (a.preserve_attachments[i] != b.preserve_attachments[i]) { + return false; + } + } + + return true; + } + + _FORCE_INLINE_ uint32_t _hash_rids(uint32_t h, const RID &arg) { + return hash_murmur3_one_64(arg.get_id(), h); + } + + template <typename... Args> + uint32_t _hash_rids(uint32_t h, const RID &arg, Args... args) { + h = hash_murmur3_one_64(arg.get_id(), h); + return _hash_rids(h, args...); + } + + _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg) { + return textures[idx] == arg; + } + + template <typename... Args> + _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg, Args... args) { + if (textures[idx] != arg) { + return false; + } + return _compare_args(idx + 1, textures, args...); + } + + _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg) { + textures.push_back(arg); + } + + template <typename... Args> + _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg, Args... args) { + textures.push_back(arg); + _create_args(textures, args...); + } + + static FramebufferCacheRD *singleton; + + uint32_t cache_instances_used = 0; + + void _invalidate(Cache *p_cache); + static void _framebuffer_invalidation_callback(void *p_userdata); + + RID _allocate_from_data(uint32_t p_views, uint32_t p_hash, uint32_t p_table_idx, const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes) { + RID rid; + if (p_passes.size()) { + rid = RD::get_singleton()->framebuffer_create_multipass(p_textures, p_passes, RD::INVALID_ID, p_views); + } else { + rid = RD::get_singleton()->framebuffer_create(p_textures, RD::INVALID_ID, p_views); + } + + ERR_FAIL_COND_V(rid.is_null(), rid); + + Cache *c = cache_allocator.alloc(); + c->views = p_views; + c->cache = rid; + c->hash = p_hash; + c->textures.resize(p_textures.size()); + for (uint32_t i = 0; i < c->textures.size(); i++) { + c->textures[i] = p_textures[i]; + } + c->passes.resize(p_passes.size()); + for (uint32_t i = 0; i < c->passes.size(); i++) { + c->passes[i] = p_passes[i]; + } + c->prev = nullptr; + c->next = hash_table[p_table_idx]; + if (hash_table[p_table_idx]) { + hash_table[p_table_idx]->prev = c; + } + hash_table[p_table_idx] = c; + + RD::get_singleton()->framebuffer_set_invalidation_callback(rid, _framebuffer_invalidation_callback, c); + + cache_instances_used++; + + return rid; + } + +public: + template <typename... Args> + RID get_cache(Args... args) { + uint32_t h = hash_murmur3_one_32(1); //1 view + h = hash_murmur3_one_32(sizeof...(Args), h); + h = _hash_args(h, args...); + h = hash_murmur3_one_32(0, h); // 0 passes + h = hash_fmix32(h); + + uint32_t table_idx = h % HASH_TABLE_SIZE; + { + const Cache *c = hash_table[table_idx]; + + while (c) { + if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == 1 && _compare_args(0, c->textures, args...)) { + return c->cache; + } + c = c->next; + } + } + + // Not in cache, create: + + Vector<RID> textures; + _create_args(textures, args...); + + return _allocate_from_data(1, h, table_idx, textures, Vector<RD::FramebufferPass>()); + } + + template <typename... Args> + RID get_cache_multiview(uint32_t p_views, Args... args) { + uint32_t h = hash_murmur3_one_32(p_views); + h = hash_murmur3_one_32(sizeof...(Args), h); + h = _hash_args(h, args...); + h = hash_murmur3_one_32(0, h); // 0 passes + h = hash_fmix32(h); + + uint32_t table_idx = h % HASH_TABLE_SIZE; + { + const Cache *c = hash_table[table_idx]; + + while (c) { + if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == p_views && _compare_args(0, c->textures, args...)) { + return c->cache; + } + c = c->next; + } + } + + // Not in cache, create: + + Vector<RID> textures; + _create_args(textures, args...); + + return _allocate_from_data(p_views, h, table_idx, textures, Vector<RD::FramebufferPass>()); + } + + RID get_cache_multipass(const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes, uint32_t p_views = 1) { + uint32_t h = hash_murmur3_one_32(p_views); + h = hash_murmur3_one_32(p_textures.size()); + for (int i = 0; i < p_textures.size(); i++) { + h = hash_murmur3_one_64(p_textures[i].get_id(), h); + } + h = hash_murmur3_one_32(p_passes.size()); + for (int i = 0; i < p_passes.size(); i++) { + h = _hash_pass(p_passes[i], h); + } + + h = hash_fmix32(h); + + uint32_t table_idx = h % HASH_TABLE_SIZE; + { + const Cache *c = hash_table[table_idx]; + + while (c) { + if (c->hash == h && c->views == p_views && c->textures.size() == (uint32_t)p_textures.size() && c->passes.size() == (uint32_t)p_passes.size()) { + bool all_ok = true; + + for (int i = 0; i < p_textures.size(); i++) { + if (p_textures[i] != c->textures[i]) { + all_ok = false; + break; + } + } + + if (all_ok) { + for (int i = 0; i < p_passes.size(); i++) { + if (!_compare_pass(p_passes[i], c->passes[i])) { + all_ok = false; + break; + } + } + } + + if (all_ok) { + return c->cache; + } + } + c = c->next; + } + } + + // Not in cache, create: + return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes); + } + + static FramebufferCacheRD *get_singleton() { return singleton; } + + FramebufferCacheRD(); + ~FramebufferCacheRD(); +}; + +#endif // FRAMEBUFFER_CACHE_RD_H diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index ad83fc76b7..882e459bcd 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -97,4 +97,4 @@ public: ~PipelineCacheRD(); }; -#endif // RENDER_PIPELINE_CACHE_RD_H +#endif // PIPELINE_CACHE_RD_H diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index b87b189d53..c1b08ee4c9 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -192,7 +192,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[1] = vd; - buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR); + buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_COLOR); } //uvs @@ -220,7 +220,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[2] = vd; - buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV); + buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_TEX_UV); } //bones @@ -253,7 +253,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[3] = vd; - buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES); + buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_BONES); } //weights @@ -286,7 +286,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[4] = vd; - buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS); + buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_WEIGHTS); } //check that everything is as it should be @@ -528,7 +528,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform + push_constant.flags |= FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { @@ -988,7 +988,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -1031,7 +1031,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 9; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); uniforms.push_back(u); } @@ -1115,7 +1115,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co if (material != prev_material) { CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { - material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); + material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D)); } if (material_data) { @@ -1304,7 +1304,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p Size2i ssize = texture_storage->render_target_get_size(p_to_render_target); Transform3D screen_transform; - screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); @@ -1383,7 +1383,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_valid()) { - CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); + CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D)); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -1581,9 +1581,10 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); - CameraMatrix projection; + Projection projection; { real_t fov = 90; real_t nearp = p_near; @@ -1599,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, } Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); - projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1670,11 +1671,11 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh cc.push_back(Color(1, 1, 1, 1)); Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); - CameraMatrix projection; + Projection projection; projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); - projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse()); + projection = projection * Projection(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse()); ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1742,7 +1743,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); - CameraMatrix projection; + Projection projection; ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1967,6 +1968,10 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS:: oc->cull_mode = p_mode; } +void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { //compile @@ -2166,7 +2171,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S } } -void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -2180,7 +2185,22 @@ void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -2241,7 +2261,7 @@ RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() { } } -RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_func() { CanvasShaderData *shader_data = memnew(CanvasShaderData); return shader_data; } @@ -2256,7 +2276,7 @@ RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { CanvasMaterialData *material_data = memnew(CanvasMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -2431,6 +2451,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; + actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; @@ -2448,7 +2469,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; actions.base_varying_index = 4; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; shader.compiler.initialize(actions); } @@ -2608,8 +2629,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); //create functions for shader and material - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_material_funcs); state.time = 0; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 2ab5a7c831..5eb4cee4c6 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H -#define RENDERING_SERVER_CANVAS_RENDER_RD_H +#ifndef RENDERER_CANVAS_RENDER_RD_H +#define RENDERER_CANVAS_RENDER_RD_H #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" @@ -149,7 +149,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { ShaderCompiler compiler; } shader; - struct CanvasShaderData : public RendererRD::ShaderData { + struct CanvasShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -178,8 +178,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool uses_time = false; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -192,12 +193,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual ~CanvasShaderData(); }; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func(); } - struct CanvasMaterialData : public RendererRD::MaterialData { + struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData { CanvasShaderData *shader_data = nullptr; RID uniform_set; @@ -207,8 +208,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual ~CanvasMaterialData(); }; - RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(CanvasShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader)); } @@ -464,4 +465,4 @@ public: ~RendererCanvasRenderRD(); }; -#endif // RASTERIZER_CANVAS_RD_H +#endif // RENDERER_CANVAS_RENDER_RD_H diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index a61172c8f5..967b725b9e 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -249,6 +249,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr; RendererCompositorRD::RendererCompositorRD() { uniform_set_cache = memnew(UniformSetCacheRD); + framebuffer_cache = memnew(FramebufferCacheRD); { String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path(); @@ -316,5 +317,6 @@ RendererCompositorRD::RendererCompositorRD() { RendererCompositorRD::~RendererCompositorRD() { memdelete(uniform_set_cache); + memdelete(framebuffer_cache); ShaderRD::set_shader_cache_dir(String()); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 2be55743fb..a28335f800 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_COMPOSITOR_RD_H -#define RENDERING_SERVER_COMPOSITOR_RD_H +#ifndef RENDERER_COMPOSITOR_RD_H +#define RENDERER_COMPOSITOR_RD_H #include "core/os/os.h" -#include "core/templates/thread_work_pool.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/effects_rd.h" #include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h" #include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" @@ -51,6 +51,7 @@ class RendererCompositorRD : public RendererCompositor { protected: UniformSetCacheRD *uniform_set_cache = nullptr; + FramebufferCacheRD *framebuffer_cache = nullptr; RendererCanvasRenderRD *canvas = nullptr; RendererRD::Utilities *utilities = nullptr; RendererRD::LightStorage *light_storage = nullptr; @@ -148,4 +149,5 @@ public: RendererCompositorRD(); ~RendererCompositorRD(); }; -#endif // RASTERIZER_RD_H + +#endif // RENDERER_COMPOSITOR_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp deleted file mode 100644 index 0d9477d850..0000000000 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************/ -/* renderer_scene_environment_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" - -uint64_t RendererSceneEnvironmentRD::auto_exposure_counter = 2; - -void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { - ambient_light = p_color; - ambient_source = p_ambient; - ambient_light_energy = p_energy; - ambient_sky_contribution = p_sky_contribution; - reflection_source = p_reflection_source; -} - -void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - exposure = p_exposure; - tone_mapper = p_tone_mapper; - if (!auto_exposure && p_auto_exposure) { - auto_exposure_version = ++auto_exposure_counter; - } - auto_exposure = p_auto_exposure; - white = p_white; - min_luminance = p_min_luminance; - max_luminance = p_max_luminance; - auto_exp_speed = p_auto_exp_speed; - auto_exp_scale = p_auto_exp_scale; -} - -void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { - ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); - glow_enabled = p_enable; - glow_levels = p_levels; - glow_intensity = p_intensity; - glow_strength = p_strength; - glow_mix = p_mix; - glow_bloom = p_bloom_threshold; - glow_blend_mode = p_blend_mode; - glow_hdr_bleed_threshold = p_hdr_bleed_threshold; - glow_hdr_bleed_scale = p_hdr_bleed_scale; - glow_hdr_luminance_cap = p_hdr_luminance_cap; - glow_map_strength = p_glow_map_strength; - glow_map = p_glow_map; -} - -void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { - sdfgi_enabled = p_enable; - sdfgi_cascades = p_cascades; - sdfgi_min_cell_size = p_min_cell_size; - sdfgi_use_occlusion = p_use_occlusion; - sdfgi_bounce_feedback = p_bounce_feedback; - sdfgi_read_sky_light = p_read_sky; - sdfgi_energy = p_energy; - sdfgi_normal_bias = p_normal_bias; - sdfgi_probe_bias = p_probe_bias; - sdfgi_y_scale = p_y_scale; -} - -void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { - fog_enabled = p_enable; - fog_light_color = p_light_color; - fog_light_energy = p_light_energy; - fog_sun_scatter = p_sun_scatter; - fog_density = p_density; - fog_height = p_height; - fog_height_density = p_height_density; - fog_aerial_perspective = p_fog_aerial_perspective; -} - -void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { - volumetric_fog_enabled = p_enable; - volumetric_fog_density = p_density; - volumetric_fog_scattering = p_albedo; - volumetric_fog_emission = p_emission; - volumetric_fog_emission_energy = p_emission_energy; - volumetric_fog_anisotropy = p_anisotropy, - volumetric_fog_length = p_length; - volumetric_fog_detail_spread = p_detail_spread; - volumetric_fog_gi_inject = p_gi_inject; - volumetric_fog_temporal_reprojection = p_temporal_reprojection; - volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount; - volumetric_fog_ambient_inject = p_ambient_inject; -} - -void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { - ssr_enabled = p_enable; - ssr_max_steps = p_max_steps; - ssr_fade_in = p_fade_int; - ssr_fade_out = p_fade_out; - ssr_depth_tolerance = p_depth_tolerance; -} - -void RendererSceneEnvironmentRD::set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { - ssao_enabled = p_enable; - ssao_radius = p_radius; - ssao_intensity = p_intensity; - ssao_power = p_power; - ssao_detail = p_detail; - ssao_horizon = p_horizon; - ssao_sharpness = p_sharpness; - ssao_direct_light_affect = p_light_affect; - ssao_ao_channel_affect = p_ao_channel_affect; -} diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h deleted file mode 100644 index 4e170b8cfb..0000000000 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h +++ /dev/null @@ -1,167 +0,0 @@ -/*************************************************************************/ -/* renderer_scene_environment_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H -#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H - -#include "servers/rendering/renderer_scene_render.h" -#include "servers/rendering/rendering_device.h" - -class RendererSceneEnvironmentRD { -private: - static uint64_t auto_exposure_counter; - -public: - // BG - RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR; - RID sky; - float sky_custom_fov = 0.0; - Basis sky_orientation; - Color bg_color; - float bg_energy = 1.0; - int canvas_max_layer = 0; - RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG; - Color ambient_light; - float ambient_light_energy = 1.0; - float ambient_sky_contribution = 1.0; - RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; - - /// Tonemap - - RS::EnvironmentToneMapper tone_mapper; - float exposure = 1.0; - float white = 1.0; - bool auto_exposure = false; - float min_luminance = 0.2; - float max_luminance = 8.0; - float auto_exp_speed = 0.2; - float auto_exp_scale = 0.5; - uint64_t auto_exposure_version = 0; - - // Fog - bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); - float fog_light_energy = 1.0; - float fog_sun_scatter = 0.0; - float fog_density = 0.001; - float fog_height = 0.0; - float fog_height_density = 0.0; //can be negative to invert effect - float fog_aerial_perspective = 0.0; - - /// Volumetric Fog - /// - bool volumetric_fog_enabled = false; - float volumetric_fog_density = 0.01; - Color volumetric_fog_scattering = Color(1, 1, 1); - Color volumetric_fog_emission = Color(0, 0, 0); - float volumetric_fog_emission_energy = 0.0; - float volumetric_fog_anisotropy = 0.2; - float volumetric_fog_length = 64.0; - float volumetric_fog_detail_spread = 2.0; - float volumetric_fog_gi_inject = 0.0; - bool volumetric_fog_temporal_reprojection = true; - float volumetric_fog_temporal_reprojection_amount = 0.9; - float volumetric_fog_ambient_inject = 0.0; - - /// Glow - - bool glow_enabled = false; - Vector<float> glow_levels; - float glow_intensity = 0.8; - float glow_strength = 1.0; - float glow_bloom = 0.0; - float glow_mix = 0.01; - RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; - float glow_hdr_bleed_threshold = 1.0; - float glow_hdr_luminance_cap = 12.0; - float glow_hdr_bleed_scale = 2.0; - float glow_map_strength = 0.0f; - RID glow_map = RID(); - - /// SSAO - - bool ssao_enabled = false; - float ssao_radius = 1.0; - float ssao_intensity = 2.0; - float ssao_power = 1.5; - float ssao_detail = 0.5; - float ssao_horizon = 0.06; - float ssao_sharpness = 0.98; - float ssao_direct_light_affect = 0.0; - float ssao_ao_channel_affect = 0.0; - - /// SSR - /// - bool ssr_enabled = false; - int ssr_max_steps = 64; - float ssr_fade_in = 0.15; - float ssr_fade_out = 2.0; - float ssr_depth_tolerance = 0.2; - - /// SSIL - /// - bool ssil_enabled = false; - float ssil_radius = 5.0; - float ssil_intensity = 1.0; - float ssil_sharpness = 0.98; - float ssil_normal_rejection = 1.0; - - /// SDFGI - bool sdfgi_enabled = false; - int sdfgi_cascades = 4; - float sdfgi_min_cell_size = 0.2; - bool sdfgi_use_occlusion = false; - float sdfgi_bounce_feedback = 0.5; - bool sdfgi_read_sky_light = true; - float sdfgi_energy = 1.0; - float sdfgi_normal_bias = 1.1; - float sdfgi_probe_bias = 1.1; - RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT; - - /// Adjustments - - bool adjustments_enabled = false; - float adjustments_brightness = 1.0f; - float adjustments_contrast = 1.0f; - float adjustments_saturation = 1.0f; - bool use_1d_color_correction = false; - RID color_correction = RID(); - - void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source); - void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map); - void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); - void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective); - void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); - void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); - void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect); -}; - -#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */ diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 5185d537ec..8b3b7050d2 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -51,9 +51,8 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) { } void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - bool needs_sdfgi = env && env->sdfgi_enabled; + bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment); if (!needs_sdfgi) { if (rb->sdfgi != nullptr) { @@ -68,7 +67,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge]; - if (rb->sdfgi && (rb->sdfgi->num_cascades != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) { + if (rb->sdfgi && (rb->sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || rb->sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || rb->sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) { //configuration changed, erase rb->sdfgi->erase(); memdelete(rb->sdfgi); @@ -78,10 +77,10 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment RendererRD::GI::SDFGI *sdfgi = rb->sdfgi; if (sdfgi == nullptr) { // re-create - rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size); + rb->sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size); } else { //check for updates - rb->sdfgi->update(env, p_world_position); + rb->sdfgi->update(p_environment, p_world_position); } } @@ -159,145 +158,6 @@ Ref<Image> RendererSceneRenderRD::sky_bake_panorama(RID p_sky, float p_energy, b return sky.sky_bake_panorama(p_sky, p_energy, p_bake_irradiance, p_size); } -RID RendererSceneRenderRD::environment_allocate() { - return environment_owner.allocate_rid(); -} -void RendererSceneRenderRD::environment_initialize(RID p_rid) { - environment_owner.initialize_rid(p_rid, RendererSceneEnvironmentRD()); -} - -void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->background = p_bg; -} - -void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky = p_sky; -} - -void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_custom_fov = p_scale; -} - -void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_orientation = p_orientation; -} - -void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_color = p_color; -} - -void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_energy = p_energy; -} - -void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->canvas_max_layer = p_max_layer; -} - -void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source); -} - -RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); - return env->background; -} - -RID RendererSceneRenderRD::environment_get_sky(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RID()); - return env->sky; -} - -float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->sky_custom_fov; -} - -Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Basis()); - return env->sky_orientation; -} - -Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->bg_color; -} - -float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->bg_energy; -} - -int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->canvas_max_layer; -} - -Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->ambient_light; -} - -RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG); - return env->ambient_source; -} - -float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->ambient_light_energy; -} - -float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->ambient_sky_contribution; -} - -RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED); - return env->reflection_source; -} - -void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale); -} - -void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map); -} - void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; } @@ -306,79 +166,6 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable) glow_high_quality = p_enable; } -void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - if (!is_dynamic_gi_supported()) { - return; - } - - env->set_sdfgi(p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias); -} - -void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective); -} - -bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, false); - - return env->fog_enabled; -} -Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->fog_light_color; -} -float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->fog_light_energy; -} -float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->fog_sun_scatter; -} -float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->fog_density; -} -float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - - return env->fog_height; -} -float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->fog_height_density; -} - -float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const { - const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->fog_aerial_perspective; -} - -void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - if (!is_volumetric_supported()) { - return; - } - - env->set_volumetric_fog(p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject); -} - void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { volumetric_fog_size = p_size; volumetric_fog_depth = p_depth; @@ -399,13 +186,6 @@ void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::Env gi.sdfgi_frames_to_update_light = p_update; } -void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - env->set_ssr(p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance); -} - void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { ssr_roughness_quality = p_quality; } @@ -414,13 +194,6 @@ RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_ro return ssr_roughness_quality; } -void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - env->set_ssao(p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect); -} - void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { ssao_quality = p_quality; ssao_half_size = p_half_size; @@ -430,17 +203,6 @@ void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQual ssao_fadeout_to = p_fadeout_to; } -void RendererSceneRenderRD::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - env->ssil_enabled = p_enable; - env->ssil_radius = p_radius; - env->ssil_intensity = p_intensity; - env->ssil_sharpness = p_sharpness; - env->ssil_normal_rejection = p_normal_rejection; -} - void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { ssil_quality = p_quality; ssil_half_size = p_half_size; @@ -450,56 +212,16 @@ void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQual ssil_fadeout_to = p_fadeout_to; } -bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssao_enabled; -} - -float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0.0); - return env->ssao_ao_channel_affect; -} - -float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0.0); - return env->ssao_direct_light_affect; -} - -bool RendererSceneRenderRD::environment_is_ssil_enabled(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssil_enabled; -} - -bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssr_enabled; -} -bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, false); - return env->sdfgi_enabled; -} - -bool RendererSceneRenderRD::is_environment(RID p_env) const { - return environment_owner.owns(p_env); -} - Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Ref<Image>()); + ERR_FAIL_COND_V(p_env.is_null(), Ref<Image>()); - RS::EnvironmentBG environment_background = env->background; + RS::EnvironmentBG environment_background = environment_get_background(p_env); if (environment_background == RS::ENV_BG_CAMERA_FEED || environment_background == RS::ENV_BG_CANVAS || environment_background == RS::ENV_BG_KEEP) { return Ref<Image>(); //nothing to bake } - RS::EnvironmentAmbientSource ambient_source = env->ambient_source; + RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_env); bool use_ambient_light = false; bool use_cube_map = false; @@ -509,14 +231,14 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba use_cube_map = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && environment_background == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY; use_ambient_light = use_cube_map || ambient_source == RS::ENV_AMBIENT_SOURCE_COLOR; } - use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && env->sky.is_valid()); + use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && environment_get_sky(p_env).is_valid()); Color ambient_color; - float ambient_color_sky_mix; + float ambient_color_sky_mix = 0.0; if (use_ambient_light) { - ambient_color_sky_mix = env->ambient_sky_contribution; - const float ambient_energy = env->ambient_light_energy; - ambient_color = env->ambient_light; + ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_env); + const float ambient_energy = environment_get_ambient_light_energy(p_env); + ambient_color = environment_get_ambient_light(p_env); ambient_color = ambient_color.srgb_to_linear(); ambient_color.r *= ambient_energy; ambient_color.g *= ambient_energy; @@ -524,7 +246,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba } if (use_cube_map) { - Ref<Image> panorama = sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size); + Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy(p_env), p_bake_irradiance, p_size); if (use_ambient_light) { for (int x = 0; x < p_size.width; x++) { for (int y = 0; y < p_size.height; y++) { @@ -534,8 +256,8 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba } return panorama; } else { - const float bg_energy = env->bg_energy; - Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : env->bg_color); + const float bg_energy = environment_get_bg_energy(p_env); + Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : environment_get_bg_color(p_env)); panorama_color = panorama_color.srgb_to_linear(); panorama_color.r *= bg_energy; panorama_color.g *= bg_energy; @@ -558,29 +280,28 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba //////////////////////////////////////////////////////////// RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) { - FogVolumeInstance fvi; - fvi.volume = p_fog_volume; - return fog_volume_instance_owner.make_rid(fvi); + return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume); } + void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND(!fvi); fvi->transform = p_transform; } void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND(!fvi); fvi->active = p_active; } RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND_V(!fvi, RID()); return fvi->volume; } Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND_V(!fvi, Vector3()); return fvi->transform.get_origin(); @@ -1430,7 +1151,7 @@ void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const light_instance->aabb = p_aabb; } -void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { +void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); ERR_FAIL_COND(!light_instance); @@ -1526,7 +1247,7 @@ bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const { return gi.voxel_gi_needs_update(p_probe); } -void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) { +void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { if (!is_dynamic_gi_supported()) { return; } @@ -1534,7 +1255,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); } -void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1827,6 +1548,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->sss_texture = RID(); } + if (rb->vrs_fb.is_valid()) { + RD::get_singleton()->free(rb->vrs_fb); + rb->vrs_fb = RID(); + } + + if (rb->vrs_texture.is_valid()) { + RD::get_singleton()->free(rb->vrs_texture); + rb->vrs_texture = RID(); + } + for (int i = 0; i < 2; i++) { for (int l = 0; l < rb->blur[i].layers.size(); l++) { for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { @@ -1881,60 +1612,9 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->ss_effects.linear_depth_slices.clear(); } - if (rb->ss_effects.ssao.ao_final.is_valid()) { - RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_final); - - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]); - - rb->ss_effects.ssao.ao_deinterleaved = RID(); - rb->ss_effects.ssao.ao_pong = RID(); - rb->ss_effects.ssao.ao_final = RID(); - rb->ss_effects.ssao.importance_map[0] = RID(); - rb->ss_effects.ssao.importance_map[1] = RID(); - - rb->ss_effects.ssao.ao_deinterleaved_slices.clear(); - rb->ss_effects.ssao.ao_pong_slices.clear(); - } - - if (rb->ss_effects.ssil.ssil_final.is_valid()) { - RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final); - RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssil.pong); - RD::get_singleton()->free(rb->ss_effects.ssil.edges); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]); - - rb->ss_effects.ssil.ssil_final = RID(); - rb->ss_effects.ssil.deinterleaved = RID(); - rb->ss_effects.ssil.pong = RID(); - rb->ss_effects.ssil.edges = RID(); - rb->ss_effects.ssil.deinterleaved_slices.clear(); - rb->ss_effects.ssil.pong_slices.clear(); - rb->ss_effects.ssil.edges_slices.clear(); - rb->ss_effects.ssil.importance_map[0] = RID(); - rb->ss_effects.ssil.importance_map[1] = RID(); - - RD::get_singleton()->free(rb->ss_effects.last_frame); - rb->ss_effects.last_frame = RID(); - rb->ss_effects.last_frame_slices.clear(); - } - - if (rb->ssr.blur_radius[0].is_valid()) { - RD::get_singleton()->free(rb->ssr.blur_radius[0]); - RD::get_singleton()->free(rb->ssr.blur_radius[1]); - rb->ssr.blur_radius[0] = RID(); - rb->ssr.blur_radius[1] = RID(); - } - - if (rb->ssr.depth_scaled.is_valid()) { - RD::get_singleton()->free(rb->ssr.depth_scaled); - rb->ssr.depth_scaled = RID(); - RD::get_singleton()->free(rb->ssr.normal_scaled); - rb->ssr.normal_scaled = RID(); - } + ss_effects->ssao_free(rb->ss_effects.ssao); + ss_effects->ssil_free(rb->ss_effects.ssil); + ss_effects->ssr_free(rb->ssr); if (rb->taa.history.is_valid()) { RD::get_singleton()->free(rb->taa.history); @@ -1954,7 +1634,7 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->rbgi.free(); } -void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { +void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const Projection &p_camera) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1972,7 +1652,9 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); } -void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { +void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1980,161 +1662,45 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb if (!can_use_effects) { //just copy - RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID()); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID(), rb->view_count); return; } - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment); - ERR_FAIL_COND(!env); + ERR_FAIL_COND(p_environment.is_null()); - ERR_FAIL_COND(!env->ssr_enabled); + ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); - if (rb->ssr.depth_scaled.is_null()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = rb->internal_width / 2; - tf.height = rb->internal_height / 2; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; - - rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - - rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->internal_width / 2; - tf.height = rb->internal_height / 2; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Size2i half_size = Size2i(rb->internal_width / 2, rb->internal_height / 2); + if (rb->ssr.output.is_null()) { + ss_effects->ssr_allocate_buffers(rb->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, rb->view_count); } - - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); + RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + for (uint32_t v = 0; v < rb->view_count; v++) { + texture_slices[v] = rb->views[v].view_texture; + depth_slices[v] = rb->views[v].view_depth; } - - RendererCompositorRD::singleton->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); + ss_effects->screen_space_reflection(rb->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, p_metallic_mask, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), rb->view_count, p_projections, p_eye_offsets); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->ssr.output, rb->view_count); } -void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { +void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment); - ERR_FAIL_COND(!env); + ERR_FAIL_COND(p_environment.is_null()); RENDER_TIMESTAMP("Process SSAO"); - if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) { - RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_final); - - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]); - - rb->ss_effects.ssao.ao_deinterleaved = RID(); - rb->ss_effects.ssao.ao_pong = RID(); - rb->ss_effects.ssao.ao_final = RID(); - rb->ss_effects.ssao.importance_map[0] = RID(); - rb->ss_effects.ssao.importance_map[1] = RID(); - rb->ss_effects.ssao.ao_deinterleaved_slices.clear(); - rb->ss_effects.ssao.ao_pong_slices.clear(); - } - - int buffer_width; - int buffer_height; - int half_width; - int half_height; - if (ssao_half_size) { - buffer_width = (rb->internal_width + 3) / 4; - buffer_height = (rb->internal_height + 3) / 4; - half_width = (rb->internal_width + 7) / 8; - half_height = (rb->internal_height + 7) / 8; - } else { - buffer_width = (rb->internal_width + 1) / 2; - buffer_height = (rb->internal_height + 1) / 2; - half_width = (rb->internal_width + 3) / 4; - half_height = (rb->internal_height + 3) / 4; - } - bool uniform_sets_are_invalid = false; - if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) { - { - rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0); - rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0); - rb->ss_effects.ssao.ao_pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong"); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = half_width; - tf.height = half_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map"); - rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong"); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final"); - } - ssao_using_half_size = ssao_half_size; - uniform_sets_are_invalid = true; - } - - EffectsRD::SSAOSettings settings; - settings.radius = env->ssao_radius; - settings.intensity = env->ssao_intensity; - settings.power = env->ssao_power; - settings.detail = env->ssao_detail; - settings.horizon = env->ssao_horizon; - settings.sharpness = env->ssao_sharpness; + RendererRD::SSEffects::SSAOSettings settings; + settings.radius = environment_get_ssao_radius(p_environment); + settings.intensity = environment_get_ssao_intensity(p_environment); + settings.power = environment_get_ssao_power(p_environment); + settings.detail = environment_get_ssao_detail(p_environment); + settings.horizon = environment_get_ssao_horizon(p_environment); + settings.sharpness = environment_get_ssao_sharpness(p_environment); settings.quality = ssao_quality; settings.half_size = ssao_half_size; @@ -2143,152 +1709,26 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen settings.fadeout_from = ssao_fadeout_from; settings.fadeout_to = ssao_fadeout_to; settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height); - settings.half_screen_size = Size2i(buffer_width, buffer_height); - settings.quarter_screen_size = Size2i(half_width, half_height); - RendererCompositorRD::singleton->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set); + ss_effects->ssao_allocate_buffers(rb->ss_effects.ssao, settings, rb->ss_effects.linear_depth); + ss_effects->generate_ssao(rb->ss_effects.ssao, p_normal_buffer, p_projection, settings); } -void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment); - ERR_FAIL_COND(!env); + ERR_FAIL_COND(p_environment.is_null()); RENDER_TIMESTAMP("Process SSIL"); - if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) { - RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final); - RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssil.pong); - RD::get_singleton()->free(rb->ss_effects.ssil.edges); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]); - - rb->ss_effects.ssil.ssil_final = RID(); - rb->ss_effects.ssil.deinterleaved = RID(); - rb->ss_effects.ssil.pong = RID(); - rb->ss_effects.ssil.edges = RID(); - rb->ss_effects.ssil.deinterleaved_slices.clear(); - rb->ss_effects.ssil.pong_slices.clear(); - rb->ss_effects.ssil.edges_slices.clear(); - rb->ss_effects.ssil.importance_map[0] = RID(); - rb->ss_effects.ssil.importance_map[1] = RID(); - } - - int buffer_width; - int buffer_height; - int half_width; - int half_height; - if (ssil_half_size) { - buffer_width = (rb->width + 3) / 4; - buffer_height = (rb->height + 3) / 4; - half_width = (rb->width + 7) / 8; - half_height = (rb->height + 7) / 8; - } else { - buffer_width = (rb->width + 1) / 2; - buffer_height = (rb->height + 1) / 2; - half_width = (rb->width + 3) / 4; - half_height = (rb->height + 3) / 4; - } - bool uniform_sets_are_invalid = false; - if (rb->ss_effects.ssil.ssil_final.is_null()) { - { - rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture"); - RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1); - if (rb->ss_effects.last_frame.is_null()) { - tf.mipmaps = 6; - rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance"); - RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1); - for (uint32_t i = 0; i < 6; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i); - rb->ss_effects.last_frame_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " "); - } - } - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0); - rb->ss_effects.ssil.deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0); - rb->ss_effects.ssil.pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0); - rb->ss_effects.ssil.edges_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = half_width; - tf.height = half_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map"); - rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong"); - } - uniform_sets_are_invalid = true; - ssil_using_half_size = ssil_half_size; - } - - EffectsRD::SSILSettings settings; - settings.radius = env->ssil_radius; - settings.intensity = env->ssil_intensity; - settings.sharpness = env->ssil_sharpness; - settings.normal_rejection = env->ssil_normal_rejection; + RendererRD::SSEffects::SSILSettings settings; + settings.radius = environment_get_ssil_radius(p_environment); + settings.intensity = environment_get_ssil_intensity(p_environment); + settings.sharpness = environment_get_ssil_sharpness(p_environment); + settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment); settings.quality = ssil_quality; settings.half_size = ssil_half_size; @@ -2297,17 +1737,16 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen settings.fadeout_from = ssil_fadeout_from; settings.fadeout_to = ssil_fadeout_to; settings.full_screen_size = Size2i(rb->width, rb->height); - settings.half_screen_size = Size2i(buffer_width, buffer_height); - settings.quarter_screen_size = Size2i(half_width, half_height); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_projection; + Projection projection = correction * p_projection; Transform3D transform = p_transform; transform.set_origin(Vector3(0.0, 0.0, 0.0)); - CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse(); + Projection last_frame_projection = rb->ss_effects.last_frame_projection * Projection(rb->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); - RendererCompositorRD::singleton->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set); + ss_effects->ssil_allocate_buffers(rb->ss_effects.ssil, settings, rb->ss_effects.linear_depth); + ss_effects->screen_space_indirect_lighting(rb->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); rb->ss_effects.last_frame_projection = projection; rb->ss_effects.last_frame_transform = transform; } @@ -2316,15 +1755,15 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - if (rb->ss_effects.last_frame.is_valid()) { - copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); + if (rb->ss_effects.ssil.last_frame.is_valid()) { + copy_effects->copy_to_rect(rb->texture, rb->ss_effects.ssil.last_frame, Rect2i(0, 0, rb->width, rb->height)); int width = rb->width; int height = rb->height; - for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) { + for (int i = 0; i < rb->ss_effects.ssil.last_frame_slices.size() - 1; i++) { width = MAX(1, width >> 1); height = MAX(1, height >> 1); - copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); + copy_effects->make_mipmap(rb->ss_effects.ssil.last_frame_slices[i], rb->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height)); } } } @@ -2421,7 +1860,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); // Glow and override exposure (if enabled). CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); @@ -2481,21 +1919,21 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RD::get_singleton()->draw_command_end_label(); } - if (can_use_effects && env && env->auto_exposure) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) { RENDER_TIMESTAMP("Auto exposure"); RD::get_singleton()->draw_command_begin_label("Auto exposure"); if (rb->luminance.current.is_null()) { _allocate_luminance_textures(rb); } - bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version; - rb->auto_exposure_version = env->auto_exposure_version; + bool set_immediate = environment_get_auto_exposure_version(p_render_data->environment) != rb->auto_exposure_version; + rb->auto_exposure_version = environment_get_auto_exposure_version(p_render_data->environment); - double step = env->auto_exp_speed * time_step; + double step = environment_get_auto_exp_speed(p_render_data->environment) * time_step; if (can_use_storage) { - RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate); } else { - RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate); } // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); @@ -2509,7 +1947,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende int max_glow_level = -1; - if (can_use_effects && env && env->glow_enabled) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) { RENDER_TIMESTAMP("Glow"); RD::get_singleton()->draw_command_begin_label("Gaussian Glow"); @@ -2520,7 +1958,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { - if (env->glow_levels[i] > 0.0) { + if (environment_get_glow_levels(p_render_data->environment)[i] > 0.0) { if (i >= rb->blur[1].layers[0].mipmaps.size()) { max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1; } else { @@ -2537,19 +1975,19 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (i == 0) { RID luminance_texture; - if (env->auto_exposure && rb->luminance.current.is_valid()) { + if (environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) { luminance_texture = rb->luminance.current; } if (can_use_storage) { - copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment)); } else { - copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment)); } } else { if (can_use_storage) { - copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality); } else { - copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality); } } } @@ -2564,36 +2002,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RendererRD::ToneMapper::TonemapSettings tonemap; - if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) { tonemap.use_auto_exposure = true; tonemap.exposure_texture = rb->luminance.current; - tonemap.auto_exposure_grey = env->auto_exp_scale; + tonemap.auto_exposure_grey = environment_get_auto_exp_scale(p_render_data->environment); } else { - tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } - if (can_use_effects && env && env->glow_enabled) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) { tonemap.use_glow = true; - tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(env->glow_blend_mode); - tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity; + tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(environment_get_glow_blend_mode(p_render_data->environment)); + tonemap.glow_intensity = environment_get_glow_blend_mode(p_render_data->environment) == RS::ENV_GLOW_BLEND_MODE_MIX ? environment_get_glow_mix(p_render_data->environment) : environment_get_glow_intensity(p_render_data->environment); for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { - tonemap.glow_levels[i] = env->glow_levels[i]; + tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i]; } tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width; tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; tonemap.glow_texture = rb->blur[1].texture; - if (env->glow_map.is_valid()) { - tonemap.glow_map_strength = env->glow_map_strength; - tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map); + if (environment_get_glow_map(p_render_data->environment).is_valid()) { + tonemap.glow_map_strength = environment_get_glow_map_strength(p_render_data->environment); + tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment)); } else { tonemap.glow_map_strength = 0.0f; - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } } else { - tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2603,10 +2041,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_debanding = rb->use_debanding; tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height); - if (env) { - tonemap.tonemap_mode = env->tone_mapper; - tonemap.white = env->white; - tonemap.exposure = env->exposure; + if (p_render_data->environment.is_valid()) { + tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment); + tonemap.white = environment_get_white(p_render_data->environment); + tonemap.exposure = environment_get_exposure(p_render_data->environment); } if (camfx && camfx->override_exposure_enabled) { @@ -2615,17 +2053,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); - - if (can_use_effects && env) { - tonemap.use_bcs = env->adjustments_enabled; - tonemap.brightness = env->adjustments_brightness; - tonemap.contrast = env->adjustments_contrast; - tonemap.saturation = env->adjustments_saturation; - if (env->adjustments_enabled && env->color_correction.is_valid()) { + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); + + if (can_use_effects && p_render_data->environment.is_valid()) { + tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment); + tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment); + tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment); + tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment); + if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) { tonemap.use_color_correction = true; - tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); + tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment)); } } @@ -2655,7 +2093,6 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); // Override exposure (if enabled). CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); @@ -2665,10 +2102,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr RendererRD::ToneMapper::TonemapSettings tonemap; - if (env) { - tonemap.tonemap_mode = env->tone_mapper; - tonemap.exposure = env->exposure; - tonemap.white = env->white; + if (p_render_data->environment.is_valid()) { + tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment); + tonemap.exposure = environment_get_exposure(p_render_data->environment); + tonemap.white = environment_get_white(p_render_data->environment); } if (camfx && camfx->override_exposure_enabled) { @@ -2678,32 +2115,32 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr // We don't support glow or auto exposure here, if they are needed, don't use subpasses! // The problem is that we need to use the result so far and process them before we can // apply this to our results. - if (can_use_effects && env && env->glow_enabled) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) { ERR_FAIL_MSG("Glow is not supported when using subpasses."); } - if (can_use_effects && env && env->auto_exposure) { + if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) { ERR_FAIL_MSG("Glow is not supported when using subpasses."); } tonemap.use_glow = false; - tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; - tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); - - if (can_use_effects && env) { - tonemap.use_bcs = env->adjustments_enabled; - tonemap.brightness = env->adjustments_brightness; - tonemap.contrast = env->adjustments_contrast; - tonemap.saturation = env->adjustments_saturation; - if (env->adjustments_enabled && env->color_correction.is_valid()) { + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); + + if (can_use_effects && p_render_data->environment.is_valid()) { + tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment); + tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment); + tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment); + tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment); + if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) { tonemap.use_color_correction = true; - tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); + tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment)); } } @@ -2737,7 +2174,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { - shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); } Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); @@ -2807,18 +2244,6 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID } } -void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - - env->adjustments_enabled = p_enable; - env->adjustments_brightness = p_brightness; - env->adjustments_contrast = p_contrast; - env->adjustments_saturation = p_saturation; - env->use_1d_color_correction = p_use_1d_color_correction; - env->color_correction = p_color_correction; -} - RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); @@ -3023,7 +2448,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() { return true; } -void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { +void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3034,11 +2459,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p p_internal_width = p_width; } - if (p_width != p_internal_width) { - float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias; - material_storage->sampler_rd_configure_custom(fsr_mipmap_bias); - update_uniform_sets(); - } + const float texture_mipmap_bias = -log2f(p_width / p_internal_width) + p_texture_mipmap_bias; + material_storage->sampler_rd_configure_custom(texture_mipmap_bias); + update_uniform_sets(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); @@ -3151,8 +2574,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p } } + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target); + if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb); + } + RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count); + rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture); if (is_clustered_enabled()) { rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); @@ -3176,7 +2604,7 @@ void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, floa sss_depth_scale = p_depth_scale; } -void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (shadows_quality != p_quality) { @@ -3223,7 +2651,7 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { _update_shader_quality_settings(); } -void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (directional_shadow_quality != p_quality) { @@ -3441,7 +2869,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); } - light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base); + light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0; float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); if (angular_diameter > 0.0) { @@ -3458,24 +2886,24 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const angular_diameter = 0.0; } - if (light_data.shadow_enabled) { + if (light_data.shadow_opacity > 0.001) { RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base); int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base); for (int j = 0; j < 4; j++) { Rect2 atlas_rect = li->shadow_transform[j].atlas_rect; - CameraMatrix matrix = li->shadow_transform[j].camera; + Projection matrix = li->shadow_transform[j].camera; float split = li->shadow_transform[MIN(limit, j)].split; - CameraMatrix bias; + Projection bias; bias.set_light_bias(); - CameraMatrix rectm; + Projection rectm; rectm.set_light_atlas_rect(atlas_rect); Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse(); - CameraMatrix shadow_mtx = rectm * bias * matrix * modelview; + Projection shadow_mtx = rectm * bias * matrix * modelview; light_data.shadow_split_offsets[j] = split; float bias_scale = li->shadow_transform[j].bias_scale; light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale; @@ -3612,19 +3040,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // Reuse fade begin, fade length and distance for shadow LOD determination later. float fade_begin = 0.0; + float fade_shadow = 0.0; float fade_length = 0.0; real_t distance = 0.0; float fade = 1.0; + float shadow_opacity_fade = 1.0; if (light_storage->light_is_distance_fade_enabled(li->light)) { fade_begin = light_storage->light_get_distance_fade_begin(li->light); + fade_shadow = light_storage->light_get_distance_fade_shadow(li->light); fade_length = light_storage->light_get_distance_fade_length(li->light); distance = camera_plane.distance_to(li->transform.origin); + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. if (distance > fade_begin) { - // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); } + + if (distance > fade_shadow) { + shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length); + } } float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade; @@ -3692,7 +3127,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const bool in_shadow_range = true; if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) { - if (distance > light_storage->light_get_distance_fade_shadow(li->light)) { + if (distance > light_storage->light_get_distance_fade_shadow(li->light) + light_storage->light_get_distance_fade_length(li->light)) { // Out of range, don't draw shadows to improve performance. in_shadow_range = false; } @@ -3701,7 +3136,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const if (needs_shadow && in_shadow_range) { // fill in the shadow information - light_data.shadow_enabled = true; + light_data.shadow_opacity = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) * shadow_opacity_fade; float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0; @@ -3743,16 +3178,16 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.direction[1] = omni_offset.y * float(rect.size.height); } else if (type == RS::LIGHT_SPOT) { Transform3D modelview = (inverse_transform * light_transform).inverse(); - CameraMatrix bias; + Projection bias; bias.set_light_bias(); - CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview; + Projection shadow_mtx = bias * li->shadow_transform[0].camera * modelview; RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix); if (size > 0.0 && light_data.soft_shadow_scale > 0.0) { // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. - CameraMatrix cm = li->shadow_transform[0].camera; + Projection cm = li->shadow_transform[0].camera; float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle)); light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; } else { @@ -3761,7 +3196,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const } } } else { - light_data.shadow_enabled = false; + light_data.shadow_opacity = 0.0; } li->cull_mask = light_storage->light_get_cull_mask(base); @@ -3963,242 +3398,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const //////////////////////////////////////////////////////////////////////////////// // FOG SHADER -void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { - //compile - - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - - if (code.is_empty()) { - return; //just invalid, but no error - } - - ShaderCompiler::GeneratedCode gen_code; - ShaderCompiler::IdentifierActions actions; - actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE; - - uses_time = false; - - actions.usage_flag_pointers["TIME"] = &uses_time; - - actions.uniforms = &uniforms; - - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); - ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); - - if (version.is_null()) { - version = scene_singleton->volumetric_fog.shader.version_create(); - } - - scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); - ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0)); - - valid = true; -} - -void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - RBMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - for (const KeyValue<int, StringName> &E : order) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RendererSceneRenderRD::FogShaderData::is_animated() const { - return false; -} - -bool RendererSceneRenderRD::FogShaderData::casts_shadows() const { - return false; -} - -Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - -RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version); -} - -RendererSceneRenderRD::FogShaderData::~FogShaderData() { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - ERR_FAIL_COND(!scene_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - scene_singleton->volumetric_fog.shader.version_free(version); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Fog material - -bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - uniform_set_updated = true; - - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); -} - -RendererSceneRenderRD::FogMaterialData::~FogMaterialData() { - free_parameters_uniform_set(uniform_set); -} - -RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { - FogShaderData *shader_data = memnew(FogShaderData); - return shader_data; -} - -RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { - return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func(); -}; - -RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { - FogMaterialData *material_data = memnew(FogMaterialData); - material_data->shader_data = p_shader; - //update will happen later anyway so do nothing. - return material_data; -} - -RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { - return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); -}; - -//////////////////////////////////////////////////////////////////////////////// -// Volumetric Fog - -void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->volumetric_fog); - - RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map); - RD::get_singleton()->free(rb->volumetric_fog->light_density_map); - RD::get_singleton()->free(rb->volumetric_fog->fog_map); - RD::get_singleton()->free(rb->volumetric_fog->density_map); - RD::get_singleton()->free(rb->volumetric_fog->light_map); - RD::get_singleton()->free(rb->volumetric_fog->emissive_map); - - if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); - } - if (rb->volumetric_fog->process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set_density); - } - if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); - } - if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2); - } - if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set); - } - if (rb->volumetric_fog->sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sky_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->sky_uniform_set); - } - - memdelete(rb->volumetric_fog); - - rb->volumetric_fog = nullptr; -} - -Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) { - Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point); - view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera - Vector3 fog_position = Vector3(0, 0, 0); - - view_position.y = -view_position.y; - fog_position.z = -view_position.z / fog_end; - fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5; - fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5; - fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread)); - fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5); - - fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x); - fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y); - fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z); - - return Vector3i(fog_position); -} - -void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - +void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment); float ratio = float(rb->width) / float((rb->width + rb->height) / 2); uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio); @@ -4206,694 +3409,49 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (rb->volumetric_fog) { //validate - if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) { - _volumetric_fog_erase(rb); + if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) { + memdelete(rb->volumetric_fog); + rb->volumetric_fog = nullptr; } } - if (!env || !env->volumetric_fog_enabled) { + if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment)) { //no reason to enable or update, bye return; } - RENDER_TIMESTAMP("> Volumetric Fog"); - RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); - - if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) { + if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !rb->volumetric_fog) { //required volumetric fog but not existing, create - rb->volumetric_fog = memnew(VolumetricFog); - rb->volumetric_fog->width = target_width; - rb->volumetric_fog->height = target_height; - rb->volumetric_fog->depth = volumetric_fog_depth; - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = target_width; - tf.height = target_height; - tf.depth = volumetric_fog_depth; - tf.texture_type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - - rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map"); - - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - - rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map"); - -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - Vector<uint8_t> dm; - dm.resize(target_width * target_height * volumetric_fog_depth * 4); - dm.fill(0); - - rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map"); - rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map"); - rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); -#else - tf.format = RD::DATA_FORMAT_R32_UINT; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); -#endif - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.append_id(rb->volumetric_fog->fog_map); - uniforms.push_back(u); - } - - rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG); - } - - if (p_fog_volumes.size() > 0) { - RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); - - RENDER_TIMESTAMP("Render FogVolumes"); - - VolumetricFogShader::VolumeUBO params; - - Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); - Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); - float z_near = p_cam_projection.get_z_near(); - float z_far = p_cam_projection.get_z_far(); - float fog_end = env->volumetric_fog_length; - - Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); - Vector2 fog_near_size; - if (p_cam_projection.is_orthogonal()) { - fog_near_size = fog_far_size; - } else { - fog_near_size = Vector2(); - } - - params.fog_frustum_size_begin[0] = fog_near_size.x; - params.fog_frustum_size_begin[1] = fog_near_size.y; - - params.fog_frustum_size_end[0] = fog_far_size.x; - params.fog_frustum_size_end[1] = fog_far_size.y; - - params.fog_frustum_end = fog_end; - params.z_near = z_near; - params.z_far = z_far; - params.time = time; - - params.fog_volume_size[0] = rb->volumetric_fog->width; - params.fog_volume_size[1] = rb->volumetric_fog->height; - params.fog_volume_size[2] = rb->volumetric_fog->depth; - - params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection; - params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; - params.detail_spread = env->volumetric_fog_detail_spread; - params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; - - Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; - RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); - RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); - - RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - - if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 1; - u.append_id(rb->volumetric_fog->emissive_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(volumetric_fog.volume_ubo); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 3; - u.append_id(rb->volumetric_fog->density_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 4; - u.append_id(rb->volumetric_fog->light_map); - uniforms.push_back(u); - } - - rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); - } - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - bool any_uses_time = false; - - for (int i = 0; i < (int)p_fog_volumes.size(); i++) { - FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); - ERR_FAIL_COND(!fog_volume_instance); - RID fog_volume = fog_volume_instance->volume; - - RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); - - FogMaterialData *material = nullptr; - - if (fog_material.is_valid()) { - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); - if (!material || !material->shader_data->valid) { - material = nullptr; - } - } - - if (!material) { - fog_material = volumetric_fog.default_material; - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); - } - - ERR_FAIL_COND(!material); - - FogShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - any_uses_time |= shader_data->uses_time; - - Vector3i min = Vector3i(); - Vector3i max = Vector3i(); - Vector3i kernel_size = Vector3i(); - - Vector3 position = fog_volume_instance->transform.get_origin(); - RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); - Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); - - if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { - // Local fog volume. - Vector3i points[8]; - points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - - min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1); - max = Vector3i(1, 1, 1); - - for (int j = 0; j < 8; j++) { - min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z)); - max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z)); - } - - kernel_size = max - min; - } else { - // Volume type global runs on all cells - extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - min = Vector3i(0, 0, 0); - kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth)); - } - - if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { - continue; - } - - volumetric_fog.push_constant.position[0] = position.x; - volumetric_fog.push_constant.position[1] = position.y; - volumetric_fog.push_constant.position[2] = position.z; - volumetric_fog.push_constant.extents[0] = extents.x; - volumetric_fog.push_constant.extents[1] = extents.y; - volumetric_fog.push_constant.extents[2] = extents.z; - volumetric_fog.push_constant.corner[0] = min.x; - volumetric_fog.push_constant.corner[1] = min.y; - volumetric_fog.push_constant.corner[2] = min.z; - volumetric_fog.push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); - RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant)); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); - if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); - } - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); - } - if (any_uses_time || env->volumetric_fog_temporal_reprojection) { - RenderingServerDefault::redraw_request(); - } - - RD::get_singleton()->draw_command_end_label(); - - RD::get_singleton()->compute_list_end(); - } - - if (rb->volumetric_fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { - //re create uniform set if needed - Vector<RD::Uniform> uniforms; - Vector<RD::Uniform> copy_uniforms; - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); - } else { - u.append_id(shadow_atlas->depth); - } - - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - if (directional_shadow.depth.is_valid()) { - u.append_id(directional_shadow.depth); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); - } - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 3; - u.append_id(get_omni_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 4; - u.append_id(get_spot_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 5; - u.append_id(get_directional_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 6; - u.append_id(rb->cluster_builder->get_cluster_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 7; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 8; - u.append_id(rb->volumetric_fog->light_density_map); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; - u.append_id(rb->volumetric_fog->fog_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; - u.append_id(rb->volumetric_fog->prev_light_density_map); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 10; - u.append_id(shadow_sampler); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 11; - u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 12; - for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->rbgi.voxel_gi_textures[i]); - } - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 13; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 14; - u.append_id(volumetric_fog.params_ubo); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 15; - u.append_id(rb->volumetric_fog->prev_light_density_map); - uniforms.push_back(u); - } - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 16; - u.append_id(rb->volumetric_fog->density_map); - uniforms.push_back(u); - } - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 17; - u.append_id(rb->volumetric_fog->light_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 18; - u.append_id(rb->volumetric_fog->emissive_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 19; - RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); - u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); - uniforms.push_back(u); - } - - rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); - - rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); - - RID aux7 = uniforms.write[7].get_id(0); - RID aux8 = uniforms.write[8].get_id(0); - - uniforms.write[7].set_id(0, aux8); - uniforms.write[8].set_id(0, aux7); - - rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); - - uniforms.remove_at(8); - uniforms.write[7].set_id(0, aux7); - rb->volumetric_fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); - } - - bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr); - - if (using_sdfgi) { - if (rb->volumetric_fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) { - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.append_id(gi.sdfgi_ubo); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - u.append_id(rb->sdfgi->ambient_texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - u.append_id(rb->sdfgi->occlusion_texture); - uniforms.push_back(u); - } - - rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); - } - } - - rb->volumetric_fog->length = env->volumetric_fog_length; - rb->volumetric_fog->spread = env->volumetric_fog_detail_spread; - - VolumetricFogShader::ParamsUBO params; - - Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); - Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); - float z_near = p_cam_projection.get_z_near(); - float z_far = p_cam_projection.get_z_far(); - float fog_end = env->volumetric_fog_length; - - Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); - Vector2 fog_near_size; - if (p_cam_projection.is_orthogonal()) { - fog_near_size = fog_far_size; - } else { - fog_near_size = Vector2(); - } - - params.fog_frustum_size_begin[0] = fog_near_size.x; - params.fog_frustum_size_begin[1] = fog_near_size.y; - - params.fog_frustum_size_end[0] = fog_far_size.x; - params.fog_frustum_size_end[1] = fog_far_size.y; - - params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy; - params.z_far = z_far; - - params.fog_frustum_end = fog_end; - - Color ambient_color = env->ambient_light.srgb_to_linear(); - params.ambient_color[0] = ambient_color.r; - params.ambient_color[1] = ambient_color.g; - params.ambient_color[2] = ambient_color.b; - params.sky_contribution = env->ambient_sky_contribution; - - params.fog_volume_size[0] = rb->volumetric_fog->width; - params.fog_volume_size[1] = rb->volumetric_fog->height; - params.fog_volume_size[2] = rb->volumetric_fog->depth; - - params.directional_light_count = p_directional_light_count; - - Color emission = env->volumetric_fog_emission.srgb_to_linear(); - params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy; - params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy; - params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy; - params.base_density = env->volumetric_fog_density; - - Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear(); - params.base_scattering[0] = base_scattering.r; - params.base_scattering[1] = base_scattering.g; - params.base_scattering[2] = base_scattering.b; - params.phase_g = env->volumetric_fog_anisotropy; - - params.detail_spread = env->volumetric_fog_detail_spread; - params.gi_inject = env->volumetric_fog_gi_inject; - - params.cam_rotation[0] = p_cam_transform.basis[0][0]; - params.cam_rotation[1] = p_cam_transform.basis[1][0]; - params.cam_rotation[2] = p_cam_transform.basis[2][0]; - params.cam_rotation[3] = 0; - params.cam_rotation[4] = p_cam_transform.basis[0][1]; - params.cam_rotation[5] = p_cam_transform.basis[1][1]; - params.cam_rotation[6] = p_cam_transform.basis[2][1]; - params.cam_rotation[7] = 0; - params.cam_rotation[8] = p_cam_transform.basis[0][2]; - params.cam_rotation[9] = p_cam_transform.basis[1][2]; - params.cam_rotation[10] = p_cam_transform.basis[2][2]; - params.cam_rotation[11] = 0; - params.filter_axis = 0; - params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0; - params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; - - Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; - RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); - - params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection; - params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; - - { - uint32_t cluster_size = rb->cluster_builder->get_cluster_size(); - params.cluster_shift = get_shift_from_power_of_2(cluster_size); - - uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1; - uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1; - params.max_cluster_element_count_div_32 = max_cluster_elements / 32; - params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); - params.cluster_width = cluster_screen_width; - - params.screen_size[0] = rb->width; - params.screen_size[1] = rb->height; + rb->volumetric_fog = memnew(RendererRD::Fog::VolumetricFog(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd)); } - Basis sky_transform = env->sky_orientation; - sky_transform = sky_transform.inverse() * p_cam_transform.basis; - RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); - - RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); - - RENDER_TIMESTAMP("Render Fog"); - RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set_density, 0); - - if (using_sdfgi) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1); - } - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - // Copy fog to history buffer - if (env->volumetric_fog_temporal_reprojection) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - RD::get_singleton()->draw_command_end_label(); - - if (volumetric_fog_filter_active) { - RD::get_singleton()->draw_command_begin_label("Filter Fog"); - - RENDER_TIMESTAMP("Filter Fog"); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - - RD::get_singleton()->compute_list_end(); - //need restart for buffer update - - params.filter_axis = 1; - RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); + if (rb->volumetric_fog) { + RendererRD::Fog::VolumetricFogSettings settings; + settings.rb_size = Vector2i(rb->width, rb->height); + settings.time = time; + settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array(); + settings.max_cluster_elements = max_cluster_elements; + settings.volumetric_fog_filter_active = volumetric_fog_filter_active; + + settings.shadow_sampler = shadow_sampler; + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); + settings.shadow_atlas_depth = shadow_atlas ? shadow_atlas->depth : RID(); + settings.voxel_gl_buffer = render_buffers_get_voxel_gi_buffer(p_render_buffers); + settings.omni_light_buffer = get_omni_light_buffer(); + settings.spot_light_buffer = get_spot_light_buffer(); + settings.directional_shadow_depth = directional_shadow.depth; + settings.directional_light_buffer = get_directional_light_buffer(); - compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); + settings.vfog = rb->volumetric_fog; + settings.cluster_builder = rb->cluster_builder; + settings.rbgi = &rb->rbgi; + settings.sdfgi = rb->sdfgi; + settings.env = p_environment; + settings.sky = &sky; + settings.gi = &gi; - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); + RendererRD::Fog::get_singleton()->volumetric_fog_update(settings, p_cam_projection, p_cam_transform, p_prev_cam_inv_transform, p_shadow_atlas, p_directional_light_count, p_use_directional_shadows, p_positional_light_count, p_voxel_gi_count, p_fog_volumes); } - - RENDER_TIMESTAMP("Integrate Fog"); - RD::get_singleton()->draw_command_begin_label("Integrate Fog"); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1); - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); - - RENDER_TIMESTAMP("< Volumetric Fog"); - RD::get_singleton()->draw_command_end_label(); - RD::get_singleton()->draw_command_end_label(); } bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { @@ -4915,8 +3473,7 @@ void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bo return; } - RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); - rb->sdfgi->update_probes(env, sky.sky_owner.get_or_null(env->sky)); + rb->sdfgi->update_probes(p_render_data->environment, sky.sky_owner.get_or_null(environment_get_sky(p_render_data->environment))); } } } @@ -4929,7 +3486,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo } } -void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); @@ -5004,7 +3561,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //start GI if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_views, p_voxel_gi_buffer, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); } //Do shadow rendering (in parallel with GI) @@ -5016,7 +3573,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier } - if (p_render_data->render_buffers.is_valid()) { + if (p_render_data->render_buffers.is_valid() && ss_effects) { if (p_use_ssao || p_use_ssil) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); @@ -5041,17 +3598,17 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool invalidate_uniform_set = true; } - RendererCompositorRD::singleton->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); + ss_effects->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); } if (p_use_ssao) { - // TODO make these proper stereo and thus use p_normal_roughness_views correctly - _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection); + // TODO make these proper stereo + _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection); } if (p_use_ssil) { - // TODO make these proper stereo and thus use p_normal_roughness_views correctly - _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection, p_render_data->cam_transform); + // TODO make these proper stereo + _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform); } } @@ -5087,7 +3644,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool if (p_render_data->render_buffers.is_valid()) { bool directional_shadows = false; for (uint32_t i = 0; i < directional_light_count; i++) { - if (cluster.directional_lights[i].shadow_enabled) { + if (cluster.directional_lights[i].shadow_opacity > 0.001) { directional_shadows = true; break; } @@ -5098,7 +3655,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool } } -void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { +void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily @@ -5240,6 +3797,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); } + if (rb != nullptr && rb->vrs_fb.is_valid()) { + // vrs_fb will only be valid if vrs is enabled + vrs->update_vrs_texture(rb->vrs_fb, rb->render_target); + } + _render_scene(&render_data, clear_color); if (p_render_buffers.is_valid()) { @@ -5288,7 +3850,7 @@ void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) { } } -void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) { +void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light); ERR_FAIL_COND(!light_instance); @@ -5309,7 +3871,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, bool flip_y = false; - CameraMatrix light_projection; + Projection light_projection; Transform3D light_transform; if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) { @@ -5451,7 +4013,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); //restore transform so it can be properly used - light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0); + light_instance_set_shadow_transform(p_light, Projection(), light_instance->transform, zfar, 0, 0, 0); } } else { @@ -5460,16 +4022,16 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, } } -void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region); } -void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { +void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) { RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider)); Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale(); - CameraMatrix cm; + Projection cm; cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0); Vector3 cam_pos = p_transform.origin; @@ -5494,15 +4056,15 @@ bool RendererSceneRenderRD::free(RID p_rid) { rb->sdfgi = nullptr; } if (rb->volumetric_fog) { - _volumetric_fog_erase(rb); + memdelete(rb->volumetric_fog); + rb->volumetric_fog = nullptr; } if (rb->cluster_builder) { memdelete(rb->cluster_builder); } render_buffers_owner.free(p_rid); - } else if (environment_owner.owns(p_rid)) { - //not much to delete, just free it - environment_owner.free(p_rid); + } else if (is_environment(p_rid)) { + environment_free(p_rid); } else if (camera_effects_owner.owns(p_rid)) { //not much to delete, just free it camera_effects_owner.free(p_rid); @@ -5569,8 +4131,8 @@ bool RendererSceneRenderRD::free(RID p_rid) { } else if (shadow_atlas_owner.owns(p_rid)) { shadow_atlas_set_size(p_rid, 0); shadow_atlas_owner.free(p_rid); - } else if (fog_volume_instance_owner.owns(p_rid)) { - fog_volume_instance_owner.free(p_rid); + } else if (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) { + RendererRD::Fog::get_singleton()->fog_instance_free(p_rid); } else { return false; } @@ -5642,7 +4204,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto //RID sampled_light; - GeometryInstance *gi = geometry_instance_create(p_base); + RenderGeometryInstance *gi = geometry_instance_create(p_base); uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base); Vector<RID> materials; @@ -5654,7 +4216,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto } } - geometry_instance_set_surface_materials(gi, materials); + gi->set_surface_materials(materials); if (cull_argument.size() == 0) { cull_argument.push_back(nullptr); @@ -5736,6 +4298,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const { return cluster.max_directional_lights; } +bool RendererSceneRenderRD::is_vrs_supported() const { + return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS); +} + bool RendererSceneRenderRD::is_dynamic_gi_supported() const { // usable by default (unless low end = true) return true; @@ -5760,8 +4326,6 @@ RendererSceneRenderRD::RendererSceneRenderRD() { } void RendererSceneRenderRD::init() { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - max_cluster_elements = get_max_elements(); directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); @@ -5812,124 +4376,7 @@ void RendererSceneRenderRD::init() { } if (is_volumetric_supported()) { - { - // Initialize local fog shader - Vector<String> volumetric_fog_modes; - volumetric_fog_modes.push_back(""); - volumetric_fog.shader.initialize(volumetric_fog_modes); - - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); - volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); - } - - { - ShaderCompiler::DefaultIdentifierActions actions; - - actions.renames["TIME"] = "scene_params.time"; - actions.renames["PI"] = _MKSTR(Math_PI); - actions.renames["TAU"] = _MKSTR(Math_TAU); - actions.renames["E"] = _MKSTR(Math_E); - actions.renames["WORLD_POSITION"] = "world.xyz"; - actions.renames["OBJECT_POSITION"] = "params.position"; - actions.renames["UVW"] = "uvw"; - actions.renames["EXTENTS"] = "params.extents"; - actions.renames["ALBEDO"] = "albedo"; - actions.renames["DENSITY"] = "density"; - actions.renames["EMISSION"] = "emission"; - actions.renames["SDF"] = "sdf"; - - actions.usage_defines["SDF"] = "#define SDF_USED\n"; - actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n"; - actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n"; - actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n"; - - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL; - actions.base_uniform_string = "material."; - - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; - actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; - actions.global_buffer_array_variable = "global_variables.data"; - - volumetric_fog.compiler.initialize(actions); - } - - { - // default material and shader for fog shader - volumetric_fog.default_shader = material_storage->shader_allocate(); - material_storage->shader_initialize(volumetric_fog.default_shader); - material_storage->shader_set_code(volumetric_fog.default_shader, R"( -// Default fog shader. - -shader_type fog; - -void fog() { - DENSITY = 1.0; - ALBEDO = vec3(1.0); -} -)"); - volumetric_fog.default_material = material_storage->material_allocate(); - material_storage->material_initialize(volumetric_fog.default_material); - material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - - FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); - volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); - - Vector<RD::Uniform> uniforms; - - { - Vector<RID> ids; - ids.resize(12); - RID *ids_ptr = ids.ptrw(); - ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - - RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); - uniforms.push_back(u); - } - - volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); - } - { - String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n"; - defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; - if (is_using_radiance_cubemap_array()) { - defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; - } - Vector<String> volumetric_fog_modes; - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); - volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); - volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); - volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); - - volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); - volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); - for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { - volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i)); - } - volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO)); - } + RendererRD::Fog::get_singleton()->init_fog_shader(cluster.max_directional_lights, get_roughness_layers(), is_using_radiance_cubemap_array()); } { @@ -5960,8 +4407,8 @@ void fog() { directional_soft_shadow_kernel = memnew_arr(float, 128); penumbra_shadow_kernel = memnew_arr(float, 128); soft_shadow_kernel = memnew_arr(float, 128); - shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality")))); - directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality")))); + positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality")))); + directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality")))); environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth")); environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")); @@ -5975,11 +4422,13 @@ void fog() { bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); + vrs = memnew(RendererRD::VRS); + if (can_use_storage) { + ss_effects = memnew(RendererRD::SSEffects); + } } RendererSceneRenderRD::~RendererSceneRenderRD() { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - if (bokeh_dof) { memdelete(bokeh_dof); } @@ -5989,6 +4438,12 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (tone_mapper) { memdelete(tone_mapper); } + if (vrs) { + memdelete(vrs); + } + if (ss_effects) { + memdelete(ss_effects); + } for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { RD::get_singleton()->free(E.value.cubemap); @@ -6003,11 +4458,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { } if (is_volumetric_supported()) { - volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); - RD::get_singleton()->free(volumetric_fog.volume_ubo); - RD::get_singleton()->free(volumetric_fog.params_ubo); - material_storage->shader_free(volumetric_fog.default_shader); - material_storage->material_free(volumetric_fog.default_material); + RendererRD::Fog::get_singleton()->free_fog_shader(); } memdelete_arr(directional_penumbra_shadow_kernel); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index e8296882c9..22e9ead243 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H -#define RENDERING_SERVER_SCENE_RENDER_RD_H +#ifndef RENDERER_SCENE_RENDER_RD_H +#define RENDERER_SCENE_RENDER_RD_H #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" @@ -37,12 +37,12 @@ #include "servers/rendering/renderer_rd/cluster_builder_rd.h" #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" +#include "servers/rendering/renderer_rd/effects/vrs.h" +#include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/environment/gi.h" -#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" -#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -51,24 +51,24 @@ struct RenderDataRD { RID render_buffers; Transform3D cam_transform; - CameraMatrix cam_projection; + Projection cam_projection; Vector2 taa_jitter; bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; Transform3D prev_cam_transform; - CameraMatrix prev_cam_projection; + Projection prev_cam_projection; Vector2 prev_taa_jitter; - CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; float z_near = 0.0; float z_far = 0.0; - const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; + const PagedArray<RenderGeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *reflection_probes = nullptr; const PagedArray<RID> *voxel_gi_instances = nullptr; @@ -97,18 +97,19 @@ struct RenderDataRD { }; class RendererSceneRenderRD : public RendererSceneRender { - friend RendererSceneSkyRD; + friend RendererRD::SkyRD; friend RendererRD::GI; protected: RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; + RendererRD::VRS *vrs = nullptr; double time = 0.0; double time_step = 0.0; struct RenderBufferData { - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0; + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0; virtual ~RenderBufferData() {} }; virtual RenderBufferData *_create_render_buffer_data() = 0; @@ -120,16 +121,16 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0; virtual void _render_shadow_begin() = 0; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0; virtual void _render_shadow_process() = 0; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; - void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void _debug_draw_cluster(RID p_render_buffers); RenderBufferData *render_buffers_get_data(RID p_render_buffers); @@ -138,10 +139,11 @@ protected: virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0; - void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); - void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive); - void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera); - void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); + void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); + void _process_sss(RID p_render_buffers, const Projection &p_camera); + void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); + void _copy_framebuffer_to_ssil(RID p_render_buffers); void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far); @@ -149,7 +151,7 @@ protected: void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer); + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); @@ -158,19 +160,12 @@ protected: void _disable_clear_request(const RenderDataRD *p_render_data); // needed for a single argument calls (material and uv2) - PagedArrayPool<GeometryInstance *> cull_argument_pool; - PagedArray<GeometryInstance *> cull_argument; //need this to exist + PagedArrayPool<RenderGeometryInstance *> cull_argument_pool; + PagedArray<RenderGeometryInstance *> cull_argument; //need this to exist + RendererRD::SSEffects *ss_effects = nullptr; RendererRD::GI gi; - RendererSceneSkyRD sky; - - RendererSceneEnvironmentRD *get_environment(RID p_environment) { - if (p_environment.is_valid()) { - return environment_owner.get_or_null(p_environment); - } else { - return nullptr; - } - }; + RendererRD::SkyRD sky; //used for mobile renderer mostly @@ -207,7 +202,7 @@ private: struct Reflection { RID owner; - RendererSceneSkyRD::ReflectionData data; + RendererRD::SkyRD::ReflectionData data; RID fbs[6]; }; @@ -360,7 +355,7 @@ private: struct LightInstance { struct ShadowTransform { - CameraMatrix camera; + Projection camera; Transform3D transform; float farplane; float split; @@ -402,21 +397,10 @@ private: mutable RID_Owner<LightInstance> light_instance_owner; - /* FOG VOLUMES */ - - struct FogVolumeInstance { - RID volume; - Transform3D transform; - bool active = false; - }; - - mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner; - /* ENVIRONMENT */ RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; - bool ssao_using_half_size = false; float ssao_adaptive_target = 0.5; int ssao_blur_passes = 2; float ssao_fadeout_from = 50.0; @@ -434,8 +418,6 @@ private: bool glow_high_quality = false; RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; - mutable RID_Owner<RendererSceneEnvironmentRD, true> environment_owner; - /* CAMERA EFFECTS */ struct CameraEffects { @@ -467,8 +449,6 @@ private: ClusterBuilderSharedDataRD cluster_builder_shared; ClusterBuilderRD *current_cluster_builder = nullptr; - struct VolumetricFog; - struct RenderBuffers { RenderBufferData *data = nullptr; int internal_width = 0; @@ -492,6 +472,8 @@ private: RID depth_texture; //main depth texture RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) + RID vrs_texture; // texture for vrs. + RID vrs_fb; // framebuffer to write to our vrs texture // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) struct View { @@ -502,8 +484,8 @@ private: Vector<View> views; RendererRD::GI::SDFGI *sdfgi = nullptr; - VolumetricFog *volumetric_fog = nullptr; RendererRD::GI::RenderBuffersGI rbgi; + RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr; ClusterBuilderRD *cluster_builder = nullptr; @@ -557,47 +539,14 @@ private: RID downsample_uniform_set; - RID last_frame; - Vector<RID> last_frame_slices; - - CameraMatrix last_frame_projection; + Projection last_frame_projection; Transform3D last_frame_transform; - struct SSAO { - RID ao_deinterleaved; - Vector<RID> ao_deinterleaved_slices; - RID ao_pong; - Vector<RID> ao_pong_slices; - RID ao_final; - RID importance_map[2]; - RID depth_texture_view; - - RID gather_uniform_set; - RID importance_map_uniform_set; - } ssao; - - struct SSIL { - RID ssil_final; - RID deinterleaved; - Vector<RID> deinterleaved_slices; - RID pong; - Vector<RID> pong_slices; - RID edges; - Vector<RID> edges_slices; - RID importance_map[2]; - RID depth_texture_view; - - RID gather_uniform_set; - RID importance_map_uniform_set; - RID projection_uniform_set; - } ssil; + RendererRD::SSEffects::SSAORenderBuffers ssao; + RendererRD::SSEffects::SSILRenderBuffers ssil; } ss_effects; - struct SSR { - RID normal_scaled; - RID depth_scaled; - RID blur_radius[2]; - } ssr; + RendererRD::SSEffects::SSRRenderBuffers ssr; struct TAA { RID history; @@ -659,7 +608,7 @@ private: float inv_spot_attenuation; float cos_spot_angle; float specular_amount; - uint32_t shadow_enabled; + float shadow_opacity; float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv float shadow_matrix[16]; @@ -684,7 +633,7 @@ private: float softshadow_angle; float soft_shadow_scale; uint32_t blend_splits; - uint32_t shadow_enabled; + float shadow_opacity; float fade_from; float fade_to; uint32_t pad[2]; @@ -776,203 +725,6 @@ private: bool depth_prepass_used; // this does not seem used anywhere... } render_state; - struct VolumetricFog { - enum { - MAX_TEMPORAL_FRAMES = 16 - }; - - uint32_t width = 0; - uint32_t height = 0; - uint32_t depth = 0; - - float length; - float spread; - - RID light_density_map; - RID prev_light_density_map; - RID fog_map; - RID density_map; - RID light_map; - RID emissive_map; - - RID fog_uniform_set; - RID copy_uniform_set; - RID process_uniform_set_density; - RID process_uniform_set; - RID process_uniform_set2; - RID sdfgi_uniform_set; - RID sky_uniform_set; - - int last_shadow_filter = -1; - }; - - struct VolumetricFogShader { - enum FogSet { - FOG_SET_BASE, - FOG_SET_UNIFORMS, - FOG_SET_MATERIAL, - FOG_SET_MAX, - }; - - struct FogPushConstant { - float position[3]; - float pad; - - float extents[3]; - float pad2; - - int32_t corner[3]; - uint32_t shape; - - float transform[16]; - }; - - struct VolumeUBO { - float fog_frustum_size_begin[2]; - float fog_frustum_size_end[2]; - - float fog_frustum_end; - float z_near; - float z_far; - float time; - - int32_t fog_volume_size[3]; - uint32_t directional_light_count; - - uint32_t use_temporal_reprojection; - uint32_t temporal_frame; - float detail_spread; - float temporal_blend; - - float to_prev_view[16]; - float transform[16]; - }; - - ShaderCompiler compiler; - VolumetricFogShaderRD shader; - FogPushConstant push_constant; - RID volume_ubo; - - RID default_shader; - RID default_material; - RID default_shader_rd; - - RID base_uniform_set; - - RID params_ubo; - - enum { - VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY, - VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI, - VOLUMETRIC_FOG_PROCESS_SHADER_FILTER, - VOLUMETRIC_FOG_PROCESS_SHADER_FOG, - VOLUMETRIC_FOG_PROCESS_SHADER_COPY, - VOLUMETRIC_FOG_PROCESS_SHADER_MAX, - }; - - struct ParamsUBO { - float fog_frustum_size_begin[2]; - float fog_frustum_size_end[2]; - - float fog_frustum_end; - float ambient_inject; - float z_far; - uint32_t filter_axis; - - float ambient_color[3]; - float sky_contribution; - - int32_t fog_volume_size[3]; - uint32_t directional_light_count; - - float base_emission[3]; - float base_density; - - float base_scattering[3]; - float phase_g; - - float detail_spread; - float gi_inject; - uint32_t max_voxel_gi_instances; - uint32_t cluster_type_size; - - float screen_size[2]; - uint32_t cluster_shift; - uint32_t cluster_width; - - uint32_t max_cluster_element_count_div_32; - uint32_t use_temporal_reprojection; - uint32_t temporal_frame; - float temporal_blend; - - float cam_rotation[12]; - float to_prev_view[16]; - float radiance_inverse_xform[12]; - }; - - VolumetricFogProcessShaderRD process_shader; - - RID process_shader_version; - RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX]; - - } volumetric_fog; - - uint32_t volumetric_fog_depth = 128; - uint32_t volumetric_fog_size = 128; - bool volumetric_fog_filter_active = true; - - Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); - void _volumetric_fog_erase(RenderBuffers *rb); - void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); - - struct FogShaderData : public RendererRD::ShaderData { - bool valid = false; - RID version; - - RID pipeline; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; - - Vector<uint32_t> ubo_offsets; - uint32_t ubo_size = 0; - - String path; - String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; - - bool uses_time = false; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; - virtual bool is_animated() const; - virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; - virtual RS::ShaderNativeSourceCode get_native_source_code() const; - - FogShaderData() {} - virtual ~FogShaderData(); - }; - - struct FogMaterialData : public RendererRD::MaterialData { - FogShaderData *shader_data = nullptr; - RID uniform_set; - bool uniform_set_updated; - - virtual void set_render_priority(int p_priority) {} - virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~FogMaterialData(); - }; - - RendererRD::ShaderData *_create_fog_shader_func(); - static RendererRD::ShaderData *_create_fog_shader_funcs(); - - RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); - RID shadow_sampler; uint64_t scene_pass = 0; @@ -987,11 +739,18 @@ private: uint32_t max_cluster_elements = 512; - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr); + + /* Volumetric Fog */ + + uint32_t volumetric_fog_size = 128; + uint32_t volumetric_fog_depth = 128; + bool volumetric_fog_filter_active = true; + + void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); public: - virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0; - virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0; + static RendererSceneRenderRD *get_singleton() { return singleton; } /* GI */ @@ -1053,65 +812,16 @@ public: /* ENVIRONMENT API */ - virtual RID environment_allocate() override; - virtual void environment_initialize(RID p_rid) override; - - virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override; - virtual void environment_set_sky(RID p_env, RID p_sky) override; - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) override; - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override; - virtual void environment_set_bg_color(RID p_env, const Color &p_color) override; - virtual void environment_set_bg_energy(RID p_env, float p_energy) override; - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override; - - virtual RS::EnvironmentBG environment_get_background(RID p_env) const override; - RID environment_get_sky(RID p_env) const; - float environment_get_sky_custom_fov(RID p_env) const; - Basis environment_get_sky_orientation(RID p_env) const; - Color environment_get_bg_color(RID p_env) const; - float environment_get_bg_energy(RID p_env) const; - virtual int environment_get_canvas_max_layer(RID p_env) const override; - Color environment_get_ambient_light_color(RID p_env) const; - RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const; - float environment_get_ambient_light_energy(RID p_env) const; - float environment_get_ambient_sky_contribution(RID p_env) const; - RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; - - virtual bool is_environment(RID p_env) const override; - - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override; virtual void environment_glow_set_use_high_quality(bool p_enable) override; - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override; - bool environment_is_fog_enabled(RID p_env) const; - Color environment_get_fog_light_color(RID p_env) const; - float environment_get_fog_light_energy(RID p_env) const; - float environment_get_fog_sun_scatter(RID p_env) const; - float environment_get_fog_density(RID p_env) const; - float environment_get_fog_height(RID p_env) const; - float environment_get_fog_height_density(RID p_env) const; - float environment_get_fog_aerial_perspective(RID p_env) const; - - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override; - virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override; - virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override; virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override; + virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - bool environment_is_ssao_enabled(RID p_env) const; - float environment_get_ssao_ao_affect(RID p_env) const; - float environment_get_ssao_light_affect(RID p_env) const; - bool environment_is_ssil_enabled(RID p_env) const; - bool environment_is_ssr_enabled(RID p_env) const; - bool environment_is_sdfgi_enabled(RID p_env) const; - - virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override; @@ -1119,9 +829,6 @@ public: virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override; RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const; - virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override; - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override; - virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override; /* CAMERA EFFECTS */ @@ -1146,7 +853,7 @@ public: virtual RID light_instance_create(RID p_light) override; virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override; virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override; - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; + virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; virtual void light_instance_mark_visible(RID p_light_instance) override; _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) { @@ -1195,7 +902,7 @@ public: return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); } - _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) { + _FORCE_INLINE_ Projection light_instance_get_shadow_camera(RID p_light_instance, int p_index) { LightInstance *li = light_instance_owner.get_or_null(p_light_instance); return li->shadow_transform[p_index].camera; } @@ -1389,7 +1096,7 @@ public: virtual RID voxel_gi_instance_create(RID p_base) override; virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override; virtual bool voxel_gi_needs_update(RID p_probe) const override; - virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override; + virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override; virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; } /* render buffers */ @@ -1398,7 +1105,7 @@ public: virtual RD::DataFormat _render_buffers_get_color_format(); virtual bool _render_buffers_can_be_storage(); virtual RID render_buffers_create() override; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; virtual void gi_set_use_half_resolution(bool p_enable) override; RID render_buffers_get_depth_texture(RID p_render_buffers); @@ -1432,11 +1139,11 @@ public: virtual void update_uniform_sets(){}; - virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; + virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; + virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override; virtual void set_scene_pass(uint64_t p_pass) override { scene_pass = p_pass; @@ -1454,8 +1161,8 @@ public: RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override; - virtual void shadows_quality_set(RS::ShadowQuality p_quality) override; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override; + virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; + virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; virtual void decals_set_filter(RS::DecalFilter p_filter) override; virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override; @@ -1503,6 +1210,7 @@ public: virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override; + virtual bool is_vrs_supported() const; virtual bool is_dynamic_gi_supported() const; virtual bool is_clustered_enabled() const; virtual bool is_volumetric_supported() const; @@ -1514,4 +1222,4 @@ public: ~RendererSceneRenderRD(); }; -#endif // RASTERIZER_SCENE_RD_H +#endif // RENDERER_SCENE_RENDER_RD_H diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 04e05380f1..c9b6d09d4c 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -177,7 +177,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c for (const KeyValue<StringName, CharString> &E : p_version->code_sections) { builder.append(String("#define ") + String(E.key) + "_CODE_USED\n"); } -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) builder.append("#define MOLTENVK_USED\n"); #endif } break; @@ -476,7 +476,9 @@ void ShaderRD::_compile_version(Version *p_version) { #if 1 - RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + #else for (int i = 0; i < variant_defines.size(); i++) { _compile_variant(i, p_version); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 12f57b0178..2ea6965c09 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -138,10 +138,10 @@ layout(set = 0, binding = 7) uniform texture2D sdf_texture; layout(set = 0, binding = 8) uniform sampler material_samplers[12]; -layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalShaderUniformData { vec4 data[]; } -global_variables; +global_shader_uniforms; /* SET1: Is reserved for the material */ diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 9787c9879d..1c17eabb56 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color; layout(set = 1, binding = 0) uniform sampler2DArray source_depth; layout(location = 1) out float depth; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ layout(set = 0, binding = 0) uniform sampler2D source_color; #ifdef MODE_TWO_SOURCES layout(set = 1, binding = 0) uniform sampler2D source_color2; @@ -139,7 +139,7 @@ void main() { //uv.y = 1.0 - uv.y; uv = 1.0 - uv; } -#endif +#endif /* MODE_PANORAMA_TO_DP */ #ifdef MULTIVIEW vec4 color = textureLod(source_color, uv, 0.0); @@ -148,12 +148,13 @@ void main() { depth = textureLod(source_depth, uv, 0.0).r; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ vec4 color = textureLod(source_color, uv, 0.0); #ifdef MODE_TWO_SOURCES color += textureLod(source_color2, uv, 0.0); #endif /* MODE_TWO_SOURCES */ #endif /* MULTIVIEW */ + if (params.force_luminance) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } @@ -163,5 +164,6 @@ void main() { if (params.srgb) { color.rgb = linear_to_srgb(color.rgb); } + frag_color = color; } diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index a416891ff2..246ef81cb2 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -32,12 +32,17 @@ layout(push_constant, std430) uniform Params { bool use_half_res; uint metallic_mask; - mat4 projection; + uint view_index; + uint pad1; + uint pad2; + uint pad3; } params; +#include "screen_space_reflection_inc.glsl" + vec2 view_to_screen(vec3 view_pos, out float w) { - vec4 projected = params.projection * vec4(view_pos, 1.0); + vec4 projected = scene_data.projection[params.view_index] * vec4(view_pos, 1.0); projected.xyz /= projected.w; projected.xy = projected.xy * 0.5 + 0.5; w = projected.w; @@ -46,24 +51,16 @@ vec2 view_to_screen(vec3 view_pos, out float w) { #define M_PI 3.14159265359 -vec3 reconstructCSPosition(vec2 S, float z) { - if (params.orthogonal) { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); - } else { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); - } -} - void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } vec2 pixel_size = 1.0 / vec2(params.screen_size); - vec2 uv = vec2(ssC) * pixel_size; + vec2 uv = vec2(ssC.xy) * pixel_size; uv += pixel_size * 0.5; @@ -77,7 +74,12 @@ void main() { normal = normalize(normal); normal.y = -normal.y; //because this code reads flipped - vec3 view_dir = normalize(vertex); + vec3 view_dir; + if (sc_multiview) { + view_dir = normalize(vertex + scene_data.eye_offset[params.view_index].xyz); + } else { + view_dir = normalize(vertex); + } vec3 ray_dir = normalize(reflect(view_dir, normal)); if (dot(ray_dir, normal) < 0.001) { @@ -154,6 +156,11 @@ void main() { // convert to linear depth depth = imageLoad(source_depth, ivec2(pos - 0.5)).r; + if (sc_multiview) { + depth = depth * 2.0 - 1.0; + depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + depth = -depth; + } z_from = z_to; z_to = z / w; @@ -175,17 +182,18 @@ void main() { if (found) { float margin_blend = 1.0; - vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin - if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) { - // clip outside screen + margin + vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin + if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) { + // clip at the screen edges imageStore(ssr_image, ssC, vec4(0.0)); return; } { - //blend fading out towards external margin - vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0))); - margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y)); + //blend fading out towards inner margin + // 0.5 = midpoint of reflection + vec2 margin_grad = mix(params.screen_size - pos, pos, lessThan(pos, params.screen_size * 0.5)); + margin_blend = smoothstep(0.0, margin.x * margin.y, margin_grad.x * margin_grad.y); //margin_blend = 1.0; } @@ -222,13 +230,16 @@ void main() { blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h); } } + + // Isn't this going to be overwritten after our endif? final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size)); imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8 -#endif +#endif // MODE_ROUGH final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); + //change blend by metallic vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask); final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0)); diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl index 20e1712496..a63d60e0b2 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl @@ -22,7 +22,7 @@ layout(push_constant, std430) uniform Params { bool orthogonal; float edge_tolerance; int increment; - uint pad; + uint view_index; ivec2 screen_size; bool vertical; @@ -30,6 +30,8 @@ layout(push_constant, std430) uniform Params { } params; +#include "screen_space_reflection_inc.glsl" + #define GAUSS_TABLE_SIZE 15 const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[]( @@ -64,14 +66,6 @@ float gauss_weight(float p_val) { #define M_PI 3.14159265359 -vec3 reconstructCSPosition(vec2 S, float z) { - if (params.orthogonal) { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); - } else { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); - } -} - void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) { for (int i = 1; i < params.steps; i++) { float d = float(i * params.increment); @@ -110,7 +104,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } @@ -130,13 +124,13 @@ void main() { ivec2 direction = ivec2(params.increment, 0); #endif float depth = imageLoad(source_depth, ssC).r; - vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth); + vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth); vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0; normal = normalize(normal); normal.y = -normal.y; - do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius); - do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius); + do_filter(accum, accum_radius, divisor, ssC.xy, direction, pos, normal, radius); + do_filter(accum, accum_radius, divisor, ssC.xy, -direction, pos, normal, radius); if (divisor > 0.0) { accum /= divisor; diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl new file mode 100644 index 0000000000..26405ab040 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl @@ -0,0 +1,28 @@ +layout(constant_id = 0) const bool sc_multiview = false; + +layout(set = 4, binding = 0, std140) uniform SceneData { + mat4x4 projection[2]; + mat4x4 inv_projection[2]; + vec4 eye_offset[2]; +} +scene_data; + +vec3 reconstructCSPosition(vec2 screen_pos, float z) { + if (sc_multiview) { + vec4 pos; + pos.xy = (2.0 * vec2(screen_pos) / vec2(params.screen_size)) - 1.0; + pos.z = z * 2.0 - 1.0; + pos.w = 1.0; + + pos = scene_data.inv_projection[params.view_index] * pos; + pos.xyz /= pos.w; + + return pos.xyz; + } else { + if (params.orthogonal) { + return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw), z); + } else { + return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw) * z, z); + } + } +} diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl index 3f537e273a..a7da0812df 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl @@ -6,6 +6,11 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_multiview = false; + +/* inputs */ layout(set = 0, binding = 0) uniform sampler2D source_ssr; layout(set = 1, binding = 0) uniform sampler2D source_depth; layout(set = 1, binding = 1) uniform sampler2D source_normal; @@ -28,7 +33,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } //do not filter, SSR will generate arctifacts if this is done @@ -57,13 +62,19 @@ void main() { normal.xyz += nr.xyz * 2.0 - 1.0; normal.w += nr.w; - d = d * 2.0 - 1.0; - if (params.orthogonal) { - d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + if (sc_multiview) { + // we're doing a full unproject so we need the value as is. + depth += d; } else { - d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near)); + // unproject our Z value so we can use it directly. + d = d * 2.0 - 1.0; + if (params.orthogonal) { + d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + } else { + d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near)); + } + depth += -d; } - depth += -d; } color /= 4.0; @@ -71,17 +82,22 @@ void main() { normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5; normal.w /= 4.0; } else { - color = texelFetch(source_ssr, ssC << 1, 0); - depth = texelFetch(source_depth, ssC << 1, 0).r; - normal = texelFetch(source_normal, ssC << 1, 0); - - depth = depth * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; - } else { - depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + ivec2 ofs = ssC << 1; + + color = texelFetch(source_ssr, ofs, 0); + depth = texelFetch(source_depth, ofs, 0).r; + normal = texelFetch(source_normal, ofs, 0); + + if (!sc_multiview) { + // unproject our Z value so we can use it directly. + depth = depth * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + } else { + depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + } + depth = -depth; } - depth = -depth; } imageStore(dest_ssr, ssC, color); diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl new file mode 100644 index 0000000000..c62144fdaf --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl @@ -0,0 +1,112 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else // USE_MULTIVIEW +layout(location = 0) out vec2 uv_interp; +#endif //USE_MULTIVIEW + +void main() { + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + +#ifdef USE_MULTIVIEW + uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex); + + gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0); +#else + uv_interp = base_arr[gl_VertexIndex]; + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +#endif +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(location = 0) in vec3 uv_interp; +#else // USE_MULTIVIEW +layout(location = 0) in vec2 uv_interp; +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(set = 0, binding = 0) uniform sampler2DArray specular; +#else // USE_MULTIVIEW +layout(set = 0, binding = 0) uniform sampler2D specular; +#endif //USE_MULTIVIEW + +#ifdef MODE_SSR + +#ifdef USE_MULTIVIEW +layout(set = 1, binding = 0) uniform sampler2DArray ssr; +#else // USE_MULTIVIEW +layout(set = 1, binding = 0) uniform sampler2D ssr; +#endif //USE_MULTIVIEW + +#endif + +#ifdef MODE_MERGE + +#ifdef USE_MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2DArray diffuse; +#else // USE_MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2D diffuse; +#endif //USE_MULTIVIEW + +#endif + +layout(location = 0) out vec4 frag_color; + +void main() { + frag_color.rgb = texture(specular, uv_interp).rgb; + frag_color.a = 0.0; +#ifdef MODE_SSR + + vec4 ssr_color = texture(ssr, uv_interp); + frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a); +#endif + +#ifdef MODE_MERGE + frag_color += texture(diffuse, uv_interp); +#endif + //added using additive blend +} diff --git a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index 134aae5ce7..134aae5ce7 100644 --- a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl index 2a87e273bc..2a87e273bc 100644 --- a/servers/rendering/renderer_rd/shaders/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl index f42734c46d..f42734c46d 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl index 04f98964e8..04f98964e8 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl index f6a9a92fac..f6a9a92fac 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl index 513791dfbf..513791dfbf 100644 --- a/servers/rendering/renderer_rd/shaders/ssil.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl index 47c56571f6..47c56571f6 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl index 6b6b02739d..6b6b02739d 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl index 9e86ac0cf0..9e86ac0cf0 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl new file mode 100644 index 0000000000..5ef83c0b44 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -0,0 +1,72 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else +layout(location = 0) out vec2 uv_interp; +#endif + +void main() { + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv_interp.xy = base_arr[gl_VertexIndex]; +#ifdef MULTIVIEW + uv_interp.z = ViewIndex; +#endif + + gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0); +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) in vec3 uv_interp; +layout(set = 0, binding = 0) uniform sampler2DArray source_color; +#else /* MULTIVIEW */ +layout(location = 0) in vec2 uv_interp; +layout(set = 0, binding = 0) uniform sampler2D source_color; +#endif /* MULTIVIEW */ + +layout(location = 0) out uint frag_color; + +void main() { +#ifdef MULTIVIEW + vec3 uv = uv_interp; +#else + vec2 uv = uv_interp; +#endif + +#ifdef MULTIVIEW + vec4 color = textureLod(source_color, uv, 0.0); +#else /* MULTIVIEW */ + vec4 color = textureLod(source_color, uv, 0.0); +#endif /* MULTIVIEW */ + + // See if we can change the sampler to one that returns int... + frag_color = uint(color.r * 256.0); +} diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index f687d50a2d..6ea8cb1377 100644 --- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define M_PI 3.141592 +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_half_res = false; +layout(constant_id = 1) const bool sc_use_full_projection_matrix = false; +layout(constant_id = 2) const bool sc_use_vrs = false; + #define SDFGI_MAX_CASCADES 8 //set 0 for SDFGI and render buffers @@ -97,18 +103,20 @@ layout(set = 0, binding = 18, std140) uniform SceneData { } scene_data; +layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer; + layout(push_constant, std430) uniform Params { - uint view_index; uint max_voxel_gi_instances; bool high_quality_vct; bool orthogonal; + uint view_index; vec4 proj_info; float z_near; float z_far; - float pad1; float pad2; + float pad3; } params; @@ -140,34 +148,34 @@ vec4 blend_color(vec4 src, vec4 dst) { } vec3 reconstruct_position(ivec2 screen_pos) { -#ifdef USE_MULTIVIEW - vec4 pos; - pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; - pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; - pos.w = 1.0; + if (sc_use_full_projection_matrix) { + vec4 pos; + pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; + pos.w = 1.0; - pos = scene_data.inv_projection[params.view_index] * pos; + pos = scene_data.inv_projection[params.view_index] * pos; - return pos.xyz / pos.w; -#else - vec3 pos; - pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; - - pos.z = pos.z * 2.0 - 1.0; - if (params.orthogonal) { - pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + return pos.xyz / pos.w; } else { - pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); - } - pos.z = -pos.z; + vec3 pos; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; + + pos.z = pos.z * 2.0 - 1.0; + if (params.orthogonal) { + pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); + } + pos.z = -pos.z; - pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; - if (!params.orthogonal) { - pos.xy *= pos.z; - } + pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; + if (!params.orthogonal) { + pos.xy *= pos.z; + } - return pos; -#endif + return pos; + } } void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { @@ -587,7 +595,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 vec4 fetch_normal_and_roughness(ivec2 pos) { vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0); - normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0); return normal_roughness; } @@ -600,7 +607,7 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref if (normal.length() > 0.5) { //valid normal, can do GI float roughness = normal_roughness.w; - vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[params.view_index].xyz)); + vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz)); vertex = mat3(scene_data.cam_transform) * vertex; normal = normalize(mat3(scene_data.cam_transform) * normal); vec3 reflection = normalize(reflect(-view, normal)); @@ -648,9 +655,35 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); -#ifdef MODE_HALF_RES - pos <<= 1; -#endif + uint vrs_x, vrs_y; + if (sc_use_vrs) { + ivec2 vrs_pos; + + // Currently we use a 16x16 texel, possibly some day make this configurable. + if (sc_half_res) { + vrs_pos = pos >> 3; + } else { + vrs_pos = pos >> 4; + } + + uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r; + // note, valid values for vrs_x and vrs_y are 1, 2 and 4. + vrs_x = 1 << ((vrs_texel >> 2) & 3); + vrs_y = 1 << (vrs_texel & 3); + + if (mod(pos.x, vrs_x) != 0) { + return; + } + + if (mod(pos.y, vrs_y) != 0) { + return; + } + } + + if (sc_half_res) { + pos <<= 1; + } + if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing return; } @@ -663,10 +696,69 @@ void main() { process_gi(pos, vertex, ambient_light, reflection_light); -#ifdef MODE_HALF_RES - pos >>= 1; -#endif + if (sc_half_res) { + pos >>= 1; + } imageStore(ambient_buffer, pos, ambient_light); imageStore(reflection_buffer, pos, reflection_light); + + if (sc_use_vrs) { + if (vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light); + } + + if (vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light); + } + + if (vrs_y > 1) { + imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light); + } + + if (vrs_y > 2) { + imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light); + } + } } diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl index af5f7d0a58..9640d30e78 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl @@ -37,16 +37,14 @@ layout(push_constant, std430) uniform Params { uint max_cascades; ivec2 screen_size; - bool use_occlusion; float y_mult; - int probe_axis_size; float z_near; - float reserved1; - float reserved2; - mat4 cam_transform; - mat4 inv_projection; + mat3x4 inv_projection; + // We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery. + float cam_basis[3][3]; + float cam_origin[3]; } params; @@ -82,13 +80,21 @@ void main() { vec3 ray_pos; vec3 ray_dir; { - ray_pos = params.cam_transform[3].xyz; + ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]); ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0); ray_dir.z = params.z_near; - ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz; - ray_dir = normalize(mat3(params.cam_transform) * ray_dir); + ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz; + + mat3 cam_basis; + { + vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]); + vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]); + vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]); + cam_basis = mat3(c0, c1, c2); + } + ray_dir = normalize(cam_basis * ray_dir); } ray_pos.y *= params.y_mult; diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 5b4594da99..e825020a4e 100644 --- a/servers/rendering/renderer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -77,10 +77,10 @@ params; layout(set = 0, binding = 0) uniform sampler material_samplers[12]; -layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUniformData { vec4 data[]; } -global_variables; +global_shader_uniforms; layout(set = 0, binding = 2, std140) uniform SceneData { bool volumetric_fog_enabled; diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index eee609fb48..4658afd02d 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -21,17 +21,17 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; #define DENSITY_SCALE 1024.0 -#include "cluster_data_inc.glsl" -#include "light_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../light_data_inc.glsl" #define M_PI 3.14159265359 layout(set = 0, binding = 1) uniform sampler material_samplers[12]; -layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData { vec4 data[]; } -global_variables; +global_shader_uniforms; layout(push_constant, std430) uniform Params { vec3 position; diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index fdbd7d3e35..6f79b9e771 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -19,8 +19,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #endif -#include "cluster_data_inc.glsl" -#include "light_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../light_data_inc.glsl" #define M_PI 3.14159265359 @@ -377,7 +377,7 @@ void main() { for (uint i = 0; i < params.directional_light_count; i++) { vec3 shadow_attenuation = vec3(1.0); - if (directional_lights.data[i].shadow_enabled) { + if (directional_lights.data[i].shadow_opacity > 0.001) { float depth_z = -view_pos.z; vec4 pssm_coord; @@ -486,7 +486,7 @@ void main() { vec3 light = omni_lights.data[light_index].color; - if (omni_lights.data[light_index].shadow_enabled) { + if (omni_lights.data[light_index].shadow_opacity > 0.001) { //has shadow vec4 uv_rect = omni_lights.data[light_index].atlas_rect; vec2 flip_offset = omni_lights.data[light_index].direction.xy; @@ -572,7 +572,7 @@ void main() { vec3 light = spot_lights.data[light_index].color; - if (spot_lights.data[light_index].shadow_enabled) { + if (spot_lights.data[light_index].shadow_opacity > 0.001) { //has shadow vec4 uv_rect = spot_lights.data[light_index].atlas_rect; vec2 flip_offset = spot_lights.data[light_index].direction.xy; diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl index 61c8488a05..799f7087b6 100644 --- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl @@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible mediump float cone_attenuation; mediump float cone_angle; mediump float specular_amount; - bool shadow_enabled; + mediump float shadow_opacity; highp vec4 atlas_rect; // rect in the shadow atlas highp mat4 shadow_matrix; @@ -60,7 +60,7 @@ struct DirectionalLightData { highp float softshadow_angle; highp float soft_shadow_scale; bool blend_splits; - bool shadow_enabled; + mediump float shadow_opacity; highp float fade_from; highp float fade_to; uvec2 pad; diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index acb62b812e..fb5759bc17 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -25,10 +25,10 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout(set = 0, binding = 1) uniform sampler material_samplers[12]; -layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData { vec4 data[]; } -global_variables; +global_shader_uniforms; /* Set 1: FRAME AND PARTICLE DATA */ @@ -458,11 +458,11 @@ void main() { } break; case ATTRACTOR_TYPE_VECTOR_FIELD: { - vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0; + vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5; if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) { continue; } - vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz; + vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0; dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction amount = length(s); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 5947fc5351..e9515c7670 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -947,9 +947,9 @@ void fragment_shader(in SceneData scene_data) { if (decals.data[decal_index].emission_rect != vec4(0.0)) { //emission is additive, so its independent from albedo if (sc_decal_use_mipmaps) { - emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade; } else { - emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; + emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade; } } } @@ -988,8 +988,10 @@ void fragment_shader(in SceneData scene_data) { vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); vec3 ref_vec = reflect(-view, bent_normal); + ref_vec = mix(ref_vec, bent_normal, roughness * roughness); #else vec3 ref_vec = reflect(-view, normal); + ref_vec = mix(ref_vec, normal, roughness * roughness); #endif float horizon = min(1.0 + dot(ref_vec, normal), 1.0); @@ -1046,6 +1048,7 @@ void fragment_shader(in SceneData scene_data) { ambient_light *= attenuation; specular_light *= attenuation; + ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness); float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; @@ -1203,6 +1206,7 @@ void fragment_shader(in SceneData scene_data) { uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; vec3 ref_vec = normalize(reflect(-view, normal)); + ref_vec = mix(ref_vec, normal, roughness * roughness); //find arbitrary tangent and bitangent, then build a matrix vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); vec3 tangent = normalize(cross(v0, normal)); @@ -1302,6 +1306,18 @@ void fragment_shader(in SceneData scene_data) { item_to = subgroupBroadcastFirst(subgroupMax(item_to)); #endif +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else + vec3 bent_normal = normal; +#endif + vec3 ref_vec = normalize(reflect(-view, bent_normal)); + ref_vec = mix(ref_vec, bent_normal, roughness * roughness); + for (uint i = item_from; i < item_to; i++) { uint mask = cluster_buffer.data[cluster_reflection_offset + i]; mask &= cluster_get_range_clip_mask(i, item_min, item_max); @@ -1324,16 +1340,8 @@ void fragment_shader(in SceneData scene_data) { if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) { continue; //not masked } -#ifdef LIGHT_ANISOTROPY_USED - // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy - vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; - vec3 anisotropic_tangent = cross(anisotropic_direction, view); - vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); - vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); -#else - vec3 bent_normal = normal; -#endif - reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + + reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } } @@ -1381,7 +1389,7 @@ void fragment_shader(in SceneData scene_data) { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } @@ -1417,7 +1425,7 @@ void fragment_shader(in SceneData scene_data) { float shadow = 1.0; - if (directional_lights.data[i].shadow_enabled) { + if (directional_lights.data[i].shadow_opacity > 0.001) { float depth_z = -vertex.z; vec3 light_dir = directional_lights.data[i].direction; vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); @@ -1626,7 +1634,7 @@ void fragment_shader(in SceneData scene_data) { #ifdef LIGHT_TRANSMITTANCE_USED float transmittance_z = transmittance_depth; - if (directional_lights.data[i].shadow_enabled) { + if (directional_lights.data[i].shadow_opacity > 0.001) { float depth_z = -vertex.z; if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { @@ -1681,6 +1689,8 @@ void fragment_shader(in SceneData scene_data) { } else { shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0; } + + shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity; #endif blur_shadow(shadow); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index 0c23de96c3..f0717294ef 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -129,10 +129,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { } decals; -layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData { vec4 data[]; } -global_variables; +global_shader_uniforms; struct SDFVoxelGICascadeData { vec3 position; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index c92b29b14a..7299bb0576 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -199,7 +199,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -392,7 +395,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) { float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { #ifndef SHADOWS_DISABLED - if (omni_lights.data[idx].shadow_enabled) { + if (omni_lights.data[idx].shadow_opacity > 0.001) { // there is a shadowmap vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size; vec4 base_uv_rect = omni_lights.data[idx].atlas_rect; @@ -495,6 +498,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { } shadow /= float(sc_penumbra_shadow_samples); + shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity); } else { //no blockers found, so no shadow @@ -513,7 +517,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { vec2 pos = shadow_sample.xy / shadow_sample.z; float depth = shadow_len - omni_lights.data[idx].shadow_bias; depth *= omni_lights.data[idx].inv_radius; - shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth); + shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity); } return shadow; @@ -671,7 +675,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { #ifndef SHADOWS_DISABLED - if (spot_lights.data[idx].shadow_enabled) { + if (spot_lights.data[idx].shadow_opacity > 0.001) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; float light_length = length(light_rel_vec); vec3 spot_dir = spot_lights.data[idx].direction; @@ -732,6 +736,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { } shadow /= float(sc_penumbra_shadow_samples); + shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity); } else { //no blockers found, so no shadow @@ -740,7 +745,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { } else { //hard shadow vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z); - shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv); + shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity); } return shadow; @@ -869,7 +874,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v diffuse_light, specular_light); } -void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { +void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { vec3 box_extents = reflections.data[ref_index].box_extents; vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz; @@ -877,8 +882,6 @@ void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, flo return; } - vec3 ref_vec = normalize(reflect(-view, normal)); - vec3 inner_pos = abs(local_pos / box_extents); float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); //make blend more rounded diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 26d0de46c2..6548793bee 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -889,8 +889,10 @@ void main() { vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); vec3 ref_vec = reflect(-view, bent_normal); + ref_vec = mix(ref_vec, bent_normal, roughness * roughness); #else vec3 ref_vec = reflect(-view, normal); + ref_vec = mix(ref_vec, normal, roughness * roughness); #endif float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; @@ -940,6 +942,7 @@ void main() { vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map float NoV = max(dot(n, view), 0.0001); vec3 ref_vec = reflect(-view, n); + ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness); // The clear coat layer assumes an IOR of 1.5 (4% reflectance) float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV)); float attenuation = 1.0 - Fc; @@ -1036,6 +1039,19 @@ void main() { vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); uint reflection_indices = draw_call.reflection_probes.x; + +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else + vec3 bent_normal = normal; +#endif + vec3 ref_vec = normalize(reflect(-view, bent_normal)); + ref_vec = mix(ref_vec, bent_normal, roughness * roughness); + for (uint i = 0; i < 8; i++) { uint reflection_index = reflection_indices & 0xFF; if (i == 4) { @@ -1047,16 +1063,8 @@ void main() { if (reflection_index == 0xFF) { break; } -#ifdef LIGHT_ANISOTROPY_USED - // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy - vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; - vec3 anisotropic_tangent = cross(anisotropic_direction, view); - vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); - vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); -#else - vec3 bent_normal = normal; -#endif - reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + + reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } if (reflection_accum.a > 0.0) { @@ -1134,7 +1142,7 @@ void main() { #ifdef USE_SOFT_SHADOWS //version with soft shadows, more expensive - if (directional_lights.data[i].shadow_enabled) { + if (directional_lights.data[i].shadow_opacity > 0.001) { float depth_z = -vertex.z; vec4 pssm_coord; @@ -1286,7 +1294,7 @@ void main() { #else // Soft shadow disabled version - if (directional_lights.data[i].shadow_enabled) { + if (directional_lights.data[i].shadow_opacity > 0.001) { float depth_z = -vertex.z; vec4 pssm_coord; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index 7413d8730a..98ad674ce0 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -118,10 +118,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { } decals; -layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData { highp vec4 data[]; } -global_variables; +global_shader_uniforms; /* Set 1: Render Pass (changes per render pass) */ diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl deleted file mode 100644 index 3579c35cce..0000000000 --- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl +++ /dev/null @@ -1,53 +0,0 @@ -#[vertex] - -#version 450 - -#VERSION_DEFINES - -layout(location = 0) out vec2 uv_interp; - -void main() { - vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - - gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); -} - -#[fragment] - -#version 450 - -#VERSION_DEFINES - -layout(location = 0) in vec2 uv_interp; - -layout(set = 0, binding = 0) uniform sampler2D specular; - -#ifdef MODE_SSR - -layout(set = 1, binding = 0) uniform sampler2D ssr; - -#endif - -#ifdef MODE_MERGE - -layout(set = 2, binding = 0) uniform sampler2D diffuse; - -#endif - -layout(location = 0) out vec4 frag_color; - -void main() { - frag_color.rgb = texture(specular, uv_interp).rgb; - frag_color.a = 0.0; -#ifdef MODE_SSR - - vec4 ssr_color = texture(ssr, uv_interp); - frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a); -#endif - -#ifdef MODE_MERGE - frag_color += texture(diffuse, uv_interp); -#endif - //added using additive blend -} diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl index ddd984ad83..b0a0839836 100644 --- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl @@ -189,7 +189,7 @@ vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) { // Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1 // License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae - // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding + // We're going to sample a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding // down the sample location to get the exact center of our "starting" texel. The starting texel will be at // location [1, 1] in the grid, where [0, 0] is the top left corner. vec2 sample_pos = uv * resolution; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index e65f676785..882afdfa54 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -56,7 +56,7 @@ LightStorage::LightStorage() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -88,6 +88,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) { light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0; light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; + light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0; light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0; light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0; light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1; @@ -366,6 +367,13 @@ AABB LightStorage::light_get_aabb(RID p_light) const { ERR_FAIL_V(AABB()); } +Dependency *LightStorage::light_get_dependency(RID p_light) const { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL_V(light, nullptr); + + return &light->dependency; +} + /* REFLECTION PROBE */ RID LightStorage::reflection_probe_allocate() { @@ -601,6 +609,13 @@ float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const return reflection_probe->ambient_color_energy; } +Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const { + ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); + ERR_FAIL_NULL_V(reflection_probe, nullptr); + + return &reflection_probe->dependency; +} + /* LIGHTMAP API */ RID LightStorage::lightmap_allocate() { @@ -628,17 +643,17 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use //erase lightmap users if (lm->light_texture.is_valid()) { - RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); + RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); + RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -725,6 +740,13 @@ void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) { lightmap_probe_capture_update_speed = p_speed; } +Dependency *LightStorage::lightmap_get_dependency(RID p_lightmap) const { + Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); + ERR_FAIL_NULL_V(lm, nullptr); + + return &lm->dependency; +} + void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index fb25e4da7e..3e3246e8e9 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -39,87 +39,81 @@ namespace RendererRD { -/* LIGHT */ - -struct Light { - RS::LightType type; - float param[RS::LIGHT_PARAM_MAX]; - Color color = Color(1, 1, 1, 1); - RID projector; - bool shadow = false; - bool negative = false; - bool reverse_cull = false; - RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; - uint32_t max_sdfgi_cascade = 2; - uint32_t cull_mask = 0xFFFFFFFF; - bool distance_fade = false; - real_t distance_fade_begin = 40.0; - real_t distance_fade_shadow = 50.0; - real_t distance_fade_length = 10.0; - RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; - RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - bool directional_blend_splits = false; - RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; - uint64_t version = 0; - - Dependency dependency; -}; - -/* REFLECTION PROBE */ - -struct ReflectionProbe { - RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; - int resolution = 256; - float intensity = 1.0; - RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; - Color ambient_color; - float ambient_color_energy = 1.0; - float max_distance = 0; - Vector3 extents = Vector3(1, 1, 1); - Vector3 origin_offset; - bool interior = false; - bool box_projection = false; - bool enable_shadows = false; - uint32_t cull_mask = (1 << 20) - 1; - float mesh_lod_threshold = 0.01; - - Dependency dependency; -}; - -/* LIGHTMAP */ - -struct Lightmap { - RID light_texture; - bool uses_spherical_harmonics = false; - bool interior = false; - AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); - int32_t array_index = -1; //unassigned - PackedVector3Array points; - PackedColorArray point_sh; - PackedInt32Array tetrahedra; - PackedInt32Array bsp_tree; - - struct BSP { - static const int32_t EMPTY_LEAF = INT32_MIN; - float plane[4]; - int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; - }; - - Dependency dependency; -}; - class LightStorage : public RendererLightStorage { private: static LightStorage *singleton; /* LIGHT */ + struct Light { + RS::LightType type; + float param[RS::LIGHT_PARAM_MAX]; + Color color = Color(1, 1, 1, 1); + RID projector; + bool shadow = false; + bool negative = false; + bool reverse_cull = false; + RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; + uint32_t max_sdfgi_cascade = 2; + uint32_t cull_mask = 0xFFFFFFFF; + bool distance_fade = false; + real_t distance_fade_begin = 40.0; + real_t distance_fade_shadow = 50.0; + real_t distance_fade_length = 10.0; + RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + bool directional_blend_splits = false; + RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; + uint64_t version = 0; + + Dependency dependency; + }; + mutable RID_Owner<Light, true> light_owner; /* REFLECTION PROBE */ + + struct ReflectionProbe { + RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; + int resolution = 256; + float intensity = 1.0; + RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; + Color ambient_color; + float ambient_color_energy = 1.0; + float max_distance = 0; + Vector3 extents = Vector3(1, 1, 1); + Vector3 origin_offset; + bool interior = false; + bool box_projection = false; + bool enable_shadows = false; + uint32_t cull_mask = (1 << 20) - 1; + float mesh_lod_threshold = 0.01; + + Dependency dependency; + }; mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner; /* LIGHTMAP */ + struct Lightmap { + RID light_texture; + bool uses_spherical_harmonics = false; + bool interior = false; + AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); + int32_t array_index = -1; //unassigned + PackedVector3Array points; + PackedColorArray point_sh; + PackedInt32Array tetrahedra; + PackedInt32Array bsp_tree; + + struct BSP { + static const int32_t EMPTY_LEAF = INT32_MIN; + float plane[4]; + int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; + }; + + Dependency dependency; + }; + bool using_lightmap_array; Vector<RID> lightmap_textures; uint64_t lightmap_array_version = 0; @@ -135,7 +129,6 @@ public: /* LIGHT */ - Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }; bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }; void _light_initialize(RID p_rid, RS::LightType p_type); @@ -268,9 +261,10 @@ public: virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override; virtual uint64_t light_get_version(RID p_light) const override; + Dependency *light_get_dependency(RID p_light) const; + /* REFLECTION PROBE */ - ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); }; bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; virtual RID reflection_probe_allocate() override; @@ -310,9 +304,10 @@ public: Color reflection_probe_get_ambient_color(RID p_probe) const; float reflection_probe_get_ambient_color_energy(RID p_probe) const; + Dependency *reflection_probe_get_dependency(RID p_probe) const; + /* LIGHTMAP */ - Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); }; bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; virtual RID lightmap_allocate() override; @@ -332,6 +327,8 @@ public: virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override; virtual void lightmap_set_probe_capture_update_speed(float p_speed) override; + Dependency *lightmap_get_dependency(RID p_lightmap) const; + virtual float lightmap_get_probe_capture_update_speed() const override { return lightmap_probe_capture_update_speed; } @@ -368,4 +365,4 @@ public: } // namespace RendererRD -#endif // !LIGHT_STORAGE_RD_H +#endif // LIGHT_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index fcd25852eb..41dd1ccc40 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -172,75 +172,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_UINT: { @@ -267,75 +276,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_FLOAT: { @@ -514,13 +532,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[1] = v.y; gui[2] = v.z; gui[3] = v.w; - } else { + } else if (value.get_type() == Variant::PLANE) { Plane v = value; gui[0] = v.normal.x; gui[1] = v.normal.y; gui[2] = v.normal.z; gui[3] = v.d; + } else { + Vector4 v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } } break; @@ -670,7 +695,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[i + 15] = 1; } } - } else { + } else if (value.get_type() == Variant::TRANSFORM3D) { Transform3D v = value; gui[0] = v.basis.rows[0][0]; gui[1] = v.basis.rows[1][0]; @@ -691,6 +716,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[13] = v.origin.y; gui[14] = v.origin.z; gui[15] = 1; + } else { + Projection v = value; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + gui[i * 4 + j] = v.matrix[i][j]; + } + } } } break; default: { @@ -894,9 +926,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, } /////////////////////////////////////////////////////////////////////////// -// MaterialData +// MaterialStorage::MaterialData -void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -911,7 +943,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it - GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key); uint32_t index = 0; if (gv) { index = gv->buffer_index; @@ -967,33 +999,33 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (uses_global_buffer != (global_buffer_E != nullptr)) { if (uses_global_buffer) { - global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self); + global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self); } else { - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); global_buffer_E = nullptr; } } } -MaterialData::~MaterialData() { +MaterialStorage::MaterialData::~MaterialData() { MaterialStorage *material_storage = MaterialStorage::get_singleton(); if (global_buffer_E) { //unregister global buffers - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); } if (global_texture_E) { //unregister global textures for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } } //unregister material from those using global textures - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); } if (uniform_buffer.is_valid()) { @@ -1001,14 +1033,14 @@ MaterialData::~MaterialData() { } } -void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { TextureStorage *texture_storage = TextureStorage::get_singleton(); MaterialStorage *material_storage = MaterialStorage::get_singleton(); #ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; + TextureStorage::Texture *roughness_detect_texture = nullptr; RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - Texture *normal_detect_texture = nullptr; + TextureStorage::Texture *normal_detect_texture = nullptr; #endif bool uses_global_textures = false; @@ -1023,7 +1055,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (p_texture_uniforms[i].global) { uses_global_textures = true; - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name); if (v) { if (v->buffer_index >= 0) { WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); @@ -1091,19 +1123,22 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::TYPE_SAMPLER2D: { switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); } break; default: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } break; } } break; @@ -1111,27 +1146,27 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::TYPE_SAMPLERCUBE: { switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } break; default: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); } break; } } break; case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); } break; case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } break; case ShaderLanguage::TYPE_ISAMPLER2DARRAY: case ShaderLanguage::TYPE_USAMPLER2DARRAY: case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } break; default: { @@ -1153,7 +1188,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color; for (int j = 0; j < textures.size(); j++) { - Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); + TextureStorage::Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); if (tex) { rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; @@ -1175,7 +1210,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet #endif } if (rd_texture.is_null()) { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } #ifdef TOOLS_ENABLED if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { @@ -1193,7 +1228,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (E.value != global_textures_pass) { to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1207,23 +1242,23 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet //handle registering/unregistering global textures if (uses_global_textures != (global_texture_E != nullptr)) { if (uses_global_textures) { - global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self); + global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self); } else { - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); global_texture_E = nullptr; } } } } -void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { +void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_set) { if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); RD::get_singleton()->free(p_uniform_set); } } -bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -1441,22 +1476,22 @@ MaterialStorage::MaterialStorage() { shader_data_request_func[i] = nullptr; } - static_assert(sizeof(GlobalVariables::Value) == 16); + static_assert(sizeof(GlobalShaderUniforms::Value) == 16); - global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); - global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); - memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); - global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); - global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); + global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); + global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size); + memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + global_shader_uniforms.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size); } MaterialStorage::~MaterialStorage() { - memdelete_arr(global_variables.buffer_values); - memdelete_arr(global_variables.buffer_usage); - memdelete_arr(global_variables.buffer_dirty_regions); - RD::get_singleton()->free(global_variables.buffer); + memdelete_arr(global_shader_uniforms.buffer_values); + memdelete_arr(global_shader_uniforms.buffer_usage); + memdelete_arr(global_shader_uniforms.buffer_dirty_regions); + RD::get_singleton()->free(global_shader_uniforms.buffer); // buffers @@ -1577,17 +1612,17 @@ void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) { } } -/* GLOBAL VARIABLE API */ +/* GLOBAL SHADER UNIFORM API */ -int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { +int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) { int32_t idx = 0; - while (idx + p_elements <= global_variables.buffer_size) { - if (global_variables.buffer_usage[idx].elements == 0) { + while (idx + p_elements <= global_shader_uniforms.buffer_size) { + if (global_shader_uniforms.buffer_usage[idx].elements == 0) { bool valid = true; for (uint32_t i = 1; i < p_elements; i++) { - if (global_variables.buffer_usage[idx + i].elements > 0) { + if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) { valid = false; - idx += i + global_variables.buffer_usage[idx + i].elements; + idx += i + global_shader_uniforms.buffer_usage[idx + i].elements; break; } } @@ -1598,17 +1633,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { return idx; } else { - idx += global_variables.buffer_usage[idx].elements; + idx += global_shader_uniforms.buffer_usage[idx].elements; } } return -1; } -void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { +void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; bool b = p_value; bv.x = b ? 1.0 : 0.0; bv.y = 0.0; @@ -1617,7 +1652,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_BVEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1625,7 +1660,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1633,7 +1668,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1641,7 +1676,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = (bvec & 8) ? 1.0 : 0.0; } break; case RS::GLOBAL_VAR_TYPE_INT: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; int32_t v = p_value; bv.x = v; bv.y = 0; @@ -1649,7 +1684,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC2: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1657,7 +1692,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC3: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1665,7 +1700,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC4: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1673,7 +1708,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_RECT2I: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Rect2i v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1681,7 +1716,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_UINT: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; uint32_t v = p_value; bv.x = v; bv.y = 0; @@ -1689,7 +1724,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC2: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1697,7 +1732,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC3: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1705,7 +1740,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC4: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1713,7 +1748,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_FLOAT: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; float v = p_value; bv.x = v; bv.y = 0; @@ -1721,7 +1756,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector2 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1729,7 +1764,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector3 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1737,7 +1772,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Plane v = p_value; bv.x = v.normal.x; bv.y = v.normal.y; @@ -1745,14 +1780,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.d; } break; case RS::GLOBAL_VAR_TYPE_COLOR: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Color v = p_value; bv.x = v.r; bv.y = v.g; bv.z = v.b; bv.w = v.a; - GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; + GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1]; v = v.srgb_to_linear(); bv_linear.x = v.r; bv_linear.y = v.g; @@ -1761,7 +1796,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_RECT2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Rect2 v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1769,7 +1804,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_MAT2: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 4) { m2.resize(4); @@ -1786,7 +1821,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT3: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Basis v = p_value; bv[0].x = v.rows[0][0]; bv[0].y = v.rows[1][0]; @@ -1805,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT4: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 16) { @@ -1834,7 +1869,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform2D v = p_value; bv[0].x = v.columns[0][0]; bv[0].y = v.columns[0][1]; @@ -1853,7 +1888,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform3D v = p_value; bv[0].x = v.basis.rows[0][0]; bv[0].y = v.basis.rows[1][0]; @@ -1882,15 +1917,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } } -void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { +void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { int32_t prev_chunk = -1; for (int32_t i = 0; i < p_elements; i++) { - int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; if (chunk != prev_chunk) { - if (!global_variables.buffer_dirty_regions[chunk]) { - global_variables.buffer_dirty_regions[chunk] = true; - global_variables.buffer_dirty_region_count++; + if (!global_shader_uniforms.buffer_dirty_regions[chunk]) { + global_shader_uniforms.buffer_dirty_regions[chunk] = true; + global_shader_uniforms.buffer_dirty_region_count++; } } @@ -1898,16 +1933,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_ } } -void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { - ERR_FAIL_COND(global_variables.variables.has(p_name)); - GlobalVariables::Variable gv; +void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) { + ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable gv; gv.type = p_type; gv.value = p_value; gv.buffer_index = -1; if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { //is texture - global_variables.must_update_texture_materials = true; //normally there are none + global_shader_uniforms.must_update_texture_materials = true; //normally there are none } else { gv.buffer_elements = 1; if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { @@ -1924,56 +1959,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa } //is vector, allocate in buffer and update index - gv.buffer_index = _global_variable_allocate(gv.buffer_elements); + gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements); ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); - global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - global_variables.must_update_buffer_materials = true; //normally there are none + global_shader_uniforms.must_update_buffer_materials = true; //normally there are none } - global_variables.variables[p_name] = gv; + global_shader_uniforms.variables[p_name] = gv; } -void MaterialStorage::global_variable_remove(const StringName &p_name) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) { + if (!global_shader_uniforms.variables.has(p_name)) { return; } - const GlobalVariables::Variable &gv = global_variables.variables[p_name]; + const GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; if (gv.buffer_index >= 0) { - global_variables.buffer_usage[gv.buffer_index].elements = 0; - global_variables.must_update_buffer_materials = true; + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0; + global_shader_uniforms.must_update_buffer_materials = true; } else { - global_variables.must_update_texture_materials = true; + global_shader_uniforms.must_update_texture_materials = true; } - global_variables.variables.erase(p_name); + global_shader_uniforms.variables.erase(p_name); } -Vector<StringName> MaterialStorage::global_variable_get_list() const { +Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } Vector<StringName> names; - for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) { names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; } -void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!global_variables.variables.has(p_name)); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; +void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.value = p_value; if (gv.override.get_type() == Variant::NIL) { if (gv.buffer_index >= 0) { //buffer - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1986,26 +2021,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } } -void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) { + if (!global_shader_uniforms.variables.has(p_name)) { return; //variable may not exist } ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.override = p_value; if (gv.buffer_index >= 0) { //buffer if (gv.override.get_type() == Variant::NIL) { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); } else { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override); } - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -2017,35 +2052,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } } -Variant MaterialStorage::global_variable_get(const StringName &p_name) const { +Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); } - if (!global_variables.variables.has(p_name)) { + if (!global_shader_uniforms.variables.has(p_name)) { return Variant(); } - return global_variables.variables[p_name].value; + return global_shader_uniforms.variables[p_name].value; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const { - if (!global_variables.variables.has(p_name)) { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const { + if (!global_shader_uniforms.variables.has(p_name)) { return RS::GLOBAL_VAR_TYPE_MAX; } - return global_variables.variables[p_name].type; + return global_shader_uniforms.variables[p_name].type; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); } - return global_variable_get_type_internal(p_name); + return global_shader_uniform_get_type_internal(p_name); } -void MaterialStorage::global_variables_load_settings(bool p_load_textures) { +void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) { List<PropertyInfo> settings; ProjectSettings::get_singleton()->get_property_list(&settings); @@ -2090,11 +2125,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { "samplerCube", }; - RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX; for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { if (global_var_type_names[i] == type) { - gvtype = RS::GlobalVariableType(i); + gvtype = RS::GlobalShaderUniformType(i); break; } } @@ -2116,47 +2151,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { value = resource; } - if (global_variables.variables.has(name)) { + if (global_shader_uniforms.variables.has(name)) { //has it, update it - global_variable_set(name, value); + global_shader_uniform_set(name, value); } else { - global_variable_add(name, gvtype, value); + global_shader_uniform_add(name, gvtype, value); } } } } -void MaterialStorage::global_variables_clear() { - global_variables.variables.clear(); //not right but for now enough +void MaterialStorage::global_shader_uniforms_clear() { + global_shader_uniforms.variables.clear(); //not right but for now enough } -RID MaterialStorage::global_variables_get_storage_buffer() const { - return global_variables.buffer; +RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const { + return global_shader_uniforms.buffer; } -int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) { - ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); - int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - global_variables.instance_buffer_pos[p_instance] = pos; //save anyway +int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) { + ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1); + int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); - global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; + global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; return pos; } -void MaterialStorage::global_variables_instance_free(RID p_instance) { - ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); - int32_t pos = global_variables.instance_buffer_pos[p_instance]; +void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) { + ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance)); + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos >= 0) { - global_variables.buffer_usage[pos].elements = 0; + global_shader_uniforms.buffer_usage[pos].elements = 0; } - global_variables.instance_buffer_pos.erase(p_instance); + global_shader_uniforms.instance_buffer_pos.erase(p_instance); } -void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { - if (!global_variables.instance_buffer_pos.has(p_instance)) { +void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) { + if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) { return; //just not allocated, ignore } - int32_t pos = global_variables.instance_buffer_pos[p_instance]; + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos < 0) { return; //again, not allocated, ignore @@ -2177,11 +2212,14 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind ShaderLanguage::TYPE_VEC3, // vec3 ShaderLanguage::TYPE_IVEC3, //vec3i ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //vec4 + ShaderLanguage::TYPE_IVEC4, //vec4i ShaderLanguage::TYPE_VEC4, //plane ShaderLanguage::TYPE_VEC4, //quat ShaderLanguage::TYPE_MAX, //aabb not supported here ShaderLanguage::TYPE_MAX, //basis not supported here ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_MAX, //projection not supported here ShaderLanguage::TYPE_VEC4 //color }; @@ -2191,57 +2229,57 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind pos += p_index; - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer - _global_variable_mark_buffer_dirty(pos, 1); + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos], true); //instances always use linear color in this renderer + _global_shader_uniform_mark_buffer_dirty(pos, 1); } -void MaterialStorage::_update_global_variables() { +void MaterialStorage::_update_global_shader_uniforms() { MaterialStorage *material_storage = MaterialStorage::get_singleton(); - if (global_variables.buffer_dirty_region_count > 0) { - uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (total_regions / global_variables.buffer_dirty_region_count <= 4) { + if (global_shader_uniforms.buffer_dirty_region_count > 0) { + uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; + if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) { // 25% of regions dirty, just update all buffer - RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); + RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions); } else { - uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; for (uint32_t i = 0; i < total_regions; i++) { - if (global_variables.buffer_dirty_regions[i]) { - RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); + if (global_shader_uniforms.buffer_dirty_regions[i]) { + RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]); - global_variables.buffer_dirty_regions[i] = false; + global_shader_uniforms.buffer_dirty_regions[i] = false; } } } - global_variables.buffer_dirty_region_count = 0; + global_shader_uniforms.buffer_dirty_region_count = 0; } - if (global_variables.must_update_buffer_materials) { + if (global_shader_uniforms.must_update_buffer_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_buffer) { + for (const RID &E : global_shader_uniforms.materials_using_buffer) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, true, false); } - global_variables.must_update_buffer_materials = false; + global_shader_uniforms.must_update_buffer_materials = false; } - if (global_variables.must_update_texture_materials) { + if (global_shader_uniforms.must_update_texture_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_texture) { + for (const RID &E : global_shader_uniforms.materials_using_texture) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, false, true); } - global_variables.must_update_texture_materials = false; + global_shader_uniforms.must_update_texture_materials = false; } } @@ -2341,6 +2379,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { + shader->data->set_path_hint(shader->path_hint); shader->data->set_code(p_code); } @@ -2351,17 +2390,27 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } } +void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->path_hint = p_path; + if (shader->data) { + shader->data->set_path_hint(p_path); + } +} + String MaterialStorage::shader_get_code(RID p_shader) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, String()); return shader->code; } -void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { +void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (shader->data) { - return shader->data->get_param_list(p_param_list); + return shader->data->get_shader_uniform_list(p_param_list); } } @@ -2534,6 +2583,15 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { _material_queue_update(material, true, true); } +MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_material) { + const MaterialStorage::Material *material = MaterialStorage::get_singleton()->get_material(p_material); + if (material && material->shader && material->shader->data) { + return material->shader->data; + } + + return nullptr; +} + void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); @@ -2614,14 +2672,14 @@ bool MaterialStorage::material_casts_shadows(RID p_material) { return true; //by default everything casts shadows } -void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { +void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); if (material->shader && material->shader->data) { material->shader->data->get_instance_param_list(r_parameters); if (material->next_pass.is_valid()) { - material_get_instance_shader_parameters(material->next_pass, r_parameters); + material_get_instance_shader_uniforms(material->next_pass, r_parameters); } } } @@ -2635,12 +2693,12 @@ void MaterialStorage::material_update_dependency(RID p_material, DependencyTrack } } -void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { +void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) { ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); material_data_request_func[p_shader_type] = p_function; } -MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { +MaterialStorage::MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr); return material_data_request_func[p_shader_type]; } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index e35d5e7669..dbf7a92e23 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -31,7 +31,7 @@ #ifndef MATERIAL_STORAGE_RD_H #define MATERIAL_STORAGE_RD_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" @@ -42,159 +42,62 @@ namespace RendererRD { -class MaterialStorage; - -/* SHADER Structs */ - -enum ShaderType { - SHADER_TYPE_2D, - SHADER_TYPE_3D, - SHADER_TYPE_PARTICLES, - SHADER_TYPE_SKY, - SHADER_TYPE_FOG, - SHADER_TYPE_MAX -}; - -struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; - - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; - virtual bool is_animated() const = 0; - virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; - virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - - virtual ~ShaderData() {} -}; - -typedef ShaderData *(*ShaderDataRequestFunction)(); - -struct Material; - -struct Shader { - ShaderData *data = nullptr; - String code; - ShaderType type; - HashMap<StringName, HashMap<int, RID>> default_texture_parameter; - HashSet<Material *> owners; -}; - -/* Material structs */ - -struct MaterialData { - void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - - virtual void set_render_priority(int p_priority) = 0; - virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; - virtual ~MaterialData(); - - //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void free_parameters_uniform_set(RID p_uniform_set); - -private: - friend class MaterialStorage; - RID self; - List<RID>::Element *global_buffer_E = nullptr; - List<RID>::Element *global_texture_E = nullptr; - uint64_t global_textures_pass = 0; - HashMap<StringName, uint64_t> used_global_textures; - - //internally by update_parameters_uniform_set - Vector<uint8_t> ubo_data; - RID uniform_buffer; - Vector<RID> texture_cache; -}; - -typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - -struct Material { - RID self; - MaterialData *data = nullptr; - Shader *shader = nullptr; - //shortcut to shader data and type - ShaderType shader_type = SHADER_TYPE_MAX; - uint32_t shader_id = 0; - bool uniform_dirty = false; - bool texture_dirty = false; - HashMap<StringName, Variant> params; - int32_t priority = 0; - RID next_pass; - SelfList<Material> update_element; - - Dependency dependency; - - Material() : - update_element(this) {} -}; - -/* Global variable structs */ -struct GlobalVariables { - enum { - BUFFER_DIRTY_REGION_SIZE = 1024 - }; - struct Variable { - HashSet<RID> texture_materials; // materials using this - - RS::GlobalVariableType type; - Variant value; - Variant override; - int32_t buffer_index; //for vectors - int32_t buffer_elements; //for vectors +class MaterialStorage : public RendererMaterialStorage { +public: + enum ShaderType { + SHADER_TYPE_2D, + SHADER_TYPE_3D, + SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, + SHADER_TYPE_FOG, + SHADER_TYPE_MAX }; - HashMap<StringName, Variable> variables; - - struct Value { - float x; - float y; - float z; - float w; - }; + struct ShaderData { + virtual void set_code(const String &p_Code) = 0; + virtual void set_path_hint(const String &p_hint) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0; - struct ValueInt { - int32_t x; - int32_t y; - int32_t z; - int32_t w; - }; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; + virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_animated() const = 0; + virtual bool casts_shadows() const = 0; + virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - struct ValueUInt { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; + virtual ~ShaderData() {} }; - struct ValueUsage { - uint32_t elements = 0; - }; + struct MaterialData { + void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - List<RID> materials_using_buffer; - List<RID> materials_using_texture; + virtual void set_render_priority(int p_priority) = 0; + virtual void set_next_pass(RID p_pass) = 0; + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual ~MaterialData(); - RID buffer; - Value *buffer_values = nullptr; - ValueUsage *buffer_usage = nullptr; - bool *buffer_dirty_regions = nullptr; - uint32_t buffer_dirty_region_count = 0; + //to be used internally by update_parameters, in the most common configuration of material parameters + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void free_parameters_uniform_set(RID p_uniform_set); - uint32_t buffer_size; + private: + friend class MaterialStorage; - bool must_update_texture_materials = false; - bool must_update_buffer_materials = false; + RID self; + List<RID>::Element *global_buffer_E = nullptr; + List<RID>::Element *global_texture_E = nullptr; + uint64_t global_textures_pass = 0; + HashMap<StringName, uint64_t> used_global_textures; - HashMap<RID, int32_t> instance_buffer_pos; -}; + //internally by update_parameters_uniform_set + Vector<uint8_t> ubo_data; + RID uniform_buffer; + Vector<RID> texture_cache; + }; -class MaterialStorage : public RendererMaterialStorage { private: - friend struct MaterialData; static MaterialStorage *singleton; /* Samplers */ @@ -207,22 +110,116 @@ private: RID quad_index_buffer; RID quad_index_array; - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ + + struct GlobalShaderUniforms { + enum { + BUFFER_DIRTY_REGION_SIZE = 1024 + }; + struct Variable { + HashSet<RID> texture_materials; // materials using this + + RS::GlobalShaderUniformType type; + Variant value; + Variant override; + int32_t buffer_index; //for vectors + int32_t buffer_elements; //for vectors + }; + + HashMap<StringName, Variable> variables; + + struct Value { + float x; + float y; + float z; + float w; + }; + + struct ValueInt { + int32_t x; + int32_t y; + int32_t z; + int32_t w; + }; + + struct ValueUInt { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + }; + + struct ValueUsage { + uint32_t elements = 0; + }; + + List<RID> materials_using_buffer; + List<RID> materials_using_texture; + + RID buffer; + Value *buffer_values = nullptr; + ValueUsage *buffer_usage = nullptr; + bool *buffer_dirty_regions = nullptr; + uint32_t buffer_dirty_region_count = 0; + + uint32_t buffer_size; + + bool must_update_texture_materials = false; + bool must_update_buffer_materials = false; + + HashMap<RID, int32_t> instance_buffer_pos; + } global_shader_uniforms; + + int32_t _global_shader_uniform_allocate(uint32_t p_elements); + void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value); + void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements); - GlobalVariables global_variables; + /* SHADER API */ - int32_t _global_variable_allocate(uint32_t p_elements); - void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); - void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); + struct Material; - /* SHADER API */ + struct Shader { + ShaderData *data = nullptr; + String code; + String path_hint; + ShaderType type; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + HashSet<Material *> owners; + }; + typedef ShaderData *(*ShaderDataRequestFunction)(); ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Shader, true> shader_owner; + Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); } /* MATERIAL API */ + + typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); + + struct Material { + RID self; + MaterialData *data = nullptr; + Shader *shader = nullptr; + //shortcut to shader data and type + ShaderType shader_type = SHADER_TYPE_MAX; + uint32_t shader_id = 0; + bool uniform_dirty = false; + bool texture_dirty = false; + HashMap<StringName, Variant> params; + int32_t priority = 0; + RID next_pass; + SelfList<Material> update_element; + + Dependency dependency; + + Material() : + update_element(this) {} + }; + MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner<Material, true> material_owner; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; SelfList<Material>::List material_update_list; @@ -300,7 +297,7 @@ public: p_array[11] = p_mtx.origin.z; } - static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { p_array[i * 4 + j] = p_mtx.matrix[i][j]; @@ -331,32 +328,31 @@ public: RID get_quad_index_array() { return quad_index_array; } - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - void _update_global_variables(); + void _update_global_shader_uniforms(); - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override; - virtual void global_variable_remove(const StringName &p_name) override; - virtual Vector<StringName> global_variable_get_list() const override; + virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override; + virtual void global_shader_uniform_remove(const StringName &p_name) override; + virtual Vector<StringName> global_shader_uniform_get_list() const override; - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override; - virtual Variant global_variable_get(const StringName &p_name) const override; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override; - RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_shader_uniform_get(const StringName &p_name) const override; + virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override; + RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const; - virtual void global_variables_load_settings(bool p_load_textures = true) override; - virtual void global_variables_clear() override; + virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override; + virtual void global_shader_uniforms_clear() override; - virtual int32_t global_variables_instance_allocate(RID p_instance) override; - virtual void global_variables_instance_free(RID p_instance) override; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override; + virtual void global_shader_uniforms_instance_free(RID p_instance) override; + virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override; - RID global_variables_get_storage_buffer() const; + RID global_shader_uniforms_get_storage_buffer() const; /* SHADER API */ - Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }; bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; virtual RID shader_allocate() override; @@ -364,8 +360,9 @@ public: virtual void shader_free(RID p_rid) override; virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) override; virtual String shader_get_code(RID p_shader) const override; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; + virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; @@ -376,7 +373,6 @@ public: /* MATERIAL API */ - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; void _material_queue_update(Material *material, bool p_uniform, bool p_texture); @@ -387,6 +383,7 @@ public: virtual void material_free(RID p_rid) override; virtual void material_set_shader(RID p_material, RID p_shader) override; + ShaderData *material_get_shader_data(RID p_material); virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override; virtual Variant material_get_param(RID p_material, const StringName &p_param) const override; @@ -397,7 +394,7 @@ public: virtual bool material_is_animated(RID p_material) override; virtual bool material_casts_shadows(RID p_material) override; - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; + virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override; @@ -421,4 +418,4 @@ public: } // namespace RendererRD -#endif // !MATERIAL_STORAGE_RD_H +#endif // MATERIAL_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 3875eb6615..dc3f35f942 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -758,6 +758,13 @@ bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); } +Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + + return &mesh->dependency; +} + /* MESH INSTANCE */ RID MeshStorage::mesh_instance_create(RID p_base) { @@ -1473,6 +1480,13 @@ RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { return multimesh->mesh; } +Dependency *MeshStorage::multimesh_get_dependency(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, nullptr); + + return &multimesh->dependency; +} + Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform3D()); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 9cdda6bfca..5c0d019c15 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -40,240 +40,151 @@ namespace RendererRD { -/* Mesh */ - -enum DefaultRDBuffer { - DEFAULT_RD_BUFFER_VERTEX, - DEFAULT_RD_BUFFER_NORMAL, - DEFAULT_RD_BUFFER_TANGENT, - DEFAULT_RD_BUFFER_COLOR, - DEFAULT_RD_BUFFER_TEX_UV, - DEFAULT_RD_BUFFER_TEX_UV2, - DEFAULT_RD_BUFFER_CUSTOM0, - DEFAULT_RD_BUFFER_CUSTOM1, - DEFAULT_RD_BUFFER_CUSTOM2, - DEFAULT_RD_BUFFER_CUSTOM3, - DEFAULT_RD_BUFFER_BONES, - DEFAULT_RD_BUFFER_WEIGHTS, - DEFAULT_RD_BUFFER_MAX, -}; +class MeshStorage : public RendererMeshStorage { +public: + enum DefaultRDBuffer { + DEFAULT_RD_BUFFER_VERTEX, + DEFAULT_RD_BUFFER_NORMAL, + DEFAULT_RD_BUFFER_TANGENT, + DEFAULT_RD_BUFFER_COLOR, + DEFAULT_RD_BUFFER_TEX_UV, + DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_CUSTOM0, + DEFAULT_RD_BUFFER_CUSTOM1, + DEFAULT_RD_BUFFER_CUSTOM2, + DEFAULT_RD_BUFFER_CUSTOM3, + DEFAULT_RD_BUFFER_BONES, + DEFAULT_RD_BUFFER_WEIGHTS, + DEFAULT_RD_BUFFER_MAX, + }; -struct MeshInstance; - -struct Mesh { - struct Surface { - RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; - uint32_t format = 0; - - RID vertex_buffer; - RID attribute_buffer; - RID skin_buffer; - uint32_t vertex_count = 0; - uint32_t vertex_buffer_size = 0; - uint32_t skin_buffer_size = 0; - - // A different pipeline needs to be allocated - // depending on the inputs available in the - // material. - // There are never that many geometry/material - // combinations, so a simple array is the most - // cache-efficient structure. - - struct Version { - uint32_t input_mask = 0; - RD::VertexFormatID vertex_format = 0; - RID vertex_array; - }; +private: + static MeshStorage *singleton; - SpinLock version_lock; //needed to access versions - Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; + RID default_rd_storage_buffer; - RID index_buffer; - RID index_array; - uint32_t index_count = 0; + /* Mesh */ - struct LOD { - float edge_length = 0.0; - uint32_t index_count = 0; - RID index_buffer; - RID index_array; - }; + RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - LOD *lods = nullptr; - uint32_t lod_count = 0; + struct MeshInstance; + + struct Mesh { + struct Surface { + RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; + uint32_t format = 0; + + RID vertex_buffer; + RID attribute_buffer; + RID skin_buffer; + uint32_t vertex_count = 0; + uint32_t vertex_buffer_size = 0; + uint32_t skin_buffer_size = 0; + + // A different pipeline needs to be allocated + // depending on the inputs available in the + // material. + // There are never that many geometry/material + // combinations, so a simple array is the most + // cache-efficient structure. + + struct Version { + uint32_t input_mask = 0; + RD::VertexFormatID vertex_format = 0; + RID vertex_array; + }; + + SpinLock version_lock; //needed to access versions + Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; - AABB aabb; + RID index_buffer; + RID index_array; + uint32_t index_count = 0; - Vector<AABB> bone_aabbs; + struct LOD { + float edge_length = 0.0; + uint32_t index_count = 0; + RID index_buffer; + RID index_array; + }; - RID blend_shape_buffer; + LOD *lods = nullptr; + uint32_t lod_count = 0; - RID material; + AABB aabb; - uint32_t render_index = 0; - uint64_t render_pass = 0; + Vector<AABB> bone_aabbs; - uint32_t multimesh_render_index = 0; - uint64_t multimesh_render_pass = 0; + RID blend_shape_buffer; - uint32_t particles_render_index = 0; - uint64_t particles_render_pass = 0; + RID material; - RID uniform_set; - }; + uint32_t render_index = 0; + uint64_t render_pass = 0; - uint32_t blend_shape_count = 0; - RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; + uint32_t multimesh_render_index = 0; + uint64_t multimesh_render_pass = 0; - Surface **surfaces = nullptr; - uint32_t surface_count = 0; + uint32_t particles_render_index = 0; + uint64_t particles_render_pass = 0; - Vector<AABB> bone_aabbs; + RID uniform_set; + }; - bool has_bone_weights = false; + uint32_t blend_shape_count = 0; + RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; - AABB aabb; - AABB custom_aabb; + Surface **surfaces = nullptr; + uint32_t surface_count = 0; - Vector<RID> material_cache; + Vector<AABB> bone_aabbs; - List<MeshInstance *> instances; + bool has_bone_weights = false; - RID shadow_mesh; - HashSet<Mesh *> shadow_owners; + AABB aabb; + AABB custom_aabb; - Dependency dependency; -}; + Vector<RID> material_cache; -/* Mesh Instance */ + List<MeshInstance *> instances; -struct MeshInstance { - Mesh *mesh = nullptr; - RID skeleton; - struct Surface { - RID vertex_buffer; - RID uniform_set; + RID shadow_mesh; + HashSet<Mesh *> shadow_owners; - Mesh::Surface::Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; + Dependency dependency; }; - LocalVector<Surface> surfaces; - LocalVector<float> blend_weights; - - RID blend_weights_buffer; - List<MeshInstance *>::Element *I = nullptr; //used to erase itself - uint64_t skeleton_version = 0; - bool dirty = false; - bool weights_dirty = false; - SelfList<MeshInstance> weight_update_list; - SelfList<MeshInstance> array_update_list; - MeshInstance() : - weight_update_list(this), array_update_list(this) {} -}; - -/* MultiMesh */ - -struct MultiMesh { - RID mesh; - int instances = 0; - RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; - bool uses_colors = false; - bool uses_custom_data = false; - int visible_instances = -1; - AABB aabb; - bool aabb_dirty = false; - bool buffer_set = false; - uint32_t stride_cache = 0; - uint32_t color_offset_cache = 0; - uint32_t custom_data_offset_cache = 0; - - Vector<float> data_cache; //used if individual setting is used - bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; - - RID buffer; //storage buffer - RID uniform_set_3d; - RID uniform_set_2d; - - bool dirty = false; - MultiMesh *dirty_list = nullptr; - - Dependency dependency; -}; -/* Skeleton */ - -struct SkeletonShader { - struct PushConstant { - uint32_t has_normal; - uint32_t has_tangent; - uint32_t has_skeleton; - uint32_t has_blend_shape; + mutable RID_Owner<Mesh, true> mesh_owner; - uint32_t vertex_count; - uint32_t vertex_stride; - uint32_t skin_stride; - uint32_t skin_weight_offset; + /* Mesh Instance API */ - uint32_t blend_shape_count; - uint32_t normalized_blend_shapes; - uint32_t pad0; - uint32_t pad1; - }; + struct MeshInstance { + Mesh *mesh = nullptr; + RID skeleton; + struct Surface { + RID vertex_buffer; + RID uniform_set; - enum { - UNIFORM_SET_INSTANCE = 0, - UNIFORM_SET_SURFACE = 1, - UNIFORM_SET_SKELETON = 2, - }; - enum { - SHADER_MODE_2D, - SHADER_MODE_3D, - SHADER_MODE_MAX + Mesh::Surface::Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + }; + LocalVector<Surface> surfaces; + LocalVector<float> blend_weights; + + RID blend_weights_buffer; + List<MeshInstance *>::Element *I = nullptr; //used to erase itself + uint64_t skeleton_version = 0; + bool dirty = false; + bool weights_dirty = false; + SelfList<MeshInstance> weight_update_list; + SelfList<MeshInstance> array_update_list; + MeshInstance() : + weight_update_list(this), array_update_list(this) {} }; - SkeletonShaderRD shader; - RID version; - RID version_shader[SHADER_MODE_MAX]; - RID pipeline[SHADER_MODE_MAX]; - - RID default_skeleton_uniform_set; -}; - -struct Skeleton { - bool use_2d = false; - int size = 0; - Vector<float> data; - RID buffer; - - bool dirty = false; - Skeleton *dirty_list = nullptr; - Transform2D base_transform_2d; - - RID uniform_set_3d; - RID uniform_set_mi; - - uint64_t version = 1; - - Dependency dependency; -}; - -class MeshStorage : public RendererMeshStorage { -private: - static MeshStorage *singleton; - - RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - RID default_rd_storage_buffer; - - /* Mesh */ - - mutable RID_Owner<Mesh, true> mesh_owner; - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); - /* Mesh Instance API */ - void _mesh_instance_clear(MeshInstance *mi); void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); @@ -284,6 +195,34 @@ private: /* MultiMesh */ + struct MultiMesh { + RID mesh; + int instances = 0; + RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + Vector<float> data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + RID uniform_set_2d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + Dependency dependency; + }; + mutable RID_Owner<MultiMesh, true> multimesh_owner; MultiMesh *multimesh_dirty_list = nullptr; @@ -295,7 +234,60 @@ private: /* Skeleton */ - SkeletonShader skeleton_shader; + struct SkeletonShader { + struct PushConstant { + uint32_t has_normal; + uint32_t has_tangent; + uint32_t has_skeleton; + uint32_t has_blend_shape; + + uint32_t vertex_count; + uint32_t vertex_stride; + uint32_t skin_stride; + uint32_t skin_weight_offset; + + uint32_t blend_shape_count; + uint32_t normalized_blend_shapes; + uint32_t pad0; + uint32_t pad1; + }; + + enum { + UNIFORM_SET_INSTANCE = 0, + UNIFORM_SET_SURFACE = 1, + UNIFORM_SET_SKELETON = 2, + }; + enum { + SHADER_MODE_2D, + SHADER_MODE_3D, + SHADER_MODE_MAX + }; + + SkeletonShaderRD shader; + RID version; + RID version_shader[SHADER_MODE_MAX]; + RID pipeline[SHADER_MODE_MAX]; + + RID default_skeleton_uniform_set; + } skeleton_shader; + + struct Skeleton { + bool use_2d = false; + int size = 0; + Vector<float> data; + RID buffer; + + bool dirty = false; + Skeleton *dirty_list = nullptr; + Transform2D base_transform_2d; + + RID uniform_set_3d; + RID uniform_set_mi; + + uint64_t version = 1; + + Dependency dependency; + }; mutable RID_Owner<Skeleton, true> skeleton_owner; @@ -309,11 +301,10 @@ public: MeshStorage(); virtual ~MeshStorage(); - RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } + RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; } /* MESH API */ - Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }; bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; virtual RID mesh_allocate() override; @@ -542,10 +533,11 @@ public: return s->particles_render_index; } + Dependency *mesh_get_dependency(RID p_mesh) const; + /* MESH INSTANCE API */ - MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; - bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }; virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -556,7 +548,6 @@ public: /* MULTIMESH API */ - MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; virtual RID multimesh_allocate() override; @@ -654,10 +645,11 @@ public: return multimesh->uniform_set_2d; } + Dependency *multimesh_get_dependency(RID p_multimesh) const; + /* SKELETON API */ - Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; - bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }; virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_skeleton) override; @@ -703,4 +695,4 @@ public: } // namespace RendererRD -#endif // !MESH_STORAGE_RD_H +#endif // MESH_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 5200e0d318..ba644e7eb9 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -54,8 +54,8 @@ ParticlesStorage::ParticlesStorage() { particles_modes.push_back(""); particles_shader.shader.initialize(particles_modes, String()); } - MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); - MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + MaterialStorage::get_singleton()->shader_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); + MaterialStorage::get_singleton()->material_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -112,7 +112,7 @@ ParticlesStorage::ParticlesStorage() { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; particles_shader.compiler.initialize(actions); } @@ -134,7 +134,7 @@ void process() { material_storage->material_initialize(particles_shader.default_material); material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); + ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -164,7 +164,7 @@ void process() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(material_storage->global_variables_get_storage_buffer()); + u.append_id(material_storage->global_shader_uniforms_get_storage_buffer()); uniforms.push_back(u); } @@ -987,14 +987,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; if (i < collision_3d_textures_used) { - Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); - if (t && t->type == Texture::TYPE_3D) { - rd_tex = t->rd_texture; + if (TextureStorage::get_singleton()->texture_get_type(collision_3d_textures[i]) == TextureStorage::TYPE_3D) { + rd_tex = TextureStorage::get_singleton()->texture_get_rd_texture(collision_3d_textures[i]); } } if (rd_tex == RID()) { - rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_tex = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(rd_tex); } @@ -1007,7 +1006,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (collision_heightmap_texture.is_valid()) { u.append_id(collision_heightmap_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); } @@ -1073,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES)); + ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); if (!m) { - m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); + m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -1228,10 +1227,10 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p void ParticlesStorage::_particles_update_buffers(Particles *particles) { uint32_t userdata_count = 0; - const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material); - if (material && material->shader && material->shader->data) { - const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); - userdata_count = shader_data->userdata_count; + MaterialStorage::ShaderData *shader_data = MaterialStorage::get_singleton()->material_get_shader_data(particles->process_material); + if (shader_data) { + const ParticlesShaderData *particle_shader_data = static_cast<const ParticlesShaderData *>(shader_data); + userdata_count = particle_shader_data->userdata_count; } if (userdata_count != particles->userdata_count) { @@ -1503,6 +1502,13 @@ void ParticlesStorage::update_particles() { } } +Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const { + Particles *particles = particles_owner.get_or_null(p_particles); + ERR_FAIL_NULL_V(particles, nullptr); + + return &particles->dependency; +} + bool ParticlesStorage::particles_is_inactive(RID p_particles) const { ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); const Particles *particles = particles_owner.get_or_null(p_particles); @@ -1512,6 +1518,9 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const { /* Particles SHADER */ +void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) { + path = p_path; +} void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { ParticlesStorage *particles_storage = ParticlesStorage::get_singleton(); //compile @@ -1594,7 +1603,7 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri } } -void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void ParticlesStorage::ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -1609,7 +1618,22 @@ void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -1667,7 +1691,7 @@ ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() { } } -ShaderData *ParticlesStorage::_create_particles_shader_func() { +MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { ParticlesShaderData *shader_data = memnew(ParticlesShaderData); return shader_data; } @@ -1680,7 +1704,7 @@ ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { free_parameters_uniform_set(uniform_set); } -MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { +MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -1866,6 +1890,15 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; } +Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const { + ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision); + ERR_FAIL_NULL_V(pc, nullptr); + + return &pc->dependency; +} + +/* Particles collision instance */ + RID ParticlesStorage::particles_collision_instance_create(RID p_collision) { ParticlesCollisionInstance pci; pci.collision = p_collision; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 70ac6f0349..97d100e2da 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -43,231 +43,203 @@ namespace RendererRD { -/* PARTICLES */ - -struct ParticleData { - float xform[16]; - float velocity[3]; - uint32_t active; - float color[4]; - float custom[3]; - float lifetime; -}; +class ParticlesStorage : public RendererParticlesStorage { +private: + static ParticlesStorage *singleton; -struct ParticlesFrameParams { - enum { - MAX_ATTRACTORS = 32, - MAX_COLLIDERS = 32, - MAX_3D_TEXTURES = 7 - }; + /* PARTICLES */ - enum AttractorType { - ATTRACTOR_TYPE_SPHERE, - ATTRACTOR_TYPE_BOX, - ATTRACTOR_TYPE_VECTOR_FIELD, + struct ParticleData { + float xform[16]; + float velocity[3]; + uint32_t active; + float color[4]; + float custom[3]; + float lifetime; }; - struct Attractor { - float transform[16]; - float extents[3]; //exents or radius - uint32_t type; + struct ParticlesFrameParams { + enum { + MAX_ATTRACTORS = 32, + MAX_COLLIDERS = 32, + MAX_3D_TEXTURES = 7 + }; - uint32_t texture_index; //texture index for vector field - float strength; - float attenuation; - float directionality; - }; + enum AttractorType { + ATTRACTOR_TYPE_SPHERE, + ATTRACTOR_TYPE_BOX, + ATTRACTOR_TYPE_VECTOR_FIELD, + }; - enum CollisionType { - COLLISION_TYPE_SPHERE, - COLLISION_TYPE_BOX, - COLLISION_TYPE_SDF, - COLLISION_TYPE_HEIGHT_FIELD, - COLLISION_TYPE_2D_SDF, + struct Attractor { + float transform[16]; + float extents[3]; //exents or radius + uint32_t type; - }; + uint32_t texture_index; //texture index for vector field + float strength; + float attenuation; + float directionality; + }; - struct Collider { - float transform[16]; - float extents[3]; //exents or radius - uint32_t type; + enum CollisionType { + COLLISION_TYPE_SPHERE, + COLLISION_TYPE_BOX, + COLLISION_TYPE_SDF, + COLLISION_TYPE_HEIGHT_FIELD, + COLLISION_TYPE_2D_SDF, - uint32_t texture_index; //texture index for vector field - real_t scale; - uint32_t pad[2]; - }; + }; - uint32_t emitting; - float system_phase; - float prev_system_phase; - uint32_t cycle; + struct Collider { + float transform[16]; + float extents[3]; //exents or radius + uint32_t type; - real_t explosiveness; - real_t randomness; - float time; - float delta; + uint32_t texture_index; //texture index for vector field + real_t scale; + uint32_t pad[2]; + }; - uint32_t frame; - uint32_t pad0; - uint32_t pad1; - uint32_t pad2; + uint32_t emitting; + float system_phase; + float prev_system_phase; + uint32_t cycle; - uint32_t random_seed; - uint32_t attractor_count; - uint32_t collider_count; - float particle_size; + real_t explosiveness; + real_t randomness; + float time; + float delta; - float emission_transform[16]; + uint32_t frame; + uint32_t pad0; + uint32_t pad1; + uint32_t pad2; - Attractor attractors[MAX_ATTRACTORS]; - Collider colliders[MAX_COLLIDERS]; -}; + uint32_t random_seed; + uint32_t attractor_count; + uint32_t collider_count; + float particle_size; -struct ParticleEmissionBufferData { -}; + float emission_transform[16]; -struct ParticleEmissionBuffer { - struct Data { - float xform[16]; - float velocity[3]; - uint32_t flags; - float color[4]; - float custom[4]; + Attractor attractors[MAX_ATTRACTORS]; + Collider colliders[MAX_COLLIDERS]; }; - 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 { - RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; - bool inactive = true; - double inactive_time = 0.0; - bool emitting = false; - bool one_shot = false; - int amount = 0; - double lifetime = 1.0; - double pre_process_time = 0.0; - real_t explosiveness = 0.0; - real_t randomness = 0.0; - bool restart_request = false; - AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); - bool use_local_coords = true; - bool has_collision_cache = false; - - bool has_sdf_collision = false; - Transform2D sdf_collision_transform; - Rect2 sdf_collision_to_screen; - RID sdf_collision_texture; - - RID process_material; - uint32_t frame_counter = 0; - RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; - - RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; - - Vector<RID> draw_passes; - Vector<Transform3D> trail_bind_poses; - bool trail_bind_poses_dirty = false; - RID trail_bind_pose_buffer; - RID trail_bind_pose_uniform_set; - - RID particle_buffer; - RID particle_instance_buffer; - RID frame_params_buffer; - - uint32_t userdata_count = 0; - - RID particles_material_uniform_set; - RID particles_copy_uniform_set; - RID particles_transforms_buffer_uniform_set; - RID collision_textures_uniform_set; - - RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; - uint32_t collision_3d_textures_used = 0; - RID collision_heightmap_texture; + struct ParticleEmissionBufferData { + }; - RID particles_sort_buffer; - RID particles_sort_uniform_set; + struct ParticleEmissionBuffer { + struct Data { + float xform[16]; + float velocity[3]; + uint32_t flags; + float color[4]; + float custom[4]; + }; - bool dirty = false; - Particles *update_list = nullptr; + 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++ + }; - RID sub_emitter; + struct Particles { + RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; + bool inactive = true; + double inactive_time = 0.0; + bool emitting = false; + bool one_shot = false; + int amount = 0; + double lifetime = 1.0; + double pre_process_time = 0.0; + real_t explosiveness = 0.0; + real_t randomness = 0.0; + bool restart_request = false; + AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); + bool use_local_coords = false; + bool has_collision_cache = false; + + bool has_sdf_collision = false; + Transform2D sdf_collision_transform; + Rect2 sdf_collision_to_screen; + RID sdf_collision_texture; + + RID process_material; + uint32_t frame_counter = 0; + RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; + + RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; + + Vector<RID> draw_passes; + Vector<Transform3D> trail_bind_poses; + bool trail_bind_poses_dirty = false; + RID trail_bind_pose_buffer; + RID trail_bind_pose_uniform_set; + + RID particle_buffer; + RID particle_instance_buffer; + RID frame_params_buffer; - double phase = 0.0; - double prev_phase = 0.0; - uint64_t prev_ticks = 0; - uint32_t random_seed = 0; + uint32_t userdata_count = 0; - uint32_t cycle_number = 0; + RID particles_material_uniform_set; + RID particles_copy_uniform_set; + RID particles_transforms_buffer_uniform_set; + RID collision_textures_uniform_set; - double speed_scale = 1.0; + RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; + uint32_t collision_3d_textures_used = 0; + RID collision_heightmap_texture; - int fixed_fps = 30; - bool interpolate = true; - bool fractional_delta = false; - double frame_remainder = 0; - real_t collision_base_size = 0.01; + RID particles_sort_buffer; + RID particles_sort_uniform_set; - bool clear = true; + bool dirty = false; + Particles *update_list = nullptr; - bool force_sub_emit = false; + RID sub_emitter; - Transform3D emission_transform; + double phase = 0.0; + double prev_phase = 0.0; + uint64_t prev_ticks = 0; + uint32_t random_seed = 0; - Vector<uint8_t> emission_buffer_data; + uint32_t cycle_number = 0; - ParticleEmissionBuffer *emission_buffer = nullptr; - RID emission_storage_buffer; + double speed_scale = 1.0; - HashSet<RID> collisions; + int fixed_fps = 30; + bool interpolate = true; + bool fractional_delta = false; + double frame_remainder = 0; + real_t collision_base_size = 0.01; - Dependency dependency; + bool clear = true; - double trail_length = 1.0; - bool trails_enabled = false; - LocalVector<ParticlesFrameParams> frame_history; - LocalVector<ParticlesFrameParams> trail_params; + bool force_sub_emit = false; - Particles() { - } -}; + Transform3D emission_transform; -/* Particles Collision */ + Vector<uint8_t> emission_buffer_data; -struct ParticlesCollision { - RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; - uint32_t cull_mask = 0xFFFFFFFF; - float radius = 1.0; - Vector3 extents = Vector3(1, 1, 1); - float attractor_strength = 1.0; - float attractor_attenuation = 1.0; - float attractor_directionality = 0.0; - RID field_texture; - RID heightfield_texture; - RID heightfield_fb; - Size2i heightfield_fb_size; + ParticleEmissionBuffer *emission_buffer = nullptr; + RID emission_storage_buffer; - RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; + HashSet<RID> collisions; - Dependency dependency; -}; + Dependency dependency; -struct ParticlesCollisionInstance { - RID collision; - Transform3D transform; - bool active = false; -}; + double trail_length = 1.0; + bool trails_enabled = false; + LocalVector<ParticlesFrameParams> frame_history; + LocalVector<ParticlesFrameParams> trail_params; -class ParticlesStorage : public RendererParticlesStorage { -private: - static ParticlesStorage *singleton; - - /* PARTICLES */ + Particles() { + } + }; void _particles_process(Particles *p_particles, double p_delta); void _particles_allocate_emission_buffer(Particles *particles); @@ -340,7 +312,7 @@ private: /* Particle Shader */ - struct ParticlesShaderData : public ShaderData { + struct ParticlesShaderData : public MaterialStorage::ShaderData { bool valid = false; RID version; bool uses_collision = false; @@ -363,8 +335,9 @@ private: uint32_t userdata_count = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_hint); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; @@ -376,12 +349,12 @@ private: virtual ~ParticlesShaderData(); }; - ShaderData *_create_particles_shader_func(); - static ShaderData *_create_particles_shader_funcs() { + MaterialStorage::ShaderData *_create_particles_shader_func(); + static MaterialStorage::ShaderData *_create_particles_shader_funcs() { return ParticlesStorage::get_singleton()->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialData { + struct ParticlesMaterialData : public MaterialStorage::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; @@ -391,13 +364,37 @@ private: virtual ~ParticlesMaterialData(); }; - MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); - static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { + MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); + static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) { return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); } /* Particles Collision */ + struct ParticlesCollision { + RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; + uint32_t cull_mask = 0xFFFFFFFF; + float radius = 1.0; + Vector3 extents = Vector3(1, 1, 1); + float attractor_strength = 1.0; + float attractor_attenuation = 1.0; + float attractor_directionality = 0.0; + RID field_texture; + RID heightfield_texture; + RID heightfield_fb; + Size2i heightfield_fb_size; + + RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; + + Dependency dependency; + }; + + struct ParticlesCollisionInstance { + RID collision; + Transform3D transform; + bool active = false; + }; + mutable RID_Owner<ParticlesCollision, true> particles_collision_owner; mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; @@ -410,7 +407,6 @@ public: /* PARTICLES */ - Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); } bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } virtual RID particles_allocate() override; @@ -525,9 +521,10 @@ public: virtual void update_particles() override; + Dependency *particles_get_dependency(RID p_particles) const; + /* Particles Collision */ - ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); } bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); } virtual RID particles_collision_allocate() override; @@ -549,8 +546,9 @@ public: virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + Dependency *particles_collision_get_dependency(RID p_particles) const; + //used from 2D and 3D - ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); } bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); } virtual RID particles_collision_instance_create(RID p_collision) override; @@ -561,4 +559,4 @@ public: } // namespace RendererRD -#endif // !PARTICLES_STORAGE_RD_H +#endif // PARTICLES_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 1109357a74..e20a04ff2a 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -35,9 +35,9 @@ using namespace RendererRD; /////////////////////////////////////////////////////////////////////////// -// CanvasTexture +// TextureStorage::CanvasTexture -void CanvasTexture::clear_sets() { +void TextureStorage::CanvasTexture::clear_sets() { if (cleared_cache) { return; } @@ -52,14 +52,14 @@ void CanvasTexture::clear_sets() { cleared_cache = true; } -CanvasTexture::~CanvasTexture() { +TextureStorage::CanvasTexture::~CanvasTexture() { clear_sets(); } /////////////////////////////////////////////////////////////////////////// -// Texture +// TextureStorage::Texture -void Texture::cleanup() { +void TextureStorage::Texture::cleanup() { if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) { //erase this first, as it's a dependency of the one below RD::get_singleton()->free(rd_texture_srgb); @@ -96,6 +96,7 @@ TextureStorage::TextureStorage() { Vector<uint8_t> pv; pv.resize(16 * 4); for (int i = 0; i < 16; i++) { + // Opaque white. pv.set(i * 4 + 0, 255); pv.set(i * 4 + 1, 255); pv.set(i * 4 + 2, 255); @@ -109,6 +110,7 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Opaque black. pv.set(i * 4 + 0, 0); pv.set(i * 4 + 1, 0); pv.set(i * 4 + 2, 0); @@ -122,6 +124,21 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Transparent black. + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_TRANSPARENT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + // Opaque normal map "flat" color. pv.set(i * 4 + 0, 128); pv.set(i * 4 + 1, 128); pv.set(i * 4 + 2, 255); @@ -135,6 +152,7 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Opaque flowmap "flat" color. pv.set(i * 4 + 0, 255); pv.set(i * 4 + 1, 128); pv.set(i * 4 + 2, 255); @@ -191,7 +209,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap + { //create default black cubemap array RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -219,7 +237,35 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap array + { //create default white cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default black cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -247,7 +293,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap white array + { //create default white cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -349,7 +395,6 @@ TextureStorage::TextureStorage() { Vector<uint8_t> pv; pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { pv.set(i * 4 + 0, 0); pv.set(i * 4 + 1, 0); @@ -358,7 +403,6 @@ TextureStorage::TextureStorage() { } { - //take the chance and initialize decal atlas to something Vector<Vector<uint8_t>> vpv; vpv.push_back(pv); decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); @@ -366,6 +410,28 @@ TextureStorage::TextureStorage() { } } + { //create default VRS + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8_UINT; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(4 * 4); + for (int i = 0; i < 4 * 4; i++) { + pv.set(i, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + { Vector<String> sdf_modes; sdf_modes.push_back("\n#define MODE_LOAD\n"); @@ -486,7 +552,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte ct = t->canvas_texture; } else { - ct = get_canvas_texture(p_texture); + ct = canvas_texture_owner.get_or_null(p_texture); } if (!ct) { @@ -609,7 +675,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im Texture texture; - texture.type = Texture::TYPE_2D; + texture.type = TextureStorage::TYPE_2D; texture.width = p_image->get_width(); texture.height = p_image->get_height(); @@ -705,7 +771,7 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R Texture texture; - texture.type = Texture::TYPE_LAYERED; + texture.type = TextureStorage::TYPE_LAYERED; texture.layered_type = p_layered_type; texture.width = p_layers[0]->get_width(); @@ -835,7 +901,7 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format Texture texture; - texture.type = Texture::TYPE_3D; + texture.type = TextureStorage::TYPE_3D; texture.width = p_width; texture.height = p_height; texture.depth = p_depth; @@ -927,7 +993,7 @@ void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); ERR_FAIL_COND(p_image->get_format() != tex->format); - if (tex->type == Texture::TYPE_LAYERED) { + if (tex->type == TextureStorage::TYPE_LAYERED) { ERR_FAIL_INDEX(p_layer, tex->layers); } @@ -947,7 +1013,7 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + ERR_FAIL_COND(tex->type != TextureStorage::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) { @@ -1119,7 +1185,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); - ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != TextureStorage::TYPE_3D, Vector<Ref<Image>>()); Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); @@ -1195,7 +1261,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + ERR_FAIL_COND(tex->type != TextureStorage::TYPE_2D); tex->width_2d = p_width; tex->height_2d = p_height; @@ -1807,6 +1873,13 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { return AABB(-decal->extents, decal->extents * 2.0); } +Dependency *TextureStorage::decal_get_dependency(RID p_decal) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND_V(!decal, nullptr); + + return &decal->dependency; +} + void TextureStorage::update_decal_atlas() { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL(copy_effects); @@ -2751,3 +2824,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe ERR_FAIL_COND(!rt); rt->backbuffer_uniform_set = p_uniform_set; } + +void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_mode = p_mode; +} + +void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_texture = p_texture; +} + +RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED); + + return rt->vrs_mode; +} + +RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->vrs_texture; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 7a96e6c6ed..682c951f63 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -38,242 +38,133 @@ namespace RendererRD { -enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_DEPTH, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_3D_BLACK, - DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_2D_UINT, - DEFAULT_RD_TEXTURE_MAX -}; +class LightStorage; +class MaterialStorage; -class CanvasTexture { +class TextureStorage : public RendererTextureStorage { public: - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - - void clear_sets(); - ~CanvasTexture(); -}; + enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_TRANSPARENT, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_DEPTH, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_3D_BLACK, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_VRS, + DEFAULT_RD_TEXTURE_MAX + }; -class Texture { -public: - enum Type { + enum TextureType { TYPE_2D, TYPE_LAYERED, TYPE_3D }; - Type type; - RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - - RD::TextureView rd_view; +private: + friend class LightStorage; + friend class MaterialStorage; - Image::Format format; - Image::Format validated_format; + static TextureStorage *singleton; - int width; - int height; - int depth; - int layers; - int mipmaps; + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; - int height_2d; - int width_2d; + /* Canvas Texture API */ - struct BufferSlice3D { - Size2i size; - uint32_t offset = 0; - uint32_t buffer_size = 0; + class CanvasTexture { + public: + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; + + void clear_sets(); + ~CanvasTexture(); }; - Vector<BufferSlice3D> buffer_slices_3d; - uint32_t buffer_size_3d = 0; - - bool is_render_target; - bool is_proxy; - - Ref<Image> image_cache_2d; - String path; - - RID proxy_to; - Vector<RID> proxies; - - HashSet<RID> lightmap_users; - RS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - RS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; - - RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; - - CanvasTexture *canvas_texture = nullptr; - - void cleanup(); -}; + RID_Owner<CanvasTexture, true> canvas_texture_owner; -struct DecalAtlas { - struct Texture { - int panorama_to_dp_users; - int users; - Rect2 uv_rect; - }; - - struct SortItem { - RID texture; - Size2i pixel_size; - Size2i size; - Point2i pos; - - bool operator<(const SortItem &p_item) const { - //sort larger to smaller - if (size.height == p_item.size.height) { - return size.width > p_item.size.width; - } else { - return size.height > p_item.size.height; - } - } - }; + /* Texture API */ - HashMap<RID, Texture> textures; - bool dirty = true; - int mipmaps = 5; + class Texture { + public: + TextureType type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - RID texture; - RID texture_srgb; - struct MipMap { - RID fb; - RID texture; - Size2i size; - }; - Vector<MipMap> texture_mipmaps; + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; - Size2i size; -}; + RD::TextureView rd_view; -struct Decal { - Vector3 extents = Vector3(1, 1, 1); - RID textures[RS::DECAL_TEXTURE_MAX]; - float emission_energy = 1.0; - float albedo_mix = 1.0; - Color modulate = Color(1, 1, 1, 1); - uint32_t cull_mask = (1 << 20) - 1; - float upper_fade = 0.3; - float lower_fade = 0.3; - bool distance_fade = false; - float distance_fade_begin = 10; - float distance_fade_length = 1; - float normal_fade = 0.0; - - Dependency dependency; -}; + Image::Format format; + Image::Format validated_format; -struct RenderTarget { - Size2i size; - uint32_t view_count; - RID framebuffer; - RID color; + int width; + int height; + int depth; + int layers; + int mipmaps; - //used for retrieving from CPU - RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8; - RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; - Image::Format image_format = Image::FORMAT_L8; + int height_2d; + int width_2d; - bool is_transparent = false; + 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 sdf_enabled = false; + bool is_render_target; + bool is_proxy; - RID backbuffer; //used for effects - RID backbuffer_fb; - RID backbuffer_mipmap0; + Ref<Image> image_cache_2d; + String path; - Vector<RID> backbuffer_mipmaps; + RID proxy_to; + Vector<RID> proxies; - RID framebuffer_uniform_set; - RID backbuffer_uniform_set; + HashSet<RID> lightmap_users; - RID sdf_buffer_write; - RID sdf_buffer_write_fb; - RID sdf_buffer_process[2]; - RID sdf_buffer_read; - RID sdf_buffer_process_uniform_sets[2]; - RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT; - RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; - Size2i process_size; + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; - //texture generated for this owner (nor RD). - RID texture; - bool was_used; + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; - //clear request - bool clear_requested; - Color clear_color; -}; + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; -struct RenderTargetSDF { - enum { - SHADER_LOAD, - SHADER_LOAD_SHRINK, - SHADER_PROCESS, - SHADER_PROCESS_OPTIMIZED, - SHADER_STORE, - SHADER_STORE_SHRINK, - SHADER_MAX - }; + CanvasTexture *canvas_texture = nullptr; - struct PushConstant { - int32_t size[2]; - int32_t stride; - int32_t shift; - int32_t base_size[2]; - int32_t pad[2]; + void cleanup(); }; - CanvasSdfShaderRD shader; - RID shader_version; - RID pipelines[SHADER_MAX]; -}; - -class TextureStorage : public RendererTextureStorage { -private: - static TextureStorage *singleton; - - /* Canvas Texture API */ - - RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner; - - /* Texture API */ - //textures can be created from threads, so this RID_Owner is thread safe mutable RID_Owner<Texture, true> texture_owner; + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; struct TextureToRDFormat { RD::DataFormat format; @@ -297,13 +188,115 @@ private: /* DECAL API */ - DecalAtlas decal_atlas; + struct DecalAtlas { + struct Texture { + int panorama_to_dp_users; + int users; + Rect2 uv_rect; + }; + + struct SortItem { + RID texture; + Size2i pixel_size; + Size2i size; + Point2i pos; + + bool operator<(const SortItem &p_item) const { + //sort larger to smaller + if (size.height == p_item.size.height) { + return size.width > p_item.size.width; + } else { + return size.height > p_item.size.height; + } + } + }; + + HashMap<RID, Texture> textures; + bool dirty = true; + int mipmaps = 5; + + RID texture; + RID texture_srgb; + struct MipMap { + RID fb; + RID texture; + Size2i size; + }; + Vector<MipMap> texture_mipmaps; + + Size2i size; + } decal_atlas; + + struct Decal { + Vector3 extents = Vector3(1, 1, 1); + RID textures[RS::DECAL_TEXTURE_MAX]; + float emission_energy = 1.0; + float albedo_mix = 1.0; + Color modulate = Color(1, 1, 1, 1); + uint32_t cull_mask = (1 << 20) - 1; + float upper_fade = 0.3; + float lower_fade = 0.3; + bool distance_fade = false; + float distance_fade_begin = 40.0; + float distance_fade_length = 10.0; + float normal_fade = 0.0; + + Dependency dependency; + }; mutable RID_Owner<Decal, true> decal_owner; + Decal *get_decal(RID p_rid) const { return decal_owner.get_or_null(p_rid); }; /* RENDER TARGET API */ + struct RenderTarget { + Size2i size; + uint32_t view_count; + RID framebuffer; + RID color; + + //used for retrieving from CPU + RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8; + RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; + Image::Format image_format = Image::FORMAT_L8; + + bool is_transparent = false; + + bool sdf_enabled = false; + + RID backbuffer; //used for effects + RID backbuffer_fb; + RID backbuffer_mipmap0; + + Vector<RID> backbuffer_mipmaps; + + RID framebuffer_uniform_set; + RID backbuffer_uniform_set; + + RID sdf_buffer_write; + RID sdf_buffer_write_fb; + RID sdf_buffer_process[2]; + RID sdf_buffer_read; + RID sdf_buffer_process_uniform_sets[2]; + RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT; + RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; + Size2i process_size; + + // VRS + RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; + RID vrs_texture; + + //texture generated for this owner (nor RD). + RID texture; + bool was_used; + + //clear request + bool clear_requested; + Color clear_color; + }; + mutable RID_Owner<RenderTarget> render_target_owner; + RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }; void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); @@ -312,13 +305,33 @@ private: void _render_target_clear_sdf(RenderTarget *rt); Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const; - RenderTargetSDF rt_sdf; + struct RenderTargetSDF { + enum { + SHADER_LOAD, + SHADER_LOAD_SHRINK, + SHADER_PROCESS, + SHADER_PROCESS_OPTIMIZED, + SHADER_STORE, + SHADER_STORE_SHRINK, + SHADER_MAX + }; + + struct PushConstant { + int32_t size[2]; + int32_t stride; + int32_t shift; + int32_t base_size[2]; + int32_t pad[2]; + }; + + CanvasSdfShaderRD shader; + RID shader_version; + RID pipelines[SHADER_MAX]; + } rt_sdf; public: static TextureStorage *get_singleton(); - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { return default_rd_textures[p_texture]; } @@ -328,7 +341,6 @@ public: /* Canvas Texture API */ - CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; virtual RID canvas_texture_allocate() override; @@ -345,8 +357,7 @@ public: /* Texture API */ - Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; - bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }; virtual bool can_create_resources_async() const override; @@ -388,12 +399,29 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override; //internal usage + _FORCE_INLINE_ TextureType texture_get_type(RID p_texture) { + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); + if (tex == nullptr) { + return TYPE_2D; + } + + return tex->type; + } + + _FORCE_INLINE_ int texture_get_layers(RID p_texture) { + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); + if (tex == nullptr) { + return 1; + } + + return tex->layers; + } _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { if (p_texture.is_null()) { return RID(); } - RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); if (!tex) { return RID(); @@ -405,7 +433,7 @@ public: if (p_texture.is_null()) { return Size2i(); } - RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); if (!tex) { return Size2i(); @@ -417,8 +445,7 @@ public: void update_decal_atlas(); - Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); }; - bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); }; + bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }; RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; @@ -512,11 +539,11 @@ public: } virtual AABB decal_get_aabb(RID p_decal) const override; + Dependency *decal_get_dependency(RID p_decal); /* RENDER TARGET API */ - RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; - bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; + bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; @@ -549,6 +576,12 @@ public: virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; bool render_target_is_sdf_enabled(RID p_render_target) const; + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; + + RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const; + RID render_target_get_vrs_texture(RID p_render_target) const; + Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); @@ -564,4 +597,4 @@ public: } // namespace RendererRD -#endif // !_TEXTURE_STORAGE_RD_H +#endif // TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index a1f62c16c7..ae1f22be3b 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -138,35 +138,37 @@ bool Utilities::free(RID p_rid) { void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) { if (MeshStorage::get_singleton()->owns_mesh(p_base)) { - Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base); - p_instance->update_dependency(&mesh->dependency); + Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) { - MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base); - p_instance->update_dependency(&multimesh->dependency); - if (multimesh->mesh.is_valid()) { - base_update_dependency(multimesh->mesh, p_instance); + Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base); + p_instance->update_dependency(dependency); + + RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base); + if (mesh.is_valid()) { + base_update_dependency(mesh, p_instance); } } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) { - ReflectionProbe *rp = LightStorage::get_singleton()->get_reflection_probe(p_base); - p_instance->update_dependency(&rp->dependency); + Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (TextureStorage::get_singleton()->owns_decal(p_base)) { - Decal *decal = TextureStorage::get_singleton()->get_decal(p_base); - p_instance->update_dependency(&decal->dependency); + Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (GI::get_singleton()->owns_voxel_gi(p_base)) { GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base); p_instance->update_dependency(&gip->dependency); } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) { - Lightmap *lm = LightStorage::get_singleton()->get_lightmap(p_base); - p_instance->update_dependency(&lm->dependency); + Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (LightStorage::get_singleton()->owns_light(p_base)) { - Light *l = LightStorage::get_singleton()->get_light(p_base); - p_instance->update_dependency(&l->dependency); + Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) { - Particles *p = ParticlesStorage::get_singleton()->get_particles(p_base); - p_instance->update_dependency(&p->dependency); + Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) { - ParticlesCollision *pc = ParticlesStorage::get_singleton()->get_particles_collision(p_base); - p_instance->update_dependency(&pc->dependency); + Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (Fog::get_singleton()->owns_fog_volume(p_base)) { Fog::FogVolume *fv = Fog::get_singleton()->get_fog_volume(p_base); p_instance->update_dependency(&fv->dependency); @@ -219,21 +221,21 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de if (p_enter) { if (!vn->enter_callback.is_null()) { if (p_deferred) { - vn->enter_callback.call_deferred(nullptr, 0); + vn->enter_callback.call_deferredp(nullptr, 0); } else { Variant r; Callable::CallError ce; - vn->enter_callback.call(nullptr, 0, r, ce); + vn->enter_callback.callp(nullptr, 0, r, ce); } } } else { if (!vn->exit_callback.is_null()) { if (p_deferred) { - vn->exit_callback.call_deferred(nullptr, 0); + vn->exit_callback.call_deferredp(nullptr, 0); } else { Variant r; Callable::CallError ce; - vn->exit_callback.call(nullptr, 0, r, ce); + vn->exit_callback.callp(nullptr, 0, r, ce); } } } @@ -272,7 +274,7 @@ String Utilities::get_captured_timestamp_name(uint32_t p_index) const { /* MISC */ void Utilities::update_dirty_resources() { - MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update + MaterialStorage::get_singleton()->_update_global_shader_uniforms(); //must do before materials, so it can queue them for update MaterialStorage::get_singleton()->_update_queued_materials(); MeshStorage::get_singleton()->_update_dirty_multimeshes(); MeshStorage::get_singleton()->_update_dirty_skeletons(); @@ -288,9 +290,14 @@ bool Utilities::has_os_feature(const String &p_feature) const { return true; } +#if !defined(ANDROID_ENABLED) && !defined(IPHONE_ENABLED) + // Some Android devices report support for S3TC but we don't expect that and don't export the textures. + // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs). + // For good measure we do the same hack for iOS, just in case. if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { return true; } +#endif if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { return true; diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h index 979e984546..a80eb8510e 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.h +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -119,4 +119,4 @@ public: } // namespace RendererRD -#endif // !UTILITIES_RD_H +#endif // UTILITIES_RD_H diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h index af22a48716..bca8b02178 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef UNIFORM_SET_CACHE_H -#define UNIFORM_SET_CACHE_H +#ifndef UNIFORM_SET_CACHE_RD_H +#define UNIFORM_SET_CACHE_RD_H #include "core/templates/local_vector.h" #include "core/templates/paged_allocator.h" @@ -163,7 +163,7 @@ public: const Cache *c = hash_table[table_idx]; while (c) { - if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) { + if (c->hash == h && c->set == p_set && c->shader == p_shader && sizeof...(Args) == c->uniforms.size() && _compare_args(0, c->uniforms, args...)) { return c->cache; } c = c->next; @@ -193,7 +193,7 @@ public: const Cache *c = hash_table[table_idx]; while (c) { - if (c->hash == h && c->set == p_set && c->shader == p_shader) { + if (c->hash == h && c->set == p_set && c->shader == p_shader && (uint32_t)p_uniforms.size() == c->uniforms.size()) { bool all_ok = true; for (int i = 0; i < p_uniforms.size(); i++) { if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) { @@ -220,4 +220,4 @@ public: ~UniformSetCacheRD(); }; -#endif // UNIFORMSETCACHE_H +#endif // UNIFORM_SET_CACHE_RD_H diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index b773ed61f4..ba6fb71e67 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERINGSERVERSCENE_H -#define RENDERINGSERVERSCENE_H +#ifndef RENDERER_SCENE_H +#define RENDERER_SCENE_H #include "servers/rendering_server.h" #include "servers/xr/xr_interface.h" @@ -100,10 +100,10 @@ public: virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0; virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0; virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; - virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0; - virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; - virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0; - virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0; + virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0; + virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; + virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const = 0; + virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const = 0; virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; @@ -122,6 +122,7 @@ public: virtual RID environment_allocate() = 0; virtual void environment_initialize(RID p_rid) = 0; + // Background virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; virtual void environment_set_sky(RID p_env, RID p_sky) = 0; virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; @@ -131,41 +132,152 @@ public: virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0; - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0; - 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 RS::EnvironmentBG environment_get_background(RID p_Env) const = 0; + virtual RID environment_get_sky(RID p_env) const = 0; + virtual float environment_get_sky_custom_fov(RID p_env) const = 0; + virtual Basis environment_get_sky_orientation(RID p_env) const = 0; + virtual Color environment_get_bg_color(RID p_env) const = 0; + virtual float environment_get_bg_energy(RID p_env) const = 0; + virtual int environment_get_canvas_max_layer(RID p_env) const = 0; + virtual RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const = 0; + virtual Color environment_get_ambient_light(RID p_env) const = 0; + virtual float environment_get_ambient_light_energy(RID p_env) const = 0; + virtual float environment_get_ambient_sky_contribution(RID p_env) const = 0; + virtual RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const = 0; + + // Tonemap + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; + + virtual RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const = 0; + virtual float environment_get_exposure(RID p_env) const = 0; + virtual float environment_get_white(RID p_env) const = 0; + virtual bool environment_get_auto_exposure(RID p_env) const = 0; + virtual float environment_get_min_luminance(RID p_env) const = 0; + virtual float environment_get_max_luminance(RID p_env) const = 0; + virtual float environment_get_auto_exp_speed(RID p_env) const = 0; + virtual float environment_get_auto_exp_scale(RID p_env) const = 0; + virtual uint64_t environment_get_auto_exposure_version(RID p_env) const = 0; + + // Fog + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + virtual bool environment_get_fog_enabled(RID p_env) const = 0; + virtual Color environment_get_fog_light_color(RID p_env) const = 0; + virtual float environment_get_fog_light_energy(RID p_env) const = 0; + virtual float environment_get_fog_sun_scatter(RID p_env) const = 0; + virtual float environment_get_fog_density(RID p_env) const = 0; + virtual float environment_get_fog_height(RID p_env) const = 0; + virtual float environment_get_fog_height_density(RID p_env) const = 0; + virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0; + + // Volumetric Fog virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0; + virtual bool environment_get_volumetric_fog_enabled(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_density(RID p_env) const = 0; + virtual Color environment_get_volumetric_fog_scattering(RID p_env) const = 0; + virtual Color environment_get_volumetric_fog_emission(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_emission_energy(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_anisotropy(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_length(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_detail_spread(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_gi_inject(RID p_env) const = 0; + virtual bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_ambient_inject(RID p_env) const = 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; + // Glow + + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0; + + virtual bool environment_get_glow_enabled(RID p_env) const = 0; + virtual Vector<float> environment_get_glow_levels(RID p_env) const = 0; + virtual float environment_get_glow_intensity(RID p_env) const = 0; + virtual float environment_get_glow_strength(RID p_env) const = 0; + virtual float environment_get_glow_bloom(RID p_env) const = 0; + virtual float environment_get_glow_mix(RID p_env) const = 0; + virtual RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const = 0; + virtual float environment_get_glow_hdr_bleed_threshold(RID p_env) const = 0; + virtual float environment_get_glow_hdr_luminance_cap(RID p_env) const = 0; + virtual float environment_get_glow_hdr_bleed_scale(RID p_env) const = 0; + virtual float environment_get_glow_map_strength(RID p_env) const = 0; + virtual RID environment_get_glow_map(RID p_env) const = 0; + + virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; + + // SSR + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0; + + virtual bool environment_get_ssr_enabled(RID p_env) const = 0; + virtual int environment_get_ssr_max_steps(RID p_env) const = 0; + virtual float environment_get_ssr_fade_in(RID p_env) const = 0; + virtual float environment_get_ssr_fade_out(RID p_env) const = 0; + virtual float environment_get_ssr_depth_tolerance(RID p_env) const = 0; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0; + // SSAO virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0; + + virtual bool environment_get_ssao_enabled(RID p_env) const = 0; + virtual float environment_get_ssao_radius(RID p_env) const = 0; + virtual float environment_get_ssao_intensity(RID p_env) const = 0; + virtual float environment_get_ssao_power(RID p_env) const = 0; + virtual float environment_get_ssao_detail(RID p_env) const = 0; + virtual float environment_get_ssao_horizon(RID p_env) const = 0; + virtual float environment_get_ssao_sharpness(RID p_env) const = 0; + virtual float environment_get_ssao_direct_light_affect(RID p_env) const = 0; + virtual float environment_get_ssao_ao_channel_affect(RID p_env) const = 0; + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; + // SSIL + virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0; + + virtual bool environment_get_ssil_enabled(RID p_env) const = 0; + virtual float environment_get_ssil_radius(RID p_env) const = 0; + virtual float environment_get_ssil_intensity(RID p_env) const = 0; + virtual float environment_get_ssil_sharpness(RID p_env) const = 0; + virtual float environment_get_ssil_normal_rejection(RID p_env) const = 0; + virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; + // SDFGI virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + virtual bool environment_get_sdfgi_enabled(RID p_env) const = 0; + virtual int environment_get_sdfgi_cascades(RID p_env) const = 0; + virtual float environment_get_sdfgi_min_cell_size(RID p_env) const = 0; + virtual bool environment_get_sdfgi_use_occlusion(RID p_env) const = 0; + virtual float environment_get_sdfgi_bounce_feedback(RID p_env) const = 0; + virtual bool environment_get_sdfgi_read_sky_light(RID p_env) const = 0; + virtual float environment_get_sdfgi_energy(RID p_env) const = 0; + virtual float environment_get_sdfgi_normal_bias(RID p_env) const = 0; + virtual float environment_get_sdfgi_probe_bias(RID p_env) const = 0; + virtual RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const = 0; + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0; - virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; - + // Adjustment virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + virtual bool environment_get_adjustments_enabled(RID p_env) const = 0; + virtual float environment_get_adjustments_brightness(RID p_env) const = 0; + virtual float environment_get_adjustments_contrast(RID p_env) const = 0; + virtual float environment_get_adjustments_saturation(RID p_env) const = 0; + virtual bool environment_get_use_1d_color_correction(RID p_env) const = 0; + virtual RID environment_get_color_correction(RID p_env) const = 0; virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; - virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0; - virtual int environment_get_canvas_max_layer(RID p_env) const = 0; - virtual bool is_environment(RID p_environment) const = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; @@ -183,8 +295,8 @@ public: virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; + virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; + virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; virtual RID shadow_atlas_create() = 0; virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0; @@ -194,7 +306,7 @@ public: virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; @@ -226,4 +338,4 @@ public: virtual ~RendererScene(); }; -#endif // RENDERINGSERVERSCENE_H +#endif // RENDERER_SCENE_H diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index aaf7ab8efd..0b20bb372a 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -470,12 +470,12 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base); } else { - RSG::mesh_storage->mesh_free(p_instance->mesh_instance); + RSG::mesh_storage->mesh_instance_free(p_instance->mesh_instance); p_instance->mesh_instance = RID(); } InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance); + geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance); if (p_instance->scenario && p_instance->array_index >= 0) { InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index]; @@ -637,20 +637,20 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { instance->base_data = geom; geom->geometry_instance = scene_render->geometry_instance_create(p_base); - scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton); - scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override); - scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay); - scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials); - scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb); - scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask); - scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias); - scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light); - scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi); - scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); - scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); - scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency); + geom->geometry_instance->set_skeleton(instance->skeleton); + geom->geometry_instance->set_material_override(instance->material_override); + geom->geometry_instance->set_material_overlay(instance->material_overlay); + geom->geometry_instance->set_surface_materials(instance->materials); + geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb); + geom->geometry_instance->set_layer_mask(instance->layer_mask); + geom->geometry_instance->set_lod_bias(instance->lod_bias); + geom->geometry_instance->set_transparency(instance->transparency); + geom->geometry_instance->set_use_baked_light(instance->baked_light); + geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi); + geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); + geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); if (instance->lightmap_sh.size() == 9) { - scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); + geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr()); } for (Instance *E : instance->visibility_dependencies) { @@ -836,7 +836,7 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask); + geom->geometry_instance->set_layer_mask(p_mask); } } @@ -848,7 +848,7 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency); + geom->geometry_instance->set_transparency(p_transparency); } } @@ -1009,7 +1009,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) _instance_update_mesh_instance(instance); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton); + geom->geometry_instance->set_skeleton(p_skeleton); } } @@ -1129,7 +1129,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled); + geom->geometry_instance->set_use_baked_light(p_enabled); } } break; @@ -1149,7 +1149,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled); + geom->geometry_instance->set_use_dynamic_gi(p_enabled); } } break; @@ -1207,7 +1207,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); + geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); } _instance_queue_update(instance, false, true); @@ -1222,7 +1222,7 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material); + geom->geometry_instance->set_material_override(p_material); } } @@ -1235,7 +1235,7 @@ void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, R if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material); + geom->geometry_instance->set_material_overlay(p_material); } } @@ -1358,9 +1358,9 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins bool end_enabled = p_instance->visibility_range_end > 0.0f; float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin; float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin; - scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max); + idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max); } else { - scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f); + idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f); } } @@ -1375,7 +1375,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins } else { idata.parent_array_index = -1; if (is_geometry_instance) { - scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f); + idata.instance_geometry->set_parent_fade_alpha(1.0f); } } } @@ -1407,7 +1407,7 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index); + geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index); } } @@ -1419,66 +1419,66 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); - scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias); + geom->geometry_instance->set_lod_bias(p_lod_bias); } } -void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) { +void RendererSceneCull::instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) { Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter); + HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_uniforms.find(p_parameter); if (!E) { Instance::InstanceShaderParameter isp; isp.index = -1; isp.info = PropertyInfo(); isp.value = p_value; - instance->instance_shader_parameters[p_parameter] = isp; + instance->instance_shader_uniforms[p_parameter] = isp; } else { E->value.value = p_value; - if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) { + if (E->value.index >= 0 && instance->instance_allocated_shader_uniforms) { //update directly - RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value); + RSG::material_storage->global_shader_uniforms_instance_update(p_instance, E->value.index, p_value); } } } -Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const { +Variant RendererSceneCull::instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!instance, Variant()); - if (instance->instance_shader_parameters.has(p_parameter)) { - return instance->instance_shader_parameters[p_parameter].value; + if (instance->instance_shader_uniforms.has(p_parameter)) { + return instance->instance_shader_uniforms[p_parameter].value; } return Variant(); } -Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const { +Variant RendererSceneCull::instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!instance, Variant()); - if (instance->instance_shader_parameters.has(p_parameter)) { - return instance->instance_shader_parameters[p_parameter].default_value; + if (instance->instance_shader_uniforms.has(p_parameter)) { + return instance->instance_shader_uniforms[p_parameter].default_value; } return Variant(); } -void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const { +void RendererSceneCull::instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); const_cast<RendererSceneCull *>(this)->update_dirty_instances(); Vector<StringName> names; - for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_parameters) { + for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_uniforms) { names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); for (int i = 0; i < names.size(); i++) { - PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info; + PropertyInfo pinfo = instance->instance_shader_uniforms[names[i]].info; p_parameters->push_back(pinfo); } } @@ -1587,11 +1587,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { if (!p_instance->lightmap_sh.is_empty()) { p_instance->lightmap_sh.clear(); //don't need SH p_instance->lightmap_target_sh.clear(); //don't need SH - scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr); + geom->geometry_instance->set_lightmap_capture(nullptr); } } - scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb); + geom->geometry_instance->set_transform(p_instance->transform, p_instance->aabb, p_instance->transformed_aabb); } // note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes. @@ -1818,10 +1818,10 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { // Clear these now because the InstanceData containing the dirty flags is gone InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0); - scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0); - scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0); - scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0); + geom->geometry_instance->pair_light_instances(nullptr, 0); + geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0); + geom->geometry_instance->pair_decal_instances(nullptr, 0); + geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0); } for (Instance *E : p_instance->visibility_dependencies) { @@ -1829,7 +1829,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { if (dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1; if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f); + dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f); } } } @@ -1990,10 +1990,10 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) } } - scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr()); + geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr()); } -void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) { +void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); Transform3D light_transform = p_instance->transform; @@ -2045,7 +2045,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i)); // setup a camera matrix for that range! - CameraMatrix camera_matrix; + Projection camera_matrix; real_t aspect = p_cam_projection.get_aspect(); @@ -2185,7 +2185,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in z_max = z_vec.dot(center) + radius + pancake_size; { - CameraMatrix ortho_camera; + Projection ortho_camera; real_t half_x = (x_max_cam - x_min_cam) * 0.5; real_t half_y = (y_max_cam - y_min_cam) * 0.5; @@ -2210,7 +2210,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in } } -bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) { +bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); Transform3D light_transform = p_instance->transform; @@ -2283,7 +2283,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons RSG::mesh_storage->update_mesh_instances(); - scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0); + scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0); shadow_data.light = light->instance; shadow_data.pass = i; } @@ -2294,7 +2294,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, radius * 0.005f, radius); for (int i = 0; i < 6; i++) { @@ -2366,7 +2366,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } //restore the regular DP matrix - //scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0); + //scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0); } } break; @@ -2380,7 +2380,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); - CameraMatrix cm; + Projection cm; cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius); Vector<Plane> planes = cm.get_projection_planes(light_transform); @@ -2450,7 +2450,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ if (p_xr_interface.is_null()) { // Normal camera Transform3D transform = camera->transform; - CameraMatrix projection; + Projection projection; bool vaspect = camera->vaspect; bool is_orthogonal = false; @@ -2489,7 +2489,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ // Setup our camera for our XR interface. // We can support multiple views here each with their own camera Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection projections[RendererSceneRender::MAX_RENDER_VIEWS]; uint32_t view_count = p_xr_interface->get_view_count(); ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported"); @@ -2518,14 +2518,14 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ RENDER_TIMESTAMP("Update Occlusion Buffer") // For now just cull on the first camera - RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool); + RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal); _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info); #endif } void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) { - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t bin_from = p_thread * cull_data->cull_count / total_threads; uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads); @@ -2622,7 +2622,7 @@ bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, co void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) { uint32_t cull_total = cull_data->scenario->instance_data.size(); - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t cull_from = p_thread * cull_total / total_threads; uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads); @@ -2742,7 +2742,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index; fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha; } - scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade); + idata.instance_geometry->set_parent_fade_alpha(fade); } if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) { @@ -2757,14 +2757,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } - scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx); + geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY); } if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); - scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0); + geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY); } @@ -2781,7 +2781,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } - scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); + geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY); } @@ -2797,7 +2797,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul break; } } - scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx); + geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY); } @@ -2813,7 +2813,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } - scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx); + geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY); } @@ -2824,7 +2824,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul for (uint32_t j = 0; j < 9; j++) { sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); } - scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh); + geom->geometry_instance->set_lightmap_capture(sh); idata.instance->last_frame_pass = frame_number; } @@ -2919,7 +2919,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } if (visibility_cull_data.cull_count > thread_cull_threshold) { - RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("VisibilityCullInstances")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } else { _visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count); } @@ -3024,7 +3025,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c scene_cull_result_threads[i].clear(); } - RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { scene_cull_result.append_from(scene_cull_result_threads[i]); @@ -3243,7 +3245,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c render_sdfgi_data[i].instances.clear(); } - // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; + // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; } RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { @@ -3280,9 +3282,9 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RENDER_TIMESTAMP("Render Empty 3D Scene"); RendererSceneRender::CameraData camera_data; - camera_data.set_camera(Transform3D(), CameraMatrix(), true, false); + camera_data.set_camera(Transform3D(), Projection(), true, false); - scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); + scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); #endif } @@ -3329,7 +3331,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int max_distance = MAX(max_distance, distance); //render cubemap side - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, 0.01, max_distance); Transform3D local_view; @@ -3586,7 +3588,7 @@ void RendererSceneCull::render_probes() { } } - scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx); + geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx); ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY); } @@ -3640,9 +3642,9 @@ void RendererSceneCull::render_particle_colliders() { } } -void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { +void RendererSceneCull::_update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { List<RendererMaterialStorage::InstanceShaderParam> plist; - RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); + RSG::material_storage->material_get_instance_shader_uniforms(p_material, &plist); for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { StringName name = E.info.name; if (isparams.has(name)) { @@ -3722,7 +3724,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { can_cast_shadows = false; } is_animated = RSG::material_storage->material_is_animated(p_instance->material_override); - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override); + _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_override); } else { if (p_instance->base_type == RS::INSTANCE_MESH) { RID mesh = p_instance->base; @@ -3744,7 +3746,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { is_animated = true; } - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat); RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } @@ -3775,7 +3777,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { is_animated = true; } - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat); RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } @@ -3813,7 +3815,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { is_animated = true; } - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat); RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker); } @@ -3829,7 +3831,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (p_instance->material_overlay.is_valid()) { can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay); is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay); - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay); + _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_overlay); } if (can_cast_shadows != geom->can_cast_shadows) { @@ -3843,23 +3845,23 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } geom->material_is_animated = is_animated; - p_instance->instance_shader_parameters = isparams; + p_instance->instance_shader_uniforms = isparams; - if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) { - p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0); - if (p_instance->instance_allocated_shader_parameters) { - p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self); - scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset); + if (p_instance->instance_allocated_shader_uniforms != (p_instance->instance_shader_uniforms.size() > 0)) { + p_instance->instance_allocated_shader_uniforms = (p_instance->instance_shader_uniforms.size() > 0); + if (p_instance->instance_allocated_shader_uniforms) { + p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self); + geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_allocated_shader_uniforms_offset); - for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) { + for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_uniforms) { if (E.value.value.get_type() != Variant::NIL) { - RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value); + RSG::material_storage->global_shader_uniforms_instance_update(p_instance->self, E.value.index, E.value.value); } } } else { - RSG::material_storage->global_variables_instance_free(p_instance->self); - p_instance->instance_allocated_shader_parameters_offset = -1; - scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1); + RSG::material_storage->global_shader_uniforms_instance_free(p_instance->self); + p_instance->instance_allocated_shader_uniforms_offset = -1; + geom->geometry_instance->set_instance_shader_uniforms_offset(-1); } } } @@ -3872,7 +3874,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials); + geom->geometry_instance->set_surface_materials(p_instance->materials); } } @@ -3951,9 +3953,9 @@ bool RendererSceneCull::free(RID p_rid) { instance_geometry_set_material_overlay(p_rid, RID()); instance_attach_skeleton(p_rid, RID()); - if (instance->instance_allocated_shader_parameters) { + if (instance->instance_allocated_shader_uniforms) { //free the used shader parameters - RSG::material_storage->global_variables_instance_free(instance->self); + RSG::material_storage->global_shader_uniforms_instance_free(instance->self); } update_dirty_instances(); //in case something changed this @@ -4030,14 +4032,14 @@ RendererSceneCull::RendererSceneCull() { } scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); - scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count()); for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); } indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame"); thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances"); - thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU + thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU taa_jitter_array.resize(TAA_JITTER_COUNT); for (int i = 0; i < TAA_JITTER_COUNT; i++) { diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 198898141e..540fb0e27a 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_CULL_H -#define RENDERING_SERVER_SCENE_CULL_H +#ifndef RENDERER_SCENE_CULL_H +#define RENDERER_SCENE_CULL_H #include "core/math/dynamic_bvh.h" #include "core/templates/bin_sorted_array.h" @@ -272,7 +272,7 @@ public: RID base_rid; union { uint64_t instance_data_rid; - RendererSceneRender::GeometryInstance *instance_geometry; + RenderGeometryInstance *instance_geometry; InstanceVisibilityNotifierData *visibility_notifier = nullptr; }; Instance *instance = nullptr; @@ -426,9 +426,9 @@ public: PropertyInfo info; }; - HashMap<StringName, InstanceShaderParameter> instance_shader_parameters; - bool instance_allocated_shader_parameters = false; - int32_t instance_allocated_shader_parameters_offset = -1; + HashMap<StringName, InstanceShaderParameter> instance_shader_uniforms; + bool instance_allocated_shader_uniforms = false; + int32_t instance_allocated_shader_uniforms_offset = -1; // @@ -578,7 +578,7 @@ public: void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false); struct InstanceGeometryData : public InstanceBaseData { - RendererSceneRender::GeometryInstance *geometry_instance = nullptr; + RenderGeometryInstance *geometry_instance = nullptr; HashSet<Instance *> lights; bool can_cast_shadows; bool material_is_animated; @@ -782,14 +782,14 @@ public: HashSet<Instance *> heightfield_particle_colliders_update_list; PagedArrayPool<Instance *> instance_cull_page_pool; - PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool; + PagedArrayPool<RenderGeometryInstance *> geometry_instance_cull_page_pool; PagedArrayPool<RID> rid_cull_page_pool; PagedArray<Instance *> instance_cull_result; PagedArray<Instance *> instance_shadow_cull_result; struct InstanceCullResult { - PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances; + PagedArray<RenderGeometryInstance *> geometry_instances; PagedArray<Instance *> lights; PagedArray<RID> light_instances; PagedArray<RID> lightmaps; @@ -800,10 +800,10 @@ public: PagedArray<RID> fog_volumes; struct DirectionalShadow { - PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; + PagedArray<RenderGeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; } directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS]; - PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; + PagedArray<RenderGeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES]; void clear() { @@ -882,7 +882,7 @@ public: } } - void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) { + void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RenderGeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) { geometry_instances.set_page_pool(p_geometry_instance_pool); light_instances.set_page_pool(p_rid_pool); lights.set_page_pool(p_instance_pool); @@ -967,12 +967,12 @@ public: virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias); - void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); + void _update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); - virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); - virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; - virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const; - virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const; + virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value); + virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const; + virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const; + virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const; _FORCE_INLINE_ void _update_instance(Instance *p_instance); _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); @@ -980,9 +980,9 @@ public: _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); void _unpair_instance(Instance *p_instance); - void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect); + void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect); - _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold); + _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold); RID _render_get_environment(RID p_camera, RID p_scenario); @@ -992,7 +992,7 @@ public: struct Cascade { Frustum frustum; - CameraMatrix projection; + Projection projection; Transform3D transform; real_t zfar; real_t split; @@ -1045,7 +1045,7 @@ public: uint32_t visible_layers; Instance *render_reflection_probe = nullptr; const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer; - const CameraMatrix *camera_matrix; + const Projection *camera_matrix; uint64_t visibility_viewport_mask; }; @@ -1093,6 +1093,7 @@ public: PASS1RC(bool, is_environment, RID) + // Background PASS2(environment_set_background, RID, RS::EnvironmentBG) PASS2(environment_set_sky, RID, RID) PASS2(environment_set_sky_custom_fov, RID, float) @@ -1102,36 +1103,146 @@ public: PASS2(environment_set_canvas_max_layer, RID, int) PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource) + PASS1RC(RS::EnvironmentBG, environment_get_background, RID) + PASS1RC(RID, environment_get_sky, RID) + PASS1RC(float, environment_get_sky_custom_fov, RID) + PASS1RC(Basis, environment_get_sky_orientation, RID) + PASS1RC(Color, environment_get_bg_color, RID) + PASS1RC(float, environment_get_bg_energy, RID) + PASS1RC(int, environment_get_canvas_max_layer, RID) + PASS1RC(RS::EnvironmentAmbientSource, environment_get_ambient_source, RID) + PASS1RC(Color, environment_get_ambient_light, RID) + PASS1RC(float, environment_get_ambient_light_energy, RID) + PASS1RC(float, environment_get_ambient_sky_contribution, RID) + PASS1RC(RS::EnvironmentReflectionSource, environment_get_reflection_source, RID) + + // Tonemap + PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float) + PASS1RC(RS::EnvironmentToneMapper, environment_get_tone_mapper, RID) + PASS1RC(float, environment_get_exposure, RID) + PASS1RC(float, environment_get_white, RID) + PASS1RC(bool, environment_get_auto_exposure, RID) + PASS1RC(float, environment_get_min_luminance, RID) + PASS1RC(float, environment_get_max_luminance, RID) + PASS1RC(float, environment_get_auto_exp_speed, RID) + PASS1RC(float, environment_get_auto_exp_scale, RID) + PASS1RC(uint64_t, environment_get_auto_exposure_version, RID) + + // Fog + PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) + + PASS1RC(bool, environment_get_fog_enabled, RID) + PASS1RC(Color, environment_get_fog_light_color, RID) + PASS1RC(float, environment_get_fog_light_energy, RID) + PASS1RC(float, environment_get_fog_sun_scatter, RID) + PASS1RC(float, environment_get_fog_density, RID) + PASS1RC(float, environment_get_fog_height, RID) + PASS1RC(float, environment_get_fog_height_density, RID) + PASS1RC(float, environment_get_fog_aerial_perspective, RID) + + PASS2(environment_set_volumetric_fog_volume_size, int, int) + PASS1(environment_set_volumetric_fog_filter_active, bool) + + // Volumentric Fog + PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float) + + PASS1RC(bool, environment_get_volumetric_fog_enabled, RID) + PASS1RC(float, environment_get_volumetric_fog_density, RID) + PASS1RC(Color, environment_get_volumetric_fog_scattering, RID) + PASS1RC(Color, environment_get_volumetric_fog_emission, RID) + PASS1RC(float, environment_get_volumetric_fog_emission_energy, RID) + PASS1RC(float, environment_get_volumetric_fog_anisotropy, RID) + PASS1RC(float, environment_get_volumetric_fog_length, RID) + PASS1RC(float, environment_get_volumetric_fog_detail_spread, RID) + PASS1RC(float, environment_get_volumetric_fog_gi_inject, RID) + PASS1RC(bool, environment_get_volumetric_fog_temporal_reprojection, RID) + PASS1RC(float, environment_get_volumetric_fog_temporal_reprojection_amount, RID) + PASS1RC(float, environment_get_volumetric_fog_ambient_inject, RID) + + // Glow + PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID) + + PASS1RC(bool, environment_get_glow_enabled, RID) + PASS1RC(Vector<float>, environment_get_glow_levels, RID) + PASS1RC(float, environment_get_glow_intensity, RID) + PASS1RC(float, environment_get_glow_strength, RID) + PASS1RC(float, environment_get_glow_bloom, RID) + PASS1RC(float, environment_get_glow_mix, RID) + PASS1RC(RS::EnvironmentGlowBlendMode, environment_get_glow_blend_mode, RID) + PASS1RC(float, environment_get_glow_hdr_bleed_threshold, RID) + PASS1RC(float, environment_get_glow_hdr_luminance_cap, RID) + PASS1RC(float, environment_get_glow_hdr_bleed_scale, RID) + PASS1RC(float, environment_get_glow_map_strength, RID) + PASS1RC(RID, environment_get_glow_map, RID) + + PASS1(environment_glow_set_use_bicubic_upscale, bool) + PASS1(environment_glow_set_use_high_quality, bool) + + // SSR PASS6(environment_set_ssr, RID, bool, int, float, float, float) + + PASS1RC(bool, environment_get_ssr_enabled, RID) + PASS1RC(int, environment_get_ssr_max_steps, RID) + PASS1RC(float, environment_get_ssr_fade_in, RID) + PASS1RC(float, environment_get_ssr_fade_out, RID) + PASS1RC(float, environment_get_ssr_depth_tolerance, RID) + PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality) + // SSAO PASS10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float) + + PASS1RC(bool, environment_get_ssao_enabled, RID) + PASS1RC(float, environment_get_ssao_radius, RID) + PASS1RC(float, environment_get_ssao_intensity, RID) + PASS1RC(float, environment_get_ssao_power, RID) + PASS1RC(float, environment_get_ssao_detail, RID) + PASS1RC(float, environment_get_ssao_horizon, RID) + PASS1RC(float, environment_get_ssao_sharpness, RID) + PASS1RC(float, environment_get_ssao_direct_light_affect, RID) + PASS1RC(float, environment_get_ssao_ao_channel_affect, RID) + PASS6(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool, float, int, float, float) + // SSIL PASS6(environment_set_ssil, RID, bool, float, float, float, float) - PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float) - PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID) - PASS1(environment_glow_set_use_bicubic_upscale, bool) - PASS1(environment_glow_set_use_high_quality, bool) + PASS1RC(bool, environment_get_ssil_enabled, RID) + PASS1RC(float, environment_get_ssil_radius, RID) + PASS1RC(float, environment_get_ssil_intensity, RID) + PASS1RC(float, environment_get_ssil_sharpness, RID) + PASS1RC(float, environment_get_ssil_normal_rejection, RID) - PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float) + PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float) - PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) + // SDFGI - PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) - PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float) + PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float) - PASS2(environment_set_volumetric_fog_volume_size, int, int) - PASS1(environment_set_volumetric_fog_filter_active, bool) + PASS1RC(bool, environment_get_sdfgi_enabled, RID) + PASS1RC(int, environment_get_sdfgi_cascades, RID) + PASS1RC(float, environment_get_sdfgi_min_cell_size, RID) + PASS1RC(bool, environment_get_sdfgi_use_occlusion, RID) + PASS1RC(float, environment_get_sdfgi_bounce_feedback, RID) + PASS1RC(bool, environment_get_sdfgi_read_sky_light, RID) + PASS1RC(float, environment_get_sdfgi_energy, RID) + PASS1RC(float, environment_get_sdfgi_normal_bias, RID) + PASS1RC(float, environment_get_sdfgi_probe_bias, RID) + PASS1RC(RS::EnvironmentSDFGIYScale, environment_get_sdfgi_y_scale, RID) - PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float) PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount) PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge) PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight) - PASS1RC(RS::EnvironmentBG, environment_get_background, RID) - PASS1RC(int, environment_get_canvas_max_layer, RID) + // Adjustment + PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) + + PASS1RC(bool, environment_get_adjustments_enabled, RID) + PASS1RC(float, environment_get_adjustments_brightness, RID) + PASS1RC(float, environment_get_adjustments_contrast, RID) + PASS1RC(float, environment_get_adjustments_saturation, RID) + PASS1RC(bool, environment_get_use_1d_color_correction, RID) + PASS1RC(RID, environment_get_color_correction, RID) PASS3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &) @@ -1150,8 +1261,8 @@ public: PASS8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) PASS3(camera_effects_set_custom_exposure, RID, bool, float) - PASS1(shadows_quality_set, RS::ShadowQuality) - PASS1(directional_shadow_quality_set, RS::ShadowQuality) + PASS1(positional_soft_shadow_filter_set_quality, RS::ShadowQuality) + PASS1(directional_soft_shadow_filter_set_quality, RS::ShadowQuality) PASS2(sdfgi_set_debug_probe_select, const Vector3 &, const Vector3 &) @@ -1183,4 +1294,4 @@ public: virtual ~RendererSceneCull(); }; -#endif // RENDERING_SERVER_SCENE_CULL_H +#endif // RENDERER_SCENE_CULL_H diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h index 7198379ade..0d466e8a32 100644 --- a/servers/rendering/renderer_scene_occlusion_cull.h +++ b/servers/rendering/renderer_scene_occlusion_cull.h @@ -31,7 +31,7 @@ #ifndef RENDERER_SCENE_OCCLUSION_CULL_H #define RENDERER_SCENE_OCCLUSION_CULL_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/local_vector.h" #include "servers/rendering_server.h" @@ -60,7 +60,7 @@ public: void update_mips(); - _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const { + _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const { if (is_empty()) { return false; } @@ -183,7 +183,8 @@ public: } virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warning(); } virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warning(); } - virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {} + virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {} + virtual RID buffer_get_debug_texture(RID p_buffer) { _print_warning(); return RID(); @@ -200,4 +201,4 @@ public: }; }; -#endif //RENDERER_SCENE_OCCLUSION_CULL_H +#endif // RENDERER_SCENE_OCCLUSION_CULL_H diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index 600908cf16..e024e59ec3 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -30,7 +30,10 @@ #include "renderer_scene_render.h" -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) { +///////////////////////////////////////////////////////////////////////////// +// CameraData + +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) { view_count = 1; is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; @@ -43,7 +46,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, taa_jitter = p_taa_jitter; } -void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) { ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view"); view_count = p_view_count; @@ -60,8 +63,8 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count } // 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis. - Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal; - Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal; + Vector3 n0 = planes[0][Projection::PLANE_LEFT].normal; + Vector3 n1 = planes[1][Projection::PLANE_RIGHT].normal; Vector3 z = (n0 + n1).normalized(); Vector3 y = n0.cross(n1).normalized(); Vector3 x = y.cross(z).normalized(); @@ -73,13 +76,13 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 4. Intersect horizon, left and right to obtain the combined camera origin. ERR_FAIL_COND_MSG( - !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin"); + !horizon.intersect_3(planes[0][Projection::PLANE_LEFT], planes[1][Projection::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin"); // handy to have the inverse of the transform we just build Transform3D main_transform_inv = main_transform.inverse(); // 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters - Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5; + Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5; Plane far(-z, far_center); ///////////////////////////////////////////////////////////////////////////// @@ -88,9 +91,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left. Vector3 top_left, other; ERR_FAIL_COND_MSG( - !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector"); + !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector"); ERR_FAIL_COND_MSG( - !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector"); + !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/left/top vector"); if (y.dot(top_left) < y.dot(other)) { top_left = other; } @@ -98,9 +101,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left. Vector3 bottom_left; ERR_FAIL_COND_MSG( - !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector"); + !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector"); ERR_FAIL_COND_MSG( - !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector"); + !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector"); if (y.dot(other) < y.dot(bottom_left)) { bottom_left = other; } @@ -108,9 +111,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right. Vector3 top_right; ERR_FAIL_COND_MSG( - !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector"); + !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector"); ERR_FAIL_COND_MSG( - !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector"); + !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/right/top vector"); if (y.dot(top_right) < y.dot(other)) { top_right = other; } @@ -118,9 +121,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right. Vector3 bottom_right; ERR_FAIL_COND_MSG( - !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector"); + !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector"); ERR_FAIL_COND_MSG( - !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector"); + !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector"); if (y.dot(other) < y.dot(bottom_right)) { bottom_right = other; } @@ -146,18 +149,18 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec Vector3 min_vec; ERR_FAIL_COND_MSG( - !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector"); + !near.intersect_3(bottom, planes[0][Projection::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector"); ERR_FAIL_COND_MSG( - !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector"); + !near.intersect_3(bottom, planes[1][Projection::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector"); if (x.dot(other) < x.dot(min_vec)) { min_vec = other; } Vector3 max_vec; ERR_FAIL_COND_MSG( - !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector"); + !near.intersect_3(top, planes[0][Projection::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector"); ERR_FAIL_COND_MSG( - !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector"); + !near.intersect_3(top, planes[1][Projection::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector"); if (x.dot(max_vec) < x.dot(other)) { max_vec = other; } @@ -177,6 +180,464 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count // 3. Copy our view data for (uint32_t v = 0; v < view_count; v++) { view_offset[v] = main_transform_inv * p_transforms[v]; - view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v].inverse()); + view_projection[v] = p_projections[v] * Projection(view_offset[v].inverse()); } } + +/* Environment API */ + +RID RendererSceneRender::environment_allocate() { + return environment_storage.environment_allocate(); +} + +void RendererSceneRender::environment_initialize(RID p_rid) { + environment_storage.environment_initialize(p_rid); +} + +void RendererSceneRender::environment_free(RID p_rid) { + environment_storage.environment_free(p_rid); +} + +bool RendererSceneRender::is_environment(RID p_rid) const { + return environment_storage.is_environment(p_rid); +} + +// background + +void RendererSceneRender::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { + environment_storage.environment_set_background(p_env, p_bg); +} + +void RendererSceneRender::environment_set_sky(RID p_env, RID p_sky) { + environment_storage.environment_set_sky(p_env, p_sky); +} + +void RendererSceneRender::environment_set_sky_custom_fov(RID p_env, float p_scale) { + environment_storage.environment_set_sky_custom_fov(p_env, p_scale); +} + +void RendererSceneRender::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { + environment_storage.environment_set_sky_orientation(p_env, p_orientation); +} + +void RendererSceneRender::environment_set_bg_color(RID p_env, const Color &p_color) { + environment_storage.environment_set_bg_color(p_env, p_color); +} + +void RendererSceneRender::environment_set_bg_energy(RID p_env, float p_energy) { + environment_storage.environment_set_bg_energy(p_env, p_energy); +} + +void RendererSceneRender::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { + environment_storage.environment_set_canvas_max_layer(p_env, p_max_layer); +} + +void RendererSceneRender::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { + environment_storage.environment_set_ambient_light(p_env, p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source); +} + +RS::EnvironmentBG RendererSceneRender::environment_get_background(RID p_env) const { + return environment_storage.environment_get_background(p_env); +} + +RID RendererSceneRender::environment_get_sky(RID p_env) const { + return environment_storage.environment_get_sky(p_env); +} + +float RendererSceneRender::environment_get_sky_custom_fov(RID p_env) const { + return environment_storage.environment_get_sky_custom_fov(p_env); +} + +Basis RendererSceneRender::environment_get_sky_orientation(RID p_env) const { + return environment_storage.environment_get_sky_orientation(p_env); +} + +Color RendererSceneRender::environment_get_bg_color(RID p_env) const { + return environment_storage.environment_get_bg_color(p_env); +} + +float RendererSceneRender::environment_get_bg_energy(RID p_env) const { + return environment_storage.environment_get_bg_energy(p_env); +} + +int RendererSceneRender::environment_get_canvas_max_layer(RID p_env) const { + return environment_storage.environment_get_canvas_max_layer(p_env); +} + +RS::EnvironmentAmbientSource RendererSceneRender::environment_get_ambient_source(RID p_env) const { + return environment_storage.environment_get_ambient_source(p_env); +} + +Color RendererSceneRender::environment_get_ambient_light(RID p_env) const { + return environment_storage.environment_get_ambient_light(p_env); +} + +float RendererSceneRender::environment_get_ambient_light_energy(RID p_env) const { + return environment_storage.environment_get_ambient_light_energy(p_env); +} + +float RendererSceneRender::environment_get_ambient_sky_contribution(RID p_env) const { + return environment_storage.environment_get_ambient_sky_contribution(p_env); +} + +RS::EnvironmentReflectionSource RendererSceneRender::environment_get_reflection_source(RID p_env) const { + return environment_storage.environment_get_reflection_source(p_env); +} + +// Tonemap + +void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { + environment_storage.environment_set_tonemap(p_env, p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale); +} + +RS::EnvironmentToneMapper RendererSceneRender::environment_get_tone_mapper(RID p_env) const { + return environment_storage.environment_get_tone_mapper(p_env); +} + +float RendererSceneRender::environment_get_exposure(RID p_env) const { + return environment_storage.environment_get_exposure(p_env); +} + +float RendererSceneRender::environment_get_white(RID p_env) const { + return environment_storage.environment_get_white(p_env); +} + +bool RendererSceneRender::environment_get_auto_exposure(RID p_env) const { + return environment_storage.environment_get_auto_exposure(p_env); +} + +float RendererSceneRender::environment_get_min_luminance(RID p_env) const { + return environment_storage.environment_get_min_luminance(p_env); +} + +float RendererSceneRender::environment_get_max_luminance(RID p_env) const { + return environment_storage.environment_get_max_luminance(p_env); +} + +float RendererSceneRender::environment_get_auto_exp_speed(RID p_env) const { + return environment_storage.environment_get_auto_exp_speed(p_env); +} + +float RendererSceneRender::environment_get_auto_exp_scale(RID p_env) const { + return environment_storage.environment_get_auto_exp_scale(p_env); +} + +uint64_t RendererSceneRender::environment_get_auto_exposure_version(RID p_env) const { + return environment_storage.environment_get_auto_exposure_version(p_env); +} + +// Fog + +void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) { + environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective); +} + +bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const { + return environment_storage.environment_get_fog_enabled(p_env); +} + +Color RendererSceneRender::environment_get_fog_light_color(RID p_env) const { + return environment_storage.environment_get_fog_light_color(p_env); +} + +float RendererSceneRender::environment_get_fog_light_energy(RID p_env) const { + return environment_storage.environment_get_fog_light_energy(p_env); +} + +float RendererSceneRender::environment_get_fog_sun_scatter(RID p_env) const { + return environment_storage.environment_get_fog_sun_scatter(p_env); +} + +float RendererSceneRender::environment_get_fog_density(RID p_env) const { + return environment_storage.environment_get_fog_density(p_env); +} + +float RendererSceneRender::environment_get_fog_height(RID p_env) const { + return environment_storage.environment_get_fog_height(p_env); +} + +float RendererSceneRender::environment_get_fog_height_density(RID p_env) const { + return environment_storage.environment_get_fog_height_density(p_env); +} + +float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) const { + return environment_storage.environment_get_fog_aerial_perspective(p_env); +} + +// Volumetric Fog + +void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { + environment_storage.environment_set_volumetric_fog(p_env, p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject); +} + +bool RendererSceneRender::environment_get_volumetric_fog_enabled(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_enabled(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_density(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_density(p_env); +} + +Color RendererSceneRender::environment_get_volumetric_fog_scattering(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_scattering(p_env); +} + +Color RendererSceneRender::environment_get_volumetric_fog_emission(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_emission(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_emission_energy(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_emission_energy(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_anisotropy(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_anisotropy(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_length(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_length(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_detail_spread(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_detail_spread(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_gi_inject(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_gi_inject(p_env); +} + +bool RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_temporal_reprojection(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_temporal_reprojection_amount(p_env); +} + +float RendererSceneRender::environment_get_volumetric_fog_ambient_inject(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_ambient_inject(p_env); +} + +// GLOW + +void RendererSceneRender::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { + environment_storage.environment_set_glow(p_env, p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map); +} + +bool RendererSceneRender::environment_get_glow_enabled(RID p_env) const { + return environment_storage.environment_get_glow_enabled(p_env); +} + +Vector<float> RendererSceneRender::environment_get_glow_levels(RID p_env) const { + return environment_storage.environment_get_glow_levels(p_env); +} + +float RendererSceneRender::environment_get_glow_intensity(RID p_env) const { + return environment_storage.environment_get_glow_intensity(p_env); +} + +float RendererSceneRender::environment_get_glow_strength(RID p_env) const { + return environment_storage.environment_get_glow_strength(p_env); +} + +float RendererSceneRender::environment_get_glow_bloom(RID p_env) const { + return environment_storage.environment_get_glow_bloom(p_env); +} + +float RendererSceneRender::environment_get_glow_mix(RID p_env) const { + return environment_storage.environment_get_glow_mix(p_env); +} + +RS::EnvironmentGlowBlendMode RendererSceneRender::environment_get_glow_blend_mode(RID p_env) const { + return environment_storage.environment_get_glow_blend_mode(p_env); +} + +float RendererSceneRender::environment_get_glow_hdr_bleed_threshold(RID p_env) const { + return environment_storage.environment_get_glow_hdr_bleed_threshold(p_env); +} + +float RendererSceneRender::environment_get_glow_hdr_luminance_cap(RID p_env) const { + return environment_storage.environment_get_glow_hdr_luminance_cap(p_env); +} + +float RendererSceneRender::environment_get_glow_hdr_bleed_scale(RID p_env) const { + return environment_storage.environment_get_glow_hdr_bleed_scale(p_env); +} + +float RendererSceneRender::environment_get_glow_map_strength(RID p_env) const { + return environment_storage.environment_get_glow_map_strength(p_env); +} + +RID RendererSceneRender::environment_get_glow_map(RID p_env) const { + return environment_storage.environment_get_glow_map(p_env); +} + +// SSR + +void RendererSceneRender::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { + environment_storage.environment_set_ssr(p_env, p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance); +} + +bool RendererSceneRender::environment_get_ssr_enabled(RID p_env) const { + return environment_storage.environment_get_ssr_enabled(p_env); +} + +int RendererSceneRender::environment_get_ssr_max_steps(RID p_env) const { + return environment_storage.environment_get_ssr_max_steps(p_env); +} + +float RendererSceneRender::environment_get_ssr_fade_in(RID p_env) const { + return environment_storage.environment_get_ssr_fade_in(p_env); +} + +float RendererSceneRender::environment_get_ssr_fade_out(RID p_env) const { + return environment_storage.environment_get_ssr_fade_out(p_env); +} + +float RendererSceneRender::environment_get_ssr_depth_tolerance(RID p_env) const { + return environment_storage.environment_get_ssr_depth_tolerance(p_env); +} + +// SSAO + +void RendererSceneRender::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { + environment_storage.environment_set_ssao(p_env, p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect); +} + +bool RendererSceneRender::environment_get_ssao_enabled(RID p_env) const { + return environment_storage.environment_get_ssao_enabled(p_env); +} + +float RendererSceneRender::environment_get_ssao_radius(RID p_env) const { + return environment_storage.environment_get_ssao_radius(p_env); +} + +float RendererSceneRender::environment_get_ssao_intensity(RID p_env) const { + return environment_storage.environment_get_ssao_intensity(p_env); +} + +float RendererSceneRender::environment_get_ssao_power(RID p_env) const { + return environment_storage.environment_get_ssao_power(p_env); +} + +float RendererSceneRender::environment_get_ssao_detail(RID p_env) const { + return environment_storage.environment_get_ssao_detail(p_env); +} + +float RendererSceneRender::environment_get_ssao_horizon(RID p_env) const { + return environment_storage.environment_get_ssao_horizon(p_env); +} + +float RendererSceneRender::environment_get_ssao_sharpness(RID p_env) const { + return environment_storage.environment_get_ssao_sharpness(p_env); +} + +float RendererSceneRender::environment_get_ssao_direct_light_affect(RID p_env) const { + return environment_storage.environment_get_ssao_direct_light_affect(p_env); +} + +float RendererSceneRender::environment_get_ssao_ao_channel_affect(RID p_env) const { + return environment_storage.environment_get_ssao_ao_channel_affect(p_env); +} + +// SSIL + +void RendererSceneRender::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) { + environment_storage.environment_set_ssil(p_env, p_enable, p_radius, p_intensity, p_sharpness, p_normal_rejection); +} + +bool RendererSceneRender::environment_get_ssil_enabled(RID p_env) const { + return environment_storage.environment_get_ssil_enabled(p_env); +} + +float RendererSceneRender::environment_get_ssil_radius(RID p_env) const { + return environment_storage.environment_get_ssil_radius(p_env); +} + +float RendererSceneRender::environment_get_ssil_intensity(RID p_env) const { + return environment_storage.environment_get_ssil_intensity(p_env); +} + +float RendererSceneRender::environment_get_ssil_sharpness(RID p_env) const { + return environment_storage.environment_get_ssil_sharpness(p_env); +} + +float RendererSceneRender::environment_get_ssil_normal_rejection(RID p_env) const { + return environment_storage.environment_get_ssil_normal_rejection(p_env); +} + +// SDFGI + +void RendererSceneRender::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { + environment_storage.environment_set_sdfgi(p_env, p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias); +} + +bool RendererSceneRender::environment_get_sdfgi_enabled(RID p_env) const { + return environment_storage.environment_get_sdfgi_enabled(p_env); +} + +int RendererSceneRender::environment_get_sdfgi_cascades(RID p_env) const { + return environment_storage.environment_get_sdfgi_cascades(p_env); +} + +float RendererSceneRender::environment_get_sdfgi_min_cell_size(RID p_env) const { + return environment_storage.environment_get_sdfgi_min_cell_size(p_env); +} + +bool RendererSceneRender::environment_get_sdfgi_use_occlusion(RID p_env) const { + return environment_storage.environment_get_sdfgi_use_occlusion(p_env); +} + +float RendererSceneRender::environment_get_sdfgi_bounce_feedback(RID p_env) const { + return environment_storage.environment_get_sdfgi_bounce_feedback(p_env); +} + +bool RendererSceneRender::environment_get_sdfgi_read_sky_light(RID p_env) const { + return environment_storage.environment_get_sdfgi_read_sky_light(p_env); +} + +float RendererSceneRender::environment_get_sdfgi_energy(RID p_env) const { + return environment_storage.environment_get_sdfgi_energy(p_env); +} + +float RendererSceneRender::environment_get_sdfgi_normal_bias(RID p_env) const { + return environment_storage.environment_get_sdfgi_normal_bias(p_env); +} + +float RendererSceneRender::environment_get_sdfgi_probe_bias(RID p_env) const { + return environment_storage.environment_get_sdfgi_probe_bias(p_env); +} + +RS::EnvironmentSDFGIYScale RendererSceneRender::environment_get_sdfgi_y_scale(RID p_env) const { + return environment_storage.environment_get_sdfgi_y_scale(p_env); +} + +// Adjustments + +void RendererSceneRender::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { + environment_storage.environment_set_adjustment(p_env, p_enable, p_brightness, p_contrast, p_saturation, p_use_1d_color_correction, p_color_correction); +} + +bool RendererSceneRender::environment_get_adjustments_enabled(RID p_env) const { + return environment_storage.environment_get_adjustments_enabled(p_env); +} + +float RendererSceneRender::environment_get_adjustments_brightness(RID p_env) const { + return environment_storage.environment_get_adjustments_brightness(p_env); +} + +float RendererSceneRender::environment_get_adjustments_contrast(RID p_env) const { + return environment_storage.environment_get_adjustments_contrast(p_env); +} + +float RendererSceneRender::environment_get_adjustments_saturation(RID p_env) const { + return environment_storage.environment_get_adjustments_saturation(p_env); +} + +bool RendererSceneRender::environment_get_use_1d_color_correction(RID p_env) const { + return environment_storage.environment_get_use_1d_color_correction(p_env); +} + +RID RendererSceneRender::environment_get_color_correction(RID p_env) const { + return environment_storage.environment_get_color_correction(p_env); +} diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 280277c6d8..7f70f4b939 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -28,14 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERINGSERVERSCENERENDER_H -#define RENDERINGSERVERSCENERENDER_H +#ifndef RENDERER_SCENE_RENDER_H +#define RENDERER_SCENE_RENDER_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/paged_array.h" +#include "servers/rendering/renderer_geometry_instance.h" #include "servers/rendering/renderer_scene.h" +#include "servers/rendering/storage/environment_storage.h" +#include "storage/utilities.h" class RendererSceneRender { +private: + RendererEnvironmentStorage environment_storage; + public: enum { MAX_DIRECTIONAL_LIGHTS = 8, @@ -43,38 +49,11 @@ public: MAX_RENDER_VIEWS = 2 }; - struct GeometryInstance { - virtual ~GeometryInstance() {} - }; - - virtual GeometryInstance *geometry_instance_create(RID p_base) = 0; - virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0; - virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0; - virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0; - virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0; - virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0; - virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0; - virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0; - virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0; - virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0; - virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0; - virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0; - virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0; - virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0; - virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0; - virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0; - virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0; - virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0; + /* Geometry Instance */ + virtual RenderGeometryInstance *geometry_instance_create(RID p_base) = 0; + virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) = 0; virtual uint32_t geometry_instance_get_pair_mask() = 0; - virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0; - virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0; - virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0; - virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0; - - virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0; - - virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0; /* SHADOW ATLAS API */ @@ -106,57 +85,160 @@ public: /* ENVIRONMENT API */ - virtual RID environment_allocate() = 0; - virtual void environment_initialize(RID p_rid) = 0; - - virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; - virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; - virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0; + RID environment_allocate(); + void environment_initialize(RID p_rid); + void environment_free(RID p_rid); + + bool is_environment(RID p_env) const; + + // Background + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg); + void environment_set_sky(RID p_env, RID p_sky); + void environment_set_sky_custom_fov(RID p_env, float p_scale); + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); + void environment_set_bg_color(RID p_env, const Color &p_color); + void environment_set_bg_energy(RID p_env, float p_energy); + void environment_set_canvas_max_layer(RID p_env, int p_max_layer); + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG); // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 - virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; + void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); #endif - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0; - virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; - virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; + RS::EnvironmentBG environment_get_background(RID p_env) const; + RID environment_get_sky(RID p_env) const; + float environment_get_sky_custom_fov(RID p_env) const; + Basis environment_get_sky_orientation(RID p_env) const; + Color environment_get_bg_color(RID p_env) const; + float environment_get_bg_energy(RID p_env) const; + int environment_get_canvas_max_layer(RID p_env) const; + RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const; + Color environment_get_ambient_light(RID p_env) const; + float environment_get_ambient_light_energy(RID p_env) const; + float environment_get_ambient_sky_contribution(RID p_env) const; + RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + + // Tonemap + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); + RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const; + float environment_get_exposure(RID p_env) const; + float environment_get_white(RID p_env) const; + bool environment_get_auto_exposure(RID p_env) const; + float environment_get_min_luminance(RID p_env) const; + float environment_get_max_luminance(RID p_env) const; + float environment_get_auto_exp_speed(RID p_env) const; + float environment_get_auto_exp_scale(RID p_env) const; + uint64_t environment_get_auto_exposure_version(RID p_env) const; + + // Fog + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective); + bool environment_get_fog_enabled(RID p_env) const; + Color environment_get_fog_light_color(RID p_env) const; + float environment_get_fog_light_energy(RID p_env) const; + float environment_get_fog_sun_scatter(RID p_env) const; + float environment_get_fog_density(RID p_env) const; + float environment_get_fog_height(RID p_env) const; + float environment_get_fog_height_density(RID p_env) const; + float environment_get_fog_aerial_perspective(RID p_env) const; + + // Volumetric Fog + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); + bool environment_get_volumetric_fog_enabled(RID p_env) const; + float environment_get_volumetric_fog_density(RID p_env) const; + Color environment_get_volumetric_fog_scattering(RID p_env) const; + Color environment_get_volumetric_fog_emission(RID p_env) const; + float environment_get_volumetric_fog_emission_energy(RID p_env) const; + float environment_get_volumetric_fog_anisotropy(RID p_env) const; + float environment_get_volumetric_fog_length(RID p_env) const; + float environment_get_volumetric_fog_detail_spread(RID p_env) const; + float environment_get_volumetric_fog_gi_inject(RID p_env) const; + bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const; + float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const; + float environment_get_volumetric_fog_ambient_inject(RID p_env) const; - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 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_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0; + // GLOW + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map); + bool environment_get_glow_enabled(RID p_env) const; + Vector<float> environment_get_glow_levels(RID p_env) const; + float environment_get_glow_intensity(RID p_env) const; + float environment_get_glow_strength(RID p_env) const; + float environment_get_glow_bloom(RID p_env) const; + float environment_get_glow_mix(RID p_env) const; + RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const; + float environment_get_glow_hdr_bleed_threshold(RID p_env) const; + float environment_get_glow_hdr_luminance_cap(RID p_env) const; + float environment_get_glow_hdr_bleed_scale(RID p_env) const; + float environment_get_glow_map_strength(RID p_env) const; + RID environment_get_glow_map(RID p_env) const; + + virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; + + // SSR + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); + bool environment_get_ssr_enabled(RID p_env) const; + int environment_get_ssr_max_steps(RID p_env) const; + float environment_get_ssr_fade_in(RID p_env) const; + float environment_get_ssr_fade_out(RID p_env) const; + float environment_get_ssr_depth_tolerance(RID p_env) const; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0; + // SSAO + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect); + bool environment_get_ssao_enabled(RID p_env) const; + float environment_get_ssao_radius(RID p_env) const; + float environment_get_ssao_intensity(RID p_env) const; + float environment_get_ssao_power(RID p_env) const; + float environment_get_ssao_detail(RID p_env) const; + float environment_get_ssao_horizon(RID p_env) const; + float environment_get_ssao_sharpness(RID p_env) const; + float environment_get_ssao_direct_light_affect(RID p_env) const; + float environment_get_ssao_ao_channel_affect(RID p_env) const; + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; - virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0; + // SSIL + void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection); + bool environment_get_ssil_enabled(RID p_env) const; + float environment_get_ssil_radius(RID p_env) const; + float environment_get_ssil_intensity(RID p_env) const; + float environment_get_ssil_sharpness(RID p_env) const; + float environment_get_ssil_normal_rejection(RID p_env) const; + virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; - virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + // SDFGI + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); + bool environment_get_sdfgi_enabled(RID p_env) const; + int environment_get_sdfgi_cascades(RID p_env) const; + float environment_get_sdfgi_min_cell_size(RID p_env) const; + bool environment_get_sdfgi_use_occlusion(RID p_env) const; + float environment_get_sdfgi_bounce_feedback(RID p_env) const; + bool environment_get_sdfgi_read_sky_light(RID p_env) const; + float environment_get_sdfgi_energy(RID p_env) const; + float environment_get_sdfgi_normal_bias(RID p_env) const; + float environment_get_sdfgi_probe_bias(RID p_env) const; + RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const; virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0; - virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; - - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; - - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + // Adjustment + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction); + bool environment_get_adjustments_enabled(RID p_env) const; + float environment_get_adjustments_brightness(RID p_env) const; + float environment_get_adjustments_contrast(RID p_env) const; + float environment_get_adjustments_saturation(RID p_env) const; + bool environment_get_use_1d_color_correction(RID p_env) const; + RID environment_get_color_correction(RID p_env) const; virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; - virtual bool is_environment(RID p_env) const = 0; - virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0; - virtual int environment_get_canvas_max_layer(RID p_env) const = 0; - virtual RID camera_effects_allocate() = 0; virtual void camera_effects_initialize(RID p_rid) = 0; @@ -166,13 +248,13 @@ public: virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; + virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; + virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; virtual RID light_instance_create(RID p_light) = 0; virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0; virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0; + virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0; virtual void light_instance_mark_visible(RID p_light_instance) = 0; virtual bool light_instances_can_render_shadow_cube() const { return true; @@ -205,19 +287,19 @@ public: virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0; virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0; virtual bool voxel_gi_needs_update(RID p_probe) const = 0; - virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0; + virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) = 0; virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0; struct RenderShadowData { RID light; int pass = 0; - PagedArray<GeometryInstance *> instances; + PagedArray<RenderGeometryInstance *> instances; }; struct RenderSDFGIData { int region = 0; - PagedArray<GeometryInstance *> instances; + PagedArray<RenderGeometryInstance *> instances; }; struct RenderSDFGIUpdateData { @@ -239,27 +321,27 @@ public: // Main/center projection Transform3D main_transform; - CameraMatrix main_projection; + Projection main_projection; Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; Vector2 taa_jitter; - void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2()); - void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect); + void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2()); + void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); }; - virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; + virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0; + virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; virtual void set_scene_pass(uint64_t p_pass) = 0; virtual void set_time(double p_time, double p_step) = 0; virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; @@ -281,4 +363,4 @@ public: virtual ~RendererSceneRender() {} }; -#endif // RENDERINGSERVERSCENERENDER_H +#endif // RENDERER_SCENE_RENDER_H diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 2fccb1fd38..118bf532b3 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -138,7 +138,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { p_viewport->internal_size = Size2(render_width, render_height); - RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count()); + RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->texture_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count()); } } } @@ -154,7 +154,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) { if (p_viewport->use_occlusion_culling) { if (p_viewport->occlusion_buffer_dirty) { float aspect = p_viewport->size.aspect(); - int max_size = occlusion_rays_per_thread * RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + int max_size = occlusion_rays_per_thread * WorkerThreadPool::get_singleton()->get_thread_count(); int viewport_size = p_viewport->size.width * p_viewport->size.height; max_size = CLAMP(max_size, viewport_size / (32 * 32), viewport_size / (2 * 2)); // At least one depth pixel for every 16x16 region. At most one depth pixel for every 2x2 region. @@ -746,11 +746,11 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn _configure_3d_render_buffers(viewport); } -void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) { +void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - viewport->fsr_mipmap_bias = p_mipmap_bias; + viewport->texture_mipmap_bias = p_mipmap_bias; _configure_3d_render_buffers(viewport); } @@ -1016,7 +1016,7 @@ void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas viewport->canvas_map[p_canvas].sublayer = p_sublayer; } -void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) { +void RendererViewport::viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); @@ -1026,7 +1026,7 @@ void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits); } -void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { +void RendererViewport::viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); @@ -1207,6 +1207,22 @@ RID RendererViewport::viewport_find_from_screen_attachment(DisplayServer::Window return RID(); } +void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + + RSG::texture_storage->render_target_set_vrs_mode(viewport->render_target, p_mode); + _configure_3d_render_buffers(viewport); +} + +void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + + RSG::texture_storage->render_target_set_vrs_texture(viewport->render_target, p_texture); + _configure_3d_render_buffers(viewport); +} + bool RendererViewport::free(RID p_rid) { if (viewport_owner.owns(p_rid)) { Viewport *viewport = viewport_owner.get_or_null(p_rid); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index acab8063d1..5e37c96336 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -48,33 +48,34 @@ public: RID self; RID parent; - bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */ + // use xr interface to override camera positioning and projection matrices and control output + bool use_xr = false; Size2i internal_size; Size2i size; RID camera; RID scenario; - RS::ViewportScaling3DMode scaling_3d_mode; + RS::ViewportScaling3DMode scaling_3d_mode = RenderingServer::VIEWPORT_SCALING_3D_MODE_BILINEAR; float scaling_3d_scale = 1.0; float fsr_sharpness = 0.2f; - float fsr_mipmap_bias = 0.0f; - bool fsr_enabled; - RS::ViewportUpdateMode update_mode; + float texture_mipmap_bias = 0.0f; + bool fsr_enabled = false; + RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE; RID render_target; RID render_target_texture; RID render_buffers; - RS::ViewportMSAA msaa; - RS::ViewportScreenSpaceAA screen_space_aa; - bool use_taa; - bool use_debanding; + RS::ViewportMSAA msaa = RenderingServer::VIEWPORT_MSAA_DISABLED; + RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + bool use_taa = false; + bool use_debanding = false; RendererSceneRender::CameraData prev_camera_data; uint64_t prev_camera_data_frame = 0; - bool use_occlusion_culling; - bool occlusion_buffer_dirty; + bool use_occlusion_culling = false; + bool occlusion_buffer_dirty = false; DisplayServer::WindowID viewport_to_screen; Rect2 viewport_to_screen_rect; @@ -83,10 +84,10 @@ public: bool disable_2d = false; bool disable_environment = false; bool disable_3d = false; - bool measure_render_time; + bool measure_render_time = false; - bool snap_2d_transforms_to_pixel; - bool snap_2d_vertices_to_pixel; + bool snap_2d_transforms_to_pixel = false; + bool snap_2d_vertices_to_pixel = false; uint64_t time_cpu_begin; uint64_t time_cpu_end; @@ -95,23 +96,23 @@ public: uint64_t time_gpu_end; RID shadow_atlas; - int shadow_atlas_size; + int shadow_atlas_size = 2048; bool shadow_atlas_16_bits = true; - bool sdf_active; + bool sdf_active = false; float mesh_lod_threshold = 1.0; uint64_t last_pass = 0; - RS::ViewportDebugDraw debug_draw; + RS::ViewportDebugDraw debug_draw = RenderingServer::VIEWPORT_DEBUG_DRAW_DISABLED; - RS::ViewportClearMode clear_mode; + RS::ViewportClearMode clear_mode = RenderingServer::VIEWPORT_CLEAR_ALWAYS; RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - bool transparent_bg; + bool transparent_bg = false; struct CanvasKey { int64_t stacking; @@ -228,7 +229,7 @@ public: void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode); void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale); void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness); - void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias); + void viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias); void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode); void viewport_set_vflip(RID p_viewport, bool p_enable); @@ -255,8 +256,8 @@ public: void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform); void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer); - void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true); - void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); + void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true); + void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa); void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode); @@ -284,6 +285,9 @@ public: virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const; + void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode); + void viewport_set_vrs_texture(RID p_viewport, RID p_texture); + void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time); void set_default_clear_color(const Color &p_color); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 6fc5d0b3e8..c07a783302 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -64,12 +64,12 @@ Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_ ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>()); - return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, &device_capabilities); + return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, this); } String RenderingDevice::shader_get_spirv_cache_key() const { if (get_spirv_cache_key_function) { - return get_spirv_cache_key_function(&device_capabilities); + return get_spirv_cache_key_function(this); } return String(); } @@ -279,6 +279,7 @@ static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constan } return ret; } + RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) { PipelineRasterizationState rasterization_state; if (p_rasterization_state.is_valid()) { @@ -386,6 +387,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1)); ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID)); ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format); + ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid); ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 0973e29974..a864cfa74c 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -123,21 +123,14 @@ public: DeviceFamily device_family = DEVICE_UNKNOWN; uint32_t version_major = 1.0; uint32_t version_minor = 0.0; - - // subgroup capabilities - uint32_t subgroup_size = 0; - uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. - uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations - - // features - bool supports_multiview = false; // If true this device supports multiview options - bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode }; - typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities); - typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities); + typedef String (*ShaderSPIRVGetCacheKeyFunction)(const RenderingDevice *p_render_device); + typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device); typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language); + typedef void (*InvalidationCallback)(void *); + private: static ShaderCompileToSPIRVFunction compile_to_spirv_function; static ShaderCacheFunction cache_function; @@ -444,6 +437,7 @@ public: TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7), TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8), TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9), + TEXTURE_USAGE_VRS_ATTACHMENT_BIT = (1 << 10), }; enum TextureSwizzle { @@ -552,15 +546,18 @@ public: Vector<int32_t> resolve_attachments; Vector<int32_t> preserve_attachments; int32_t depth_attachment = ATTACHMENT_UNUSED; + int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported }; - virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0; + virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0; virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0; virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0; virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0; - virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0; + virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0; virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0; + virtual bool framebuffer_is_valid(RID p_framebuffer) const = 0; + virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) = 0; virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0; @@ -675,6 +672,13 @@ public: const Capabilities *get_device_capabilities() const { return &device_capabilities; }; + enum Features { + SUPPORTS_MULTIVIEW, + SUPPORTS_FSR_HALF_FLOAT, + SUPPORTS_ATTACHMENT_VRS, + }; + virtual bool has_feature(const Features p_feature) const = 0; + virtual Vector<uint8_t> shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true); virtual String shader_get_spirv_cache_key() const; @@ -793,8 +797,7 @@ public: virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0; virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; - typedef void (*UniformSetInvalidatedCallback)(void *); - virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0; + virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) = 0; virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; @@ -1221,9 +1224,12 @@ public: LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X, LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y, LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z, + LIMIT_SUBGROUP_SIZE, + LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. + LIMIT_SUBGROUP_OPERATIONS, }; - virtual uint64_t limit_get(Limit p_limit) = 0; + virtual uint64_t limit_get(Limit p_limit) const = 0; //methods below not exposed, used by RenderingDeviceRD virtual void prepare_screen_for_drawing() = 0; @@ -1324,6 +1330,7 @@ VARIANT_ENUM_CAST(RenderingDevice::InitialAction) VARIANT_ENUM_CAST(RenderingDevice::FinalAction) VARIANT_ENUM_CAST(RenderingDevice::Limit) VARIANT_ENUM_CAST(RenderingDevice::MemoryType) +VARIANT_ENUM_CAST(RenderingDevice::Features) typedef RenderingDevice RD; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index bcd7e6a1dd..8071b7e416 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -106,7 +106,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { Callable c = frame_drawn_callbacks.front()->get(); Variant result; Callable::CallError ce; - c.call(nullptr, 0, result, ce); + c.callp(nullptr, 0, result, ce); if (ce.error != Callable::CallError::CALL_OK) { String err = Variant::get_callable_error_text(c, nullptr, 0, ce); ERR_PRINT("Error calling frame drawn function: " + err); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 584d9a7a51..cc79d09503 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -224,9 +224,10 @@ public: FUNCRIDSPLIT(shader) FUNC2(shader_set_code, RID, const String &) + FUNC2(shader_set_path_hint, RID, const String &) FUNC1RC(String, shader_get_code, RID) - FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *) + FUNC2SC(shader_get_shader_uniform_list, RID, List<PropertyInfo> *) FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int) FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int) @@ -590,7 +591,7 @@ public: FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode) FUNC2(viewport_set_scaling_3d_scale, RID, float) FUNC2(viewport_set_fsr_sharpness, RID, float) - FUNC2(viewport_set_fsr_mipmap_bias, RID, float) + FUNC2(viewport_set_texture_mipmap_bias, RID, float) FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) @@ -615,9 +616,9 @@ public: FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) - FUNC3(viewport_set_shadow_atlas_size, RID, int, bool) + FUNC3(viewport_set_positional_shadow_atlas_size, RID, int, bool) FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale) - FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) + FUNC3(viewport_set_positional_shadow_atlas_quadrant_subdivision, RID, int, int) FUNC2(viewport_set_msaa, RID, ViewportMSAA) FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) FUNC2(viewport_set_use_taa, RID, bool) @@ -637,6 +638,9 @@ public: FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID) + FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode) + FUNC2(viewport_set_vrs_texture, RID, RID) + /* ENVIRONMENT API */ #undef server_name @@ -715,8 +719,8 @@ public: FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) FUNC3(camera_effects_set_custom_exposure, RID, bool, float) - FUNC1(shadows_quality_set, ShadowQuality); - FUNC1(directional_shadow_quality_set, ShadowQuality); + FUNC1(positional_soft_shadow_filter_set_quality, ShadowQuality); + FUNC1(directional_soft_shadow_filter_set_quality, ShadowQuality); FUNC1(decals_set_filter, RS::DecalFilter); FUNC1(light_projectors_set_filter, RS::LightProjectorFilter); @@ -769,10 +773,10 @@ public: FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) FUNC2(instance_geometry_set_lod_bias, RID, float) FUNC2(instance_geometry_set_transparency, RID, float) - FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) - FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) - FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &) - FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *) + FUNC3(instance_geometry_set_shader_uniform, RID, const StringName &, const Variant &) + FUNC2RC(Variant, instance_geometry_get_shader_uniform, RID, const StringName &) + FUNC2RC(Variant, instance_geometry_get_shader_uniform_default_value, RID, const StringName &) + FUNC2C(instance_geometry_get_shader_uniform_list, RID, List<PropertyInfo> *) FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &) @@ -896,7 +900,7 @@ public: FUNC1(canvas_set_shadow_texture_size, int) - /* GLOBAL VARIABLES */ + /* GLOBAL SHADER UNIFORMS */ #undef server_name #undef ServerName @@ -904,16 +908,16 @@ public: #define ServerName RendererMaterialStorage #define server_name RSG::material_storage - FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &) - FUNC1(global_variable_remove, const StringName &) - FUNC0RC(Vector<StringName>, global_variable_get_list) - FUNC2(global_variable_set, const StringName &, const Variant &) - FUNC2(global_variable_set_override, const StringName &, const Variant &) - FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &) - FUNC1RC(Variant, global_variable_get, const StringName &) + FUNC3(global_shader_uniform_add, const StringName &, GlobalShaderUniformType, const Variant &) + FUNC1(global_shader_uniform_remove, const StringName &) + FUNC0RC(Vector<StringName>, global_shader_uniform_get_list) + FUNC2(global_shader_uniform_set, const StringName &, const Variant &) + FUNC2(global_shader_uniform_set_override, const StringName &, const Variant &) + FUNC1RC(GlobalShaderUniformType, global_shader_uniform_get_type, const StringName &) + FUNC1RC(Variant, global_shader_uniform_get, const StringName &) - FUNC1(global_variables_load_settings, bool) - FUNC0(global_variables_clear) + FUNC1(global_shader_uniforms_load_settings, bool) + FUNC0(global_shader_uniforms_clear) #undef server_name #undef ServerName @@ -977,4 +981,4 @@ public: ~RenderingServerDefault(); }; -#endif +#endif // RENDERING_SERVER_DEFAULT_H diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 463b67033d..7637eae4a6 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -370,7 +370,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str } } -static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) { +static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) { switch (p_type) { case ShaderLanguage::TYPE_BOOL: { return "(" + p_buffer + "[" + p_index + "].x != 0.0)"; @@ -903,11 +903,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is //global variable, this means the code points to an index to the global table - code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); + code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); } else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { //instance variable, index it as such code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")"; - code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); + code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); } else { //regular uniform, index from UBO code = actions.base_uniform_string + _mkid(vnode->name); @@ -1003,11 +1003,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is //global variable, this means the code points to an index to the global table - code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); + code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); } else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { //instance variable, index it as such code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")"; - code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); + code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type); } else { //regular uniform, index from UBO code = actions.base_uniform_string + _mkid(anode->name); @@ -1309,8 +1309,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) { - RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type); - return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt); + RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_type); + return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); } Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { @@ -1318,23 +1318,81 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident info.functions = ShaderTypes::get_singleton()->get_functions(p_mode); info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode); info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_variable_type_func = _get_variable_type; + info.global_shader_uniform_type_func = _get_variable_type; Error err = parser.compile(p_code, info); if (err != OK) { + Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions(); + + String current; + HashMap<String, Vector<String>> includes; + includes[""] = Vector<String>(); + Vector<String> include_stack; Vector<String> shader = p_code.split("\n"); + + // Reconstruct the files. for (int i = 0; i < shader.size(); i++) { - if (i + 1 == parser.get_error_line()) { - // Mark the error line to be visible without having to look at - // the trace at the end. - print_line(vformat("E%4d-> %s", i + 1, shader[i])); + String l = shader[i]; + if (l.begins_with("@@>")) { + String inc_path = l.replace_first("@@>", ""); + + l = "#include \"" + inc_path + "\""; + includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive + include_stack.push_back(current); + current = inc_path; + includes[inc_path] = Vector<String>(); + + } else if (l.begins_with("@@<")) { + if (include_stack.size()) { + current = include_stack[include_stack.size() - 1]; + include_stack.resize(include_stack.size() - 1); + } + } else { + includes[current].push_back(l); + } + } + + // Print the files. + for (const KeyValue<String, Vector<String>> &E : includes) { + if (E.key.is_empty()) { + if (p_path == "") { + print_line("--Main Shader--"); + } else { + print_line("--" + p_path + "--"); + } } else { - print_line(vformat("%5d | %s", i + 1, shader[i])); + print_line("--" + E.key + "--"); } + int err_line = -1; + for (int i = 0; i < include_positions.size(); i++) { + if (include_positions[i].file == E.key) { + err_line = include_positions[i].line; + } + } + const Vector<String> &V = E.value; + for (int i = 0; i < V.size(); i++) { + if (i == err_line - 1) { + // Mark the error line to be visible without having to look at + // the trace at the end. + print_line(vformat("E%4d-> %s", i + 1, V[i])); + } else { + print_line(vformat("%5d | %s", i + 1, V[i])); + } + } + } + + String file; + int line; + if (include_positions.size() > 1) { + file = include_positions[include_positions.size() - 1].file; + line = include_positions[include_positions.size() - 1].line; + } else { + file = p_path; + line = parser.get_error_line(); } - _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER); + _err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER); return err; } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index ad9b51ac0c..839f5b8eea 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -32,7 +32,9 @@ #include "core/os/os.h" #include "core/string/print_string.h" +#include "core/templates/local_vector.h" #include "servers/rendering_server.h" +#include "shader_types.h" #define HAS_WARNING(flag) (warning_flags & flag) @@ -193,6 +195,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "SOURCE_COLOR", "HINT_DEFAULT_WHITE_TEXTURE", "HINT_DEFAULT_BLACK_TEXTURE", + "HINT_DEFAULT_TRANSPARENT_TEXTURE", "HINT_NORMAL_TEXTURE", "HINT_ANISOTROPY_TEXTURE", "HINT_RANGE", @@ -308,6 +311,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { // global space keywords { TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} }, + { TK_UNIFORM_GROUP, "group_uniforms", CF_GLOBAL_SPACE, {}, {} }, { TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} }, { TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} }, { TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} }, @@ -351,6 +355,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} }, @@ -574,6 +579,37 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { return _make_token(TK_OP_MOD); } break; + case '@': { + if (GETCHAR(0) == '@' && GETCHAR(1) == '>') { + char_idx += 2; + + LocalVector<char32_t> incp; + while (GETCHAR(0) != '\n') { + incp.push_back(GETCHAR(0)); + char_idx++; + } + incp.push_back(0); // Zero end it. + String include_path(incp.ptr()); + include_positions.write[include_positions.size() - 1].line = tk_line; + FilePosition fp; + fp.file = include_path; + fp.line = 0; + tk_line = 0; + include_positions.push_back(fp); + + } else if (GETCHAR(0) == '@' && GETCHAR(1) == '<') { + if (include_positions.size() == 1) { + return _make_token(TK_ERROR, "Invalid include exit hint @@< without matching enter hint."); + } + char_idx += 2; + + include_positions.resize(include_positions.size() - 1); // Pop back. + tk_line = include_positions[include_positions.size() - 1].line; // Restore line. + + } else { + return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)"); + } + } break; default: { char_idx--; //go back one, since we have no idea what this is @@ -1054,6 +1090,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_DEFAULT_WHITE: { result = "hint_default_white"; } break; + case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + result = "hint_default_transparent"; + } break; case ShaderNode::Uniform::HINT_ANISOTROPY: { result = "hint_anisotropy"; } break; @@ -1113,6 +1152,8 @@ void ShaderLanguage::clear() { current_function = StringName(); last_name = StringName(); last_type = IDENTIFIER_MAX; + current_uniform_group_name = ""; + current_uniform_subgroup_name = ""; completion_type = COMPLETION_NONE; completion_block = nullptr; @@ -1122,6 +1163,9 @@ void ShaderLanguage::clear() { completion_base = TYPE_VOID; completion_base_array = false; + include_positions.clear(); + include_positions.push_back(FilePosition()); + #ifdef DEBUG_ENABLED keyword_completion_context = CF_GLOBAL_SPACE; used_constants.clear(); @@ -1183,17 +1227,36 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden #endif // DEBUG_ENABLED 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, ConstantNode::Value *r_constant_value) { - if (p_function_info.built_ins.has(p_identifier)) { - if (r_data_type) { - *r_data_type = p_function_info.built_ins[p_identifier].type; - } - if (r_is_const) { - *r_is_const = p_function_info.built_ins[p_identifier].constant; + if (is_shader_inc) { + for (int i = 0; i < RenderingServer::SHADER_MAX; i++) { + for (const KeyValue<StringName, FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) { + if ((current_function == E.key || E.key == "global") && E.value.built_ins.has(p_identifier)) { + if (r_data_type) { + *r_data_type = E.value.built_ins[p_identifier].type; + } + if (r_is_const) { + *r_is_const = E.value.built_ins[p_identifier].constant; + } + if (r_type) { + *r_type = IDENTIFIER_BUILTIN_VAR; + } + return true; + } + } } - if (r_type) { - *r_type = IDENTIFIER_BUILTIN_VAR; + } else { + if (p_function_info.built_ins.has(p_identifier)) { + if (r_data_type) { + *r_data_type = p_function_info.built_ins[p_identifier].type; + } + if (r_is_const) { + *r_is_const = p_function_info.built_ins[p_identifier].constant; + } + if (r_type) { + *r_type = IDENTIFIER_BUILTIN_VAR; + } + return true; } - return true; } if (p_function_info.stage_functions.has(p_identifier)) { @@ -2400,11 +2463,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { // reflect + { "reflect", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, + { "reflect", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, // refract + { "refract", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, + { "refract", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, // faceforward @@ -3798,18 +3865,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C } value = Variant(array); } else { - Basis p; - p[0][0] = p_value[0].real; - p[0][1] = p_value[1].real; - p[0][2] = p_value[2].real; - p[1][0] = p_value[4].real; - p[1][1] = p_value[5].real; - p[1][2] = p_value[6].real; - p[2][0] = p_value[8].real; - p[2][1] = p_value[9].real; - p[2][2] = p_value[10].real; - Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real)); - value = Variant(t); + Projection p = Projection(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real), + Vector4(p_value[4].real, p_value[5].real, p_value[6].real, p_value[7].real), + Vector4(p_value[8].real, p_value[9].real, p_value[10].real, p_value[11].real), + Vector4(p_value[12].real, p_value[13].real, p_value[14].real, p_value[15].real)); + value = Variant(p); } break; } @@ -3891,13 +3951,29 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform } } } break; - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_IVEC4: case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_IVEC2: { + if (p_uniform.array_size > 0) { + pi.type = Variant::PACKED_INT32_ARRAY; + } else { + pi.type = Variant::VECTOR2I; + } + } break; case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_UVEC4: { - pi.type = Variant::PACKED_INT32_ARRAY; + case ShaderLanguage::TYPE_IVEC3: { + if (p_uniform.array_size > 0) { + pi.type = Variant::PACKED_INT32_ARRAY; + } else { + pi.type = Variant::VECTOR3I; + } + } break; + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_IVEC4: { + if (p_uniform.array_size > 0) { + pi.type = Variant::PACKED_INT32_ARRAY; + } else { + pi.type = Variant::VECTOR4I; + } } break; case ShaderLanguage::TYPE_FLOAT: { if (p_uniform.array_size > 0) { @@ -3945,7 +4021,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { pi.type = Variant::COLOR; } else { - pi.type = Variant::QUATERNION; + pi.type = Variant::VECTOR4; } } } break; @@ -3967,7 +4043,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_FLOAT32_ARRAY; } else { - pi.type = Variant::TRANSFORM3D; + pi.type = Variant::PROJECTION; } break; case ShaderLanguage::TYPE_SAMPLER2D: @@ -7086,9 +7162,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!n) { return ERR_PARSE_ERROR; } - if (n->get_datatype() != TYPE_INT) { - _set_error(RTR("Expected an integer expression.")); - return ERR_PARSE_ERROR; + { + const ShaderLanguage::DataType switch_type = n->get_datatype(); + if (switch_type != TYPE_INT && switch_type != TYPE_UINT) { + _set_error(RTR("Expected an integer expression.")); + return ERR_PARSE_ERROR; + } } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { @@ -7678,34 +7757,38 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci } Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) { - Token tk = _get_token(); + Token tk; TkPos prev_pos; Token next; - if (tk.type != TK_SHADER_TYPE) { - _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); - return ERR_PARSE_ERROR; - } + if (!is_shader_inc) { + tk = _get_token(); + + if (tk.type != TK_SHADER_TYPE) { + _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); + return ERR_PARSE_ERROR; + } #ifdef DEBUG_ENABLED - keyword_completion_context = CF_UNSPECIFIED; + keyword_completion_context = CF_UNSPECIFIED; #endif // DEBUG_ENABLED - _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier); - if (shader_type_identifier == StringName()) { - _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); - return ERR_PARSE_ERROR; - } - if (!p_shader_types.has(shader_type_identifier)) { - _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types))); - return ERR_PARSE_ERROR; - } - prev_pos = _get_tkpos(); - tk = _get_token(); + _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier); + if (shader_type_identifier == StringName()) { + _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); + return ERR_PARSE_ERROR; + } + if (!p_shader_types.has(shader_type_identifier)) { + _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types))); + return ERR_PARSE_ERROR; + } + prev_pos = _get_tkpos(); + tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_tkpos(prev_pos); - _set_expected_after_error(";", "shader_type " + String(shader_type_identifier)); - return ERR_PARSE_ERROR; + if (tk.type != TK_SEMICOLON) { + _set_tkpos(prev_pos); + _set_expected_after_error(";", "shader_type " + String(shader_type_identifier)); + return ERR_PARSE_ERROR; + } } #ifdef DEBUG_ENABLED @@ -7760,25 +7843,54 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f bool found = false; - for (int i = 0; i < p_render_modes.size(); i++) { - const ModeInfo &info = p_render_modes[i]; - const String name = String(info.name); + if (is_shader_inc) { + for (int i = 0; i < RenderingServer::SHADER_MAX; i++) { + const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i)); - if (smode.begins_with(name)) { - if (!info.options.is_empty()) { - if (info.options.has(smode.substr(name.length() + 1))) { - found = true; + for (int j = 0; j < modes.size(); j++) { + const ModeInfo &info = modes[j]; + const String name = String(info.name); - if (defined_modes.has(name)) { - _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name])); - return ERR_PARSE_ERROR; + if (smode.begins_with(name)) { + if (!info.options.is_empty()) { + if (info.options.has(smode.substr(name.length() + 1))) { + found = true; + + if (defined_modes.has(name)) { + _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name])); + return ERR_PARSE_ERROR; + } + defined_modes.insert(name, smode); + break; + } + } else { + found = true; + break; + } + } + } + } + } else { + for (int i = 0; i < p_render_modes.size(); i++) { + const ModeInfo &info = p_render_modes[i]; + const String name = String(info.name); + + if (smode.begins_with(name)) { + if (!info.options.is_empty()) { + if (info.options.has(smode.substr(name.length() + 1))) { + found = true; + + if (defined_modes.has(name)) { + _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name])); + return ERR_PARSE_ERROR; + } + defined_modes.insert(name, smode); + break; } - defined_modes.insert(name, smode); + } else { + found = true; break; } - } else { - found = true; - break; } } } @@ -8177,7 +8289,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (is_uniform) { if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor. //validate global uniform - DataType gvtype = global_var_get_type_func(name); + DataType gvtype = global_shader_uniform_get_type_func(name); if (gvtype == TYPE_MAX) { _set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name))); return ERR_PARSE_ERROR; @@ -8194,6 +8306,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f uniform.scope = uniform_scope; uniform.precision = precision; uniform.array_size = array_size; + uniform.group = current_uniform_group_name; + uniform.subgroup = current_uniform_subgroup_name; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -8308,6 +8422,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_HINT_DEFAULT_WHITE_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE; } break; + case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT; + } break; case TK_HINT_NORMAL_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_NORMAL; } break; @@ -8620,6 +8737,45 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } } break; + case TK_UNIFORM_GROUP: { + tk = _get_token(); + if (tk.type == TK_IDENTIFIER) { + current_uniform_group_name = tk.text; + tk = _get_token(); + if (tk.type == TK_PERIOD) { + tk = _get_token(); + if (tk.type == TK_IDENTIFIER) { + current_uniform_subgroup_name = tk.text; + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_expected_error(";"); + return ERR_PARSE_ERROR; + } + } else { + _set_error(RTR("Expected an uniform subgroup identifier.")); + return ERR_PARSE_ERROR; + } + } else if (tk.type != TK_SEMICOLON) { + _set_expected_error(";", "."); + return ERR_PARSE_ERROR; + } + } else { + if (tk.type != TK_SEMICOLON) { + if (current_uniform_group_name.is_empty()) { + _set_error(RTR("Expected an uniform group identifier.")); + } else { + _set_error(RTR("Expected an uniform group identifier or `;`.")); + } + return ERR_PARSE_ERROR; + } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) { + _set_error(RTR("Group needs to be opened before.")); + return ERR_PARSE_ERROR; + } else { + current_uniform_group_name = ""; + current_uniform_subgroup_name = ""; + } + } + } break; case TK_SHADER_TYPE: { _set_error(RTR("Shader type is already defined.")); return ERR_PARSE_ERROR; @@ -9508,9 +9664,11 @@ uint32_t ShaderLanguage::get_warning_flags() const { Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) { clear(); + is_shader_inc = p_info.is_include; code = p_code; - global_var_get_type_func = p_info.global_variable_type_func; + global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func; + varying_function_names = p_info.varying_function_names; nodes = nullptr; @@ -9532,12 +9690,13 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) { clear(); + is_shader_inc = p_info.is_include; code = p_code; varying_function_names = p_info.varying_function_names; nodes = nullptr; - global_var_get_type_func = p_info.global_variable_type_func; + global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func; shader = alloc_node<ShaderNode>(); _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types); @@ -9577,30 +9736,64 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ return OK; } break; case COMPLETION_RENDER_MODE: { - for (int i = 0; i < p_info.render_modes.size(); i++) { - const ModeInfo &info = p_info.render_modes[i]; + if (is_shader_inc) { + for (int i = 0; i < RenderingServer::SHADER_MAX; i++) { + const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i)); - if (!info.options.is_empty()) { - bool found = false; + for (int j = 0; j < modes.size(); j++) { + const ModeInfo &info = modes[j]; - for (int j = 0; j < info.options.size(); j++) { - if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) { - found = true; + if (!info.options.is_empty()) { + bool found = false; + + for (int k = 0; k < info.options.size(); k++) { + if (shader->render_modes.has(String(info.name) + "_" + String(info.options[k]))) { + found = true; + } + } + + if (!found) { + for (int k = 0; k < info.options.size(); k++) { + ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[k]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } + } + } else { + const String name = String(info.name); + + if (!shader->render_modes.has(name)) { + ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } } } + } + } else { + for (int i = 0; i < p_info.render_modes.size(); i++) { + const ModeInfo &info = p_info.render_modes[i]; + + if (!info.options.is_empty()) { + bool found = false; - if (!found) { for (int j = 0; j < info.options.size(); j++) { - ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - r_options->push_back(option); + if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) { + found = true; + } } - } - } else { - const String name = String(info.name); - if (!shader->render_modes.has(name)) { - ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - r_options->push_back(option); + if (!found) { + for (int j = 0; j < info.options.size(); j++) { + ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } + } + } else { + const String name = String(info.name); + + if (!shader->render_modes.has(name)) { + ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } } } } @@ -9668,33 +9861,69 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } if (comp_ident) { - if (p_info.functions.has("global")) { - for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) { - ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; - if (E.value.constant) { - kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + if (is_shader_inc) { + for (int i = 0; i < RenderingServer::SHADER_MAX; i++) { + const HashMap<StringName, ShaderLanguage::FunctionInfo> info = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i)); + + if (info.has("global")) { + for (const KeyValue<StringName, BuiltInInfo> &E : info["global"].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + + if (info.has("constants")) { + for (const KeyValue<StringName, BuiltInInfo> &E : info["constants"].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + + if (skip_function != StringName() && info.has(skip_function)) { + for (const KeyValue<StringName, BuiltInInfo> &E : info[skip_function].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + } + } else { + if (p_info.functions.has("global")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); } - matches.insert(E.key, kind); } - } - if (p_info.functions.has("constants")) { - for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) { - ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; - if (E.value.constant) { - kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + if (p_info.functions.has("constants")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); } - matches.insert(E.key, kind); } - } - if (skip_function != StringName() && p_info.functions.has(skip_function)) { - for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) { - ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; - if (E.value.constant) { - kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + if (skip_function != StringName() && p_info.functions.has(skip_function)) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) { + ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER; + if (E.value.constant) { + kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT; + } + matches.insert(E.key, kind); } - matches.insert(E.key, kind); } } @@ -10034,6 +10263,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_anisotropy"); options.push_back("hint_default_black"); options.push_back("hint_default_white"); + options.push_back("hint_default_transparent"); options.push_back("hint_normal"); options.push_back("hint_roughness_a"); options.push_back("hint_roughness_b"); @@ -10066,6 +10296,10 @@ String ShaderLanguage::get_error_text() { return error_str; } +Vector<ShaderLanguage::FilePosition> ShaderLanguage::get_include_positions() { + return include_positions; +} + int ShaderLanguage::get_error_line() { return error_line; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 2b147fbeb1..bfec6e1df6 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -38,6 +38,7 @@ #include "core/templates/rb_map.h" #include "core/typedefs.h" #include "core/variant/variant.h" +#include "scene/resources/shader_include.h" #ifdef DEBUG_ENABLED #include "shader_warnings.h" @@ -153,6 +154,7 @@ public: TK_SEMICOLON, TK_PERIOD, TK_UNIFORM, + TK_UNIFORM_GROUP, TK_INSTANCE, TK_GLOBAL, TK_VARYING, @@ -162,6 +164,7 @@ public: TK_RENDER_MODE, TK_HINT_DEFAULT_WHITE_TEXTURE, TK_HINT_DEFAULT_BLACK_TEXTURE, + TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, TK_HINT_NORMAL_TEXTURE, TK_HINT_ROUGHNESS_NORMAL_TEXTURE, TK_HINT_ROUGHNESS_R, @@ -662,6 +665,7 @@ public: HINT_ROUGHNESS_GRAY, HINT_DEFAULT_BLACK, HINT_DEFAULT_WHITE, + HINT_DEFAULT_TRANSPARENT, HINT_ANISOTROPY, HINT_MAX }; @@ -686,6 +690,8 @@ public: TextureRepeat repeat = REPEAT_DEFAULT; float hint_range[3]; int instance_index = 0; + String group; + String subgroup; Uniform() { hint_range[0] = 0.0f; @@ -865,7 +871,12 @@ public: }; static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); - typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name); + typedef DataType (*GlobalShaderUniformGetTypeFunc)(const StringName &p_name); + + struct FilePosition { + String file; + int line = 0; + }; private: struct KeyWord { @@ -878,12 +889,14 @@ private: static const KeyWord keyword_list[]; - GlobalVariableGetTypeFunc global_var_get_type_func = nullptr; + GlobalShaderUniformGetTypeFunc global_shader_uniform_get_type_func = nullptr; bool error_set = false; String error_str; int error_line = 0; + Vector<FilePosition> include_positions; + #ifdef DEBUG_ENABLED struct Usage { int decl_line; @@ -928,6 +941,10 @@ private: StringName current_function; bool last_const = false; StringName last_name; + bool is_shader_inc = false; + + String current_uniform_group_name; + String current_uniform_subgroup_name; VaryingFunctionNames varying_function_names; @@ -951,6 +968,7 @@ private: error_line = tk_line; error_set = true; error_str = p_str; + include_positions.write[include_positions.size() - 1].line = tk_line; } void _set_expected_error(const String &p_what) { @@ -1097,13 +1115,15 @@ public: Vector<ModeInfo> render_modes; VaryingFunctionNames varying_function_names = VaryingFunctionNames(); HashSet<String> shader_types; - GlobalVariableGetTypeFunc global_variable_type_func = nullptr; + GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr; + bool is_include = false; }; Error compile(const String &p_code, const ShaderCompileInfo &p_info); Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint); String get_error_text(); + Vector<FilePosition> get_include_positions(); int get_error_line(); ShaderNode *get_shader(); diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp new file mode 100644 index 0000000000..a7b274b3e2 --- /dev/null +++ b/servers/rendering/shader_preprocessor.cpp @@ -0,0 +1,1048 @@ +/*************************************************************************/ +/* shader_preprocessor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "shader_preprocessor.h" +#include "core/math/expression.h" + +const char32_t CURSOR = 0xFFFF; + +// Tokenizer + +void ShaderPreprocessor::Tokenizer::add_generated(const ShaderPreprocessor::Token &p_t) { + generated.push_back(p_t); +} + +char32_t ShaderPreprocessor::Tokenizer::next() { + if (index < size) { + return code[index++]; + } + return 0; +} + +int ShaderPreprocessor::Tokenizer::get_line() const { + return line; +} + +int ShaderPreprocessor::Tokenizer::get_index() const { + return index; +} + +void ShaderPreprocessor::Tokenizer::get_and_clear_generated(Vector<ShaderPreprocessor::Token> *r_out) { + for (int i = 0; i < generated.size(); i++) { + r_out->push_back(generated[i]); + } + generated.clear(); +} + +void ShaderPreprocessor::Tokenizer::backtrack(char32_t p_what) { + while (index >= 0) { + char32_t c = code[index]; + if (c == p_what) { + break; + } + index--; + } +} + +char32_t ShaderPreprocessor::Tokenizer::peek() { + if (index < size) { + return code[index]; + } + return 0; +} + +LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) { + LocalVector<ShaderPreprocessor::Token> tokens; + + while (index < size) { + char32_t c = code[index++]; + + tokens.push_back(ShaderPreprocessor::Token(c, line)); + + if (c == '\n') { + add_generated(ShaderPreprocessor::Token('\n', line)); + line++; + } + + if (c == p_what || c == 0) { + return tokens; + } + } + return LocalVector<ShaderPreprocessor::Token>(); +} + +void ShaderPreprocessor::Tokenizer::skip_whitespace() { + while (is_char_space(peek())) { + next(); + } +} + +String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) { + if (r_is_cursor != nullptr) { + *r_is_cursor = false; + } + + LocalVector<char32_t> text; + + while (true) { + char32_t c = peek(); + if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') { + break; + } + + if (is_whitespace(c) && p_started) { + break; + } + if (!is_whitespace(c)) { + p_started = true; + } + + char32_t n = next(); + if (n == CURSOR) { + if (r_is_cursor != nullptr) { + *r_is_cursor = true; + } + } else { + if (p_started) { + text.push_back(n); + } + } + } + + String id = vector_to_string(text); + if (!id.is_valid_identifier()) { + return ""; + } + + return id; +} + +String ShaderPreprocessor::Tokenizer::peek_identifier() { + const int original = index; + String id = get_identifier(); + index = original; + return id; +} + +ShaderPreprocessor::Token ShaderPreprocessor::Tokenizer::get_token() { + while (index < size) { + const char32_t c = code[index++]; + const Token t = ShaderPreprocessor::Token(c, line); + + switch (c) { + case ' ': + case '\t': + skip_whitespace(); + return ShaderPreprocessor::Token(' ', line); + case '\n': + line++; + return t; + default: + return t; + } + } + return ShaderPreprocessor::Token(char32_t(0), line); +} + +ShaderPreprocessor::Tokenizer::Tokenizer(const String &p_code) { + code = p_code; + line = 0; + index = 0; + size = code.size(); +} + +// ShaderPreprocessor::CommentRemover + +String ShaderPreprocessor::CommentRemover::get_error() const { + if (comments_open != 0) { + return "Block comment mismatch"; + } + return ""; +} + +int ShaderPreprocessor::CommentRemover::get_error_line() const { + if (comments_open != 0) { + return comment_line_open; + } + return -1; +} + +char32_t ShaderPreprocessor::CommentRemover::peek() const { + if (index < code.size()) { + return code[index]; + } + return 0; +} + +bool ShaderPreprocessor::CommentRemover::advance(char32_t p_what) { + while (index < code.size()) { + char32_t c = code[index++]; + + if (c == '\n') { + line++; + stripped.push_back('\n'); + } + + if (c == p_what) { + return true; + } + } + return false; +} + +String ShaderPreprocessor::CommentRemover::strip() { + stripped.clear(); + index = 0; + line = 0; + comment_line_open = 0; + comments_open = 0; + strings_open = 0; + + while (index < code.size()) { + char32_t c = code[index++]; + + if (c == CURSOR) { + // Cursor. Maintain. + stripped.push_back(c); + } else if (c == '"') { + if (strings_open <= 0) { + strings_open++; + } else { + strings_open--; + } + stripped.push_back(c); + } else if (c == '/' && strings_open == 0) { + char32_t p = peek(); + if (p == '/') { // Single line comment. + advance('\n'); + } else if (p == '*') { // Start of a block comment. + index++; + comment_line_open = line; + comments_open++; + while (advance('*')) { + if (peek() == '/') { // End of a block comment. + comments_open--; + index++; + break; + } + } + } else { + stripped.push_back(c); + } + } else if (c == '*' && strings_open == 0) { + if (peek() == '/') { // Unmatched end of a block comment. + comment_line_open = line; + comments_open--; + } else { + stripped.push_back(c); + } + } else if (c == '\n') { + line++; + stripped.push_back(c); + } else { + stripped.push_back(c); + } + } + return vector_to_string(stripped); +} + +ShaderPreprocessor::CommentRemover::CommentRemover(const String &p_code) { + code = p_code; + index = 0; + line = 0; + comment_line_open = 0; + comments_open = 0; + strings_open = 0; +} + +// ShaderPreprocessor::Token + +ShaderPreprocessor::Token::Token() { + text = 0; + line = -1; +} + +ShaderPreprocessor::Token::Token(char32_t p_text, int p_line) { + text = p_text; + line = p_line; +} + +// ShaderPreprocessor + +bool ShaderPreprocessor::is_char_word(char32_t p_char) { + if ((p_char >= '0' && p_char <= '9') || + (p_char >= 'a' && p_char <= 'z') || + (p_char >= 'A' && p_char <= 'Z') || + p_char == '_') { + return true; + } + + return false; +} + +bool ShaderPreprocessor::is_char_space(char32_t p_char) { + return p_char == ' ' || p_char == '\t'; +} + +bool ShaderPreprocessor::is_char_end(char32_t p_char) { + return p_char == '\n' || p_char == 0; +} + +String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, int p_start, int p_end) { + const int stop = (p_end == -1) ? p_v.size() : p_end; + const int count = stop - p_start; + + String result; + result.resize(count + 1); + for (int i = 0; i < count; i++) { + result[i] = p_v[p_start + i]; + } + result[count] = 0; // Ensure string is null terminated for length() to work. + return result; +} + +String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) { + LocalVector<char32_t> result; + for (uint32_t i = 0; i < p_tokens.size(); i++) { + result.push_back(p_tokens[i].text); + } + return vector_to_string(result); +} + +void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) { + bool is_cursor; + String directive = p_tokenizer->get_identifier(&is_cursor, true); + if (is_cursor) { + state->completion_type = COMPLETION_TYPE_DIRECTIVE; + } + + if (directive == "if") { + process_if(p_tokenizer); + } else if (directive == "ifdef") { + process_ifdef(p_tokenizer); + } else if (directive == "ifndef") { + process_ifndef(p_tokenizer); + } else if (directive == "else") { + process_else(p_tokenizer); + } else if (directive == "endif") { + process_endif(p_tokenizer); + } else if (directive == "define") { + process_define(p_tokenizer); + } else if (directive == "undef") { + process_undef(p_tokenizer); + } else if (directive == "include") { + process_include(p_tokenizer); + } else if (directive == "pragma") { + process_pragma(p_tokenizer); + } else { + set_error(RTR("Unknown directive."), p_tokenizer->get_line()); + } +} + +void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + String label = p_tokenizer->get_identifier(); + if (label.is_empty()) { + set_error(RTR("Invalid macro name."), line); + return; + } + + if (state->defines.has(label)) { + set_error(RTR("Macro redefinition."), line); + return; + } + + if (p_tokenizer->peek() == '(') { + // Macro has arguments. + p_tokenizer->get_token(); + + Vector<String> args; + while (true) { + String name = p_tokenizer->get_identifier(); + if (name.is_empty()) { + set_error(RTR("Invalid argument name."), line); + return; + } + args.push_back(name); + + p_tokenizer->skip_whitespace(); + char32_t next = p_tokenizer->get_token().text; + if (next == ')') { + break; + } else if (next != ',') { + set_error(RTR("Expected a comma in the macro argument list."), line); + return; + } + } + + Define *define = memnew(Define); + define->arguments = args; + define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + state->defines[label] = define; + } else { + // Simple substitution macro. + Define *define = memnew(Define); + define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + state->defines[label] = define; + } +} + +void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { + if (state->skip_stack_else.is_empty()) { + set_error(RTR("Unmatched else."), p_tokenizer->get_line()); + return; + } + p_tokenizer->advance('\n'); + + bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1]; + state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1); + + Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include]; + int index = vec.size() - 1; + if (index >= 0) { + SkippedCondition *cond = vec[index]; + if (cond->end_line == -1) { + cond->end_line = p_tokenizer->get_line(); + } + } + + if (skip) { + Vector<String> ends; + ends.push_back("endif"); + next_directive(p_tokenizer, ends); + } +} + +void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { + state->condition_depth--; + if (state->condition_depth < 0) { + set_error(RTR("Unmatched endif."), p_tokenizer->get_line()); + return; + } + + Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include]; + int index = vec.size() - 1; + if (index >= 0) { + SkippedCondition *cond = vec[index]; + if (cond->end_line == -1) { + cond->end_line = p_tokenizer->get_line(); + } + } + + p_tokenizer->advance('\n'); +} + +void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { + int line = p_tokenizer->get_line(); + + String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.is_empty()) { + set_error(RTR("Missing condition."), line); + return; + } + + Error error = expand_macros(body, line, body); + if (error != OK) { + return; + } + + Expression expression; + Vector<String> names; + error = expression.parse(body, names); + if (error != OK) { + set_error(expression.get_error_text(), line); + return; + } + + Variant v = expression.execute(Array(), nullptr, false); + if (v.get_type() == Variant::NIL) { + set_error(RTR("Condition evaluation error."), line); + return; + } + + bool success = v.booleanize(); + start_branch_condition(p_tokenizer, success); +} + +void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + String label = p_tokenizer->get_identifier(); + if (label.is_empty()) { + set_error(RTR("Invalid macro name."), line); + return; + } + + p_tokenizer->skip_whitespace(); + if (!is_char_end(p_tokenizer->peek())) { + set_error(RTR("Invalid ifdef."), line); + return; + } + p_tokenizer->advance('\n'); + + bool success = state->defines.has(label); + start_branch_condition(p_tokenizer, success); +} + +void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + String label = p_tokenizer->get_identifier(); + if (label.is_empty()) { + set_error(RTR("Invalid macro name."), line); + return; + } + + p_tokenizer->skip_whitespace(); + if (!is_char_end(p_tokenizer->peek())) { + set_error(RTR("Invalid ifndef."), line); + return; + } + p_tokenizer->advance('\n'); + + bool success = !state->defines.has(label); + start_branch_condition(p_tokenizer, success); +} + +void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + p_tokenizer->advance('"'); + String path = tokens_to_string(p_tokenizer->advance('"')); + for (int i = 0; i < path.length(); i++) { + if (path[i] == '\n') { + break; //stop parsing + } + if (path[i] == CURSOR) { + state->completion_type = COMPLETION_TYPE_INCLUDE_PATH; + break; + } + } + path = path.substr(0, path.length() - 1); + p_tokenizer->skip_whitespace(); + + if (path.is_empty() || !is_char_end(p_tokenizer->peek())) { + set_error(RTR("Invalid path."), line); + return; + } + + Ref<Resource> res = ResourceLoader::load(path); + if (res.is_null()) { + set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line); + return; + } + + Ref<ShaderInclude> shader_inc = res; + if (shader_inc.is_null()) { + set_error(RTR("Shader include resource type is wrong."), line); + return; + } + + String included = shader_inc->get_code(); + if (!included.is_empty()) { + uint64_t code_hash = included.hash64(); + if (state->cyclic_include_hashes.find(code_hash)) { + set_error(RTR("Cyclic include found."), line); + return; + } + } + + state->shader_includes.insert(shader_inc); + + const String real_path = shader_inc->get_path(); + if (state->includes.has(real_path)) { + // Already included, skip. + // This is a valid check because 2 separate include paths could use some + // of the same shared functions from a common shader include. + return; + } + + // Mark as included. + state->includes.insert(real_path); + + state->include_depth++; + if (state->include_depth > 25) { + set_error(RTR("Shader max include depth exceeded."), line); + return; + } + + String old_include = state->current_include; + state->current_include = real_path; + ShaderPreprocessor processor; + + int prev_condition_depth = state->condition_depth; + state->condition_depth = 0; + + FilePosition fp; + fp.file = state->current_include; + fp.line = line; + state->include_positions.push_back(fp); + + String result; + processor.preprocess(state, included, result); + add_to_output("@@>" + real_path + "\n"); // Add token for enter include path + add_to_output(result); + add_to_output("\n@@<\n"); // Add token for exit include path + + // Reset to last include if there are no errors. We want to use this as context. + if (state->error.is_empty()) { + state->current_include = old_include; + state->include_positions.pop_back(); + } else { + return; + } + + state->include_depth--; + state->condition_depth = prev_condition_depth; +} + +void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + bool is_cursor; + const String label = p_tokenizer->get_identifier(&is_cursor); + if (is_cursor) { + state->completion_type = COMPLETION_TYPE_PRAGMA; + } + + if (label.is_empty()) { + set_error(RTR("Invalid pragma directive."), line); + return; + } + + // Rxplicitly handle pragma values here. + // If more pragma options are created, then refactor into a more defined structure. + if (label == "disable_preprocessor") { + state->disabled = true; + } else { + set_error(RTR("Invalid pragma directive."), line); + return; + } + + p_tokenizer->advance('\n'); +} + +void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + const String label = p_tokenizer->get_identifier(); + if (label.is_empty() || !state->defines.has(label)) { + set_error(RTR("Invalid name."), line); + return; + } + + p_tokenizer->skip_whitespace(); + if (!is_char_end(p_tokenizer->peek())) { + set_error(RTR("Invalid undef."), line); + return; + } + + memdelete(state->defines[label]); + state->defines.erase(label); +} + +void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) { + state->condition_depth++; + + if (p_success) { + state->skip_stack_else.push_back(true); + } else { + SkippedCondition *cond = memnew(SkippedCondition()); + cond->start_line = p_tokenizer->get_line(); + state->skipped_conditions[state->current_include].push_back(cond); + + Vector<String> ends; + ends.push_back("else"); + ends.push_back("endif"); + if (next_directive(p_tokenizer, ends) == "else") { + state->skip_stack_else.push_back(false); + } else { + state->skip_stack_else.push_back(true); + } + } +} + +void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) { + String line = vector_to_string(output, p_start, output.size()); + + Error error = expand_macros(line, p_line_number - 1, line); // We are already on next line, so -1. + if (error != OK) { + return; + } + + output.resize(p_start); + + add_to_output(line); +} + +Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) { + Vector<Pair<String, Define *>> active_defines; + active_defines.resize(state->defines.size()); + int index = 0; + for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { + active_defines.set(index++, Pair<String, Define *>(E->key(), E->get())); + } + + return expand_macros(p_string, p_line, active_defines, r_expanded); +} + +Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) { + r_expanded = p_string; + // When expanding macros we must only evaluate them once. + // Later we continue expanding but with the already + // evaluated macros removed. + for (int i = 0; i < p_defines.size(); i++) { + Pair<String, Define *> define_pair = p_defines[i]; + + Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded); + if (error != OK) { + return error; + } + + // Remove expanded macro and recursively replace remaining. + p_defines.remove_at(i); + return expand_macros(r_expanded, p_line, p_defines, r_expanded); + } + + return OK; +} + +Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) { + String result = p_line; + + const String &key = p_define_pair.first; + const Define *define = p_define_pair.second; + + int index_start = 0; + int index = 0; + while (find_match(result, key, index, index_start)) { + String body = define->body; + if (define->arguments.size() > 0) { + // Complex macro with arguments. + int args_start = index + key.length(); + int args_end = p_line.find(")", args_start); + if (args_start == -1 || args_end == -1) { + set_error(RTR("Missing macro argument parenthesis."), p_line_number); + return FAILED; + } + + String values = result.substr(args_start + 1, args_end - (args_start + 1)); + Vector<String> args = values.split(","); + if (args.size() != define->arguments.size()) { + set_error(RTR("Invalid macro argument count."), p_line_number); + return FAILED; + } + + // Insert macro arguments into the body. + for (int i = 0; i < args.size(); i++) { + String arg_name = define->arguments[i]; + int arg_index_start = 0; + int arg_index = 0; + while (find_match(body, arg_name, arg_index, arg_index_start)) { + body = body.substr(0, arg_index) + args[i] + body.substr(arg_index + arg_name.length(), body.length() - (arg_index + arg_name.length())); + // Manually reset arg_index_start to where the arg value of the define finishes. + // This ensures we don't skip the other args of this macro in the string. + arg_index_start = arg_index + args[i].length() + 1; + } + } + + result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length()); + } else { + result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length())); + // Manually reset index_start to where the body value of the define finishes. + // This ensures we don't skip another instance of this macro in the string. + index_start = index + body.length() + 1; + break; + } + } + r_expanded = result; + return OK; +} + +bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) { + // Looks for value in string and then determines if the boundaries + // are non-word characters. This method semi-emulates \b in regex. + r_index = p_string.find(p_value, r_index_start); + while (r_index > -1) { + if (r_index > 0) { + if (is_char_word(p_string[r_index - 1])) { + r_index_start = r_index + 1; + r_index = p_string.find(p_value, r_index_start); + continue; + } + } + + if (r_index + p_value.length() < p_string.length()) { + if (is_char_word(p_string[r_index + p_value.length()])) { + r_index_start = r_index + p_value.length() + 1; + r_index = p_string.find(p_value, r_index_start); + continue; + } + } + + // Return and shift index start automatically for next call. + r_index_start = r_index + p_value.length() + 1; + return true; + } + + return false; +} + +String ShaderPreprocessor::next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives) { + const int line = p_tokenizer->get_line(); + int nesting = 0; + + while (true) { + p_tokenizer->advance('#'); + + String id = p_tokenizer->peek_identifier(); + if (id.is_empty()) { + break; + } + + if (nesting == 0) { + for (int i = 0; i < p_directives.size(); i++) { + if (p_directives[i] == id) { + p_tokenizer->backtrack('#'); + return id; + } + } + } + + if (id == "ifdef" || id == "ifndef" || id == "if") { + nesting++; + } else if (id == "endif") { + nesting--; + } + } + + set_error(RTR("Can't find matching branch directive."), line); + return ""; +} + +void ShaderPreprocessor::add_to_output(const String &p_str) { + for (int i = 0; i < p_str.length(); i++) { + output.push_back(p_str[i]); + } +} + +void ShaderPreprocessor::set_error(const String &p_error, int p_line) { + if (state->error.is_empty()) { + state->error = p_error; + FilePosition fp; + fp.line = p_line + 1; + state->include_positions.push_back(fp); + } +} + +ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_body) { + ShaderPreprocessor::Define *define = memnew(Define); + define->body = p_body; + return define; +} + +void ShaderPreprocessor::clear() { + if (state_owner && state != nullptr) { + for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { + memdelete(E->get()); + } + + for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) { + for (SkippedCondition *condition : E->get()) { + memdelete(condition); + } + } + + memdelete(state); + } + state_owner = false; + state = nullptr; +} + +Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) { + clear(); + + output.clear(); + + state = p_state; + + CommentRemover remover(p_code); + String stripped = remover.strip(); + String error = remover.get_error(); + if (!error.is_empty()) { + set_error(error, remover.get_error_line()); + return FAILED; + } + + // Track code hashes to prevent cyclic include. + uint64_t code_hash = p_code.hash64(); + state->cyclic_include_hashes.push_back(code_hash); + + Tokenizer p_tokenizer(stripped); + int last_size = 0; + bool has_symbols_before_directive = false; + + while (true) { + const Token &t = p_tokenizer.get_token(); + + if (t.text == 0) { + break; + } + + if (state->disabled) { + // Preprocessor was disabled. + // Read the rest of the file into the output. + output.push_back(t.text); + continue; + } else { + // Add autogenerated tokens. + Vector<Token> generated; + p_tokenizer.get_and_clear_generated(&generated); + for (int i = 0; i < generated.size(); i++) { + output.push_back(generated[i].text); + } + } + + if (t.text == '#') { + if (has_symbols_before_directive) { + set_error(RTR("Invalid symbols placed before directive."), p_tokenizer.get_line()); + state->cyclic_include_hashes.erase(code_hash); // Remove this hash. + return FAILED; + } + process_directive(&p_tokenizer); + } else { + if (is_char_end(t.text)) { + expand_output_macros(last_size, p_tokenizer.get_line()); + last_size = output.size(); + has_symbols_before_directive = false; + } else if (!is_char_space(t.text)) { + has_symbols_before_directive = true; + } + output.push_back(t.text); + } + + if (!state->error.is_empty()) { + state->cyclic_include_hashes.erase(code_hash); // Remove this hash. + return FAILED; + } + } + state->cyclic_include_hashes.erase(code_hash); // Remove this hash. + + if (!state->disabled) { + if (state->condition_depth != 0) { + set_error(RTR("Unmatched conditional statement."), p_tokenizer.line); + return FAILED; + } + + expand_output_macros(last_size, p_tokenizer.get_line()); + } + + r_result = vector_to_string(output); + + return OK; +} + +Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) { + State pp_state; + Error err = preprocess(&pp_state, p_code, r_result); + if (err != OK) { + if (r_error_text) { + *r_error_text = pp_state.error; + } + if (r_error_position) { + *r_error_position = pp_state.include_positions; + } + } + if (r_includes) { + *r_includes = pp_state.shader_includes; + } + + if (r_completion_options) { + switch (pp_state.completion_type) { + case COMPLETION_TYPE_DIRECTIVE: { + List<String> options; + get_keyword_list(&options, true); + + for (const String &E : options) { + ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_completion_options->push_back(option); + } + + } break; + case COMPLETION_TYPE_PRAGMA: { + List<String> options; + + ShaderPreprocessor::get_pragma_list(&options); + + for (const String &E : options) { + ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_completion_options->push_back(option); + } + + } break; + case COMPLETION_TYPE_INCLUDE_PATH: { + if (p_include_completion_func && r_completion_options) { + p_include_completion_func(r_completion_options); + } + + } break; + default: { + } + } + } + return err; +} + +void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) { + r_keywords->push_back("define"); + if (p_include_shader_keywords) { + r_keywords->push_back("else"); + } + r_keywords->push_back("endif"); + if (p_include_shader_keywords) { + r_keywords->push_back("if"); + } + r_keywords->push_back("ifdef"); + r_keywords->push_back("ifndef"); + r_keywords->push_back("include"); + r_keywords->push_back("pragma"); + r_keywords->push_back("undef"); +} + +void ShaderPreprocessor::get_pragma_list(List<String> *r_pragmas) { + r_pragmas->push_back("disable_preprocessor"); +} + +ShaderPreprocessor::ShaderPreprocessor() { +} + +ShaderPreprocessor::~ShaderPreprocessor() { + clear(); +} diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h new file mode 100644 index 0000000000..a93fb680dd --- /dev/null +++ b/servers/rendering/shader_preprocessor.h @@ -0,0 +1,200 @@ +/*************************************************************************/ +/* shader_preprocessor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 SHADER_PREPROCESSOR_H +#define SHADER_PREPROCESSOR_H + +#include "core/string/ustring.h" +#include "core/templates/list.h" +#include "core/templates/local_vector.h" +#include "core/templates/rb_map.h" +#include "core/templates/rb_set.h" +#include "core/typedefs.h" + +#include "core/io/resource_loader.h" +#include "core/os/os.h" +#include "scene/resources/shader.h" +#include "scene/resources/shader_include.h" + +class ShaderPreprocessor { +public: + enum CompletionType { + COMPLETION_TYPE_NONE, + COMPLETION_TYPE_DIRECTIVE, + COMPLETION_TYPE_PRAGMA_DIRECTIVE, + COMPLETION_TYPE_PRAGMA, + COMPLETION_TYPE_INCLUDE_PATH, + }; + + struct FilePosition { + String file; + int line = 0; + }; + +private: + struct Token { + char32_t text; + int line; + + Token(); + Token(char32_t p_text, int p_line); + }; + + // The real preprocessor that understands basic shader and preprocessor language syntax. + class Tokenizer { + public: + String code; + int line; + int index; + int size; + Vector<Token> generated; + + private: + void add_generated(const Token &p_t); + char32_t next(); + + public: + int get_line() const; + int get_index() const; + char32_t peek(); + + void get_and_clear_generated(Vector<Token> *r_out); + void backtrack(char32_t p_what); + LocalVector<Token> advance(char32_t p_what); + void skip_whitespace(); + String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false); + String peek_identifier(); + Token get_token(); + + Tokenizer(const String &p_code); + }; + + class CommentRemover { + private: + LocalVector<char32_t> stripped; + String code; + int index; + int line; + int comment_line_open; + int comments_open; + int strings_open; + + public: + String get_error() const; + int get_error_line() const; + char32_t peek() const; + + bool advance(char32_t p_what); + String strip(); + + CommentRemover(const String &p_code); + }; + + struct Define { + Vector<String> arguments; + String body; + }; + + struct SkippedCondition { + int start_line = -1; + int end_line = -1; + }; + + struct State { + RBMap<String, Define *> defines; + Vector<bool> skip_stack_else; + int condition_depth = 0; + RBSet<String> includes; + List<uint64_t> cyclic_include_hashes; // Holds code hash of includes. + int include_depth = 0; + String current_include; + String current_shader_type; + String error; + List<FilePosition> include_positions; + RBMap<String, Vector<SkippedCondition *>> skipped_conditions; + bool disabled = false; + CompletionType completion_type = COMPLETION_TYPE_NONE; + HashSet<Ref<ShaderInclude>> shader_includes; + }; + +private: + LocalVector<char32_t> output; + State *state = nullptr; + bool state_owner = false; + +private: + static bool is_char_word(char32_t p_char); + static bool is_char_space(char32_t p_char); + static bool is_char_end(char32_t p_char); + static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1); + static String tokens_to_string(const LocalVector<Token> &p_tokens); + + void process_directive(Tokenizer *p_tokenizer); + void process_define(Tokenizer *p_tokenizer); + void process_else(Tokenizer *p_tokenizer); + void process_endif(Tokenizer *p_tokenizer); + void process_if(Tokenizer *p_tokenizer); + void process_ifdef(Tokenizer *p_tokenizer); + void process_ifndef(Tokenizer *p_tokenizer); + void process_include(Tokenizer *p_tokenizer); + void process_pragma(Tokenizer *p_tokenizer); + void process_undef(Tokenizer *p_tokenizer); + + void start_branch_condition(Tokenizer *p_tokenizer, bool p_success); + + void expand_output_macros(int p_start, int p_line); + Error expand_macros(const String &p_string, int p_line, String &r_result); + Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result); + Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded); + bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start); + + String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives); + void add_to_output(const String &p_str); + void set_error(const String &p_error, int p_line); + + static Define *create_define(const String &p_body); + + void clear(); + + Error preprocess(State *p_state, const String &p_code, String &r_result); + +public: + typedef void (*IncludeCompletionFunction)(List<ScriptLanguage::CodeCompletionOption> *); + + Error preprocess(const String &p_code, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr); + + static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords); + static void get_pragma_list(List<String> *r_pragmas); + + ShaderPreprocessor(); + ~ShaderPreprocessor(); +}; + +#endif // SHADER_PREPROCESSOR_H diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 5772179d68..43c483a00d 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -97,6 +97,11 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); @@ -139,6 +144,11 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 107525cd15..dfec3a7111 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADERTYPES_H -#define SHADERTYPES_H +#ifndef SHADER_TYPES_H +#define SHADER_TYPES_H #include "core/templates/rb_map.h" #include "servers/rendering_server.h" @@ -59,4 +59,4 @@ public: ShaderTypes(); }; -#endif // SHADERTYPES_H +#endif // SHADER_TYPES_H diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index 8edf85842f..d5c6a4b1a6 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_WARNINGS -#define SHADER_WARNINGS +#ifndef SHADER_WARNINGS_H +#define SHADER_WARNINGS_H #ifdef DEBUG_ENABLED @@ -90,4 +90,4 @@ public: #endif // DEBUG_ENABLED -#endif // SHADER_WARNINGS +#endif // SHADER_WARNINGS_H diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp new file mode 100644 index 0000000000..1d4dc55e98 --- /dev/null +++ b/servers/rendering/storage/environment_storage.cpp @@ -0,0 +1,769 @@ +/*************************************************************************/ +/* environment_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "environment_storage.h" + +uint64_t RendererEnvironmentStorage::auto_exposure_counter = 2; + +RID RendererEnvironmentStorage::environment_allocate() { + return environment_owner.allocate_rid(); +} + +void RendererEnvironmentStorage::environment_initialize(RID p_rid) { + environment_owner.initialize_rid(p_rid, Environment()); +} + +void RendererEnvironmentStorage::environment_free(RID p_rid) { + environment_owner.free(p_rid); +} + +// Background + +void RendererEnvironmentStorage::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->background = p_bg; +} + +void RendererEnvironmentStorage::environment_set_sky(RID p_env, RID p_sky) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->sky = p_sky; +} + +void RendererEnvironmentStorage::environment_set_sky_custom_fov(RID p_env, float p_scale) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->sky_custom_fov = p_scale; +} + +void RendererEnvironmentStorage::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->sky_orientation = p_orientation; +} + +void RendererEnvironmentStorage::environment_set_bg_color(RID p_env, const Color &p_color) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->bg_color = p_color; +} + +void RendererEnvironmentStorage::environment_set_bg_energy(RID p_env, float p_energy) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->bg_energy = p_energy; +} + +void RendererEnvironmentStorage::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->canvas_max_layer = p_max_layer; +} + +void RendererEnvironmentStorage::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->ambient_light = p_color; + env->ambient_source = p_ambient; + env->ambient_light_energy = p_energy; + env->ambient_sky_contribution = p_sky_contribution; + env->reflection_source = p_reflection_source; +} + +RS::EnvironmentBG RendererEnvironmentStorage::environment_get_background(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_BG_CLEAR_COLOR); + return env->background; +} + +RID RendererEnvironmentStorage::environment_get_sky(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RID()); + return env->sky; +} + +float RendererEnvironmentStorage::environment_get_sky_custom_fov(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->sky_custom_fov; +} + +Basis RendererEnvironmentStorage::environment_get_sky_orientation(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Basis()); + return env->sky_orientation; +} + +Color RendererEnvironmentStorage::environment_get_bg_color(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->bg_color; +} + +float RendererEnvironmentStorage::environment_get_bg_energy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->bg_energy; +} + +int RendererEnvironmentStorage::environment_get_canvas_max_layer(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->canvas_max_layer; +} + +RS::EnvironmentAmbientSource RendererEnvironmentStorage::environment_get_ambient_source(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG); + return env->ambient_source; +} + +Color RendererEnvironmentStorage::environment_get_ambient_light(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->ambient_light; +} + +float RendererEnvironmentStorage::environment_get_ambient_light_energy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->ambient_light_energy; +} + +float RendererEnvironmentStorage::environment_get_ambient_sky_contribution(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->ambient_sky_contribution; +} + +RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_reflection_source(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_BG); + return env->reflection_source; +} + +// Tonemap + +void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->exposure = p_exposure; + env->tone_mapper = p_tone_mapper; + if (!env->auto_exposure && p_auto_exposure) { + env->auto_exposure_version = ++auto_exposure_counter; + } + env->auto_exposure = p_auto_exposure; + env->white = p_white; + env->min_luminance = p_min_luminance; + env->max_luminance = p_max_luminance; + env->auto_exp_speed = p_auto_exp_speed; + env->auto_exp_scale = p_auto_exp_scale; +} + +RS::EnvironmentToneMapper RendererEnvironmentStorage::environment_get_tone_mapper(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_TONE_MAPPER_LINEAR); + return env->tone_mapper; +} + +float RendererEnvironmentStorage::environment_get_exposure(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->exposure; +} + +float RendererEnvironmentStorage::environment_get_white(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->white; +} + +bool RendererEnvironmentStorage::environment_get_auto_exposure(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->auto_exposure; +} + +float RendererEnvironmentStorage::environment_get_min_luminance(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.2); + return env->min_luminance; +} + +float RendererEnvironmentStorage::environment_get_max_luminance(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 8.0); + return env->max_luminance; +} + +float RendererEnvironmentStorage::environment_get_auto_exp_speed(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.2); + return env->auto_exp_speed; +} + +float RendererEnvironmentStorage::environment_get_auto_exp_scale(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.5); + return env->auto_exp_scale; +} + +uint64_t RendererEnvironmentStorage::environment_get_auto_exposure_version(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->auto_exposure_version; +} + +// Fog + +void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->fog_enabled = p_enable; + env->fog_light_color = p_light_color; + env->fog_light_energy = p_light_energy; + env->fog_sun_scatter = p_sun_scatter; + env->fog_density = p_density; + env->fog_height = p_height; + env->fog_height_density = p_height_density; + env->fog_aerial_perspective = p_fog_aerial_perspective; +} + +bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->fog_enabled; +} + +Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Color(0.5, 0.6, 0.7)); + return env->fog_light_color; +} + +float RendererEnvironmentStorage::environment_get_fog_light_energy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->fog_light_energy; +} + +float RendererEnvironmentStorage::environment_get_fog_sun_scatter(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->fog_sun_scatter; +} + +float RendererEnvironmentStorage::environment_get_fog_density(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.001); + return env->fog_density; +} + +float RendererEnvironmentStorage::environment_get_fog_height(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->fog_height; +} + +float RendererEnvironmentStorage::environment_get_fog_height_density(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->fog_height_density; +} + +float RendererEnvironmentStorage::environment_get_fog_aerial_perspective(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->fog_aerial_perspective; +} + +// Volumetric Fog + +void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->volumetric_fog_enabled = p_enable; + env->volumetric_fog_density = p_density; + env->volumetric_fog_scattering = p_albedo; + env->volumetric_fog_emission = p_emission; + env->volumetric_fog_emission_energy = p_emission_energy; + env->volumetric_fog_anisotropy = p_anisotropy, + env->volumetric_fog_length = p_length; + env->volumetric_fog_detail_spread = p_detail_spread; + env->volumetric_fog_gi_inject = p_gi_inject; + env->volumetric_fog_temporal_reprojection = p_temporal_reprojection; + env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount; + env->volumetric_fog_ambient_inject = p_ambient_inject; +} + +bool RendererEnvironmentStorage::environment_get_volumetric_fog_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->volumetric_fog_enabled; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_density(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.01); + return env->volumetric_fog_density; +} + +Color RendererEnvironmentStorage::environment_get_volumetric_fog_scattering(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Color(1, 1, 1)); + return env->volumetric_fog_scattering; +} + +Color RendererEnvironmentStorage::environment_get_volumetric_fog_emission(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Color(0, 0, 0)); + return env->volumetric_fog_emission; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_emission_energy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->volumetric_fog_emission_energy; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_anisotropy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.2); + return env->volumetric_fog_anisotropy; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_length(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 64.0); + return env->volumetric_fog_length; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_detail_spread(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 2.0); + return env->volumetric_fog_detail_spread; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_gi_inject(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->volumetric_fog_gi_inject; +} + +bool RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, true); + return env->volumetric_fog_temporal_reprojection; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.9); + return env->volumetric_fog_temporal_reprojection_amount; +} + +float RendererEnvironmentStorage::environment_get_volumetric_fog_ambient_inject(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->volumetric_fog_ambient_inject; +} + +// GLOW + +void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); + env->glow_enabled = p_enable; + env->glow_levels = p_levels; + env->glow_intensity = p_intensity; + env->glow_strength = p_strength; + env->glow_mix = p_mix; + env->glow_bloom = p_bloom_threshold; + env->glow_blend_mode = p_blend_mode; + env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; + env->glow_hdr_bleed_scale = p_hdr_bleed_scale; + env->glow_hdr_luminance_cap = p_hdr_luminance_cap; + env->glow_map_strength = p_glow_map_strength; + env->glow_map = p_glow_map; +} + +bool RendererEnvironmentStorage::environment_get_glow_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->glow_enabled; +} + +Vector<float> RendererEnvironmentStorage::environment_get_glow_levels(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, Vector<float>()); + return env->glow_levels; +} + +float RendererEnvironmentStorage::environment_get_glow_intensity(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.8); + return env->glow_intensity; +} + +float RendererEnvironmentStorage::environment_get_glow_strength(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->glow_strength; +} + +float RendererEnvironmentStorage::environment_get_glow_bloom(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->glow_bloom; +} + +float RendererEnvironmentStorage::environment_get_glow_mix(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.01); + return env->glow_mix; +} + +RS::EnvironmentGlowBlendMode RendererEnvironmentStorage::environment_get_glow_blend_mode(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT); + return env->glow_blend_mode; +} + +float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_threshold(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->glow_hdr_bleed_threshold; +} + +float RendererEnvironmentStorage::environment_get_glow_hdr_luminance_cap(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 12.0); + return env->glow_hdr_luminance_cap; +} + +float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_scale(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 2.0); + return env->glow_hdr_bleed_scale; +} + +float RendererEnvironmentStorage::environment_get_glow_map_strength(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->glow_map_strength; +} + +RID RendererEnvironmentStorage::environment_get_glow_map(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RID()); + return env->glow_map; +} + +// SSR + +void RendererEnvironmentStorage::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->ssr_enabled = p_enable; + env->ssr_max_steps = p_max_steps; + env->ssr_fade_in = p_fade_int; + env->ssr_fade_out = p_fade_out; + env->ssr_depth_tolerance = p_depth_tolerance; +} + +bool RendererEnvironmentStorage::environment_get_ssr_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssr_enabled; +} + +int RendererEnvironmentStorage::environment_get_ssr_max_steps(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 64); + return env->ssr_max_steps; +} + +float RendererEnvironmentStorage::environment_get_ssr_fade_in(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.15); + return env->ssr_fade_in; +} + +float RendererEnvironmentStorage::environment_get_ssr_fade_out(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 2.0); + return env->ssr_fade_out; +} + +float RendererEnvironmentStorage::environment_get_ssr_depth_tolerance(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.2); + return env->ssr_depth_tolerance; +} + +// SSAO + +void RendererEnvironmentStorage::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->ssao_enabled = p_enable; + env->ssao_radius = p_radius; + env->ssao_intensity = p_intensity; + env->ssao_power = p_power; + env->ssao_detail = p_detail; + env->ssao_horizon = p_horizon; + env->ssao_sharpness = p_sharpness; + env->ssao_direct_light_affect = p_light_affect; + env->ssao_ao_channel_affect = p_ao_channel_affect; +} + +bool RendererEnvironmentStorage::environment_get_ssao_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_enabled; +} + +float RendererEnvironmentStorage::environment_get_ssao_radius(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->ssao_radius; +} + +float RendererEnvironmentStorage::environment_get_ssao_intensity(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 2.0); + return env->ssao_intensity; +} + +float RendererEnvironmentStorage::environment_get_ssao_power(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.5); + return env->ssao_power; +} + +float RendererEnvironmentStorage::environment_get_ssao_detail(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.5); + return env->ssao_detail; +} + +float RendererEnvironmentStorage::environment_get_ssao_horizon(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.06); + return env->ssao_horizon; +} + +float RendererEnvironmentStorage::environment_get_ssao_sharpness(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.98); + return env->ssao_sharpness; +} + +float RendererEnvironmentStorage::environment_get_ssao_direct_light_affect(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->ssao_direct_light_affect; +} + +float RendererEnvironmentStorage::environment_get_ssao_ao_channel_affect(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->ssao_ao_channel_affect; +} + +// SSIL + +void RendererEnvironmentStorage::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->ssil_enabled = p_enable; + env->ssil_radius = p_radius; + env->ssil_intensity = p_intensity; + env->ssil_sharpness = p_sharpness; + env->ssil_normal_rejection = p_normal_rejection; +} + +bool RendererEnvironmentStorage::environment_get_ssil_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssil_enabled; +} + +float RendererEnvironmentStorage::environment_get_ssil_radius(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 5.0); + return env->ssil_radius; +} + +float RendererEnvironmentStorage::environment_get_ssil_intensity(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->ssil_intensity; +} + +float RendererEnvironmentStorage::environment_get_ssil_sharpness(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.98); + return env->ssil_sharpness; +} + +float RendererEnvironmentStorage::environment_get_ssil_normal_rejection(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->ssil_normal_rejection; +} + +// SDFGI + +void RendererEnvironmentStorage::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->sdfgi_enabled = p_enable; + env->sdfgi_cascades = p_cascades; + env->sdfgi_min_cell_size = p_min_cell_size; + env->sdfgi_use_occlusion = p_use_occlusion; + env->sdfgi_bounce_feedback = p_bounce_feedback; + env->sdfgi_read_sky_light = p_read_sky; + env->sdfgi_energy = p_energy; + env->sdfgi_normal_bias = p_normal_bias; + env->sdfgi_probe_bias = p_probe_bias; + env->sdfgi_y_scale = p_y_scale; +} + +bool RendererEnvironmentStorage::environment_get_sdfgi_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->sdfgi_enabled; +} + +int RendererEnvironmentStorage::environment_get_sdfgi_cascades(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 4); + return env->sdfgi_cascades; +} + +float RendererEnvironmentStorage::environment_get_sdfgi_min_cell_size(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.2); + return env->sdfgi_min_cell_size; +} + +bool RendererEnvironmentStorage::environment_get_sdfgi_use_occlusion(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->sdfgi_use_occlusion; +} + +float RendererEnvironmentStorage::environment_get_sdfgi_bounce_feedback(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.5); + return env->sdfgi_bounce_feedback; +} + +bool RendererEnvironmentStorage::environment_get_sdfgi_read_sky_light(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, true); + return env->sdfgi_read_sky_light; +} + +float RendererEnvironmentStorage::environment_get_sdfgi_energy(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->sdfgi_energy; +} + +float RendererEnvironmentStorage::environment_get_sdfgi_normal_bias(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.1); + return env->sdfgi_normal_bias; +} + +float RendererEnvironmentStorage::environment_get_sdfgi_probe_bias(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.1); + return env->sdfgi_probe_bias; +} + +RS::EnvironmentSDFGIYScale RendererEnvironmentStorage::environment_get_sdfgi_y_scale(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_SDFGI_Y_SCALE_75_PERCENT); + return env->sdfgi_y_scale; +} + +// Adjustments + +void RendererEnvironmentStorage::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND(!env); + env->adjustments_enabled = p_enable; + env->adjustments_brightness = p_brightness; + env->adjustments_contrast = p_contrast; + env->adjustments_saturation = p_saturation; + env->use_1d_color_correction = p_use_1d_color_correction; + env->color_correction = p_color_correction; +} + +bool RendererEnvironmentStorage::environment_get_adjustments_enabled(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->adjustments_enabled; +} + +float RendererEnvironmentStorage::environment_get_adjustments_brightness(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->adjustments_brightness; +} + +float RendererEnvironmentStorage::environment_get_adjustments_contrast(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->adjustments_contrast; +} + +float RendererEnvironmentStorage::environment_get_adjustments_saturation(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 1.0); + return env->adjustments_saturation; +} + +bool RendererEnvironmentStorage::environment_get_use_1d_color_correction(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, false); + return env->use_1d_color_correction; +} + +RID RendererEnvironmentStorage::environment_get_color_correction(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, RID()); + return env->color_correction; +} diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h new file mode 100644 index 0000000000..29bba86930 --- /dev/null +++ b/servers/rendering/storage/environment_storage.h @@ -0,0 +1,296 @@ +/*************************************************************************/ +/* environment_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 ENVIRONMENT_STORAGE_H +#define ENVIRONMENT_STORAGE_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering_server.h" + +class RendererEnvironmentStorage { +private: + struct Environment { + // Note, we capture and store all environment parameters received from Godot here. + // Not all renderers support all effects and should just ignore the bits they don't support. + + // Background + RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR; + RID sky; + float sky_custom_fov = 0.0; + Basis sky_orientation; + Color bg_color; + float bg_energy = 1.0; + int canvas_max_layer = 0; + RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG; + Color ambient_light; + float ambient_light_energy = 1.0; + float ambient_sky_contribution = 1.0; + RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; + + // Tonemap + RS::EnvironmentToneMapper tone_mapper; + float exposure = 1.0; + float white = 1.0; + bool auto_exposure = false; + float min_luminance = 0.2; + float max_luminance = 8.0; + float auto_exp_speed = 0.2; + float auto_exp_scale = 0.5; + uint64_t auto_exposure_version = 0; + + // Fog + bool fog_enabled = false; + Color fog_light_color = Color(0.518, 0.553, 0.608); + float fog_light_energy = 1.0; + float fog_sun_scatter = 0.0; + float fog_density = 0.01; + float fog_height = 0.0; + float fog_height_density = 0.0; //can be negative to invert effect + float fog_aerial_perspective = 0.0; + + // Volumetric Fog + bool volumetric_fog_enabled = false; + float volumetric_fog_density = 0.01; + Color volumetric_fog_scattering = Color(1, 1, 1); + Color volumetric_fog_emission = Color(0, 0, 0); + float volumetric_fog_emission_energy = 0.0; + float volumetric_fog_anisotropy = 0.2; + float volumetric_fog_length = 64.0; + float volumetric_fog_detail_spread = 2.0; + float volumetric_fog_gi_inject = 1.0; + float volumetric_fog_ambient_inject = 0.0; + bool volumetric_fog_temporal_reprojection = true; + float volumetric_fog_temporal_reprojection_amount = 0.9; + + // Glow + bool glow_enabled = false; + Vector<float> glow_levels; + float glow_intensity = 0.8; + float glow_strength = 1.0; + float glow_bloom = 0.0; + float glow_mix = 0.01; + RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; + float glow_hdr_bleed_threshold = 1.0; + float glow_hdr_luminance_cap = 12.0; + float glow_hdr_bleed_scale = 2.0; + float glow_map_strength = 0.0f; // 1.0f in GLES3 ?? + RID glow_map = RID(); + + // SSR + bool ssr_enabled = false; + int ssr_max_steps = 64; + float ssr_fade_in = 0.15; + float ssr_fade_out = 2.0; + float ssr_depth_tolerance = 0.2; + + // SSAO + bool ssao_enabled = false; + float ssao_radius = 1.0; + float ssao_intensity = 2.0; + float ssao_power = 1.5; + float ssao_detail = 0.5; + float ssao_horizon = 0.06; + float ssao_sharpness = 0.98; + float ssao_direct_light_affect = 0.0; + float ssao_ao_channel_affect = 0.0; + + // SSIL + bool ssil_enabled = false; + float ssil_radius = 5.0; + float ssil_intensity = 1.0; + float ssil_sharpness = 0.98; + float ssil_normal_rejection = 1.0; + + // SDFGI + bool sdfgi_enabled = false; + int sdfgi_cascades = 4; + float sdfgi_min_cell_size = 0.2; + bool sdfgi_use_occlusion = false; + float sdfgi_bounce_feedback = 0.5; + bool sdfgi_read_sky_light = true; + float sdfgi_energy = 1.0; + float sdfgi_normal_bias = 1.1; + float sdfgi_probe_bias = 1.1; + RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT; + + // Adjustments + bool adjustments_enabled = false; + float adjustments_brightness = 1.0f; + float adjustments_contrast = 1.0f; + float adjustments_saturation = 1.0f; + bool use_1d_color_correction = false; + RID color_correction = RID(); + }; + + static uint64_t auto_exposure_counter; + + mutable RID_Owner<Environment, true> environment_owner; + +public: + RID environment_allocate(); + void environment_initialize(RID p_rid); + void environment_free(RID p_rid); + + bool is_environment(RID p_environment) const { + return environment_owner.owns(p_environment); + } + + // Background + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg); + void environment_set_sky(RID p_env, RID p_sky); + void environment_set_sky_custom_fov(RID p_env, float p_scale); + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); + void environment_set_bg_color(RID p_env, const Color &p_color); + void environment_set_bg_energy(RID p_env, float p_energy); + void environment_set_canvas_max_layer(RID p_env, int p_max_layer); + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG); +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); +#endif + + RS::EnvironmentBG environment_get_background(RID p_env) const; + RID environment_get_sky(RID p_env) const; + float environment_get_sky_custom_fov(RID p_env) const; + Basis environment_get_sky_orientation(RID p_env) const; + Color environment_get_bg_color(RID p_env) const; + float environment_get_bg_energy(RID p_env) const; + int environment_get_canvas_max_layer(RID p_env) const; + RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const; + Color environment_get_ambient_light(RID p_env) const; + float environment_get_ambient_light_energy(RID p_env) const; + float environment_get_ambient_sky_contribution(RID p_env) const; + RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + + // Tonemap + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); + RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const; + float environment_get_exposure(RID p_env) const; + float environment_get_white(RID p_env) const; + bool environment_get_auto_exposure(RID p_env) const; + float environment_get_min_luminance(RID p_env) const; + float environment_get_max_luminance(RID p_env) const; + float environment_get_auto_exp_speed(RID p_env) const; + float environment_get_auto_exp_scale(RID p_env) const; + uint64_t environment_get_auto_exposure_version(RID p_env) const; + + // Fog + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective); + bool environment_get_fog_enabled(RID p_env) const; + Color environment_get_fog_light_color(RID p_env) const; + float environment_get_fog_light_energy(RID p_env) const; + float environment_get_fog_sun_scatter(RID p_env) const; + float environment_get_fog_density(RID p_env) const; + float environment_get_fog_height(RID p_env) const; + float environment_get_fog_height_density(RID p_env) const; + float environment_get_fog_aerial_perspective(RID p_env) const; + + // Volumetric Fog + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); + bool environment_get_volumetric_fog_enabled(RID p_env) const; + float environment_get_volumetric_fog_density(RID p_env) const; + Color environment_get_volumetric_fog_scattering(RID p_env) const; + Color environment_get_volumetric_fog_emission(RID p_env) const; + float environment_get_volumetric_fog_emission_energy(RID p_env) const; + float environment_get_volumetric_fog_anisotropy(RID p_env) const; + float environment_get_volumetric_fog_length(RID p_env) const; + float environment_get_volumetric_fog_detail_spread(RID p_env) const; + float environment_get_volumetric_fog_gi_inject(RID p_env) const; + bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const; + float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const; + float environment_get_volumetric_fog_ambient_inject(RID p_env) const; + + // GLOW + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map); + bool environment_get_glow_enabled(RID p_env) const; + Vector<float> environment_get_glow_levels(RID p_env) const; + float environment_get_glow_intensity(RID p_env) const; + float environment_get_glow_strength(RID p_env) const; + float environment_get_glow_bloom(RID p_env) const; + float environment_get_glow_mix(RID p_env) const; + RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const; + float environment_get_glow_hdr_bleed_threshold(RID p_env) const; + float environment_get_glow_hdr_luminance_cap(RID p_env) const; + float environment_get_glow_hdr_bleed_scale(RID p_env) const; + float environment_get_glow_map_strength(RID p_env) const; + RID environment_get_glow_map(RID p_env) const; + + // SSR + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); + bool environment_get_ssr_enabled(RID p_env) const; + int environment_get_ssr_max_steps(RID p_env) const; + float environment_get_ssr_fade_in(RID p_env) const; + float environment_get_ssr_fade_out(RID p_env) const; + float environment_get_ssr_depth_tolerance(RID p_env) const; + + // SSAO + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect); + bool environment_get_ssao_enabled(RID p_env) const; + float environment_get_ssao_radius(RID p_env) const; + float environment_get_ssao_intensity(RID p_env) const; + float environment_get_ssao_power(RID p_env) const; + float environment_get_ssao_detail(RID p_env) const; + float environment_get_ssao_horizon(RID p_env) const; + float environment_get_ssao_sharpness(RID p_env) const; + float environment_get_ssao_direct_light_affect(RID p_env) const; + float environment_get_ssao_ao_channel_affect(RID p_env) const; + + // SSIL + void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection); + bool environment_get_ssil_enabled(RID p_env) const; + float environment_get_ssil_radius(RID p_env) const; + float environment_get_ssil_intensity(RID p_env) const; + float environment_get_ssil_sharpness(RID p_env) const; + float environment_get_ssil_normal_rejection(RID p_env) const; + + // SDFGI + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); + bool environment_get_sdfgi_enabled(RID p_env) const; + int environment_get_sdfgi_cascades(RID p_env) const; + float environment_get_sdfgi_min_cell_size(RID p_env) const; + bool environment_get_sdfgi_use_occlusion(RID p_env) const; + float environment_get_sdfgi_bounce_feedback(RID p_env) const; + bool environment_get_sdfgi_read_sky_light(RID p_env) const; + float environment_get_sdfgi_energy(RID p_env) const; + float environment_get_sdfgi_normal_bias(RID p_env) const; + float environment_get_sdfgi_probe_bias(RID p_env) const; + RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const; + + // Adjustment + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction); + bool environment_get_adjustments_enabled(RID p_env) const; + float environment_get_adjustments_brightness(RID p_env) const; + float environment_get_adjustments_contrast(RID p_env) const; + float environment_get_adjustments_saturation(RID p_env) const; + bool environment_get_use_1d_color_correction(RID p_env) const; + RID environment_get_color_correction(RID p_env) const; +}; + +#endif // ENVIRONMENT_STORAGE_H diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index f627e46e52..087ea1a025 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -135,4 +135,4 @@ public: virtual float lightmap_get_probe_capture_update_speed() const = 0; }; -#endif // !LIGHT_STORAGE_H +#endif // LIGHT_STORAGE_H diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h index 00790106af..ad8e3e79bf 100644 --- a/servers/rendering/storage/material_storage.h +++ b/servers/rendering/storage/material_storage.h @@ -38,22 +38,22 @@ class RendererMaterialStorage { public: virtual ~RendererMaterialStorage(){}; - /* GLOBAL VARIABLE API */ - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; - virtual void global_variable_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_variable_get_list() const = 0; + /* GLOBAL SHADER UNIFORM API */ + virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) = 0; + virtual void global_shader_uniform_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_shader_uniform_get_list() const = 0; - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_variable_get(const StringName &p_name) const = 0; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0; + virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0; - virtual void global_variables_load_settings(bool p_load_textures = true) = 0; - virtual void global_variables_clear() = 0; + virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) = 0; + virtual void global_shader_uniforms_clear() = 0; - virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; - virtual void global_variables_instance_free(RID p_instance) = 0; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; + virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) = 0; + virtual void global_shader_uniforms_instance_free(RID p_instance) = 0; + virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; /* SHADER API */ virtual RID shader_allocate() = 0; @@ -61,8 +61,9 @@ public: virtual void shader_free(RID p_rid) = 0; virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0; virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; @@ -93,9 +94,9 @@ public: Variant default_value; }; - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; + virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0; }; -#endif // !MATERIAL_STORAGE_H +#endif // MATERIAL_STORAGE_H diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 146f6fde40..5b3738dfd7 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -133,4 +133,4 @@ public: virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; }; -#endif // !MESH_STORAGE_H +#endif // MESH_STORAGE_H diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h index eba68210a5..ee4b8679b3 100644 --- a/servers/rendering/storage/particles_storage.h +++ b/servers/rendering/storage/particles_storage.h @@ -125,4 +125,4 @@ public: virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; }; -#endif // !PARTICLES_STORAGE_H +#endif // PARTICLES_STORAGE_H diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index e90a028713..982ab4a958 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -143,6 +143,9 @@ public: virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0; virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0; virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0; + + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0; }; -#endif // !TEXTURE_STORAGE_H +#endif // TEXTURE_STORAGE_H diff --git a/servers/rendering/storage/utilities.h b/servers/rendering/storage/utilities.h index 4d7c34383c..d240d58917 100644 --- a/servers/rendering/storage/utilities.h +++ b/servers/rendering/storage/utilities.h @@ -183,4 +183,4 @@ public: virtual String get_video_adapter_api_version() const = 0; }; -#endif // !RENDERER_UTILITIES_H +#endif // RENDERER_UTILITIES_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 9b407043fc..a54d4f0384 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -772,19 +772,11 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i elem_size = 3; } - { - elem_size *= sizeof(float); - } - - if (elem_size == 6) { - elem_size = 8; - } - + elem_size *= sizeof(float); } break; case RS::ARRAY_NORMAL: { elem_size = 4; } break; - case RS::ARRAY_TANGENT: { elem_size = 4; } break; @@ -793,12 +785,9 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i } break; case RS::ARRAY_TEX_UV: { elem_size = 8; - } break; - case RS::ARRAY_TEX_UV2: { elem_size = 8; - } break; case RS::ARRAY_CUSTOM0: case RS::ARRAY_CUSTOM1: @@ -1410,7 +1399,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su } #endif -int RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) { +int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: return ShaderLanguage::TYPE_BOOL; @@ -1511,9 +1500,9 @@ TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const { return ret; } -TypedArray<Dictionary> RenderingServer::_shader_get_param_list(RID p_shader) const { +TypedArray<Dictionary> RenderingServer::_shader_get_shader_uniform_list(RID p_shader) const { List<PropertyInfo> l; - shader_get_param_list(p_shader, &l); + shader_get_shader_uniform_list(p_shader, &l); return convert_property_list(&l); } @@ -1636,9 +1625,9 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) { return d; } -Array RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const { +Array RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const { List<PropertyInfo> params; - instance_geometry_get_shader_parameter_list(p_instance, ¶ms); + instance_geometry_get_shader_uniform_list(p_instance, ¶ms); return convert_property_list(¶ms); } @@ -1709,8 +1698,10 @@ void RenderingServer::_bind_methods() { /* SHADER */ ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create); + ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code); + ClassDB::bind_method(D_METHOD("shader_set_path_hint", "shader", "path"), &RenderingServer::shader_set_path_hint); ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code); - ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list); + ClassDB::bind_method(D_METHOD("shader_get_shader_uniform_list", "shader"), &RenderingServer::_shader_get_shader_uniform_list); ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default); ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0)); @@ -1894,9 +1885,10 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter); BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST); - BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS); BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR); + BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS); BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS); + BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC); BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL); @@ -1919,6 +1911,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS); BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS); BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_OPACITY); BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR); BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE); BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS); @@ -1939,8 +1932,8 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY); - ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set); - ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set); + ClassDB::bind_method(D_METHOD("positional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::positional_soft_shadow_filter_set_quality); + ClassDB::bind_method(D_METHOD("directional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::directional_soft_shadow_filter_set_quality); ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size); BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD); @@ -1998,9 +1991,10 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX); BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST); - BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS); BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR); + BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS); BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS); + BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC); BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC); /* GI API (affects VoxelGI and SDFGI) */ @@ -2182,7 +2176,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode); ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale); ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness); - ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias); + ClassDB::bind_method(D_METHOD("viewport_set_texture_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_texture_mipmap_bias); ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode); ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode); ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture); @@ -2207,8 +2201,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_sdf_oversize_and_scale", "viewport", "oversize", "scale"), &RenderingServer::viewport_set_sdf_oversize_and_scale); - ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_shadow_atlas_size, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision); + ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_positional_shadow_atlas_size, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_positional_shadow_atlas_quadrant_subdivision); ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa); ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa); ClassDB::bind_method(D_METHOD("viewport_set_use_taa", "viewport", "enable"), &RenderingServer::viewport_set_use_taa); @@ -2225,6 +2219,9 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu); + ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode); + ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture); + BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR); BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR); BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX); @@ -2300,6 +2297,11 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_TEXTURE); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX); + /* SKY API */ ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create); @@ -2483,10 +2485,10 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap); ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias); - ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_parameter", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_parameter); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter_default_value); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_list", "instance"), &RenderingServer::_instance_geometry_get_shader_parameter_list); + ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_uniform", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_uniform); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform_default_value); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_list", "instance"), &RenderingServer::_instance_geometry_get_shader_uniform_list); ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID())); @@ -2680,15 +2682,15 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE); BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE); - /* GLOBAL VARIABLES */ + /* GLOBAL SHADER UNIFORMS */ - ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add); - ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove); - ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list); - ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set); - ClassDB::bind_method(D_METHOD("global_variable_set_override", "name", "value"), &RenderingServer::global_variable_set_override); - ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get); - ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type); + ClassDB::bind_method(D_METHOD("global_shader_uniform_add", "name", "type", "default_value"), &RenderingServer::global_shader_uniform_add); + ClassDB::bind_method(D_METHOD("global_shader_uniform_remove", "name"), &RenderingServer::global_shader_uniform_remove); + ClassDB::bind_method(D_METHOD("global_shader_uniform_get_list"), &RenderingServer::global_shader_uniform_get_list); + ClassDB::bind_method(D_METHOD("global_shader_uniform_set", "name", "value"), &RenderingServer::global_shader_uniform_set); + ClassDB::bind_method(D_METHOD("global_shader_uniform_set_override", "name", "value"), &RenderingServer::global_shader_uniform_set_override); + ClassDB::bind_method(D_METHOD("global_shader_uniform_get", "name"), &RenderingServer::global_shader_uniform_get); + ClassDB::bind_method(D_METHOD("global_shader_uniform_get_type", "name"), &RenderingServer::global_shader_uniform_get_type); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2); @@ -2821,7 +2823,6 @@ void RenderingServer::set_render_loop_enabled(bool p_enabled) { RenderingServer::RenderingServer() { //ERR_FAIL_COND(singleton); - thread_pool = memnew(RendererThreadPool); singleton = this; } @@ -2841,14 +2842,14 @@ void RenderingServer::init() { GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096); GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048); ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384")); - GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2); - GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)")); + GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_filter_quality", 2); + GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_filter_quality.mobile", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)")); GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true); - GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2); - GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)")); + GLOBAL_DEF("rendering/shadows/positional_shadow/soft_shadow_filter_quality", 2); + GLOBAL_DEF("rendering/shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)")); GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048); @@ -2937,7 +2938,7 @@ void RenderingServer::init() { GLOBAL_DEF("rendering/scaling_3d/mode", 0); GLOBAL_DEF("rendering/scaling_3d/scale", 1.0); GLOBAL_DEF("rendering/scaling_3d/fsr_sharpness", 0.2f); - GLOBAL_DEF("rendering/scaling_3d/fsr_mipmap_bias", 0.0f); + GLOBAL_DEF("rendering/textures/default_filters/texture_mipmap_bias", 0.0f); ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode", PropertyInfo(Variant::INT, "rendering/scaling_3d/mode", @@ -2952,15 +2953,15 @@ void RenderingServer::init() { PropertyInfo(Variant::FLOAT, "rendering/scaling_3d/fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias", + ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/texture_mipmap_bias", PropertyInfo(Variant::FLOAT, - "rendering/scaling_3d/fsr_mipmap_bias", - PROPERTY_HINT_RANGE, "-2,2,0.1")); + "rendering/textures/default_filters/texture_mipmap_bias", + PROPERTY_HINT_RANGE, "-2,2,0.001")); GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)")); GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)")); GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512); GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); @@ -3022,6 +3023,5 @@ void RenderingServer::init() { } RenderingServer::~RenderingServer() { - memdelete(thread_pool); singleton = nullptr; } diff --git a/servers/rendering_server.h b/servers/rendering_server.h index ccef95f5f2..a2fe9caf19 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -35,11 +35,11 @@ #include "core/math/geometry_3d.h" #include "core/math/transform_2d.h" #include "core/object/class_db.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/rid.h" #include "core/variant/typed_array.h" #include "core/variant/variant.h" #include "servers/display_server.h" -#include "servers/rendering/renderer_thread_pool.h" #include "servers/rendering/rendering_device.h" class RenderingServer : public Object { @@ -52,8 +52,6 @@ class RenderingServer : public Object { Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const; - RendererThreadPool *thread_pool = nullptr; - const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON); const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON); @@ -170,8 +168,9 @@ public: virtual RID shader_create() = 0; virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0; virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0; @@ -426,6 +425,7 @@ public: LIGHT_PARAM_SHADOW_NORMAL_BIAS, LIGHT_PARAM_SHADOW_BIAS, LIGHT_PARAM_SHADOW_PANCAKE_SIZE, + LIGHT_PARAM_SHADOW_OPACITY, LIGHT_PARAM_SHADOW_BLUR, LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE, LIGHT_PARAM_TRANSMITTANCE_BIAS, @@ -491,14 +491,15 @@ public: SHADOW_QUALITY_MAX }; - virtual void shadows_quality_set(ShadowQuality p_quality) = 0; - virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0; + virtual void positional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0; + virtual void directional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0; enum LightProjectorFilter { LIGHT_PROJECTOR_FILTER_NEAREST, - LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS, LIGHT_PROJECTOR_FILTER_LINEAR, + LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS, LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS, + LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC, LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC, }; @@ -558,9 +559,10 @@ public: enum DecalFilter { DECAL_FILTER_NEAREST, - DECAL_FILTER_NEAREST_MIPMAPS, DECAL_FILTER_LINEAR, + DECAL_FILTER_NEAREST_MIPMAPS, DECAL_FILTER_LINEAR_MIPMAPS, + DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC, DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC, }; @@ -798,7 +800,7 @@ public: virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0; virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0; virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0; - virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0; + virtual void viewport_set_texture_mipmap_bias(RID p_viewport, float p_texture_mipmap_bias) = 0; enum ViewportUpdateMode { VIEWPORT_UPDATE_DISABLED, @@ -856,8 +858,8 @@ public: virtual void viewport_set_sdf_oversize_and_scale(RID p_viewport, ViewportSDFOversize p_oversize, ViewportSDFScale p_scale) = 0; - virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0; - virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; + virtual void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0; + virtual void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; enum ViewportMSAA { VIEWPORT_MSAA_DISABLED, @@ -946,6 +948,16 @@ public: virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const = 0; + enum ViewportVRSMode { + VIEWPORT_VRS_DISABLED, + VIEWPORT_VRS_TEXTURE, + VIEWPORT_VRS_XR, + VIEWPORT_VRS_MAX, + }; + + virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0; + virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0; + /* SKY API */ enum SkyMode { @@ -1233,10 +1245,10 @@ public: virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0; - virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0; - virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0; - virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0; - virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; + virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &, const Variant &p_value) = 0; + virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &) const = 0; + virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &) const = 0; + virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; /* Bake 3D objects */ @@ -1416,9 +1428,9 @@ public: virtual void canvas_set_shadow_texture_size(int p_size) = 0; - /* GLOBAL VARIABLES */ + /* GLOBAL SHADER UNIFORMS */ - enum GlobalVariableType { + enum GlobalShaderUniformType { GLOBAL_VAR_TYPE_BOOL, GLOBAL_VAR_TYPE_BVEC2, GLOBAL_VAR_TYPE_BVEC3, @@ -1450,20 +1462,20 @@ public: GLOBAL_VAR_TYPE_MAX }; - virtual void global_variable_add(const StringName &p_name, GlobalVariableType p_type, const Variant &p_value) = 0; - virtual void global_variable_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_variable_get_list() const = 0; + virtual void global_shader_uniform_add(const StringName &p_name, GlobalShaderUniformType p_type, const Variant &p_value) = 0; + virtual void global_shader_uniform_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_shader_uniform_get_list() const = 0; - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_variable_get(const StringName &p_name) const = 0; - virtual GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; + virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0; + virtual GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0; - virtual void global_variables_load_settings(bool p_load_textures) = 0; - virtual void global_variables_clear() = 0; + virtual void global_shader_uniforms_load_settings(bool p_load_textures) = 0; + virtual void global_shader_uniforms_clear() = 0; - static int global_variable_type_get_shader_datatype(GlobalVariableType p_type); + static int global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type); /* FREE */ @@ -1560,11 +1572,11 @@ private: RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data); TypedArray<Image> _texture_3d_get(RID p_texture) const; - TypedArray<Dictionary> _shader_get_param_list(RID p_shader) const; + TypedArray<Dictionary> _shader_get_shader_uniform_list(RID p_shader) const; RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count); void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface); Dictionary _mesh_get_surface(RID p_mesh, int p_idx); - Array _instance_geometry_get_shader_parameter_list(RID p_instance) const; + Array _instance_geometry_get_shader_uniform_list(RID p_instance) const; TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size); void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses); }; @@ -1609,6 +1621,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw); VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale); +VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode); VARIANT_ENUM_CAST(RenderingServer::SkyMode); VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource); @@ -1638,7 +1651,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode); VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode); VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter); VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode); -VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType); +VARIANT_ENUM_CAST(RenderingServer::GlobalShaderUniformType); VARIANT_ENUM_CAST(RenderingServer::RenderingInfo); VARIANT_ENUM_CAST(RenderingServer::Features); VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel); diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h index 2c4aab0784..318c844a2f 100644 --- a/servers/server_wrap_mt_common.h +++ b/servers/server_wrap_mt_common.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SERVER_WRAP_MT_COMMON_H +#define SERVER_WRAP_MT_COMMON_H + #define FUNC0R(m_r, m_type) \ virtual m_r m_type() override { \ if (Thread::get_caller_id() != server_thread) { \ @@ -762,3 +765,5 @@ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \ } \ } + +#endif // SERVER_WRAP_MT_COMMON_H diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 68959819c9..59310ab69b 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -297,9 +297,13 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(percent_sign, "language"); GDVIRTUAL_BIND(strip_diacritics, "string"); + GDVIRTUAL_BIND(is_valid_identifier, "string"); GDVIRTUAL_BIND(string_get_word_breaks, "string", "language"); + GDVIRTUAL_BIND(is_confusable, "string", "dict"); + GDVIRTUAL_BIND(spoof_check, "string"); + GDVIRTUAL_BIND(string_to_upper, "string", "language"); GDVIRTUAL_BIND(string_to_lower, "string", "language"); @@ -438,12 +442,12 @@ int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const { return 0; } -void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { +void TextServerExtension::font_set_style(const RID &p_font_rid, BitField<TextServer::FontStyle> p_style) { GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style); } -int64_t /*FontStyle*/ TextServerExtension::font_get_style(const RID &p_font_rid) const { - int64_t ret; +BitField<TextServer::FontStyle> TextServerExtension::font_get_style(const RID &p_font_rid) const { + BitField<TextServer::FontStyle> ret = 0; if (GDVIRTUAL_CALL(font_get_style, p_font_rid, ret)) { return ret; } @@ -1192,7 +1196,7 @@ RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const { return RID(); } -double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t p_jst_flags) { +double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) { double ret; if (GDVIRTUAL_CALL(shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) { return ret; @@ -1272,7 +1276,7 @@ Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const { return Vector2i(); } -PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t p_break_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const { PackedInt32Array ret; if (GDVIRTUAL_CALL(shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) { return ret; @@ -1280,7 +1284,7 @@ PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags); } -PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t p_break_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const { PackedInt32Array ret; if (GDVIRTUAL_CALL(shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) { return ret; @@ -1288,7 +1292,7 @@ PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_s return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags); } -PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const { PackedInt32Array ret; if (GDVIRTUAL_CALL(shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) { return ret; @@ -1328,7 +1332,7 @@ int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_s return -1; } -void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { +void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) { GDVIRTUAL_CALL(shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags); } @@ -1498,6 +1502,14 @@ String TextServerExtension::percent_sign(const String &p_language) const { return "%"; } +bool TextServerExtension::is_valid_identifier(const String &p_string) const { + bool ret; + if (GDVIRTUAL_CALL(is_valid_identifier, p_string, ret)) { + return ret; + } + return TextServer::is_valid_identifier(p_string); +} + String TextServerExtension::strip_diacritics(const String &p_string) const { String ret; if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) { @@ -1538,6 +1550,22 @@ PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_str return PackedInt32Array(); } +int TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const { + int ret; + if (GDVIRTUAL_CALL(is_confusable, p_string, p_dict, ret)) { + return ret; + } + return TextServer::is_confusable(p_string, p_dict); +} + +bool TextServerExtension::spoof_check(const String &p_string) const { + bool ret; + if (GDVIRTUAL_CALL(spoof_check, p_string, ret)) { + return ret; + } + return TextServer::spoof_check(p_string); +} + TextServerExtension::TextServerExtension() { //NOP } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index d948a97c66..81af1b60e5 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -92,10 +92,10 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const override; GDVIRTUAL1RC(int64_t, font_get_face_count, RID); - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; - GDVIRTUAL2(font_set_style, RID, int64_t); - GDVIRTUAL1RC(int64_t, font_get_style, RID); + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_style, RID, BitField<FontStyle>); + GDVIRTUAL1RC(BitField<FontStyle>, font_get_style, RID); virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_name(const RID &p_font_rid) const override; @@ -396,9 +396,9 @@ public: GDVIRTUAL3RC(RID, shaped_text_substr, RID, int64_t, int64_t); GDVIRTUAL1RC(RID, shaped_text_get_parent, RID); - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; - GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, int64_t); + GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, BitField<TextServer::JustificationFlag>); GDVIRTUAL2R(double, shaped_text_tab_align, RID, const PackedFloat32Array &); virtual bool shaped_text_shape(const RID &p_shaped) override; @@ -421,12 +421,12 @@ public: virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override; GDVIRTUAL1RC(Vector2i, shaped_text_get_range, RID); - virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; - virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; - virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override; - GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, int64_t); - GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, int64_t); - GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, int64_t); + virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; + virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override; + GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, BitField<TextServer::LineBreakFlag>); + GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, BitField<TextServer::LineBreakFlag>); + GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, BitField<TextServer::GraphemeFlag>); virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override; @@ -437,8 +437,8 @@ public: GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_ellipsis_glyphs, RID); GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_glyph_count, RID); - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; - GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, int64_t); + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override; + GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, BitField<TextServer::TextOverrunFlag>); virtual Array shaped_text_get_objects(const RID &p_shaped) const override; virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override; @@ -496,6 +496,9 @@ public: virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override; GDVIRTUAL2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &); + virtual bool is_valid_identifier(const String &p_string) const override; + GDVIRTUAL1RC(bool, is_valid_identifier, const String &); + virtual String string_to_upper(const String &p_string, const String &p_language = "") const override; virtual String string_to_lower(const String &p_string, const String &p_language = "") const override; GDVIRTUAL2RC(String, string_to_upper, const String &, const String &); @@ -504,6 +507,11 @@ public: Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &); + virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override; + virtual bool spoof_check(const String &p_string) const override; + GDVIRTUAL2RC(int, is_confusable, const String &, const PackedStringArray &); + GDVIRTUAL1RC(bool, spoof_check, const String &); + TextServerExtension(); ~TextServerExtension(); }; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index c1293230d8..2bf0837d88 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -446,7 +446,11 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL("")); + ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable); + ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check); + ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics); + ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier); ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL("")); ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL("")); @@ -463,12 +467,12 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(ORIENTATION_VERTICAL); /* JustificationFlag */ - BIND_ENUM_CONSTANT(JUSTIFICATION_NONE); - BIND_ENUM_CONSTANT(JUSTIFICATION_KASHIDA); - BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND); - BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES); - BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB); - BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS); + BIND_BITFIELD_FLAG(JUSTIFICATION_NONE); + BIND_BITFIELD_FLAG(JUSTIFICATION_KASHIDA); + BIND_BITFIELD_FLAG(JUSTIFICATION_WORD_BOUND); + BIND_BITFIELD_FLAG(JUSTIFICATION_TRIM_EDGE_SPACES); + BIND_BITFIELD_FLAG(JUSTIFICATION_AFTER_LAST_TAB); + BIND_BITFIELD_FLAG(JUSTIFICATION_CONSTRAIN_ELLIPSIS); /* AutowrapMode */ BIND_ENUM_CONSTANT(AUTOWRAP_OFF); @@ -477,11 +481,11 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART); /* LineBreakFlag */ - BIND_ENUM_CONSTANT(BREAK_NONE); - BIND_ENUM_CONSTANT(BREAK_MANDATORY); - BIND_ENUM_CONSTANT(BREAK_WORD_BOUND); - BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND); - BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE); + BIND_BITFIELD_FLAG(BREAK_NONE); + BIND_BITFIELD_FLAG(BREAK_MANDATORY); + BIND_BITFIELD_FLAG(BREAK_WORD_BOUND); + BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND); + BIND_BITFIELD_FLAG(BREAK_ADAPTIVE); /* VisibleCharactersBehavior */ BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING); @@ -498,25 +502,26 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS); /* TextOverrunFlag */ - BIND_ENUM_CONSTANT(OVERRUN_NO_TRIM); - BIND_ENUM_CONSTANT(OVERRUN_TRIM); - BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY); - BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS); - BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS); - BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE); + BIND_BITFIELD_FLAG(OVERRUN_NO_TRIM); + BIND_BITFIELD_FLAG(OVERRUN_TRIM); + BIND_BITFIELD_FLAG(OVERRUN_TRIM_WORD_ONLY); + BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS); + BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS); + BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE); /* GraphemeFlag */ - BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID); - BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL); - BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL); - BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE); - BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_HARD); - BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_SOFT); - BIND_ENUM_CONSTANT(GRAPHEME_IS_TAB); - BIND_ENUM_CONSTANT(GRAPHEME_IS_ELONGATION); - BIND_ENUM_CONSTANT(GRAPHEME_IS_PUNCTUATION); - BIND_ENUM_CONSTANT(GRAPHEME_IS_UNDERSCORE); - BIND_ENUM_CONSTANT(GRAPHEME_IS_CONNECTED); + BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID); + BIND_BITFIELD_FLAG(GRAPHEME_IS_RTL); + BIND_BITFIELD_FLAG(GRAPHEME_IS_VIRTUAL); + BIND_BITFIELD_FLAG(GRAPHEME_IS_SPACE); + BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_HARD); + BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_SOFT); + BIND_BITFIELD_FLAG(GRAPHEME_IS_TAB); + BIND_BITFIELD_FLAG(GRAPHEME_IS_ELONGATION); + BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION); + BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE); + BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED); + BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL); /* Hinting */ BIND_ENUM_CONSTANT(HINTING_NONE); @@ -545,6 +550,8 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE); BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION); BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA); + BIND_ENUM_CONSTANT(FEATURE_UNICODE_IDENTIFIERS); + BIND_ENUM_CONSTANT(FEATURE_UNICODE_SECURITY); /* FT Contour Point Types */ BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON); @@ -556,11 +563,12 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(SPACING_SPACE); BIND_ENUM_CONSTANT(SPACING_TOP); BIND_ENUM_CONSTANT(SPACING_BOTTOM); + BIND_ENUM_CONSTANT(SPACING_MAX); /* Font Style */ - BIND_ENUM_CONSTANT(FONT_BOLD); - BIND_ENUM_CONSTANT(FONT_ITALIC); - BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH); + BIND_BITFIELD_FLAG(FONT_BOLD); + BIND_BITFIELD_FLAG(FONT_ITALIC); + BIND_BITFIELD_FLAG(FONT_FIXED_WIDTH); /* Structured text parser */ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT); @@ -650,7 +658,7 @@ void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Ve } } -PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const { +PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const { PackedInt32Array lines; ERR_FAIL_COND_V(p_width.is_empty(), lines); @@ -687,7 +695,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped } continue; } - if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) { + if (p_break_flags.has_flag(BREAK_MANDATORY)) { if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) { lines.push_back(line_start); lines.push_back(l_gl[i].end); @@ -701,12 +709,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped continue; } } - if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) { + if (p_break_flags.has_flag(BREAK_WORD_BOUND)) { if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_safe_break = i; } } - if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) { + if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) { last_safe_break = i; } } @@ -726,7 +734,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped return lines; } -PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const { +PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const { PackedInt32Array lines; const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped); @@ -755,7 +763,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do word_count = 0; continue; } - if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) { + if (p_break_flags.has_flag(BREAK_MANDATORY)) { if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) { lines.push_back(line_start); lines.push_back(l_gl[i].end); @@ -765,16 +773,16 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do continue; } } - if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) { + if (p_break_flags.has_flag(BREAK_WORD_BOUND)) { if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_safe_break = i; word_count++; } + if (p_break_flags.has_flag(BREAK_ADAPTIVE) && word_count == 0) { + last_safe_break = i; + } } - if (((p_break_flags & BREAK_WORD_BOUND_ADAPTIVE) == BREAK_WORD_BOUND_ADAPTIVE) && word_count == 0) { - last_safe_break = i; - } - if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) { + if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) { last_safe_break = i; } } @@ -794,7 +802,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do return lines; } -PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const { +PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const { PackedInt32Array words; const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped); @@ -1729,6 +1737,26 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) return ret; } +bool TextServer::is_valid_identifier(const String &p_string) const { + const char32_t *str = p_string.ptr(); + int len = p_string.length(); + + if (len == 0) { + return false; // Empty string. + } + + if (!is_unicode_identifier_start(str[0])) { + return false; + } + + for (int i = 1; i < len; i++) { + if (!is_unicode_identifier_continue(str[i])) { + return false; + } + } + return true; +} + TextServer::TextServer() { _init_diacritics_map(); } diff --git a/servers/text_server.h b/servers/text_server.h index 0fd35f2ec0..d45bea3271 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -79,12 +79,12 @@ public: AUTOWRAP_WORD_SMART }; - enum LineBreakFlag { // LineBreakFlag can be passed in the same value as the JustificationFlag, do not use the same values. + enum LineBreakFlag { BREAK_NONE = 0, - BREAK_MANDATORY = 1 << 5, - BREAK_WORD_BOUND = 1 << 6, - BREAK_GRAPHEME_BOUND = 1 << 7, - BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8, + BREAK_MANDATORY = 1 << 0, + BREAK_WORD_BOUND = 1 << 1, + BREAK_GRAPHEME_BOUND = 1 << 2, + BREAK_ADAPTIVE = 1 << 3, }; enum OverrunBehavior { @@ -116,6 +116,7 @@ public: GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction). GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break). GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme. + GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL = 1 << 11, // It is safe to insert a U+0640 before this grapheme for elongation. }; enum Hinting { @@ -148,6 +149,8 @@ public: FEATURE_FONT_VARIABLE = 1 << 10, FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11, FEATURE_USE_SUPPORT_DATA = 1 << 12, + FEATURE_UNICODE_IDENTIFIERS = 1 << 13, + FEATURE_UNICODE_SECURITY = 1 << 14, }; enum ContourPointTag { @@ -218,8 +221,8 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const = 0; - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0; + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) = 0; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const = 0; virtual void font_set_name(const RID &p_font_rid, const String &p_name) = 0; virtual String font_get_name(const RID &p_font_rid) const = 0; @@ -398,7 +401,7 @@ public: virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range. virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0; - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) = 0; virtual bool shaped_text_shape(const RID &p_shaped) = 0; @@ -415,9 +418,9 @@ public: virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0; - virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; + virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0; virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0; @@ -425,7 +428,7 @@ public: Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0; - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) = 0; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) = 0; virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0; virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0; @@ -463,7 +466,11 @@ public: // String functions. virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0; + virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; }; + virtual bool spoof_check(const String &p_string) const { return false; }; + virtual String strip_diacritics(const String &p_string) const; + virtual bool is_valid_identifier(const String &p_string) const; // Other string operations. virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0; @@ -551,16 +558,16 @@ VARIANT_ENUM_CAST(TextServer::AutowrapMode); VARIANT_ENUM_CAST(TextServer::OverrunBehavior); VARIANT_ENUM_CAST(TextServer::Direction); VARIANT_ENUM_CAST(TextServer::Orientation); -VARIANT_ENUM_CAST(TextServer::JustificationFlag); -VARIANT_ENUM_CAST(TextServer::LineBreakFlag); -VARIANT_ENUM_CAST(TextServer::TextOverrunFlag); -VARIANT_ENUM_CAST(TextServer::GraphemeFlag); +VARIANT_BITFIELD_CAST(TextServer::JustificationFlag); +VARIANT_BITFIELD_CAST(TextServer::LineBreakFlag); +VARIANT_BITFIELD_CAST(TextServer::TextOverrunFlag); +VARIANT_BITFIELD_CAST(TextServer::GraphemeFlag); VARIANT_ENUM_CAST(TextServer::Hinting); VARIANT_ENUM_CAST(TextServer::SubpixelPositioning); VARIANT_ENUM_CAST(TextServer::Feature); VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); -VARIANT_ENUM_CAST(TextServer::FontStyle); +VARIANT_BITFIELD_CAST(TextServer::FontStyle); VARIANT_ENUM_CAST(TextServer::StructuredTextParser); GDVIRTUAL_NATIVE_PTR(Glyph); diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 7ae111b5e7..4b9ea40223 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "xr_interface.h" -// #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_compositor.h" void XRInterface::_bind_methods() { ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode"))); @@ -114,7 +114,12 @@ void XRInterface::set_primary(bool p_primary) { XRInterface::XRInterface() {} -XRInterface::~XRInterface() {} +XRInterface::~XRInterface() { + if (vrs.vrs_texture.is_valid()) { + RS::get_singleton()->free(vrs.vrs_texture); + vrs.vrs_texture = RID(); + } +} // query if this interface supports this play area mode bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { @@ -151,6 +156,85 @@ int XRInterface::get_camera_feed_id() { return 0; } +RID XRInterface::get_vrs_texture() { + // Default logic will return a standard VRS image based on our target size and default projections. + // Note that this only gets called if VRS is supported on the hardware. + + Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard. + int view_count = get_view_count(); + Size2 target_size = get_render_target_size(); + real_t aspect = target_size.x / target_size.y; // is this y/x ? + Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y)); + real_t radius = vrs_size.length() * 0.5; + Size2 vrs_sizei = vrs_size; + + if (vrs.size != vrs_sizei) { + const uint8_t densities[] = { + 0, // 1x1 + 1, // 1x2 + // 4, // 2x1 + 5, // 2x2 + 6, // 2x4 + // 9, // 4x2 + 10, // 4x4 + }; + + // out with the old + if (vrs.vrs_texture.is_valid()) { + RS::get_singleton()->free(vrs.vrs_texture); + vrs.vrs_texture = RID(); + } + + // in with the new + Vector<Ref<Image>> images; + vrs.size = vrs_sizei; + + for (int i = 0; i < view_count && i < 2; i++) { + PackedByteArray data; + data.resize(vrs_sizei.x * vrs_sizei.y); + uint8_t *data_ptr = data.ptrw(); + + // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result... + Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0); + Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0)); + + Vector2i view_center; + view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5); + view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5); + + int d = 0; + for (int y = 0; y < vrs_sizei.y; y++) { + for (int x = 0; x < vrs_sizei.x; x++) { + Vector2 offset = Vector2(x - view_center.x, y - view_center.y); + offset.y *= aspect; + real_t distance = offset.length(); + int idx = round(5.0 * distance / radius); + if (idx > 4) { + idx = 4; + } + uint8_t density = densities[idx]; + + data_ptr[d++] = density; + } + } + + Ref<Image> image; + image.instantiate(); + image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data); + + images.push_back(image); + } + + if (images.size() == 1) { + vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]); + } else { + vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY); + } + } + + return vrs.vrs_texture; +} + /** these are optional, so we want dummies **/ PackedStringArray XRInterface::get_suggested_tracker_names() const { PackedStringArray arr; diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 62eba2f00b..f11458f1cc 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -31,7 +31,7 @@ #ifndef XR_INTERFACE_H #define XR_INTERFACE_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/os/thread_safe.h" #include "servers/xr_server.h" @@ -119,7 +119,8 @@ public: virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */ virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */ - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */ + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */ + virtual RID get_vrs_texture(); /* obtain VRS texture */ // note, external color/depth/vrs texture support will be added here soon. @@ -133,6 +134,12 @@ public: XRInterface(); ~XRInterface(); + +private: + struct VRSData { + RID vrs_texture; + Size2i size; + } vrs; }; VARIANT_ENUM_CAST(XRInterface::Capabilities); diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp index 1f3d07c357..7395cd5ad4 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -50,6 +50,7 @@ void XRInterfaceExtension::_bind_methods() { GDVIRTUAL_BIND(_get_camera_transform); GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform"); GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far"); + GDVIRTUAL_BIND(_get_vrs_texture); GDVIRTUAL_BIND(_process); GDVIRTUAL_BIND(_pre_render); @@ -257,12 +258,12 @@ Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const return Transform3D(); } -CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix cm; +Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection cm; PackedFloat64Array arr; if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) { - ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats"); + ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats"); real_t *m = (real_t *)cm.matrix; for (int i = 0; i < 16; i++) { m[i] = arr[i]; @@ -270,7 +271,16 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub return cm; } - return CameraMatrix(); + return Projection(); +} + +RID XRInterfaceExtension::get_vrs_texture() { + RID vrs_texture; + if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) { + return vrs_texture; + } else { + return XRInterface::get_vrs_texture(); + } } void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) { diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h index 5a436b9fd0..65b474425e 100644 --- a/servers/xr/xr_interface_extension.h +++ b/servers/xr/xr_interface_extension.h @@ -100,13 +100,15 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual RID get_vrs_texture() override; GDVIRTUAL0R(Size2, _get_render_target_size); GDVIRTUAL0R(uint32_t, _get_view_count); GDVIRTUAL0R(Transform3D, _get_camera_transform); GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &); GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double); + GDVIRTUAL0R(RID, _get_vrs_texture); void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0); @@ -130,4 +132,4 @@ public: // RID get_render_target_depth(RID p_render_target); }; -#endif // !XR_INTERFACE_EXTENSION_H +#endif // XR_INTERFACE_EXTENSION_H diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h index f306c22390..e7d363764b 100644 --- a/servers/xr/xr_pose.h +++ b/servers/xr/xr_pose.h @@ -78,4 +78,4 @@ public: VARIANT_ENUM_CAST(XRPose::TrackingConfidence); -#endif +#endif // XR_POSE_H diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index ad61aa94bc..990281d96d 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -33,6 +33,16 @@ #include "xr/xr_interface.h" #include "xr/xr_positional_tracker.h" +XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT; + +XRServer::XRMode XRServer::get_xr_mode() { + return xr_mode; +} + +void XRServer::set_xr_mode(XRServer::XRMode p_mode) { + xr_mode = p_mode; +} + XRServer *XRServer::singleton = nullptr; XRServer *XRServer::get_singleton() { diff --git a/servers/xr_server.h b/servers/xr_server.h index d9188d2de1..74128bfb54 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -57,6 +57,12 @@ class XRServer : public Object { _THREAD_SAFE_CLASS_ public: + enum XRMode { + XRMODE_DEFAULT, /* Default behaviour, means we check project settings */ + XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */ + XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */ + }; + enum TrackerType { TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */ TRACKER_CONTROLLER = 0x02, /* tracks a controller */ @@ -75,6 +81,8 @@ public: }; private: + static XRMode xr_mode; + Vector<Ref<XRInterface>> interfaces; Dictionary trackers; @@ -90,6 +98,9 @@ protected: static void _bind_methods(); public: + static XRMode get_xr_mode(); + static void set_xr_mode(XRMode p_mode); + static XRServer *get_singleton(); /* diff --git a/tests/core/input/test_input_event_key.h b/tests/core/input/test_input_event_key.h new file mode 100644 index 0000000000..5d4ca55a35 --- /dev/null +++ b/tests/core/input/test_input_event_key.h @@ -0,0 +1,294 @@ +/*************************************************************************/ +/* test_input_event_key.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_INPUT_EVENT_KEY_H +#define TEST_INPUT_EVENT_KEY_H + +#include "core/input/input_event.h" +#include "core/os/keyboard.h" + +#include "tests/test_macros.h" + +namespace TestInputEventKey { + +TEST_CASE("[InputEventKey] Key correctly registers being pressed") { + InputEventKey key; + key.set_pressed(true); + CHECK(key.is_pressed() == true); + + key.set_pressed(false); + CHECK(key.is_pressed() == false); +} + +TEST_CASE("[InputEventKey] Key correctly stores and retrieves keycode") { + InputEventKey key; + + key.set_keycode(Key::ENTER); + CHECK(key.get_keycode() == Key::ENTER); + CHECK(key.get_keycode() != Key::PAUSE); + + key.set_physical_keycode(Key::BACKSPACE); + CHECK(key.get_physical_keycode() == Key::BACKSPACE); + CHECK(key.get_physical_keycode() != Key::PAUSE); +} + +TEST_CASE("[InputEventKey] Key correctly stores and retrieves keycode with modifiers") { + InputEventKey key; + + key.set_keycode(Key::ENTER); + key.set_ctrl_pressed(true); + + CHECK(key.get_keycode_with_modifiers() == (Key::ENTER | KeyModifierMask::CTRL)); + CHECK(key.get_keycode_with_modifiers() != (Key::ENTER | KeyModifierMask::SHIFT)); + CHECK(key.get_keycode_with_modifiers() != Key::ENTER); + + key.set_physical_keycode(Key::SPACE); + key.set_ctrl_pressed(true); + + CHECK(key.get_physical_keycode_with_modifiers() == (Key::SPACE | KeyModifierMask::CTRL)); + CHECK(key.get_physical_keycode_with_modifiers() != (Key::SPACE | KeyModifierMask::SHIFT)); + CHECK(key.get_physical_keycode_with_modifiers() != Key::SPACE); +} + +TEST_CASE("[InputEventKey] Key correctly stores and retrieves unicode") { + InputEventKey key; + + key.set_unicode('x'); + CHECK(key.get_unicode() == 'x'); + CHECK(key.get_unicode() != 'y'); +} + +TEST_CASE("[InputEventKey] Key correctly stores and checks echo") { + InputEventKey key; + + key.set_echo(true); + CHECK(key.is_echo() == true); + + key.set_echo(false); + CHECK(key.is_echo() == false); +} + +TEST_CASE("[InputEventKey] Key correctly converts itself to text") { + InputEventKey none_key; + + // These next three tests test the functionality of getting a key that is set to None + // as text. These cases are a bit weird, since None has no textual representation + // (find_keycode_name(Key::NONE) results in a nullptr). Thus, these tests look weird + // with only (Physical) or a lonely modifier with (Physical) but (as far as I + // understand the code, that is intended behaviour. + + // Key is None without a physical key. + none_key.set_keycode(Key::NONE); + CHECK(none_key.as_text() == " (Physical)"); + + // Key is none and has modifiers. + none_key.set_ctrl_pressed(true); + CHECK(none_key.as_text() == "Ctrl+ (Physical)"); + + // Key is None WITH a physical key AND modifiers. + none_key.set_physical_keycode(Key::ENTER); + CHECK(none_key.as_text() == "Ctrl+Enter (Physical)"); + + InputEventKey none_key2; + + // Key is None without modifers with a physical key. + none_key2.set_keycode(Key::NONE); + none_key2.set_physical_keycode(Key::ENTER); + + CHECK(none_key2.as_text() == "Enter (Physical)"); + + InputEventKey key; + + // Key has keycode. + key.set_keycode(Key::SPACE); + CHECK(key.as_text() != ""); + CHECK(key.as_text() == "Space"); + + // Key has keycode and modifiers. + key.set_ctrl_pressed(true); + CHECK(key.as_text() != "Space"); + CHECK(key.as_text() == "Ctrl+Space"); + + // Since the keycode is set to Key::NONE upon initialization of the + // InputEventKey and you can only update it with another Key, the keycode + // cannot be empty, so the kc.is_empty() case cannot be tested. +} + +TEST_CASE("[InputEventKey] Key correctly converts its state to a string representation") { + InputEventKey none_key; + + // Set physical to true. + CHECK(none_key.to_string() == "InputEventKey: keycode=0 (), mods=none, physical=true, pressed=false, echo=false"); + // Set physical key to Escape. + none_key.set_physical_keycode(Key::ESCAPE); + CHECK(none_key.to_string() == "InputEventKey: keycode=16777217 (Escape), mods=none, physical=true, pressed=false, echo=false"); + + InputEventKey key; + + // Set physical to None, set keycode to Space. + key.set_keycode(Key::SPACE); + CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=false, echo=false"); + + // Set pressed to true. + key.set_pressed(true); + CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=true, echo=false"); + + // set echo to true. + key.set_echo(true); + CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=true, echo=true"); + + // Press Ctrl and Alt. + key.set_ctrl_pressed(true); + key.set_alt_pressed(true); + CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=Ctrl+Alt, physical=false, pressed=true, echo=true"); +} + +TEST_CASE("[InputEventKey] Key is correctly converted to reference") { + InputEventKey base_key; + Ref<InputEventKey> key_ref = base_key.create_reference(Key::ENTER); + + CHECK(key_ref->get_keycode() == Key::ENTER); +} + +TEST_CASE("[InputEventKey] Keys are correctly matched based on action") { + bool pressed = false; + float strength, raw_strength = 0.0; + + InputEventKey key; + + // Nullptr. + CHECK_MESSAGE(key.action_match(nullptr, false, 0.0f, &pressed, &strength, &raw_strength) == false, "nullptr as key reference should result in false"); + + // Match on keycode. + key.set_keycode(Key::SPACE); + Ref<InputEventKey> match = key.create_reference(Key::SPACE); + Ref<InputEventKey> no_match = key.create_reference(Key::ENTER); + + CHECK(key.action_match(match, false, 0.0f, &pressed, &strength, &raw_strength) == true); + CHECK(key.action_match(no_match, false, 0.0f, &pressed, &strength, &raw_strength) == false); + + // Check that values are correctly transferred to the pointers. + CHECK(pressed == false); + CHECK(strength < 0.5); + CHECK(raw_strength < 0.5); + + match->set_pressed(true); + key.action_match(match, false, 0.0f, &pressed, &strength, &raw_strength); + + CHECK(pressed == true); + CHECK(strength > 0.5); + CHECK(raw_strength > 0.5); + + // Tests when keycode is None: Then you rely on physical keycode. + InputEventKey none_key; + none_key.set_physical_keycode(Key::SPACE); + + Ref<InputEventKey> match_none = none_key.create_reference(Key::NONE); + match_none->set_physical_keycode(Key::SPACE); + + Ref<InputEventKey> no_match_none = none_key.create_reference(Key::NONE); + no_match_none->set_physical_keycode(Key::ENTER); + + CHECK(none_key.action_match(match_none, false, 0.0f, &pressed, &strength, &raw_strength) == true); + CHECK(none_key.action_match(no_match_none, false, 0.0f, &pressed, &strength, &raw_strength) == false); + + // Test exact match. + InputEventKey key2, ref_key; + key2.set_keycode(Key::SPACE); + + Ref<InputEventKey> match2 = ref_key.create_reference(Key::SPACE); + + // Now both press Ctrl and Shift. + key2.set_ctrl_pressed(true); + key2.set_shift_pressed(true); + + match2->set_ctrl_pressed(true); + match2->set_shift_pressed(true); + + // Now they should match. + bool exact_match = true; + CHECK(key2.action_match(match2, exact_match, 0.0f, &pressed, &strength, &raw_strength) == true); + + // Modify matching key such that it does no longer match in terms of modifiers: Shift + // is no longer pressed. + match2->set_shift_pressed(false); + CHECK(match2->is_shift_pressed() == false); + CHECK(key2.action_match(match2, exact_match, 0.0f, &pressed, &strength, &raw_strength) == false); +} + +TEST_CASE("[IsMatch] Keys are correctly matched") { + // Key with NONE as keycode. + InputEventKey key; + key.set_keycode(Key::NONE); + key.set_physical_keycode(Key::SPACE); + + // Nullptr. + CHECK(key.is_match(nullptr, false) == false); + + Ref<InputEventKey> none_ref = key.create_reference(Key::NONE); + + none_ref->set_physical_keycode(Key::SPACE); + CHECK(key.is_match(none_ref, false) == true); + + none_ref->set_physical_keycode(Key::ENTER); + CHECK(key.is_match(none_ref, false) == false); + + none_ref->set_physical_keycode(Key::SPACE); + + key.set_ctrl_pressed(true); + none_ref->set_ctrl_pressed(false); + CHECK(key.is_match(none_ref, true) == false); + + none_ref->set_ctrl_pressed(true); + CHECK(key.is_match(none_ref, true) == true); + + // Ref with actual keycode. + InputEventKey key2; + key2.set_keycode(Key::SPACE); + + Ref<InputEventKey> match = key2.create_reference(Key::SPACE); + Ref<InputEventKey> no_match = key2.create_reference(Key::ENTER); + + CHECK(key2.is_match(match, false) == true); + CHECK(key2.is_match(no_match, false) == false); + + // Now the keycode is the same, but the modifiers differ. + no_match->set_keycode(Key::SPACE); + + key2.set_ctrl_pressed(true); + match->set_ctrl_pressed(true); + no_match->set_shift_pressed(true); + + CHECK(key2.is_match(match, true) == true); + CHECK(key2.is_match(no_match, true) == false); +} +} // namespace TestInputEventKey + +#endif // TEST_INPUT_EVENT_KEY_H diff --git a/tests/core/input/test_shortcut.h b/tests/core/input/test_shortcut.h new file mode 100644 index 0000000000..93edc685ad --- /dev/null +++ b/tests/core/input/test_shortcut.h @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* test_shortcut.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_SHORTCUT_H +#define TEST_SHORTCUT_H + +#include "core/input/input_event.h" +#include "core/input/shortcut.h" +#include "core/io/config_file.h" +#include "core/object/ref_counted.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" + +#include "tests/test_macros.h" + +namespace TestShortcut { + +TEST_CASE("[Shortcut] Empty shortcut should have no valid events and text equal to None") { + Shortcut s; + + CHECK(s.get_as_text() == "None"); + CHECK(s.has_valid_event() == false); +} + +TEST_CASE("[Shortcut] Setting and getting an event should result in the same event as the input") { + Ref<InputEventKey> k1; + Ref<InputEventKey> k2; + k1.instantiate(); + k2.instantiate(); + + k1->set_keycode(Key::ENTER); + k2->set_keycode(Key::BACKSPACE); + + // Cast to InputEvent so the internal code recognizes the objects. + Ref<InputEvent> e1 = k1; + Ref<InputEvent> e2 = k2; + + Array input_array; + input_array.append(e1); + input_array.append(e2); + + Shortcut s; + s.set_events(input_array); + + // Get result, read it out, check whether it equals the input. + Array result_array = s.get_events(); + Ref<InputEventKey> result1 = result_array.front(); + Ref<InputEventKey> result2 = result_array.back(); + + CHECK(result1->get_keycode() == k1->get_keycode()); + CHECK(result2->get_keycode() == k2->get_keycode()); +} + +TEST_CASE("[Shortcut] 'set_events_list' should result in the same events as the input") { + Ref<InputEventKey> k1; + Ref<InputEventKey> k2; + k1.instantiate(); + k2.instantiate(); + + k1->set_keycode(Key::ENTER); + k2->set_keycode(Key::BACKSPACE); + + // Cast to InputEvent so the set_events_list() method recognizes the objects. + Ref<InputEvent> e1 = k1; + Ref<InputEvent> e2 = k2; + + List<Ref<InputEvent>> list; + list.push_back(e1); + list.push_back(e2); + + Shortcut s; + s.set_events_list(&list); + + // Get result, read it out, check whether it equals the input. + Array result_array = s.get_events(); + Ref<InputEventKey> result1 = result_array.front(); + Ref<InputEventKey> result2 = result_array.back(); + + CHECK(result1->get_keycode() == k1->get_keycode()); + CHECK(result2->get_keycode() == k2->get_keycode()); +} + +TEST_CASE("[Shortcut] 'matches_event' should correctly match the same event") { + Ref<InputEventKey> original; // The one we compare with. + Ref<InputEventKey> similar_but_not_equal; // Same keycode, different event. + Ref<InputEventKey> different; // Different event, different keycode. + Ref<InputEventKey> copy; // Copy of original event. + + original.instantiate(); + similar_but_not_equal.instantiate(); + different.instantiate(); + copy.instantiate(); + + original->set_keycode(Key::ENTER); + similar_but_not_equal->set_keycode(Key::ENTER); + similar_but_not_equal->set_keycode(Key::ESCAPE); + copy = original; + + // Only the copy is really the same, so only that one should match. + // The rest should not match. + + Ref<InputEvent> e_original = original; + + Ref<InputEvent> e_similar_but_not_equal = similar_but_not_equal; + Ref<InputEvent> e_different = different; + Ref<InputEvent> e_copy = copy; + + Array a; + a.append(e_original); + Shortcut s; + s.set_events(a); + + CHECK(s.matches_event(e_similar_but_not_equal) == false); + CHECK(s.matches_event(e_different) == false); + + CHECK(s.matches_event(e_copy) == true); +} + +TEST_CASE("[Shortcut] 'get_as_text' text representation should be correct") { + Ref<InputEventKey> same; + // k2 will not go into the shortcut but only be used to compare. + Ref<InputEventKey> different; + + same.instantiate(); + different.instantiate(); + + same->set_keycode(Key::ENTER); + different->set_keycode(Key::ESCAPE); + + Ref<InputEvent> key_event1 = same; + + Array a; + a.append(key_event1); + Shortcut s; + s.set_events(a); + + CHECK(s.get_as_text() == same->as_text()); + CHECK(s.get_as_text() != different->as_text()); +} + +TEST_CASE("[Shortcut] Event validity should be correctly checked.") { + Ref<InputEventKey> valid; + // k2 will not go into the shortcut but only be used to compare. + Ref<InputEventKey> invalid = nullptr; + + valid.instantiate(); + valid->set_keycode(Key::ENTER); + + Ref<InputEvent> valid_event = valid; + Ref<InputEvent> invalid_event = invalid; + + Array a; + a.append(invalid_event); + a.append(valid_event); + + Shortcut s; + s.set_events(a); + + CHECK(s.has_valid_event() == true); + + Array b; + b.append(invalid_event); + + Shortcut shortcut_with_invalid_event; + shortcut_with_invalid_event.set_events(b); + + CHECK(shortcut_with_invalid_event.has_valid_event() == false); +} + +TEST_CASE("[Shortcut] Equal arrays should be recognized as such.") { + Ref<InputEventKey> k1; + // k2 will not go into the shortcut but only be used to compare. + Ref<InputEventKey> k2; + + k1.instantiate(); + k2.instantiate(); + + k1->set_keycode(Key::ENTER); + k2->set_keycode(Key::ESCAPE); + + Ref<InputEvent> key_event1 = k1; + Ref<InputEvent> key_event2 = k2; + + Array same; + same.append(key_event1); + + Array same_as_same; + same_as_same.append(key_event1); + + Array different1; + different1.append(key_event2); + + Array different2; + different2.append(key_event1); + different2.append(key_event2); + + Array different3; + + Shortcut s; + + CHECK(s.is_event_array_equal(same, same_as_same) == true); + CHECK(s.is_event_array_equal(same, different1) == false); + CHECK(s.is_event_array_equal(same, different2) == false); + CHECK(s.is_event_array_equal(same, different3) == false); +} +} // namespace TestShortcut + +#endif // TEST_SHORTCUT_H diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h index f0e1cceacf..aab62955cb 100644 --- a/tests/core/io/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -78,6 +78,29 @@ TEST_CASE("[FileAccess] CSV read") { CHECK(row5[1] == "tab separated"); CHECK(row5[2] == "lines, good?"); } + +TEST_CASE("[FileAccess] Get as UTF-8 String") { + Ref<FileAccess> f_lf = FileAccess::open(TestUtils::get_data_path("line_endings_lf.test.txt"), FileAccess::READ); + String s_lf = f_lf->get_as_utf8_string(); + f_lf->seek(0); + String s_lf_nocr = f_lf->get_as_utf8_string(true); + CHECK(s_lf == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + CHECK(s_lf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + + Ref<FileAccess> f_crlf = FileAccess::open(TestUtils::get_data_path("line_endings_crlf.test.txt"), FileAccess::READ); + String s_crlf = f_crlf->get_as_utf8_string(); + f_crlf->seek(0); + String s_crlf_nocr = f_crlf->get_as_utf8_string(true); + CHECK(s_crlf == "Hello darkness\r\nMy old friend\r\nI've come to talk\r\nWith you again\r\n"); + CHECK(s_crlf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + + Ref<FileAccess> f_cr = FileAccess::open(TestUtils::get_data_path("line_endings_cr.test.txt"), FileAccess::READ); + String s_cr = f_cr->get_as_utf8_string(); + f_cr->seek(0); + String s_cr_nocr = f_cr->get_as_utf8_string(true); + CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r"); + CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again"); +} } // namespace TestFileAccess #endif // TEST_FILE_ACCESS_H diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h index 1c778c3228..36e6b83bfd 100644 --- a/tests/core/io/test_image.h +++ b/tests/core/io/test_image.h @@ -161,8 +161,8 @@ TEST_CASE("[Image] Basic getters") { CHECK(image->get_height() == 4); CHECK(image->get_size() == Vector2(8, 4)); CHECK(image->get_format() == Image::FORMAT_LA8); - CHECK(image->get_used_rect() == Rect2(0, 0, 0, 0)); - Ref<Image> image_get_rect = image->get_rect(Rect2(0, 0, 2, 1)); + CHECK(image->get_used_rect() == Rect2i(0, 0, 0, 0)); + Ref<Image> image_get_rect = image->get_rect(Rect2i(0, 0, 2, 1)); CHECK(image_get_rect->get_size() == Vector2(2, 1)); } @@ -213,8 +213,8 @@ TEST_CASE("[Image] Modifying pixels of an image") { image->get_pixelv(Vector2(0, 0)).is_equal_approx(Color(1, 1, 1, 1)), "Image's get_pixel() should return the same color value as the one being set with set_pixel() in the same position."); CHECK_MESSAGE( - image->get_used_rect() == Rect2(0, 0, 1, 1), - "Image's get_used_rect should return the expected value, larger than Rect2(0, 0, 0, 0) if it's visible."); + image->get_used_rect() == Rect2i(0, 0, 1, 1), + "Image's get_used_rect should return the expected value, larger than Rect2i(0, 0, 0, 0) if it's visible."); image->set_pixelv(Vector2(0, 0), Color(0.5, 0.5, 0.5, 0.5)); Ref<Image> image2 = memnew(Image(3, 3, false, Image::FORMAT_RGBA8)); @@ -233,19 +233,19 @@ TEST_CASE("[Image] Modifying pixels of an image") { { const int img_width = 3; const int img_height = 3; - Vector<Rect2> rects; - rects.push_back(Rect2()); - rects.push_back(Rect2(-5, -5, 3, 3)); - rects.push_back(Rect2(img_width, 0, 12, 12)); - rects.push_back(Rect2(0, img_height, 12, 12)); - rects.push_back(Rect2(img_width + 1, img_height + 2, 12, 12)); - rects.push_back(Rect2(1, 1, 1, 1)); - rects.push_back(Rect2(0, 1, 2, 3)); - rects.push_back(Rect2(-5, 0, img_width + 10, 2)); - rects.push_back(Rect2(0, -5, 2, img_height + 10)); - rects.push_back(Rect2(-1, -1, img_width + 1, img_height + 1)); - - for (const Rect2 &rect : rects) { + Vector<Rect2i> rects; + rects.push_back(Rect2i()); + rects.push_back(Rect2i(-5, -5, 3, 3)); + rects.push_back(Rect2i(img_width, 0, 12, 12)); + rects.push_back(Rect2i(0, img_height, 12, 12)); + rects.push_back(Rect2i(img_width + 1, img_height + 2, 12, 12)); + rects.push_back(Rect2i(1, 1, 1, 1)); + rects.push_back(Rect2i(0, 1, 2, 3)); + rects.push_back(Rect2i(-5, 0, img_width + 10, 2)); + rects.push_back(Rect2i(0, -5, 2, img_height + 10)); + rects.push_back(Rect2i(-1, -1, img_width + 1, img_height + 1)); + + for (const Rect2i &rect : rects) { Ref<Image> img = memnew(Image(img_width, img_height, false, Image::FORMAT_RGBA8)); CHECK_NOTHROW_MESSAGE( img->fill_rect(rect, Color(1, 1, 1, 1)), @@ -267,7 +267,7 @@ TEST_CASE("[Image] Modifying pixels of an image") { } // Blend two images together - image->blend_rect(image2, Rect2(Vector2(0, 0), image2->get_size()), Vector2(0, 0)); + image->blend_rect(image2, Rect2i(Vector2i(0, 0), image2->get_size()), Vector2i(0, 0)); CHECK_MESSAGE( image->get_pixel(0, 0).a > 0.7, "blend_rect() should blend the alpha values of the two images."); @@ -279,7 +279,7 @@ TEST_CASE("[Image] Modifying pixels of an image") { image3->set_pixel(0, 0, Color(0, 1, 0, 1)); //blit_rect() two images together - image->blit_rect(image3, Rect2(Vector2(0, 0), image3->get_size()), Vector2(0, 0)); + image->blit_rect(image3, Rect2i(Vector2i(0, 0), image3->get_size()), Vector2i(0, 0)); CHECK_MESSAGE( image->get_pixel(0, 0).is_equal_approx(Color(0, 1, 0, 1)), "blit_rect() should replace old colors and not blend them."); @@ -300,4 +300,5 @@ TEST_CASE("[Image] Modifying pixels of an image") { "flip_y() should not leave old pixels behind."); } } // namespace TestImage + #endif // TEST_IMAGE_H diff --git a/tests/core/io/test_marshalls.h b/tests/core/io/test_marshalls.h index 546a2e9358..7490df2b2c 100644 --- a/tests/core/io/test_marshalls.h +++ b/tests/core/io/test_marshalls.h @@ -254,11 +254,13 @@ TEST_CASE("[Marshalls] Invalid data Variant decoding") { uint8_t some_buffer[1] = { 0x00 }; uint8_t out_of_range_type_buffer[4] = { 0xff }; // Greater than Variant::VARIANT_MAX + ERR_PRINT_OFF; CHECK(decode_variant(variant, some_buffer, /* less than 4 */ 1, &r_len) == ERR_INVALID_DATA); CHECK(r_len == 0); CHECK(decode_variant(variant, out_of_range_type_buffer, 4, &r_len) == ERR_INVALID_DATA); CHECK(r_len == 0); + ERR_PRINT_ON; } TEST_CASE("[Marshalls] NIL Variant decoding") { diff --git a/tests/core/io/test_resource.h b/tests/core/io/test_resource.h index 84d651b63f..c880ca7d2a 100644 --- a/tests/core/io/test_resource.h +++ b/tests/core/io/test_resource.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEST_RESOURCE -#define TEST_RESOURCE +#ifndef TEST_RESOURCE_H +#define TEST_RESOURCE_H #include "core/io/resource.h" #include "core/io/resource_loader.h" @@ -76,8 +76,8 @@ TEST_CASE("[Resource] Saving and loading") { resource->set_meta("other_resource", child_resource); const String save_path_binary = OS::get_singleton()->get_cache_path().plus_file("resource.res"); const String save_path_text = OS::get_singleton()->get_cache_path().plus_file("resource.tres"); - ResourceSaver::save(save_path_binary, resource); - ResourceSaver::save(save_path_text, resource); + ResourceSaver::save(resource, save_path_binary); + ResourceSaver::save(resource, save_path_text); const Ref<Resource> &loaded_resource_binary = ResourceLoader::load(save_path_binary); CHECK_MESSAGE( @@ -111,4 +111,4 @@ TEST_CASE("[Resource] Saving and loading") { } } // namespace TestResource -#endif // TEST_RESOURCE +#endif // TEST_RESOURCE_H diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index 526972a82f..447420fc12 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -299,34 +299,28 @@ TEST_CASE("[AABB] Get longest/shortest axis") { "get_shortest_axis_size() should return the expected value."); } -#ifndef _MSC_VER -#warning Support tests need to be re-done -#endif - -/* Support function was actually broken. As it was fixed, the tests now fail. Tests need to be re-done. - TEST_CASE("[AABB] Get support") { const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); CHECK_MESSAGE( - aabb.get_support(Vector3(1, 0, 0)).is_equal_approx(Vector3(-1.5, 7, 3.5)), + aabb.get_support(Vector3(1, 0, 0)).is_equal_approx(Vector3(2.5, 2, -2.5)), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0.5, 1, 0)).is_equal_approx(Vector3(-1.5, 2, 3.5)), + aabb.get_support(Vector3(0.5, 1, 0)).is_equal_approx(Vector3(2.5, 7, -2.5)), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0.5, 1, -400)).is_equal_approx(Vector3(-1.5, 2, 3.5)), + aabb.get_support(Vector3(0.5, 1, -400)).is_equal_approx(Vector3(2.5, 7, -2.5)), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0, -1, 0)).is_equal_approx(Vector3(2.5, 7, 3.5)), + aabb.get_support(Vector3(0, -1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0, -0.1, 0)).is_equal_approx(Vector3(2.5, 7, 3.5)), + aabb.get_support(Vector3(0, -0.1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3()).is_equal_approx(Vector3(2.5, 7, 3.5)), + aabb.get_support(Vector3()).is_equal_approx(Vector3(-1.5, 2, -2.5)), "get_support() should return the expected value with a null vector."); } -*/ + TEST_CASE("[AABB] Grow") { const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); CHECK_MESSAGE( diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h index ec58d95eed..ae8ca4acde 100644 --- a/tests/core/math/test_basis.h +++ b/tests/core/math/test_basis.h @@ -283,4 +283,4 @@ TEST_CASE("[Stress][Basis] Euler conversions") { } } // namespace TestBasis -#endif +#endif // TEST_BASIS_H diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h new file mode 100644 index 0000000000..94eef6c463 --- /dev/null +++ b/tests/core/math/test_quaternion.h @@ -0,0 +1,389 @@ +/*************************************************************************/ +/* test_quaternion.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_QUATERNION_H +#define TEST_QUATERNION_H + +#include "core/math/math_defs.h" +#include "core/math/math_funcs.h" +#include "core/math/quaternion.h" +#include "core/math/vector3.h" + +#include "tests/test_macros.h" + +namespace TestQuaternion { + +Quaternion quat_euler_yxz_deg(Vector3 angle) { + double yaw = Math::deg2rad(angle[1]); + double pitch = Math::deg2rad(angle[0]); + double roll = Math::deg2rad(angle[2]); + + // Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler + // constructor and quaternion product, both tested separately. + Quaternion q_y(Vector3(0.0, yaw, 0.0)); + Quaternion q_p(Vector3(pitch, 0.0, 0.0)); + Quaternion q_r(Vector3(0.0, 0.0, roll)); + // Roll-Z is followed by Pitch-X, then Yaw-Y. + Quaternion q_yxz = q_y * q_p * q_r; + + return q_yxz; +} + +TEST_CASE("[Quaternion] Default Construct") { + Quaternion q; + + CHECK(q[0] == 0.0); + CHECK(q[1] == 0.0); + CHECK(q[2] == 0.0); + CHECK(q[3] == 1.0); +} + +TEST_CASE("[Quaternion] Construct x,y,z,w") { + // Values are taken from actual use in another project & are valid (except roundoff error). + Quaternion q(0.2391, 0.099, 0.3696, 0.8924); + + CHECK(q[0] == doctest::Approx(0.2391)); + CHECK(q[1] == doctest::Approx(0.099)); + CHECK(q[2] == doctest::Approx(0.3696)); + CHECK(q[3] == doctest::Approx(0.8924)); +} + +TEST_CASE("[Quaternion] Construct AxisAngle 1") { + // Easy to visualize: 120 deg about X-axis. + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + + // 0.866 isn't close enough; doctest::Approx doesn't cut much slack! + CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle. + CHECK(q[1] == doctest::Approx(0.0)); + CHECK(q[2] == doctest::Approx(0.0)); + CHECK(q[3] == doctest::Approx(0.5)); // Cosine of half the angle. +} + +TEST_CASE("[Quaternion] Construct AxisAngle 2") { + // Easy to visualize: 30 deg about Y-axis. + Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + + CHECK(q[0] == doctest::Approx(0.0)); + CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle. + CHECK(q[2] == doctest::Approx(0.0)); + CHECK(q[3] == doctest::Approx(0.965926)); // Cosine of half the angle. +} + +TEST_CASE("[Quaternion] Construct AxisAngle 3") { + // Easy to visualize: 60 deg about Z-axis. + Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + + CHECK(q[0] == doctest::Approx(0.0)); + CHECK(q[1] == doctest::Approx(0.0)); + CHECK(q[2] == doctest::Approx(0.5)); // Sine of half the angle. + CHECK(q[3] == doctest::Approx(0.866025)); // Cosine of half the angle. +} + +TEST_CASE("[Quaternion] Construct AxisAngle 4") { + // More complex & hard to visualize, so test w/ data from online calculator. + Vector3 axis(1.0, 2.0, 0.5); + Quaternion q(axis.normalized(), Math::deg2rad(35.0)); + + CHECK(q[0] == doctest::Approx(0.131239)); + CHECK(q[1] == doctest::Approx(0.262478)); + CHECK(q[2] == doctest::Approx(0.0656194)); + CHECK(q[3] == doctest::Approx(0.953717)); +} + +TEST_CASE("[Quaternion] Construct from Quaternion") { + Vector3 axis(1.0, 2.0, 0.5); + Quaternion q_src(axis.normalized(), Math::deg2rad(35.0)); + Quaternion q(q_src); + + CHECK(q[0] == doctest::Approx(0.131239)); + CHECK(q[1] == doctest::Approx(0.262478)); + CHECK(q[2] == doctest::Approx(0.0656194)); + CHECK(q[3] == doctest::Approx(0.953717)); +} + +TEST_CASE("[Quaternion] Construct Euler SingleAxis") { + double yaw = Math::deg2rad(45.0); + double pitch = Math::deg2rad(30.0); + double roll = Math::deg2rad(10.0); + + Vector3 euler_y(0.0, yaw, 0.0); + Quaternion q_y(euler_y); + CHECK(q_y[0] == doctest::Approx(0.0)); + CHECK(q_y[1] == doctest::Approx(0.382684)); + CHECK(q_y[2] == doctest::Approx(0.0)); + CHECK(q_y[3] == doctest::Approx(0.923879)); + + Vector3 euler_p(pitch, 0.0, 0.0); + Quaternion q_p(euler_p); + CHECK(q_p[0] == doctest::Approx(0.258819)); + CHECK(q_p[1] == doctest::Approx(0.0)); + CHECK(q_p[2] == doctest::Approx(0.0)); + CHECK(q_p[3] == doctest::Approx(0.965926)); + + Vector3 euler_r(0.0, 0.0, roll); + Quaternion q_r(euler_r); + CHECK(q_r[0] == doctest::Approx(0.0)); + CHECK(q_r[1] == doctest::Approx(0.0)); + CHECK(q_r[2] == doctest::Approx(0.0871558)); + CHECK(q_r[3] == doctest::Approx(0.996195)); +} + +TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") { + double yaw = Math::deg2rad(45.0); + double pitch = Math::deg2rad(30.0); + double roll = Math::deg2rad(10.0); + + // Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler + // constructor and quaternion product, both tested separately. + Vector3 euler_y(0.0, yaw, 0.0); + Quaternion q_y(euler_y); + Vector3 euler_p(pitch, 0.0, 0.0); + Quaternion q_p(euler_p); + Vector3 euler_r(0.0, 0.0, roll); + Quaternion q_r(euler_r); + + // Roll-Z is followed by Pitch-X. + Quaternion check_xz = q_p * q_r; + // Then Yaw-Y follows both. + Quaternion check_yxz = q_y * check_xz; + + // Test construction from YXZ Euler angles. + Vector3 euler_yxz(pitch, yaw, roll); + Quaternion q(euler_yxz); + CHECK(q[0] == doctest::Approx(check_yxz[0])); + CHECK(q[1] == doctest::Approx(check_yxz[1])); + CHECK(q[2] == doctest::Approx(check_yxz[2])); + CHECK(q[3] == doctest::Approx(check_yxz[3])); + + // Sneak in a test of is_equal_approx. + CHECK(q.is_equal_approx(check_yxz)); +} + +TEST_CASE("[Quaternion] Construct Basis Euler") { + double yaw = Math::deg2rad(45.0); + double pitch = Math::deg2rad(30.0); + double roll = Math::deg2rad(10.0); + Vector3 euler_yxz(pitch, yaw, roll); + Quaternion q_yxz(euler_yxz); + Basis basis_axes(euler_yxz); + Quaternion q(basis_axes); + CHECK(q.is_equal_approx(q_yxz)); +} + +TEST_CASE("[Quaternion] Construct Basis Axes") { + // Arbitrary Euler angles. + Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + // Basis vectors from online calculation of rotation matrix. + Vector3 i_unit(0.5545787, 0.1823950, 0.8118957); + Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555); + Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192); + // Quaternion from online calculation. + Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598); + // Quaternion from local calculation. + Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34)); + // Quaternion from Euler angles constructor. + Quaternion q_euler(euler_yxz); + CHECK(q_calc.is_equal_approx(q_local)); + CHECK(q_local.is_equal_approx(q_euler)); + + // Calculate Basis and construct Quaternion. + // When this is written, C++ Basis class does not construct from basis vectors. + // This is by design, but may be subject to change. + // Workaround by constructing Basis from Euler angles. + // basis_axes = Basis(i_unit, j_unit, k_unit); + Basis basis_axes(euler_yxz); + Quaternion q(basis_axes); + + CHECK(basis_axes.get_column(0).is_equal_approx(i_unit)); + CHECK(basis_axes.get_column(1).is_equal_approx(j_unit)); + CHECK(basis_axes.get_column(2).is_equal_approx(k_unit)); + + CHECK(q.is_equal_approx(q_calc)); + CHECK_FALSE(q.inverse().is_equal_approx(q_calc)); + CHECK(q.is_equal_approx(q_local)); + CHECK(q.is_equal_approx(q_euler)); + CHECK(q[0] == doctest::Approx(0.2016913)); + CHECK(q[1] == doctest::Approx(-0.4245716)); + CHECK(q[2] == doctest::Approx(0.206033)); + CHECK(q[3] == doctest::Approx(0.8582598)); +} + +TEST_CASE("[Quaternion] Product (book)") { + // Example from "Quaternions and Rotation Sequences" by Jack Kuipers, p. 108. + Quaternion p(1.0, -2.0, 1.0, 3.0); + Quaternion q(-1.0, 2.0, 3.0, 2.0); + + Quaternion pq = p * q; + CHECK(pq[0] == doctest::Approx(-9.0)); + CHECK(pq[1] == doctest::Approx(-2.0)); + CHECK(pq[2] == doctest::Approx(11.0)); + CHECK(pq[3] == doctest::Approx(8.0)); +} + +TEST_CASE("[Quaternion] Product") { + double yaw = Math::deg2rad(45.0); + double pitch = Math::deg2rad(30.0); + double roll = Math::deg2rad(10.0); + + Vector3 euler_y(0.0, yaw, 0.0); + Quaternion q_y(euler_y); + CHECK(q_y[0] == doctest::Approx(0.0)); + CHECK(q_y[1] == doctest::Approx(0.382684)); + CHECK(q_y[2] == doctest::Approx(0.0)); + CHECK(q_y[3] == doctest::Approx(0.923879)); + + Vector3 euler_p(pitch, 0.0, 0.0); + Quaternion q_p(euler_p); + CHECK(q_p[0] == doctest::Approx(0.258819)); + CHECK(q_p[1] == doctest::Approx(0.0)); + CHECK(q_p[2] == doctest::Approx(0.0)); + CHECK(q_p[3] == doctest::Approx(0.965926)); + + Vector3 euler_r(0.0, 0.0, roll); + Quaternion q_r(euler_r); + CHECK(q_r[0] == doctest::Approx(0.0)); + CHECK(q_r[1] == doctest::Approx(0.0)); + CHECK(q_r[2] == doctest::Approx(0.0871558)); + CHECK(q_r[3] == doctest::Approx(0.996195)); + + // Test ZYX dynamic-axes since test data is available online. + // Rotate first about X axis, then new Y axis, then new Z axis. + // (Godot uses YXZ Yaw-Pitch-Roll order). + Quaternion q_yp = q_y * q_p; + CHECK(q_yp[0] == doctest::Approx(0.239118)); + CHECK(q_yp[1] == doctest::Approx(0.369644)); + CHECK(q_yp[2] == doctest::Approx(-0.099046)); + CHECK(q_yp[3] == doctest::Approx(0.892399)); + + Quaternion q_ryp = q_r * q_yp; + CHECK(q_ryp[0] == doctest::Approx(0.205991)); + CHECK(q_ryp[1] == doctest::Approx(0.389078)); + CHECK(q_ryp[2] == doctest::Approx(-0.0208912)); + CHECK(q_ryp[3] == doctest::Approx(0.897636)); +} + +TEST_CASE("[Quaternion] xform unit vectors") { + // Easy to visualize: 120 deg about X-axis. + // Transform the i, j, & k unit vectors. + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0)); + Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0)); + Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0)); + // + CHECK(i_t.is_equal_approx(Vector3(1.0, 0.0, 0.0))); + CHECK(j_t.is_equal_approx(Vector3(0.0, -0.5, 0.866025))); + CHECK(k_t.is_equal_approx(Vector3(0.0, -0.866025, -0.5))); + CHECK(i_t.length_squared() == doctest::Approx(1.0)); + CHECK(j_t.length_squared() == doctest::Approx(1.0)); + CHECK(k_t.length_squared() == doctest::Approx(1.0)); + + // Easy to visualize: 30 deg about Y-axis. + q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + i_t = q.xform(Vector3(1.0, 0.0, 0.0)); + j_t = q.xform(Vector3(0.0, 1.0, 0.0)); + k_t = q.xform(Vector3(0.0, 0.0, 1.0)); + // + CHECK(i_t.is_equal_approx(Vector3(0.866025, 0.0, -0.5))); + CHECK(j_t.is_equal_approx(Vector3(0.0, 1.0, 0.0))); + CHECK(k_t.is_equal_approx(Vector3(0.5, 0.0, 0.866025))); + CHECK(i_t.length_squared() == doctest::Approx(1.0)); + CHECK(j_t.length_squared() == doctest::Approx(1.0)); + CHECK(k_t.length_squared() == doctest::Approx(1.0)); + + // Easy to visualize: 60 deg about Z-axis. + q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + i_t = q.xform(Vector3(1.0, 0.0, 0.0)); + j_t = q.xform(Vector3(0.0, 1.0, 0.0)); + k_t = q.xform(Vector3(0.0, 0.0, 1.0)); + // + CHECK(i_t.is_equal_approx(Vector3(0.5, 0.866025, 0.0))); + CHECK(j_t.is_equal_approx(Vector3(-0.866025, 0.5, 0.0))); + CHECK(k_t.is_equal_approx(Vector3(0.0, 0.0, 1.0))); + CHECK(i_t.length_squared() == doctest::Approx(1.0)); + CHECK(j_t.length_squared() == doctest::Approx(1.0)); + CHECK(k_t.length_squared() == doctest::Approx(1.0)); +} + +TEST_CASE("[Quaternion] xform vector") { + // Arbitrary quaternion rotates an arbitrary vector. + Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + Basis basis_axes(euler_yzx); + Quaternion q(basis_axes); + + Vector3 v_arb(3.0, 4.0, 5.0); + Vector3 v_rot = q.xform(v_arb); + Vector3 v_compare = basis_axes.xform(v_arb); + + CHECK(v_rot.length_squared() == doctest::Approx(v_arb.length_squared())); + CHECK(v_rot.is_equal_approx(v_compare)); +} + +// Test vector xform for a single combination of Quaternion and Vector. +void test_quat_vec_rotate(Vector3 euler_yzx, Vector3 v_in) { + Basis basis_axes(euler_yzx); + Quaternion q(basis_axes); + + Vector3 v_rot = q.xform(v_in); + Vector3 v_compare = basis_axes.xform(v_in); + + CHECK(v_rot.length_squared() == doctest::Approx(v_in.length_squared())); + CHECK(v_rot.is_equal_approx(v_compare)); +} + +TEST_CASE("[Stress][Quaternion] Many vector xforms") { + // Many arbitrary quaternions rotate many arbitrary vectors. + // For each trial, check that rotation by Quaternion yields same result as + // rotation by Basis. + const int STEPS = 100; // Number of test steps in each dimension + const double delta = 2.0 * Math_PI / STEPS; // Angle increment per step + const double delta_vec = 20.0 / STEPS; // Vector increment per step + Vector3 vec_arb(1.0, 1.0, 1.0); + double x_angle = -Math_PI; + double y_angle = -Math_PI; + double z_angle = -Math_PI; + for (double i = 0; i < STEPS; ++i) { + vec_arb[0] = -10.0 + i * delta_vec; + x_angle = i * delta - Math_PI; + for (double j = 0; j < STEPS; ++j) { + vec_arb[1] = -10.0 + j * delta_vec; + y_angle = j * delta - Math_PI; + for (double k = 0; k < STEPS; ++k) { + vec_arb[2] = -10.0 + k * delta_vec; + z_angle = k * delta - Math_PI; + Vector3 euler_yzx(x_angle, y_angle, z_angle); + test_quat_vec_rotate(euler_yzx, vec_arb); + } + } + } +} + +} // namespace TestQuaternion + +#endif // TEST_QUATERNION_H diff --git a/tests/core/math/test_transform_2d.h b/tests/core/math/test_transform_2d.h new file mode 100644 index 0000000000..697bf63fc5 --- /dev/null +++ b/tests/core/math/test_transform_2d.h @@ -0,0 +1,88 @@ +/*************************************************************************/ +/* test_transform_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_TRANSFORM_2D_H +#define TEST_TRANSFORM_2D_H + +#include "core/math/transform_2d.h" + +#include "tests/test_macros.h" + +namespace TestTransform2D { + +Transform2D create_dummy_transform() { + return Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6)); +} + +Transform2D identity() { + return Transform2D(); +} + +TEST_CASE("[Transform2D] translation") { + Vector2 offset = Vector2(1, 2); + + // Both versions should give the same result applied to identity. + CHECK(identity().translated(offset) == identity().translated_local(offset)); + + // Check both versions against left and right multiplications. + Transform2D orig = create_dummy_transform(); + Transform2D T = identity().translated(offset); + CHECK(orig.translated(offset) == T * orig); + CHECK(orig.translated_local(offset) == orig * T); +} + +TEST_CASE("[Transform2D] scaling") { + Vector2 scaling = Vector2(1, 2); + + // Both versions should give the same result applied to identity. + CHECK(identity().scaled(scaling) == identity().scaled_local(scaling)); + + // Check both versions against left and right multiplications. + Transform2D orig = create_dummy_transform(); + Transform2D S = identity().scaled(scaling); + CHECK(orig.scaled(scaling) == S * orig); + CHECK(orig.scaled_local(scaling) == orig * S); +} + +TEST_CASE("[Transform2D] rotation") { + real_t phi = 1.0; + + // Both versions should give the same result applied to identity. + CHECK(identity().rotated(phi) == identity().rotated_local(phi)); + + // Check both versions against left and right multiplications. + Transform2D orig = create_dummy_transform(); + Transform2D R = identity().rotated(phi); + CHECK(orig.rotated(phi) == R * orig); + CHECK(orig.rotated_local(phi) == orig * R); +} +} // namespace TestTransform2D + +#endif // TEST_TRANSFORM_2D_H diff --git a/tests/core/math/test_transform_3d.h b/tests/core/math/test_transform_3d.h new file mode 100644 index 0000000000..da166b43f7 --- /dev/null +++ b/tests/core/math/test_transform_3d.h @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* test_transform_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_TRANSFORM_3D_H +#define TEST_TRANSFORM_3D_H + +#include "core/math/transform_3d.h" + +#include "tests/test_macros.h" + +namespace TestTransform3D { + +Transform3D create_dummy_transform() { + return Transform3D(Basis(Vector3(1, 2, 3), Vector3(4, 5, 6), Vector3(7, 8, 9)), Vector3(10, 11, 12)); +} + +Transform3D identity() { + return Transform3D(); +} + +TEST_CASE("[Transform3D] translation") { + Vector3 offset = Vector3(1, 2, 3); + + // Both versions should give the same result applied to identity. + CHECK(identity().translated(offset) == identity().translated_local(offset)); + + // Check both versions against left and right multiplications. + Transform3D orig = create_dummy_transform(); + Transform3D T = identity().translated(offset); + CHECK(orig.translated(offset) == T * orig); + CHECK(orig.translated_local(offset) == orig * T); +} + +TEST_CASE("[Transform3D] scaling") { + Vector3 scaling = Vector3(1, 2, 3); + + // Both versions should give the same result applied to identity. + CHECK(identity().scaled(scaling) == identity().scaled_local(scaling)); + + // Check both versions against left and right multiplications. + Transform3D orig = create_dummy_transform(); + Transform3D S = identity().scaled(scaling); + CHECK(orig.scaled(scaling) == S * orig); + CHECK(orig.scaled_local(scaling) == orig * S); +} + +TEST_CASE("[Transform3D] rotation") { + Vector3 axis = Vector3(1, 2, 3).normalized(); + real_t phi = 1.0; + + // Both versions should give the same result applied to identity. + CHECK(identity().rotated(axis, phi) == identity().rotated_local(axis, phi)); + + // Check both versions against left and right multiplications. + Transform3D orig = create_dummy_transform(); + Transform3D R = identity().rotated(axis, phi); + CHECK(orig.rotated(axis, phi) == R * orig); + CHECK(orig.rotated_local(axis, phi) == orig * R); +} +} // namespace TestTransform3D + +#endif // TEST_TRANSFORM_3D_H diff --git a/tests/core/math/test_vector4.h b/tests/core/math/test_vector4.h new file mode 100644 index 0000000000..4b8759c0ca --- /dev/null +++ b/tests/core/math/test_vector4.h @@ -0,0 +1,312 @@ +/*************************************************************************/ +/* test_vector4.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_VECTOR4_H +#define TEST_VECTOR4_H + +#include "core/math/vector4.h" +#include "tests/test_macros.h" + +#define Math_SQRT3 1.7320508075688772935274463415059 + +namespace TestVector4 { + +TEST_CASE("[Vector4] Axis methods") { + Vector4 vector = Vector4(1.2, 3.4, 5.6, -0.9); + CHECK_MESSAGE( + vector.max_axis_index() == Vector4::Axis::AXIS_Z, + "Vector4 max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector4::Axis::AXIS_W, + "Vector4 min_axis_index should work as expected."); + CHECK_MESSAGE( + vector.get_axis(vector.max_axis_index()) == (real_t)5.6, + "Vector4 get_axis should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == (real_t)-0.9, + "Vector4 array operator should work as expected."); + + vector.set_axis(Vector4::Axis::AXIS_Y, 4.7); + CHECK_MESSAGE( + vector.get_axis(Vector4::Axis::AXIS_Y) == (real_t)4.7, + "Vector4 set_axis should work as expected."); + vector[Vector4::Axis::AXIS_Y] = 3.7; + CHECK_MESSAGE( + vector[Vector4::Axis::AXIS_Y] == (real_t)3.7, + "Vector4 array operator setter should work as expected."); +} + +TEST_CASE("[Vector4] Interpolation methods") { + const Vector4 vector1 = Vector4(1, 2, 3, 4); + const Vector4 vector2 = Vector4(4, 5, 6, 7); + CHECK_MESSAGE( + vector1.lerp(vector2, 0.5) == Vector4(2.5, 3.5, 4.5, 5.5), + "Vector4 lerp should work as expected."); + CHECK_MESSAGE( + vector1.lerp(vector2, 1.0 / 3.0).is_equal_approx(Vector4(2, 3, 4, 5)), + "Vector4 lerp should work as expected."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector4(), Vector4(7, 7, 7, 7), 0.5) == Vector4(2.375, 3.5, 4.625, 5.75), + "Vector4 cubic_interpolate should work as expected."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector4(), Vector4(7, 7, 7, 7), 1.0 / 3.0).is_equal_approx(Vector4(1.851851940155029297, 2.962963104248046875, 4.074074268341064453, 5.185185185185)), + "Vector4 cubic_interpolate should work as expected."); +} + +TEST_CASE("[Vector4] Length methods") { + const Vector4 vector1 = Vector4(10, 10, 10, 10); + const Vector4 vector2 = Vector4(20, 30, 40, 50); + CHECK_MESSAGE( + vector1.length_squared() == 400, + "Vector4 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 20), + "Vector4 length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 5400, + "Vector4 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), (real_t)73.484692283495), + "Vector4 length should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.distance_to(vector2), (real_t)54.772255750517), + "Vector4 distance_to should work as expected."); +} + +TEST_CASE("[Vector4] Limiting methods") { + const Vector4 vector = Vector4(10, 10, 10, 10); + CHECK_MESSAGE( + Vector4(-5, 5, 15, -15).clamp(Vector4(), vector) == Vector4(0, 5, 10, 0), + "Vector4 clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector4(0, 10, 15, 18), Vector4(5, 10, 20, 25)) == Vector4(5, 10, 15, 18), + "Vector4 clamp should work as expected."); +} + +TEST_CASE("[Vector4] Normalization methods") { + CHECK_MESSAGE( + Vector4(1, 0, 0, 0).is_normalized() == true, + "Vector4 is_normalized should return true for a normalized vector."); + CHECK_MESSAGE( + Vector4(1, 1, 1, 1).is_normalized() == false, + "Vector4 is_normalized should return false for a non-normalized vector."); + CHECK_MESSAGE( + Vector4(1, 0, 0, 0).normalized() == Vector4(1, 0, 0, 0), + "Vector4 normalized should return the same vector for a normalized vector."); + CHECK_MESSAGE( + Vector4(1, 1, 0, 0).normalized().is_equal_approx(Vector4(Math_SQRT12, Math_SQRT12, 0, 0)), + "Vector4 normalized should work as expected."); + CHECK_MESSAGE( + Vector4(1, 1, 1, 1).normalized().is_equal_approx(Vector4(0.5, 0.5, 0.5, 0.5)), + "Vector4 normalized should work as expected."); +} + +TEST_CASE("[Vector4] Operators") { + const Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2); + const Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7); + const Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125); + const Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75); + const Vector4 int1 = Vector4(4, 5, 9, 2); + const Vector4 int2 = Vector4(1, 2, 3, 1); + + CHECK_MESSAGE( + -decimal1 == Vector4(-2.3, -4.9, -7.8, -3.2), + "Vector4 change of sign should work as expected."); + CHECK_MESSAGE( + (decimal1 + decimal2).is_equal_approx(Vector4(3.5, 8.3, 13.4, 4.9)), + "Vector4 addition should behave as expected."); + CHECK_MESSAGE( + (power1 + power2) == Vector4(1.25, 1.625, 0.875, 0.875), + "Vector4 addition with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 + int2) == Vector4(5, 7, 12, 3), + "Vector4 addition with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 - decimal2).is_equal_approx(Vector4(1.1, 1.5, 2.2, 1.5)), + "Vector4 subtraction should behave as expected."); + CHECK_MESSAGE( + (power1 - power2) == Vector4(0.25, 1.375, 0.375, -0.625), + "Vector4 subtraction with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 - int2) == Vector4(3, 3, 6, 1), + "Vector4 subtraction with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * decimal2).is_equal_approx(Vector4(2.76, 16.66, 43.68, 5.44)), + "Vector4 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * power2) == Vector4(0.375, 0.1875, 0.15625, 0.09375), + "Vector4 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * int2) == Vector4(4, 10, 27, 2), + "Vector4 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / decimal2).is_equal_approx(Vector4(1.91666666666666666, 1.44117647058823529, 1.39285714285714286, 1.88235294118)), + "Vector4 division should behave as expected."); + CHECK_MESSAGE( + (power1 / power2) == Vector4(1.5, 12.0, 2.5, 1.0 / 6.0), + "Vector4 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / int2) == Vector4(4, 2.5, 3, 2), + "Vector4 division with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * 2).is_equal_approx(Vector4(4.6, 9.8, 15.6, 6.4)), + "Vector4 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * 2) == Vector4(1.5, 3, 1.25, 0.25), + "Vector4 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * 2) == Vector4(8, 10, 18, 4), + "Vector4 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / 2).is_equal_approx(Vector4(1.15, 2.45, 3.9, 1.6)), + "Vector4 division should behave as expected."); + CHECK_MESSAGE( + (power1 / 2) == Vector4(0.375, 0.75, 0.3125, 0.0625), + "Vector4 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / 2) == Vector4(2, 2.5, 4.5, 1), + "Vector4 division with integers should give exact results."); + + CHECK_MESSAGE( + ((String)decimal1) == "(2.3, 4.9, 7.8, 3.2)", + "Vector4 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)decimal2) == "(1.2, 3.4, 5.6, 1.7)", + "Vector4 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)Vector4(9.7, 9.8, 9.9, -1.8)) == "(9.7, 9.8, 9.9, -1.8)", + "Vector4 cast to String should work as expected."); +#ifdef REAL_T_IS_DOUBLE + CHECK_MESSAGE( + ((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888, 1.73205080756888)", + "Vector4 cast to String should print the correct amount of digits for real_t = double."); +#else + CHECK_MESSAGE( + ((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051, 1.732051)", + "Vector4 cast to String should print the correct amount of digits for real_t = float."); +#endif // REAL_T_IS_DOUBLE +} + +TEST_CASE("[Vector4] Other methods") { + const Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6); + CHECK_MESSAGE( + vector.direction_to(Vector4()).is_equal_approx(-vector.normalized()), + "Vector4 direction_to should work as expected."); + CHECK_MESSAGE( + Vector4(1, 1, 1, 1).direction_to(Vector4(2, 2, 2, 2)).is_equal_approx(Vector4(0.5, 0.5, 0.5, 0.5)), + "Vector4 direction_to should work as expected."); + CHECK_MESSAGE( + vector.inverse().is_equal_approx(Vector4(1 / 1.2, 1 / 3.4, 1 / 5.6, 1 / 1.6)), + "Vector4 inverse should work as expected."); + CHECK_MESSAGE( + vector.posmod(2).is_equal_approx(Vector4(1.2, 1.4, 1.6, 1.6)), + "Vector4 posmod should work as expected."); + CHECK_MESSAGE( + (-vector).posmod(2).is_equal_approx(Vector4(0.8, 0.6, 0.4, 0.4)), + "Vector4 posmod should work as expected."); + CHECK_MESSAGE( + vector.posmodv(Vector4(1, 2, 3, 4)).is_equal_approx(Vector4(0.2, 1.4, 2.6, 1.6)), + "Vector4 posmodv should work as expected."); + CHECK_MESSAGE( + (-vector).posmodv(Vector4(2, 3, 4, 5)).is_equal_approx(Vector4(0.8, 2.6, 2.4, 3.4)), + "Vector4 posmodv should work as expected."); + CHECK_MESSAGE( + vector.snapped(Vector4(1, 1, 1, 1)) == Vector4(1, 3, 6, 2), + "Vector4 snapped to integers should be the same as rounding."); + CHECK_MESSAGE( + vector.snapped(Vector4(0.25, 0.25, 0.25, 0.25)) == Vector4(1.25, 3.5, 5.5, 1.5), + "Vector4 snapped to 0.25 should give exact results."); +} + +TEST_CASE("[Vector4] Rounding methods") { + const Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6); + const Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector4 abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector4 abs should work as expected."); + CHECK_MESSAGE( + vector1.ceil() == Vector4(2, 4, 6, 2), + "Vector4 ceil should work as expected."); + CHECK_MESSAGE( + vector2.ceil() == Vector4(2, -3, -5, -1), + "Vector4 ceil should work as expected."); + + CHECK_MESSAGE( + vector1.floor() == Vector4(1, 3, 5, 1), + "Vector4 floor should work as expected."); + CHECK_MESSAGE( + vector2.floor() == Vector4(1, -4, -6, -2), + "Vector4 floor should work as expected."); + + CHECK_MESSAGE( + vector1.round() == Vector4(1, 3, 6, 2), + "Vector4 round should work as expected."); + CHECK_MESSAGE( + vector2.round() == Vector4(1, -3, -6, -2), + "Vector4 round should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector4(1, 1, 1, 1), + "Vector4 sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector4(1, -1, -1, -1), + "Vector4 sign should work as expected."); +} + +TEST_CASE("[Vector4] Linear algebra methods") { + const Vector4 vector_x = Vector4(1, 0, 0, 0); + const Vector4 vector_y = Vector4(0, 1, 0, 0); + const Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1); + const Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4); + + CHECK_MESSAGE( + vector_x.dot(vector_y) == 0.0, + "Vector4 dot product of perpendicular vectors should be zero."); + CHECK_MESSAGE( + vector_x.dot(vector_x) == 1.0, + "Vector4 dot product of identical unit vectors should be one."); + CHECK_MESSAGE( + (vector_x * 10).dot(vector_x * 10) == 100.0, + "Vector4 dot product of same direction vectors should behave as expected."); + CHECK_MESSAGE( + Math::is_equal_approx((vector1 * 2).dot(vector2 * 4), (real_t)-25.9 * 8), + "Vector4 dot product should work as expected."); +} +} // namespace TestVector4 + +#endif // TEST_VECTOR4_H diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h new file mode 100644 index 0000000000..ac63001b24 --- /dev/null +++ b/tests/core/math/test_vector4i.h @@ -0,0 +1,148 @@ +/*************************************************************************/ +/* test_vector4i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_VECTOR4I_H +#define TEST_VECTOR4I_H + +#include "core/math/vector4i.h" +#include "tests/test_macros.h" + +namespace TestVector4i { + +TEST_CASE("[Vector4i] Axis methods") { + Vector4i vector = Vector4i(1, 2, 3, 4); + CHECK_MESSAGE( + vector.max_axis_index() == Vector4i::Axis::AXIS_W, + "Vector4i max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector4i::Axis::AXIS_X, + "Vector4i min_axis_index should work as expected."); + CHECK_MESSAGE( + vector.get_axis(vector.max_axis_index()) == 4, + "Vector4i get_axis should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == 1, + "Vector4i array operator should work as expected."); + + vector.set_axis(Vector4i::Axis::AXIS_Y, 5); + CHECK_MESSAGE( + vector.get_axis(Vector4i::Axis::AXIS_Y) == 5, + "Vector4i set_axis should work as expected."); + vector[Vector4i::Axis::AXIS_Y] = 5; + CHECK_MESSAGE( + vector[Vector4i::Axis::AXIS_Y] == 5, + "Vector4i array operator setter should work as expected."); +} + +TEST_CASE("[Vector4i] Clamp method") { + const Vector4i vector = Vector4i(10, 10, 10, 10); + CHECK_MESSAGE( + Vector4i(-5, 5, 15, INT_MAX).clamp(Vector4i(), vector) == Vector4i(0, 5, 10, 10), + "Vector4i clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector4i(0, 10, 15, -10), Vector4i(5, 10, 20, -5)) == Vector4i(5, 10, 15, -5), + "Vector4i clamp should work as expected."); +} + +TEST_CASE("[Vector4i] Length methods") { + const Vector4i vector1 = Vector4i(10, 10, 10, 10); + const Vector4i vector2 = Vector4i(20, 30, 40, 50); + CHECK_MESSAGE( + vector1.length_squared() == 400, + "Vector4i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 20), + "Vector4i length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 5400, + "Vector4i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), 73.4846922835), + "Vector4i length should work as expected."); +} + +TEST_CASE("[Vector4i] Operators") { + const Vector4i vector1 = Vector4i(4, 5, 9, 2); + const Vector4i vector2 = Vector4i(1, 2, 3, 4); + + CHECK_MESSAGE( + -vector1 == Vector4i(-4, -5, -9, -2), + "Vector4i change of sign should work as expected."); + CHECK_MESSAGE( + (vector1 + vector2) == Vector4i(5, 7, 12, 6), + "Vector4i addition with integers should give exact results."); + CHECK_MESSAGE( + (vector1 - vector2) == Vector4i(3, 3, 6, -2), + "Vector4i subtraction with integers should give exact results."); + CHECK_MESSAGE( + (vector1 * vector2) == Vector4i(4, 10, 27, 8), + "Vector4i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / vector2) == Vector4i(4, 2, 3, 0), + "Vector4i division with integers should give exact results."); + + CHECK_MESSAGE( + (vector1 * 2) == Vector4i(8, 10, 18, 4), + "Vector4i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / 2) == Vector4i(2, 2, 4, 1), + "Vector4i division with integers should give exact results."); + + CHECK_MESSAGE( + ((Vector4)vector1) == Vector4(4, 5, 9, 2), + "Vector4i cast to Vector4 should work as expected."); + CHECK_MESSAGE( + ((Vector4)vector2) == Vector4(1, 2, 3, 4), + "Vector4i cast to Vector4 should work as expected."); + CHECK_MESSAGE( + Vector4i(Vector4(1.1, 2.9, 3.9, 100.5)) == Vector4i(1, 2, 3, 100), + "Vector4i constructed from Vector4 should work as expected."); +} + +TEST_CASE("[Vector4i] Abs and sign methods") { + const Vector4i vector1 = Vector4i(1, 3, 5, 7); + const Vector4i vector2 = Vector4i(1, -3, -5, 7); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector4i abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector4i abs should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector4i(1, 1, 1, 1), + "Vector4i sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector4i(1, -1, -1, 1), + "Vector4i sign should work as expected."); +} +} // namespace TestVector4i + +#endif // TEST_VECTOR4I_H diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h index c7535426df..fc329ba0eb 100644 --- a/tests/core/object/test_class_db.h +++ b/tests/core/object/test_class_db.h @@ -493,13 +493,13 @@ void add_exposed_classes(Context &r_context) { } if (!ClassDB::is_class_exposed(class_name)) { - MESSAGE(vformat("Ignoring class '%s' because it's not exposed.", class_name).utf8().get_data()); + MESSAGE(vformat("Ignoring class '%s' because it's not exposed.", class_name)); class_list.pop_front(); continue; } if (!ClassDB::is_class_enabled(class_name)) { - MESSAGE(vformat("Ignoring class '%s' because it's not enabled.", class_name).utf8().get_data()); + MESSAGE(vformat("Ignoring class '%s' because it's not enabled.", class_name)); class_list.pop_front(); continue; } diff --git a/tests/core/object/test_method_bind.h b/tests/core/object/test_method_bind.h index 350a08b6e2..2fe0c264a1 100644 --- a/tests/core/object/test_method_bind.h +++ b/tests/core/object/test_method_bind.h @@ -155,7 +155,6 @@ public: TEST_CASE("[MethodBind] check all method binds") { MethodBindTester *mbt = memnew(MethodBindTester); - print_line("testing method bind"); mbt->run_tests(); CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD]); diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h index 5b9d9cab53..88a3e4ccad 100644 --- a/tests/core/object/test_object.h +++ b/tests/core/object/test_object.h @@ -95,8 +95,8 @@ public: Ref<Script> get_script() const override { return Ref<Script>(); } - const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { - return Vector<Multiplayer::RPCConfig>(); + const Variant get_rpc_config() const override { + return Variant(); } ScriptLanguage *get_language() override { return nullptr; diff --git a/tests/core/os/test_os.h b/tests/core/os/test_os.h new file mode 100644 index 0000000000..c46da5e156 --- /dev/null +++ b/tests/core/os/test_os.h @@ -0,0 +1,158 @@ +/*************************************************************************/ +/* test_os.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_OS_H +#define TEST_OS_H + +#include "core/os/os.h" + +#include "thirdparty/doctest/doctest.h" + +namespace TestOS { + +TEST_CASE("[OS] Environment variables") { +#ifdef WINDOWS_ENABLED + CHECK_MESSAGE( + OS::get_singleton()->has_environment("USERPROFILE"), + "The USERPROFILE environment variable should be present."); +#else + CHECK_MESSAGE( + OS::get_singleton()->has_environment("HOME"), + "The HOME environment variable should be present."); +#endif + + OS::get_singleton()->set_environment("HELLO", "world"); + CHECK_MESSAGE( + OS::get_singleton()->get_environment("HELLO") == "world", + "The previously-set HELLO environment variable should return the expected value."); +} + +TEST_CASE("[OS] Command line arguments") { + List<String> arguments = OS::get_singleton()->get_cmdline_args(); + bool found = false; + for (int i = 0; i < arguments.size(); i++) { + if (arguments[i] == "--test") { + found = true; + break; + } + } + CHECK_MESSAGE( + found, + "The `--test` option must be present in the list of command line arguments."); +} + +TEST_CASE("[OS] Executable and data paths") { + CHECK_MESSAGE( + OS::get_singleton()->get_executable_path().is_absolute_path(), + "The executable path returned should be an absolute path."); + CHECK_MESSAGE( + OS::get_singleton()->get_data_path().is_absolute_path(), + "The user data path returned should be an absolute path."); + CHECK_MESSAGE( + OS::get_singleton()->get_config_path().is_absolute_path(), + "The user configuration path returned should be an absolute path."); + CHECK_MESSAGE( + OS::get_singleton()->get_cache_path().is_absolute_path(), + "The cache path returned should be an absolute path."); +} + +TEST_CASE("[OS] Ticks") { + CHECK_MESSAGE( + OS::get_singleton()->get_ticks_usec() > 1000, + "The returned ticks (in microseconds) must be greater than 1,000."); + CHECK_MESSAGE( + OS::get_singleton()->get_ticks_msec() > 1, + "The returned ticks (in milliseconds) must be greater than 1."); +} + +TEST_CASE("[OS] Feature tags") { + CHECK_MESSAGE( + OS::get_singleton()->has_feature("editor"), + "The binary has the \"editor\" feature tag."); + CHECK_MESSAGE( + !OS::get_singleton()->has_feature("standalone"), + "The binary does not have the \"standalone\" feature tag."); + CHECK_MESSAGE( + OS::get_singleton()->has_feature("debug"), + "The binary has the \"debug\" feature tag."); + CHECK_MESSAGE( + !OS::get_singleton()->has_feature("release"), + "The binary does not have the \"release\" feature tag."); +} + +TEST_CASE("[OS] Process ID") { + CHECK_MESSAGE( + OS::get_singleton()->get_process_id() >= 1, + "The returned process ID should be greater than zero."); +} + +TEST_CASE("[OS] Processor count and memory information") { + CHECK_MESSAGE( + OS::get_singleton()->get_processor_count() >= 1, + "The returned processor count should be greater than zero."); + CHECK_MESSAGE( + OS::get_singleton()->get_static_memory_usage() >= 1, + "The returned static memory usage should be greater than zero."); + CHECK_MESSAGE( + OS::get_singleton()->get_static_memory_peak_usage() >= 1, + "The returned static memory peak usage should be greater than zero."); +} + +TEST_CASE("[OS] Execute") { +#ifdef WINDOWS_ENABLED + List<String> arguments; + arguments.push_back("/C"); + arguments.push_back("dir > NUL"); + int exit_code; + const Error err = OS::get_singleton()->execute("cmd", arguments, nullptr, &exit_code); + CHECK_MESSAGE( + err == OK, + "(Running the command `cmd /C \"dir > NUL\"` returns the expected Godot error code (OK)."); + CHECK_MESSAGE( + exit_code == 0, + "Running the command `cmd /C \"dir > NUL\"` returns a zero (successful) exit code."); +#else + List<String> arguments; + arguments.push_back("-c"); + arguments.push_back("ls > /dev/null"); + int exit_code; + const Error err = OS::get_singleton()->execute("sh", arguments, nullptr, &exit_code); + CHECK_MESSAGE( + err == OK, + "(Running the command `sh -c \"ls > /dev/null\"` returns the expected Godot error code (OK)."); + CHECK_MESSAGE( + exit_code == 0, + "Running the command `sh -c \"ls > /dev/null\"` returns a zero (successful) exit code."); +#endif +} + +} // namespace TestOS + +#endif // TEST_OS_H diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index 0c5704d6c9..8914dbfd9a 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -152,6 +152,20 @@ TEST_CASE("[String] UTF16 with BOM") { CHECK(String::utf16(cs) == s); } +TEST_CASE("[String] UTF8 with CR") { + const String base = U"Hello darkness\r\nMy old friend\nI've come to talk\rWith you again"; + + String keep_cr; + Error err = keep_cr.parse_utf8(base.utf8().get_data()); + CHECK(err == OK); + CHECK(keep_cr == base); + + String no_cr; + err = no_cr.parse_utf8(base.utf8().get_data(), -1, true); // Skip CR. + CHECK(err == OK); + CHECK(no_cr == base.replace("\r", "")); +} + TEST_CASE("[String] Invalid UTF8 (non-standard)") { ERR_PRINT_OFF static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 }; @@ -683,7 +697,9 @@ TEST_CASE("[String] sprintf") { format = "fish %-05d frog"; args.clear(); args.push_back(-5); + ERR_PRINT_OFF; // Silence warning about 0 ignored. output = format.sprintf(args, &error); + ERR_PRINT_ON; REQUIRE(error == false); CHECK(output == String("fish -5 frog")); @@ -781,7 +797,9 @@ TEST_CASE("[String] sprintf") { format = "fish %-011f frog"; args.clear(); args.push_back(-99.99); + ERR_PRINT_OFF; // Silence warning about 0 ignored. output = format.sprintf(args, &error); + ERR_PRINT_ON; REQUIRE(error == false); CHECK(output == String("fish -99.990000 frog")); diff --git a/tests/core/templates/test_hash_set.h b/tests/core/templates/test_hash_set.h index 93fc0b26a3..dad149604b 100644 --- a/tests/core/templates/test_hash_set.h +++ b/tests/core/templates/test_hash_set.h @@ -38,7 +38,6 @@ namespace TestHashSet { TEST_CASE("[HashSet] Insert element") { - print_line("SMALL BEGIN MEM: ", Memory::get_mem_usage()); HashSet<int> set; HashSet<int>::Iterator e = set.insert(42); @@ -47,7 +46,6 @@ TEST_CASE("[HashSet] Insert element") { CHECK(set.has(42)); CHECK(set.find(42)); set.reset(); - print_line("SMALL END MEM: ", Memory::get_mem_usage()); } TEST_CASE("[HashSet] Insert existing element") { @@ -225,4 +223,4 @@ TEST_CASE("[HashSet] Copy") { } // namespace TestHashSet -#endif // TEST_HASH_MAP_H +#endif // TEST_HASH_SET_H diff --git a/modules/websocket/emws_server.cpp b/tests/core/templates/test_rid.h index 2033098cad..8d4dd0703b 100644 --- a/modules/websocket/emws_server.cpp +++ b/tests/core/templates/test_rid.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* emws_server.cpp */ +/* test_rid.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,65 +28,74 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef JAVASCRIPT_ENABLED +#ifndef TEST_RID_H +#define TEST_RID_H -#include "emws_server.h" -#include "core/os/os.h" +#include "core/templates/rid.h" -void EMWSServer::set_extra_headers(const Vector<String> &p_headers) { -} +#include "tests/test_macros.h" -Error EMWSServer::listen(int p_port, Vector<String> p_protocols, bool gd_mp_api) { - return FAILED; -} +namespace TestRID { +TEST_CASE("[RID] Default Constructor") { + RID rid; -bool EMWSServer::is_listening() const { - return false; + CHECK(rid.get_id() == 0); } -void EMWSServer::stop() { -} +TEST_CASE("[RID] Factory method") { + RID rid = RID::from_uint64(1); -bool EMWSServer::has_peer(int p_id) const { - return false; + CHECK(rid.get_id() == 1); } -Ref<WebSocketPeer> EMWSServer::get_peer(int p_id) const { - return nullptr; -} +TEST_CASE("[RID] Operators") { + RID rid = RID::from_uint64(1); -Vector<String> EMWSServer::get_protocols() const { - Vector<String> out; + RID rid_zero = RID::from_uint64(0); + RID rid_one = RID::from_uint64(1); + RID rid_two = RID::from_uint64(2); - return out; -} + CHECK_FALSE(rid == rid_zero); + CHECK(rid == rid_one); + CHECK_FALSE(rid == rid_two); -IPAddress EMWSServer::get_peer_address(int p_peer_id) const { - return IPAddress(); -} + CHECK_FALSE(rid < rid_zero); + CHECK_FALSE(rid < rid_one); + CHECK(rid < rid_two); -int EMWSServer::get_peer_port(int p_peer_id) const { - return 0; -} + CHECK_FALSE(rid <= rid_zero); + CHECK(rid <= rid_one); + CHECK(rid <= rid_two); -void EMWSServer::disconnect_peer(int p_peer_id, int p_code, String p_reason) { -} + CHECK(rid > rid_zero); + CHECK_FALSE(rid > rid_one); + CHECK_FALSE(rid > rid_two); -void EMWSServer::poll() { -} + CHECK(rid >= rid_zero); + CHECK(rid >= rid_one); + CHECK_FALSE(rid >= rid_two); -int EMWSServer::get_max_packet_size() const { - return 0; + CHECK(rid != rid_zero); + CHECK_FALSE(rid != rid_one); + CHECK(rid != rid_two); } -Error EMWSServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) { - return OK; -} +TEST_CASE("[RID] 'is_valid' & 'is_null'") { + RID rid_zero = RID::from_uint64(0); + RID rid_one = RID::from_uint64(1); + + CHECK_FALSE(rid_zero.is_valid()); + CHECK(rid_zero.is_null()); -EMWSServer::EMWSServer() { + CHECK(rid_one.is_valid()); + CHECK_FALSE(rid_one.is_null()); } -EMWSServer::~EMWSServer() { +TEST_CASE("[RID] 'get_local_index'") { + CHECK(RID::from_uint64(1).get_local_index() == 1); + CHECK(RID::from_uint64(4'294'967'295).get_local_index() == 4'294'967'295); + CHECK(RID::from_uint64(4'294'967'297).get_local_index() == 1); } +} // namespace TestRID -#endif // JAVASCRIPT_ENABLED +#endif // TEST_RID_H diff --git a/tests/core/templates/test_vector.h b/tests/core/templates/test_vector.h index f27d6a332e..3fc9264f5a 100644 --- a/tests/core/templates/test_vector.h +++ b/tests/core/templates/test_vector.h @@ -291,8 +291,10 @@ TEST_CASE("[Vector] Slice") { CHECK(slice6[1] == 3); CHECK(slice6[2] == 4); + ERR_PRINT_OFF; Vector<int> slice7 = vector.slice(5, 1); - CHECK(slice7.size() == 0); + CHECK(slice7.size() == 0); // Expected to fail. + ERR_PRINT_ON; } TEST_CASE("[Vector] Find, has") { diff --git a/tests/core/threads/test_worker_thread_pool.h b/tests/core/threads/test_worker_thread_pool.h new file mode 100644 index 0000000000..641b293c8a --- /dev/null +++ b/tests/core/threads/test_worker_thread_pool.h @@ -0,0 +1,158 @@ +/*************************************************************************/ +/* test_worker_thread_pool.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_WORKER_THREAD_POOL_H +#define TEST_WORKER_THREAD_POOL_H + +#include "core/object/worker_thread_pool.h" + +#include "tests/test_macros.h" + +namespace TestWorkerThreadPool { + +int u32scmp(const char32_t *l, const char32_t *r) { + for (; *l == *r && *l && *r; l++, r++) { + // Continue. + } + return *l - *r; +} + +static void static_test(void *p_arg) { + SafeNumeric<uint32_t> *counter = (SafeNumeric<uint32_t> *)p_arg; + counter->increment(); +} + +static SafeNumeric<uint32_t> callable_counter; + +static void static_callable_test() { + callable_counter.increment(); +} + +TEST_CASE("[WorkerThreadPool] Process 256 threads using native task") { + const int count = 256; + SafeNumeric<uint32_t> counter; + WorkerThreadPool::TaskID tasks[count]; + for (int i = 0; i < count; i++) { + tasks[i] = WorkerThreadPool::get_singleton()->add_native_task(static_test, &counter, true); + } + for (int i = 0; i < count; i++) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]); + } + + CHECK(counter.get() == count); +} + +TEST_CASE("[WorkerThreadPool] Process 256 threads using native low priority") { + const int count = 256; + SafeNumeric<uint32_t> counter = SafeNumeric<uint32_t>(0); + WorkerThreadPool::TaskID tasks[count]; + for (int i = 0; i < count; i++) { + tasks[i] = WorkerThreadPool::get_singleton()->add_native_task(static_test, &counter, false); + } + for (int i = 0; i < count; i++) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]); + } + + CHECK(counter.get() == count); +} + +TEST_CASE("[WorkerThreadPool] Process 256 threads using callable") { + const int count = 256; + WorkerThreadPool::TaskID tasks[count]; + callable_counter.set(0); + for (int i = 0; i < count; i++) { + tasks[i] = WorkerThreadPool::get_singleton()->add_task(callable_mp_static(static_callable_test), true); + } + for (int i = 0; i < count; i++) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]); + } + + CHECK(callable_counter.get() == count); +} + +TEST_CASE("[WorkerThreadPool] Process 256 threads using callable low priority") { + const int count = 256; + WorkerThreadPool::TaskID tasks[count]; + callable_counter.set(0); + for (int i = 0; i < count; i++) { + tasks[i] = WorkerThreadPool::get_singleton()->add_task(callable_mp_static(static_callable_test), false); + } + for (int i = 0; i < count; i++) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]); + } + + CHECK(callable_counter.get() == count); +} + +static void static_group_test(void *p_arg, uint32_t p_index) { + SafeNumeric<uint32_t> *counter = (SafeNumeric<uint32_t> *)p_arg; + counter->exchange_if_greater(p_index); +} + +TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group") { + const int count = 256; + SafeNumeric<uint32_t> counter; + WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_native_group_task(static_group_test, &counter, count, -1, true); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group); + CHECK(counter.get() == count - 1); +} + +TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group low priority") { + const int count = 256; + SafeNumeric<uint32_t> counter; + WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_native_group_task(static_group_test, &counter, count, -1, false); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group); + CHECK(counter.get() == count - 1); +} + +static SafeNumeric<uint32_t> callable_group_counter; + +static void static_callable_group_test(uint32_t p_index) { + callable_group_counter.exchange_if_greater(p_index); +} + +TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group") { + const int count = 256; + WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_group_task(callable_mp_static(static_callable_group_test), count, -1, true); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group); + CHECK(callable_group_counter.get() == count - 1); +} + +TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group low priority") { + const int count = 256; + callable_group_counter.set(0); + WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_group_task(callable_mp_static(static_callable_group_test), count, -1, false); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group); + CHECK(callable_group_counter.get() == count - 1); +} + +} // namespace TestWorkerThreadPool + +#endif // TEST_WORKER_THREAD_POOL_H diff --git a/tests/data/line_endings_cr.test.txt b/tests/data/line_endings_cr.test.txt new file mode 100644 index 0000000000..556154bb25 --- /dev/null +++ b/tests/data/line_endings_cr.test.txt @@ -0,0 +1 @@ +Hello darkness
My old friend
I've come to talk
With you again
\ No newline at end of file diff --git a/tests/data/line_endings_crlf.test.txt b/tests/data/line_endings_crlf.test.txt new file mode 100644 index 0000000000..a3cbe55b7f --- /dev/null +++ b/tests/data/line_endings_crlf.test.txt @@ -0,0 +1,4 @@ +Hello darkness
+My old friend
+I've come to talk
+With you again
diff --git a/tests/data/line_endings_lf.test.txt b/tests/data/line_endings_lf.test.txt new file mode 100644 index 0000000000..0aabcd911e --- /dev/null +++ b/tests/data/line_endings_lf.test.txt @@ -0,0 +1,4 @@ +Hello darkness +My old friend +I've come to talk +With you again diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h new file mode 100644 index 0000000000..92c524525c --- /dev/null +++ b/tests/scene/test_audio_stream_wav.h @@ -0,0 +1,243 @@ +/*************************************************************************/ +/* test_audio_stream_wav.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_AUDIO_STREAM_WAV_H +#define TEST_AUDIO_STREAM_WAV_H + +#include "core/math/math_defs.h" +#include "core/math/math_funcs.h" +#include "scene/resources/audio_stream_wav.h" + +#include "tests/test_macros.h" + +#ifdef TOOLS_ENABLED +#include "core/io/resource_loader.h" +#include "editor/import/resource_importer_wav.h" +#endif + +namespace TestAudioStreamWAV { + +// Default wav rate for test cases. +constexpr float WAV_RATE = 44100; +/* Default wav count for test cases. 1 second of audio is used so that the file can be listened +to manually if needed. */ +constexpr int WAV_COUNT = WAV_RATE; + +float gen_wav(float frequency, float wav_rate, int wav_number) { + // formula for generating a sin wave with given frequency. + return Math::sin((Math_TAU * frequency / wav_rate) * wav_number); +} + +/* Generates a 440Hz sin wave in channel 0 (mono channel or left stereo channel) + * and a 261.63Hz wave in channel 1 (right stereo channel). + * These waves correspond to the music notes A4 and C4 respectively. + */ +Vector<uint8_t> gen_pcm8_test(float wav_rate, int wav_count, bool stereo) { + Vector<uint8_t> buffer; + buffer.resize(stereo ? wav_count * 2 : wav_count); + + uint8_t *write_ptr = buffer.ptrw(); + for (int i = 0; i < buffer.size(); i++) { + float wav; + if (stereo) { + if (i % 2 == 0) { + wav = gen_wav(440, wav_rate, i / 2); + } else { + wav = gen_wav(261.63, wav_rate, i / 2); + } + } else { + wav = gen_wav(440, wav_rate, i); + } + + // Map sin wave to full range of 8-bit values. + uint8_t wav_8bit = Math::fast_ftoi(((wav + 1) / 2) * UINT8_MAX); + // Unlike the .wav format, AudioStreamWAV expects signed 8-bit wavs. + uint8_t wav_8bit_signed = wav_8bit - (INT8_MAX + 1); + write_ptr[i] = wav_8bit_signed; + } + + return buffer; +} + +// Same as gen_pcm8_test but with 16-bit wavs. +Vector<uint8_t> gen_pcm16_test(float wav_rate, int wav_count, bool stereo) { + Vector<uint8_t> buffer; + buffer.resize(stereo ? wav_count * 4 : wav_count * 2); + + uint8_t *write_ptr = buffer.ptrw(); + for (int i = 0; i < buffer.size() / 2; i++) { + float wav; + if (stereo) { + if (i % 2 == 0) { + wav = gen_wav(440, wav_rate, i / 2); + } else { + wav = gen_wav(261.63, wav_rate, i / 2); + } + } else { + wav = gen_wav(440, wav_rate, i); + } + + // Map sin wave to full range of 16-bit values. + uint16_t wav_16bit = Math::fast_ftoi(((wav + 1) / 2) * UINT16_MAX); + // The .wav format expects wavs larger than 8 bits to be signed. + uint16_t wav_16bit_signed = wav_16bit - (INT16_MAX + 1); + encode_uint16(wav_16bit_signed, write_ptr + (i * 2)); + } + + return buffer; +} + +void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, float wav_rate, float wav_count) { + String save_path = OS::get_singleton()->get_cache_path().plus_file(file_name); + + Vector<uint8_t> test_data; + if (data_format == AudioStreamWAV::FORMAT_8_BITS) { + test_data = gen_pcm8_test(wav_rate, wav_count, stereo); + } else { + test_data = gen_pcm16_test(wav_rate, wav_count, stereo); + } + + Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV); + stream->set_mix_rate(wav_rate); + CHECK(stream->get_mix_rate() == wav_rate); + + stream->set_format(data_format); + CHECK(stream->get_format() == data_format); + + stream->set_stereo(stereo); + CHECK(stream->is_stereo() == stereo); + + stream->set_data(test_data); + CHECK(stream->get_data() == test_data); + + SUBCASE("Stream length is computed properly") { + CHECK(Math::is_equal_approx(stream->get_length(), wav_count / wav_rate)); + } + + SUBCASE("Stream can be saved as .wav") { + REQUIRE(stream->save_to_wav(save_path) == OK); + + Error error; + Ref<FileAccess> wav_file = FileAccess::open(save_path, FileAccess::READ, &error); + REQUIRE(error == OK); + +#if TOOLS_ENABLED + // The WAV importer can be used if enabled to check that the saved file is valid. + Ref<ResourceImporterWAV> wav_importer = memnew(ResourceImporterWAV); + + List<ResourceImporter::ImportOption> options_list; + wav_importer->get_import_options("", &options_list); + + HashMap<StringName, Variant> options_map; + for (const ResourceImporter::ImportOption &E : options_list) { + options_map[E.option.name] = E.default_value; + } + + REQUIRE(wav_importer->import(save_path, save_path, options_map, nullptr) == OK); + + String load_path = save_path + "." + wav_importer->get_save_extension(); + Ref<AudioStreamWAV> loaded_stream = ResourceLoader::load(load_path, "AudioStreamWAV", ResourceFormatImporter::CACHE_MODE_IGNORE, &error); + REQUIRE(error == OK); + + CHECK(loaded_stream->get_format() == stream->get_format()); + CHECK(loaded_stream->get_loop_mode() == stream->get_loop_mode()); + CHECK(loaded_stream->get_loop_begin() == stream->get_loop_begin()); + CHECK(loaded_stream->get_loop_end() == stream->get_loop_end()); + CHECK(loaded_stream->get_mix_rate() == stream->get_mix_rate()); + CHECK(loaded_stream->is_stereo() == stream->is_stereo()); + CHECK(loaded_stream->get_length() == stream->get_length()); + CHECK(loaded_stream->is_monophonic() == stream->is_monophonic()); + CHECK(loaded_stream->get_data() == stream->get_data()); +#endif + } +} + +TEST_CASE("[AudioStreamWAV] Mono PCM8 format") { + run_test("test_pcm8_mono.wav", AudioStreamWAV::FORMAT_8_BITS, false, WAV_RATE, WAV_COUNT); +} + +TEST_CASE("[AudioStreamWAV] Mono PCM16 format") { + run_test("test_pcm16_mono.wav", AudioStreamWAV::FORMAT_16_BITS, false, WAV_RATE, WAV_COUNT); +} + +TEST_CASE("[AudioStreamWAV] Stereo PCM8 format") { + run_test("test_pcm8_stereo.wav", AudioStreamWAV::FORMAT_8_BITS, true, WAV_RATE, WAV_COUNT); +} + +TEST_CASE("[AudioStreamWAV] Stereo PCM16 format") { + run_test("test_pcm16_stereo.wav", AudioStreamWAV::FORMAT_16_BITS, true, WAV_RATE, WAV_COUNT); +} + +TEST_CASE("[AudioStreamWAV] Alternate mix rate") { + run_test("test_pcm16_stereo_38000Hz.wav", AudioStreamWAV::FORMAT_16_BITS, true, 38000, 38000); +} + +TEST_CASE("[AudioStreamWAV] save_to_wav() adds '.wav' file extension automatically") { + String save_path = OS::get_singleton()->get_cache_path().plus_file("test_wav_extension"); + Vector<uint8_t> test_data = gen_pcm8_test(WAV_RATE, WAV_COUNT, false); + Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV); + stream->set_data(test_data); + + REQUIRE(stream->save_to_wav(save_path) == OK); + Error error; + Ref<FileAccess> wav_file = FileAccess::open(save_path + ".wav", FileAccess::READ, &error); + CHECK(error == OK); +} + +TEST_CASE("[AudioStreamWAV] Default values") { + Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV); + CHECK(stream->get_format() == AudioStreamWAV::FORMAT_8_BITS); + CHECK(stream->get_loop_mode() == AudioStreamWAV::LOOP_DISABLED); + CHECK(stream->get_loop_begin() == 0); + CHECK(stream->get_loop_end() == 0); + CHECK(stream->get_mix_rate() == 44100); + CHECK(stream->is_stereo() == false); + CHECK(stream->get_length() == 0); + CHECK(stream->is_monophonic() == false); + CHECK(stream->get_data() == Vector<uint8_t>{}); + CHECK(stream->get_stream_name() == ""); +} + +TEST_CASE("[AudioStreamWAV] Save empty file") { + run_test("test_empty.wav", AudioStreamWAV::FORMAT_8_BITS, false, WAV_RATE, 0); +} + +TEST_CASE("[AudioStreamWAV] Saving IMA ADPCM is not supported") { + String save_path = OS::get_singleton()->get_cache_path().plus_file("test_adpcm.wav"); + Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV); + stream->set_format(AudioStreamWAV::FORMAT_IMA_ADPCM); + ERR_PRINT_OFF; + CHECK(stream->save_to_wav(save_path) == ERR_UNAVAILABLE); + ERR_PRINT_ON; +} + +} // namespace TestAudioStreamWAV + +#endif // TEST_AUDIO_STREAM_WAV_H diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index d28380d056..7605f24cf8 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -3251,7 +3251,7 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") { SIGNAL_WATCH(code_edit, "symbol_validate"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(code_edit, Key::META); #else SEND_GUI_KEY_EVENT(code_edit, Key::CTRL); diff --git a/tests/scene/test_path_3d.h b/tests/scene/test_path_3d.h index 78f4e97f03..8ac3d7b5b4 100644 --- a/tests/scene/test_path_3d.h +++ b/tests/scene/test_path_3d.h @@ -81,4 +81,4 @@ TEST_CASE("[Path3D] Curve setter and getter") { } // namespace TestPath3D -#endif // TEST_PATH_3D +#endif // TEST_PATH_3D_H diff --git a/tests/scene/test_sprite_frames.h b/tests/scene/test_sprite_frames.h new file mode 100644 index 0000000000..61bbd16493 --- /dev/null +++ b/tests/scene/test_sprite_frames.h @@ -0,0 +1,247 @@ +/*************************************************************************/ +/* test_sprite_frames.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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_SPRITE_FRAMES_H +#define TEST_SPRITE_FRAMES_H + +#include "scene/resources/sprite_frames.h" + +#include "tests/test_macros.h" + +namespace TestSpriteFrames { +const String test_animation_name = "GodotTest"; + +TEST_CASE("[SpriteFrames] Constructor methods") { + const SpriteFrames frames; + CHECK_MESSAGE( + frames.get_animation_names().size() == 1, + "Should be initialized with 1 entry."); + CHECK_MESSAGE( + frames.get_animation_names().get(0) == "default", + "Should be initialized with default entry."); +} + +TEST_CASE("[SpriteFrames] Animation addition, list getter, renaming, removal, and retrieval") { + SpriteFrames frames; + Vector<String> test_names = { "default", "2", "1", "3" }; + + // "default" is there already + frames.add_animation("2"); + frames.add_animation("1"); + frames.add_animation("3"); + + for (int i = 0; i < test_names.size(); i++) { + CHECK_MESSAGE( + frames.has_animation(test_names[i]), + "Add animation properly worked for each value"); + } + + CHECK_MESSAGE( + !frames.has_animation("999"), + "Return false when checking for animation that does not exist"); + + List<StringName> sname_list; + frames.get_animation_list(&sname_list); + + CHECK_MESSAGE( + sname_list.size() == test_names.size(), + "StringName List getter returned list of expected size"); + + for (int i = 0; i < test_names.size(); i++) { + CHECK_MESSAGE( + sname_list[i] == StringName(test_names[i]), + "StringName List getter returned expected values"); + } + + // get_animation_names() sorts the results. + Vector<String> string_vector = frames.get_animation_names(); + test_names.sort(); + + for (int i = 0; i < test_names.size(); i++) { + CHECK_MESSAGE( + string_vector[i] == test_names[i], + "String Vector getter returned expected values"); + } + + // These error handling cases should not crash. + ERR_PRINT_OFF; + frames.rename_animation("This does not exist", "0"); + ERR_PRINT_ON; + + CHECK_MESSAGE( + !frames.has_animation("0"), + "Correctly handles rename error when entry does not exist"); + + // These error handling cases should not crash. + ERR_PRINT_OFF; + frames.rename_animation("3", "1"); + ERR_PRINT_ON; + + CHECK_MESSAGE( + frames.has_animation("3"), + "Correctly handles rename error when entry exists, but new name already exists"); + + ERR_PRINT_OFF; + frames.add_animation("1"); + ERR_PRINT_ON; + + CHECK_MESSAGE( + frames.get_animation_names().size() == 4, + "Correctly does not add when entry already exists"); + + frames.rename_animation("3", "9"); + + CHECK_MESSAGE( + frames.has_animation("9"), + "Animation renamed correctly"); + + frames.remove_animation("9"); + + CHECK_MESSAGE( + !frames.has_animation("9"), + "Animation removed correctly"); + + frames.clear_all(); + + CHECK_MESSAGE( + frames.get_animation_names().size() == 1, + "Clear all removed all animations and re-added the default animation entry"); +} + +TEST_CASE("[SpriteFrames] Animation Speed getter and setter") { + SpriteFrames frames; + + frames.add_animation(test_animation_name); + + CHECK_MESSAGE( + frames.get_animation_speed(test_animation_name) == 5.0, + "Sets new animation to default speed"); + + frames.set_animation_speed(test_animation_name, 123.0004); + + CHECK_MESSAGE( + frames.get_animation_speed(test_animation_name) == 123.0004, + "Sets animation to positive double"); + + // These error handling cases should not crash. + ERR_PRINT_OFF; + frames.get_animation_speed("This does not exist"); + frames.set_animation_speed("This does not exist", 100); + frames.set_animation_speed(test_animation_name, -999.999); + ERR_PRINT_ON; + + CHECK_MESSAGE( + frames.get_animation_speed(test_animation_name) == 123.0004, + "Prevents speed of animation being set to a negative value"); + + frames.set_animation_speed(test_animation_name, 0.0); + + CHECK_MESSAGE( + frames.get_animation_speed(test_animation_name) == 0.0, + "Sets animation to zero"); +} + +TEST_CASE("[SpriteFrames] Animation Loop getter and setter") { + SpriteFrames frames; + + frames.add_animation(test_animation_name); + + CHECK_MESSAGE( + frames.get_animation_loop(test_animation_name), + "Sets new animation to default loop value."); + + frames.set_animation_loop(test_animation_name, true); + + CHECK_MESSAGE( + frames.get_animation_loop(test_animation_name), + "Sets animation loop to true"); + + frames.set_animation_loop(test_animation_name, false); + + CHECK_MESSAGE( + !frames.get_animation_loop(test_animation_name), + "Sets animation loop to false"); + + // These error handling cases should not crash. + ERR_PRINT_OFF; + frames.get_animation_loop("This does not exist"); + frames.set_animation_loop("This does not exist", false); + ERR_PRINT_ON; +} + +// TODO +TEST_CASE("[SpriteFrames] Frame addition, removal, and retrieval") { + Ref<Texture2D> dummy_frame1; + dummy_frame1.instantiate(); + + SpriteFrames frames; + frames.add_animation(test_animation_name); + frames.add_animation("1"); + frames.add_animation("2"); + + CHECK_MESSAGE( + frames.get_frame_count(test_animation_name) == 0, + "Animation has a default frame count of 0"); + + frames.add_frame(test_animation_name, dummy_frame1, 0); + frames.add_frame(test_animation_name, dummy_frame1, 1); + frames.add_frame(test_animation_name, dummy_frame1, 2); + + CHECK_MESSAGE( + frames.get_frame_count(test_animation_name) == 3, + "Adds multiple frames"); + + frames.remove_frame(test_animation_name, 1); + frames.remove_frame(test_animation_name, 0); + + CHECK_MESSAGE( + frames.get_frame_count(test_animation_name) == 1, + "Removes multiple frames"); + + // These error handling cases should not crash. + ERR_PRINT_OFF; + frames.add_frame("does not exist", dummy_frame1, 0); + frames.remove_frame(test_animation_name, -99); + frames.remove_frame("does not exist", 0); + ERR_PRINT_ON; + + CHECK_MESSAGE( + frames.get_frame_count(test_animation_name) == 1, + "Handles bad values when adding or removing frames."); + + frames.clear(test_animation_name); + + CHECK_MESSAGE( + frames.get_frame_count(test_animation_name) == 0, + "Clears frames."); +} +} // namespace TestSpriteFrames + +#endif // TEST_SPRITE_FRAMES_H diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h index 4098dd7ace..0fce359c5a 100644 --- a/tests/scene/test_text_edit.h +++ b/tests/scene/test_text_edit.h @@ -724,7 +724,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == "t"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::ALT) #else SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::CMD) @@ -736,7 +736,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == "tes"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::ALT) #else SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::CMD) @@ -1902,7 +1902,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::ALT | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT); @@ -2013,7 +2013,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::ALT | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT); @@ -2244,7 +2244,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::UP | KeyModifierMask::CMD | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::CMD | KeyModifierMask::SHIFT); @@ -2285,7 +2285,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::DOWN | KeyModifierMask::CMD | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::CMD | KeyModifierMask::SHIFT); @@ -2326,7 +2326,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::SHIFT); @@ -2383,7 +2383,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_DISCARD("lines_edited_from"); SIGNAL_DISCARD("caret_changed"); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT); #else SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::SHIFT); @@ -3139,7 +3139,7 @@ TEST_CASE("[SceneTree][TextEdit] viewport") { v_scroll = text_edit->get_v_scroll(); SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE); text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - CHECK(text_edit->get_v_scroll() > v_scroll); + CHECK(text_edit->get_v_scroll() >= v_scroll); SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE); text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); CHECK(text_edit->get_v_scroll() == v_scroll); @@ -3148,7 +3148,7 @@ TEST_CASE("[SceneTree][TextEdit] viewport") { text_edit->set_v_scroll_speed(10000); SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE); text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - CHECK(text_edit->get_v_scroll() > v_scroll); + CHECK(text_edit->get_v_scroll() >= v_scroll); SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE); text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); CHECK(text_edit->get_v_scroll() == v_scroll); diff --git a/tests/scene/test_theme.h b/tests/scene/test_theme.h index f7cfa0fd5b..f5b21eec32 100644 --- a/tests/scene/test_theme.h +++ b/tests/scene/test_theme.h @@ -101,18 +101,24 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Good theme type names") { SUBCASE("set_type_variation") { for (const StringName &name : names) { + if (name == StringName()) { // Skip empty here, not allowed. + continue; + } Ref<Theme> theme = memnew(Theme); ErrorDetector ed; theme->set_type_variation(valid_type_name, name); - CHECK(ed.has_error == (name == StringName())); + CHECK_FALSE(ed.has_error); } for (const StringName &name : names) { + if (name == StringName()) { // Skip empty here, not allowed. + continue; + } Ref<Theme> theme = memnew(Theme); ErrorDetector ed; theme->set_type_variation(name, valid_type_name); - CHECK(ed.has_error == (name == StringName())); + CHECK_FALSE(ed.has_error); } } } @@ -125,6 +131,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme type names") { String::utf8("contains_汉å—"), }; + ERR_PRINT_OFF; // All these rightfully print errors. + SUBCASE("add_type") { for (const StringName &name : names) { Ref<Theme> theme = memnew(Theme); @@ -175,6 +183,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme type names") { CHECK(ed.has_error); } } + + ERR_PRINT_ON; } TEST_CASE_FIXTURE(Fixture, "[Theme] Good theme item names") { @@ -223,6 +233,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme item names") { String::utf8("contains_汉å—"), }; + ERR_PRINT_OFF; // All these rightfully print errors. + SUBCASE("set_theme_item") { for (const StringName &name : names) { for (const DataEntry &entry : valid_data) { @@ -250,6 +262,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme item names") { } } } + + ERR_PRINT_ON; } } // namespace TestTheme diff --git a/tests/servers/test_text_server.h b/tests/servers/test_text_server.h index 066c280fd5..9ebd0f34b4 100644 --- a/tests/servers/test_text_server.h +++ b/tests/servers/test_text_server.h @@ -28,23 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef TOOLS_ENABLED - #ifndef TEST_TEXT_SERVER_H #define TEST_TEXT_SERVER_H +#ifdef TOOLS_ENABLED + #include "editor/builtin_fonts.gen.h" #include "servers/text_server.h" #include "tests/test_macros.h" namespace TestTextServer { -TEST_SUITE("[[TextServer]") { +TEST_SUITE("[TextServer]") { TEST_CASE("[TextServer] Init, font loading and shaping") { SUBCASE("[TextServer] Loading fonts") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC)) { continue; @@ -52,7 +52,7 @@ TEST_SUITE("[[TextServer]") { RID font = ts->create_font(); ts->font_set_data_ptr(font, _font_NotoSans_Regular, _font_NotoSans_Regular_size); - TEST_FAIL_COND(font == RID(), "Loading font failed."); + CHECK_FALSE_MESSAGE(font == RID(), "Loading font failed."); ts->free_rid(font); } } @@ -60,7 +60,7 @@ TEST_SUITE("[[TextServer]") { SUBCASE("[TextServer] Text layout: Font fallback") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) { continue; @@ -79,26 +79,26 @@ TEST_SUITE("[[TextServer]") { // 6^ 17^ RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size == 0, "Shaping failed"); + CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed"); for (int j = 0; j < gl_size; j++) { if (glyphs[j].start < 6) { - TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected."); + CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[1], "Incorrect font selected."); } if ((glyphs[j].start > 6) && (glyphs[j].start < 16)) { - TEST_FAIL_COND(glyphs[j].font_rid != font[0], "Incorrect font selected."); + CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[0], "Incorrect font selected."); } if (glyphs[j].start > 16) { - TEST_FAIL_COND(glyphs[j].font_rid != RID(), "Incorrect font selected."); - TEST_FAIL_COND(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index."); + CHECK_FALSE_MESSAGE(glyphs[j].font_rid != RID(), "Incorrect font selected."); + CHECK_FALSE_MESSAGE(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index."); } - TEST_FAIL_COND((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range."); - TEST_FAIL_COND(glyphs[j].font_size != 16, "Incorrect glyph font size."); + CHECK_FALSE_MESSAGE((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range."); + CHECK_FALSE_MESSAGE(glyphs[j].font_size != 16, "Incorrect glyph font size."); } ts->free_rid(ctx); @@ -113,7 +113,7 @@ TEST_SUITE("[[TextServer]") { SUBCASE("[TextServer] Text layout: BiDi") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) { continue; @@ -132,23 +132,23 @@ TEST_SUITE("[[TextServer]") { // 7^ 26^ RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size == 0, "Shaping failed"); + CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed"); for (int j = 0; j < gl_size; j++) { if (glyphs[j].count > 0) { if (glyphs[j].start < 7) { - TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); + CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); } if ((glyphs[j].start > 8) && (glyphs[j].start < 23)) { - TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); + CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); } if (glyphs[j].start > 26) { - TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); + CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); } } } @@ -165,7 +165,7 @@ TEST_SUITE("[[TextServer]") { SUBCASE("[TextServer] Text layout: Line break and align points") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) { continue; @@ -186,16 +186,16 @@ TEST_SUITE("[[TextServer]") { { String test = U"Test test long text long text\n"; RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); ts->shaped_text_update_breaks(ctx); ts->shaped_text_update_justification_ops(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 30, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 30, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -203,11 +203,11 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 4 || j == 9 || j == 14 || j == 19 || j == 24) { - TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags."); } else if (j == 29) { - TEST_FAIL_COND((soft || !space || !hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || !space || !hard || virt || elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } ts->free_rid(ctx); @@ -216,21 +216,63 @@ TEST_SUITE("[[TextServer]") { { String test = U"الØÙ…ـد"; RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) { + ts->shaped_text_update_justification_ops(ctx); + + glyphs = ts->shaped_text_get_glyphs(ctx); + gl_size = ts->shaped_text_get_glyph_count(ctx); + + CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 1) { + CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags."); + } else { + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + } + ts->free_rid(ctx); + } + + { + String test = U"الØÙ…د"; + RID ctx = ts->create_shaped_text(); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); ts->shaped_text_update_breaks(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 6, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 5, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) { @@ -239,7 +281,7 @@ TEST_SUITE("[[TextServer]") { glyphs = ts->shaped_text_get_glyphs(ctx); gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 6, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -247,9 +289,9 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 1) { - TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } } @@ -259,15 +301,15 @@ TEST_SUITE("[[TextServer]") { { String test = U"الØÙ…ـد الرياضي العربي"; RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); ts->shaped_text_update_breaks(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 21, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 21, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -275,9 +317,9 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 6 || j == 14) { - TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } @@ -287,7 +329,7 @@ TEST_SUITE("[[TextServer]") { glyphs = ts->shaped_text_get_glyphs(ctx); gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 23, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 23, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -295,13 +337,13 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 7 || j == 16) { - TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags."); } else if (j == 3 || j == 9) { - TEST_FAIL_COND((soft || space || hard || !virt || !elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags."); } else if (j == 18) { - TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } } @@ -312,16 +354,16 @@ TEST_SUITE("[[TextServer]") { { String test = U"เป็น ภาษา ราชà¸à¸²à¸£ à¹à¸¥à¸° ภาษา"; RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); ts->shaped_text_update_breaks(ctx); ts->shaped_text_update_justification_ops(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 25, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -329,9 +371,9 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 4 || j == 9 || j == 16 || j == 20) { - TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } ts->free_rid(ctx); @@ -340,16 +382,16 @@ TEST_SUITE("[[TextServer]") { if (ts->has_feature(TextServer::FEATURE_BREAK_ITERATORS)) { String test = U"เป็นภาษาราชà¸à¸²à¸£à¹à¸¥à¸°à¸ าษา"; RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); ts->shaped_text_update_breaks(ctx); ts->shaped_text_update_justification_ops(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); int gl_size = ts->shaped_text_get_glyph_count(ctx); - TEST_FAIL_COND(gl_size != 25, "Invalid glyph count."); + CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count."); for (int j = 0; j < gl_size; j++) { bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; @@ -357,9 +399,9 @@ TEST_SUITE("[[TextServer]") { bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; if (j == 4 || j == 9 || j == 16 || j == 20) { - TEST_FAIL_COND((!soft || !space || hard || !virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((!soft || !space || hard || !virt || elo), "Invalid glyph flags."); } else { - TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags."); } } ts->free_rid(ctx); @@ -375,7 +417,7 @@ TEST_SUITE("[[TextServer]") { SUBCASE("[TextServer] Text layout: Line breaking") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) { continue; @@ -394,21 +436,21 @@ TEST_SUITE("[[TextServer]") { font.push_back(font2); RID ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); PackedInt32Array brks = ts->shaped_text_get_line_breaks(ctx, 1); - TEST_FAIL_COND(brks.size() != 6, "Invalid line breaks number."); + CHECK_FALSE_MESSAGE(brks.size() != 6, "Invalid line breaks number."); if (brks.size() == 6) { - TEST_FAIL_COND(brks[0] != 0, "Invalid line break position."); - TEST_FAIL_COND(brks[1] != 5, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[0] != 0, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[1] != 5, "Invalid line break position."); - TEST_FAIL_COND(brks[2] != 5, "Invalid line break position."); - TEST_FAIL_COND(brks[3] != 10, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[2] != 5, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[3] != 10, "Invalid line break position."); - TEST_FAIL_COND(brks[4] != 10, "Invalid line break position."); - TEST_FAIL_COND(brks[5] != 14, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[4] != 10, "Invalid line break position."); + CHECK_FALSE_MESSAGE(brks[5] != 14, "Invalid line break position."); } ts->free_rid(ctx); @@ -423,7 +465,7 @@ TEST_SUITE("[[TextServer]") { SUBCASE("[TextServer] Text layout: Justification") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) { continue; @@ -448,40 +490,40 @@ TEST_SUITE("[[TextServer]") { float width_old, width; if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) { ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); ok = ts->shaped_text_add_string(ctx, test_1, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); width_old = ts->shaped_text_get_width(ctx); width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND); - TEST_FAIL_COND((width != width_old), "Invalid fill width."); + CHECK_FALSE_MESSAGE((width != width_old), "Invalid fill width."); width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); - TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width."); + CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width."); ts->free_rid(ctx); ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); ok = ts->shaped_text_add_string(ctx, test_2, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); width_old = ts->shaped_text_get_width(ctx); width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND); - TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width."); + CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width."); width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); - TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width."); + CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width."); ts->free_rid(ctx); } ctx = ts->create_shaped_text(); - TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed."); ok = ts->shaped_text_add_string(ctx, test_3, font, 16); - TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed."); width_old = ts->shaped_text_get_width(ctx); width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND); - TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width."); + CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width."); ts->free_rid(ctx); @@ -492,10 +534,31 @@ TEST_SUITE("[[TextServer]") { } } + SUBCASE("[TextServer] Unicode identifiers") { + for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { + Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); + + static const char32_t *data[19] = { U"-30", U"100", U"10.1", U"10,1", U"1e2", U"1e-2", U"1e2e3", U"0xAB", U"AB", U"Test1", U"1Test", U"Test*1", U"test_testeT", U"test_tes teT", U"عَلَيْكÙمْ", U"عَلَيْكÙمْTest", U"Ó’Ó–ÓšÓœ", U"_test", U"ÂÃÄÅĀĂĄÇĆĈĊ" }; + static bool isid[19] = { false, false, false, false, false, false, false, false, true, true, false, false, true, false, true, true, true, true, true }; + for (int j = 0; j < 19; j++) { + String s = String(data[j]); + CHECK(ts->is_valid_identifier(s) == isid[j]); + } + + if (ts->has_feature(TextServer::FEATURE_UNICODE_IDENTIFIERS)) { + // Test UAX 3.2 ZW(N)J usage. + CHECK(ts->is_valid_identifier(U"\u0646\u0627\u0645\u0647\u200C\u0627\u06CC")); + CHECK(ts->is_valid_identifier(U"\u0D26\u0D43\u0D15\u0D4D\u200C\u0D38\u0D3E\u0D15\u0D4D\u0D37\u0D3F")); + CHECK(ts->is_valid_identifier(U"\u0DC1\u0DCA\u200D\u0DBB\u0DD3")); + } + } + } + SUBCASE("[TextServer] Strip Diacritics") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); if (ts->has_feature(TextServer::FEATURE_SHAPING)) { CHECK(ts->strip_diacritics(U"ٱلسَّلَام٠عَلَيْكÙمْ") == U"ٱلسلام عليكم"); @@ -523,7 +586,7 @@ TEST_SUITE("[[TextServer]") { continue; } - TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface."); { String text1 = U"linguistically similar and effectively form"; // 14^ 22^ 26^ 38^ @@ -561,5 +624,6 @@ TEST_SUITE("[[TextServer]") { } }; // namespace TestTextServer -#endif // TEST_TEXT_SERVER_H #endif // TOOLS_ENABLED + +#endif // TEST_TEXT_SERVER_H diff --git a/tests/test_macros.h b/tests/test_macros.h index 6029a9cfc7..69ae0d3124 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -31,6 +31,7 @@ #ifndef TEST_MACROS_H #define TEST_MACROS_H +#include "core/core_globals.h" #include "core/input/input_map.h" #include "core/object/message_queue.h" #include "core/variant/variant.h" @@ -53,12 +54,12 @@ // Temporarily disable error prints to test failure paths. // This allows to avoid polluting the test summary with error messages. -// The `_print_error_enabled` boolean is defined in `core/print_string.cpp` and +// The `print_error_enabled` boolean is defined in `core/core_globals.cpp` and // works at global scope. It's used by various loggers in `should_log()` method, // which are used by error macros which call into `OS::print_error`, effectively // disabling any error messages to be printed from the engine side (not tests). -#define ERR_PRINT_OFF _print_error_enabled = false; -#define ERR_PRINT_ON _print_error_enabled = true; +#define ERR_PRINT_OFF CoreGlobals::print_error_enabled = false; +#define ERR_PRINT_ON CoreGlobals::print_error_enabled = true; // Stringify all `Variant` compatible types for doctest output by default. // https://github.com/onqtam/doctest/blob/master/doc/markdown/stringification.md @@ -199,8 +200,8 @@ int register_test_command(String p_command, TestFunc p_function); // We toggle _print_error_enabled to prevent display server not supported warnings. #define SEND_GUI_MOUSE_MOTION_EVENT(m_object, m_local_pos, m_mask, m_modifers) \ { \ - bool errors_enabled = _print_error_enabled; \ - _print_error_enabled = false; \ + bool errors_enabled = CoreGlobals::print_error_enabled; \ + CoreGlobals::print_error_enabled = false; \ Ref<InputEventMouseMotion> event; \ event.instantiate(); \ event->set_position(m_local_pos); \ @@ -209,7 +210,7 @@ int register_test_command(String p_command, TestFunc p_function); _UPDATE_EVENT_MODIFERS(event, m_modifers); \ m_object->get_viewport()->push_input(event); \ MessageQueue::get_singleton()->flush(); \ - _print_error_enabled = errors_enabled; \ + CoreGlobals::print_error_enabled = errors_enabled; \ } // Utility class / macros for testing signals @@ -271,22 +272,20 @@ public: static SignalWatcher *get_singleton() { return singleton; } void watch_signal(Object *p_object, const String &p_signal) { - Vector<Variant> args; - args.push_back(p_signal); MethodInfo method_info; ClassDB::get_signal(p_object->get_class(), p_signal, &method_info); switch (method_info.arguments.size()) { case 0: { - p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_zero), args); + p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_zero).bind(p_signal)); } break; case 1: { - p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_one), args); + p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_one).bind(p_signal)); } break; case 2: { - p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_two), args); + p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_two).bind(p_signal)); } break; case 3: { - p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_three), args); + p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_three).bind(p_signal)); } break; default: { MESSAGE("Signal ", p_signal, " arg count not supported."); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 79cda7e512..3d186711cb 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -30,6 +30,8 @@ #include "test_main.h" +#include "tests/core/input/test_input_event_key.h" +#include "tests/core/input/test_shortcut.h" #include "tests/core/io/test_config_file.h" #include "tests/core/io/test_file_access.h" #include "tests/core/io/test_image.h" @@ -46,16 +48,22 @@ #include "tests/core/math/test_geometry_2d.h" #include "tests/core/math/test_geometry_3d.h" #include "tests/core/math/test_plane.h" +#include "tests/core/math/test_quaternion.h" #include "tests/core/math/test_random_number_generator.h" #include "tests/core/math/test_rect2.h" #include "tests/core/math/test_rect2i.h" +#include "tests/core/math/test_transform_2d.h" +#include "tests/core/math/test_transform_3d.h" #include "tests/core/math/test_vector2.h" #include "tests/core/math/test_vector2i.h" #include "tests/core/math/test_vector3.h" #include "tests/core/math/test_vector3i.h" +#include "tests/core/math/test_vector4.h" +#include "tests/core/math/test_vector4i.h" #include "tests/core/object/test_class_db.h" #include "tests/core/object/test_method_bind.h" #include "tests/core/object/test_object.h" +#include "tests/core/os/test_os.h" #include "tests/core/string/test_node_path.h" #include "tests/core/string/test_string.h" #include "tests/core/string/test_translation.h" @@ -66,18 +74,22 @@ #include "tests/core/templates/test_local_vector.h" #include "tests/core/templates/test_lru.h" #include "tests/core/templates/test_paged_array.h" +#include "tests/core/templates/test_rid.h" #include "tests/core/templates/test_vector.h" #include "tests/core/test_crypto.h" #include "tests/core/test_hashing_context.h" #include "tests/core/test_time.h" +#include "tests/core/threads/test_worker_thread_pool.h" #include "tests/core/variant/test_array.h" #include "tests/core/variant/test_dictionary.h" #include "tests/core/variant/test_variant.h" #include "tests/scene/test_animation.h" +#include "tests/scene/test_audio_stream_wav.h" #include "tests/scene/test_code_edit.h" #include "tests/scene/test_curve.h" #include "tests/scene/test_gradient.h" #include "tests/scene/test_path_3d.h" +#include "tests/scene/test_sprite_frames.h" #include "tests/scene/test_text_edit.h" #include "tests/scene/test_theme.h" #include "tests/servers/test_text_server.h" @@ -103,7 +115,7 @@ int test_main(int argc, char *argv[]) { for (int i = 0; i < argc; i++) { args.push_back(String::utf8(argv[i])); } - OS::get_singleton()->set_cmdline("", args); + OS::get_singleton()->set_cmdline("", args, List<String>()); // Run custom test tools. if (test_commands) { @@ -211,6 +223,15 @@ struct GodotTestCaseListener : public doctest::IReporter { SceneTree::get_singleton()->initialize(); return; } + + if (name.find("Audio") != -1) { + // The last driver index should always be the dummy driver. + int dummy_idx = AudioDriverManager::get_driver_count() - 1; + AudioDriverManager::initialize(dummy_idx); + AudioServer *audio_server = memnew(AudioServer); + audio_server->init(); + return; + } } void test_case_end(const doctest::CurrentTestCaseStats &) override { @@ -256,7 +277,7 @@ struct GodotTestCaseListener : public doctest::IReporter { if (RenderingServer::get_singleton()) { RenderingServer::get_singleton()->sync(); - RenderingServer::get_singleton()->global_variables_clear(); + RenderingServer::get_singleton()->global_shader_uniforms_clear(); RenderingServer::get_singleton()->finish(); memdelete(RenderingServer::get_singleton()); } @@ -273,6 +294,11 @@ struct GodotTestCaseListener : public doctest::IReporter { MessageQueue::get_singleton()->flush(); memdelete(MessageQueue::get_singleton()); } + + if (AudioServer::get_singleton()) { + AudioServer::get_singleton()->finish(); + memdelete(AudioServer::get_singleton()); + } } void test_run_start() override { diff --git a/tests/test_validate_testing.h b/tests/test_validate_testing.h index 413a7e351d..1471a952cd 100644 --- a/tests/test_validate_testing.h +++ b/tests/test_validate_testing.h @@ -31,6 +31,7 @@ #ifndef TEST_VALIDATE_TESTING_H #define TEST_VALIDATE_TESTING_H +#include "core/core_globals.h" #include "core/os/os.h" #include "tests/test_macros.h" @@ -49,10 +50,10 @@ TEST_SUITE("Validate tests") { } TEST_CASE("Muting Godot error messages") { ERR_PRINT_OFF; - CHECK_MESSAGE(!_print_error_enabled, "Error printing should be disabled."); + CHECK_MESSAGE(!CoreGlobals::print_error_enabled, "Error printing should be disabled."); ERR_PRINT("Still waiting for Godot!"); // This should never get printed! ERR_PRINT_ON; - CHECK_MESSAGE(_print_error_enabled, "Error printing should be re-enabled."); + CHECK_MESSAGE(CoreGlobals::print_error_enabled, "Error printing should be re-enabled."); } TEST_CASE("Stringify Variant types") { Variant var; diff --git a/thirdparty/README.md b/thirdparty/README.md index 94b071a2ea..664401fca6 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -44,7 +44,7 @@ Files extracted from upstream source: ## certs - Upstream: Mozilla, via https://github.com/bagder/ca-bundle -- Version: git (8b263a18fca98ea371e54227837321c5cdaa1ba7, 2021) +- Version: git (7f33e7eb8472dbcf31fdcf50cd216c89a282825d, 2022) - License: MPL 2.0 @@ -213,7 +213,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 4.4.1 (096aaa62a6e0d07c02a4894fc036efc927e5aaf9, 2022) +- Version: 5.1.0 (f1f2be776bcd994fa9262622e1a7098a066e5cf7, 2022) - License: MIT Files extracted from upstream source: @@ -231,6 +231,8 @@ Files extracted from upstream source: Files extracted from upstream source: - the `common` folder +- `scriptset.*`, `ucln_in.*`, `uspoof.cpp"` and `uspoof_impl.cpp` from the `i18n` folder +- `uspoof.h` from the `i18n/unicode` folder - `LICENSE` Files generated from upstream source: @@ -328,15 +330,15 @@ Files extracted from upstream source: ## mbedtls -- Upstream: https://tls.mbed.org/ -- Version: 2.16.12 (cf4667126010c665341f9e50ef691b7ef8294188, 2021) +- Upstream: https://github.com/Mbed-TLS/mbedtls +- Version: 2.18.1 (dd79db10014d85b26d11fe57218431f2e5ede6f2, 2022) - License: Apache 2.0 File extracted from upstream release tarball: - All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` except `config_psa.h` and `psa_util.h`. - All `*.c` and `*.h` from `library/` to `thirdparty/mbedtls/library/` except those starting with `psa_*`. -- `LICENSE` and `apache-2.0.txt` files. +- The `LICENSE` file. - Applied the patch in `patches/1453.diff` (upstream PR: https://github.com/ARMmbed/mbedtls/pull/1453). - Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h` @@ -597,7 +599,7 @@ Godot. See the patch in the `patches` folder for details. ## spirv-reflect - Upstream: https://github.com/KhronosGroup/SPIRV-Reflect -- Version: git (1aceb6af56e74b92a00378842dda5c5a73f49a4b, 2022) +- Version: git (1ef99b09fa7ce5aee2c5cf70c61a4f7458d27e09, 2022) - License: Apache 2.0 Does not track Vulkan SDK releases closely, but try to package a commit newer diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt index e218b024d0..036f630d5b 100644 --- a/thirdparty/certs/ca-certificates.crt +++ b/thirdparty/certs/ca-certificates.crt @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Thu Mar 31 08:10:21 2022 GMT +## Certificate data from Mozilla as of: Tue Jul 19 14:20:01 2022 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +14,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: d59c5c83ce7a7635fa95521d8d245677949b86d5574bfcc6f855b6a48f2d5566 +## SHA256: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066 ## @@ -993,30 +993,6 @@ tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- -Hellenic Academic and Research Institutions RootCA 2011 -======================================================= ------BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT -O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y -aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT -AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo -IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI -1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa -71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u -8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH -3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ -MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 -MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu -b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt -XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD -/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N -7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- - Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- @@ -3279,3 +3255,206 @@ PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh 4rsUecrNIdSUtUlD -----END CERTIFICATE----- + +Telia Root CA v2 +================ +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT +AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 +MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK +DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 +6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q +9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn +pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl +tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW +5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr +RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E +BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 +M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau +BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W +xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 +tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H +eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C +y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC +QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 +h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 +sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 +xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ +raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= +-----END CERTIFICATE----- + +D-TRUST BR Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 +dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu +QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom +AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +D-TRUST EV Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 +ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ +raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR +AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +DigiCert TLS ECC P384 Root G5 +============================= +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 +NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg +Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd +lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj +n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB +/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds +Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx +AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +DigiCert TLS RSA4096 Root G5 +============================ +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 +MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 +IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 +7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU +AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces +tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa +zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV +DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q +TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy +z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ +MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk +wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E +FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN +lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN +MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ +u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G +OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh +47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU +FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ +yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP +bEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +Certainly Root R1 +================= +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE +BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN +MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy +dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O +5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl +8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl +DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI +XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN +KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ +AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb +rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 +VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS +p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz +HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v +MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB +GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ +gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH +JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 +fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw +x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S +X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +Certainly Root E1 +================= +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV +UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 +MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu +bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 +fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 +YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E +AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 +rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +E-Tugra Global Root CA RSA v3 +============================= +-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ +BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb +BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290 +IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU +UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF +LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg +djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx +jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL +sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF +/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q +QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw +bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6 +04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB +eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM +bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg +h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1 +LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ +gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4 +38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q +ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s +SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY +sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl +DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X +nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH +IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX +YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE----- + +E-Tugra Global Root CA ECC v3 +============================= +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV +BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB +IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP +MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 +w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 +Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ +zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W +Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 +-----END CERTIFICATE----- diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh new file mode 100644 index 0000000000..e52a617c86 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh @@ -0,0 +1,338 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod, Garret Rieger + */ + +#ifndef OT_LAYOUT_COMMON_COVERAGE_HH +#define OT_LAYOUT_COMMON_COVERAGE_HH + +#include "../types.hh" +#include "CoverageFormat1.hh" +#include "CoverageFormat2.hh" + +namespace OT { +namespace Layout { +namespace Common { + +template<typename Iterator> +static inline void Coverage_serialize (hb_serialize_context_t *c, + Iterator it); + +struct Coverage +{ + + protected: + union { + HBUINT16 format; /* Format identifier */ + CoverageFormat1_3<SmallTypes> format1; + CoverageFormat2_4<SmallTypes> format2; +#ifndef HB_NO_BORING_EXPANSION + CoverageFormat1_3<MediumTypes>format3; + CoverageFormat2_4<MediumTypes>format4; +#endif + } u; + public: + DEFINE_SIZE_UNION (2, format); + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) + { + case 1: return_trace (u.format1.sanitize (c)); + case 2: return_trace (u.format2.sanitize (c)); +#ifndef HB_NO_BORING_EXPANSION + case 3: return_trace (u.format3.sanitize (c)); + case 4: return_trace (u.format4.sanitize (c)); +#endif + default:return_trace (true); + } + } + + /* Has interface. */ + static constexpr unsigned SENTINEL = NOT_COVERED; + typedef unsigned int value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + unsigned int get (hb_codepoint_t k) const { return get_coverage (k); } + unsigned int get_coverage (hb_codepoint_t glyph_id) const + { + switch (u.format) { + case 1: return u.format1.get_coverage (glyph_id); + case 2: return u.format2.get_coverage (glyph_id); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.get_coverage (glyph_id); + case 4: return u.format4.get_coverage (glyph_id); +#endif + default:return NOT_COVERED; + } + } + + unsigned get_population () const + { + switch (u.format) { + case 1: return u.format1.get_population (); + case 2: return u.format2.get_population (); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.get_population (); + case 4: return u.format4.get_population (); +#endif + default:return NOT_COVERED; + } + } + + template <typename Iterator, + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> + bool serialize (hb_serialize_context_t *c, Iterator glyphs) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (this))) return_trace (false); + + unsigned count = 0; + unsigned num_ranges = 0; + hb_codepoint_t last = (hb_codepoint_t) -2; + for (auto g: glyphs) + { + if (last + 1 != g) + num_ranges++; + last = g; + count++; + } + u.format = count <= num_ranges * 3 ? 1 : 2; + +#ifndef HB_NO_BORING_EXPANSION + if (count && last > 0xFFFFu) + u.format += 2; +#endif + + switch (u.format) + { + case 1: return_trace (u.format1.serialize (c, glyphs)); + case 2: return_trace (u.format2.serialize (c, glyphs)); +#ifndef HB_NO_BORING_EXPANSION + case 3: return_trace (u.format3.serialize (c, glyphs)); + case 4: return_trace (u.format4.serialize (c, glyphs)); +#endif + default:return_trace (false); + } + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto it = + + iter () + | hb_filter (c->plan->glyph_map_gsub) + | hb_map_retains_sorting (c->plan->glyph_map_gsub) + ; + + // Cache the iterator result as it will be iterated multiple times + // by the serialize code below. + hb_sorted_vector_t<hb_codepoint_t> glyphs (it); + Coverage_serialize (c->serializer, glyphs.iter ()); + return_trace (bool (glyphs)); + } + + bool intersects (const hb_set_t *glyphs) const + { + switch (u.format) + { + case 1: return u.format1.intersects (glyphs); + case 2: return u.format2.intersects (glyphs); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.intersects (glyphs); + case 4: return u.format4.intersects (glyphs); +#endif + default:return false; + } + } + bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const + { + switch (u.format) + { + case 1: return u.format1.intersects_coverage (glyphs, index); + case 2: return u.format2.intersects_coverage (glyphs, index); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.intersects_coverage (glyphs, index); + case 4: return u.format4.intersects_coverage (glyphs, index); +#endif + default:return false; + } + } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template <typename set_t> + bool collect_coverage (set_t *glyphs) const + { + switch (u.format) + { + case 1: return u.format1.collect_coverage (glyphs); + case 2: return u.format2.collect_coverage (glyphs); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.collect_coverage (glyphs); + case 4: return u.format4.collect_coverage (glyphs); +#endif + default:return false; + } + } + + template <typename IterableOut, + hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))> + void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const + { + switch (u.format) + { + case 1: return u.format1.intersect_set (glyphs, intersect_glyphs); + case 2: return u.format2.intersect_set (glyphs, intersect_glyphs); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.intersect_set (glyphs, intersect_glyphs); + case 4: return u.format4.intersect_set (glyphs, intersect_glyphs); +#endif + default:return ; + } + } + + struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> + { + static constexpr bool is_sorted_iterator = true; + iter_t (const Coverage &c_ = Null (Coverage)) + { + memset (this, 0, sizeof (*this)); + format = c_.u.format; + switch (format) + { + case 1: u.format1.init (c_.u.format1); return; + case 2: u.format2.init (c_.u.format2); return; +#ifndef HB_NO_BORING_EXPANSION + case 3: u.format3.init (c_.u.format3); return; + case 4: u.format4.init (c_.u.format4); return; +#endif + default: return; + } + } + bool __more__ () const + { + switch (format) + { + case 1: return u.format1.__more__ (); + case 2: return u.format2.__more__ (); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.__more__ (); + case 4: return u.format4.__more__ (); +#endif + default:return false; + } + } + void __next__ () + { + switch (format) + { + case 1: u.format1.__next__ (); break; + case 2: u.format2.__next__ (); break; +#ifndef HB_NO_BORING_EXPANSION + case 3: u.format3.__next__ (); break; + case 4: u.format4.__next__ (); break; +#endif + default: break; + } + } + typedef hb_codepoint_t __item_t__; + __item_t__ __item__ () const { return get_glyph (); } + + hb_codepoint_t get_glyph () const + { + switch (format) + { + case 1: return u.format1.get_glyph (); + case 2: return u.format2.get_glyph (); +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3.get_glyph (); + case 4: return u.format4.get_glyph (); +#endif + default:return 0; + } + } + bool operator != (const iter_t& o) const + { + if (unlikely (format != o.format)) return true; + switch (format) + { + case 1: return u.format1 != o.u.format1; + case 2: return u.format2 != o.u.format2; +#ifndef HB_NO_BORING_EXPANSION + case 3: return u.format3 != o.u.format3; + case 4: return u.format4 != o.u.format4; +#endif + default:return false; + } + } + iter_t __end__ () const + { + iter_t it = {}; + it.format = format; + switch (format) + { + case 1: it.u.format1 = u.format1.__end__ (); break; + case 2: it.u.format2 = u.format2.__end__ (); break; +#ifndef HB_NO_BORING_EXPANSION + case 3: it.u.format3 = u.format3.__end__ (); break; + case 4: it.u.format4 = u.format4.__end__ (); break; +#endif + default: break; + } + return it; + } + + private: + unsigned int format; + union { +#ifndef HB_NO_BORING_EXPANSION + CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */ + CoverageFormat1_3<MediumTypes>::iter_t format3; +#endif + CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */ + CoverageFormat1_3<SmallTypes>::iter_t format1; + } u; + }; + iter_t iter () const { return iter_t (*this); } +}; + +template<typename Iterator> +static inline void +Coverage_serialize (hb_serialize_context_t *c, + Iterator it) +{ c->start_embed<Coverage> ()->serialize (c, it); } + +} +} +} + +#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh new file mode 100644 index 0000000000..886babd2d1 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh @@ -0,0 +1,126 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod, Garret Rieger + */ + + +#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH +#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH + +namespace OT { +namespace Layout { +namespace Common { + +#define NOT_COVERED ((unsigned int) -1) + +template <typename Types> +struct CoverageFormat1_3 +{ + friend struct Coverage; + + protected: + HBUINT16 coverageFormat; /* Format identifier--format = 1 */ + SortedArray16Of<typename Types::HBGlyphID> + glyphArray; /* Array of GlyphIDs--in numerical order */ + public: + DEFINE_SIZE_ARRAY (4, glyphArray); + + private: + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (glyphArray.sanitize (c)); + } + + unsigned int get_coverage (hb_codepoint_t glyph_id) const + { + unsigned int i; + glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED); + return i; + } + + unsigned get_population () const + { + return glyphArray.len; + } + + template <typename Iterator, + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> + bool serialize (hb_serialize_context_t *c, Iterator glyphs) + { + TRACE_SERIALIZE (this); + return_trace (glyphArray.serialize (c, glyphs)); + } + + bool intersects (const hb_set_t *glyphs) const + { + /* TODO Speed up, using hb_set_next() and bsearch()? */ + for (const auto& g : glyphArray.as_array ()) + if (glyphs->has (g)) + return true; + return false; + } + bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const + { return glyphs->has (glyphArray[index]); } + + template <typename IterableOut, + hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))> + void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const + { + unsigned count = glyphArray.len; + for (unsigned i = 0; i < count; i++) + if (glyphs.has (glyphArray[i])) + intersect_glyphs << glyphArray[i]; + } + + template <typename set_t> + bool collect_coverage (set_t *glyphs) const + { return glyphs->add_sorted_array (glyphArray.as_array ()); } + + public: + /* Older compilers need this to be public. */ + struct iter_t + { + void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; } + bool __more__ () const { return i < c->glyphArray.len; } + void __next__ () { i++; } + hb_codepoint_t get_glyph () const { return c->glyphArray[i]; } + bool operator != (const iter_t& o) const + { return i != o.i; } + iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; } + + private: + const struct CoverageFormat1_3 *c; + unsigned int i; + }; + private: +}; + +} +} +} + +#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh new file mode 100644 index 0000000000..4ddb2a73e4 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh @@ -0,0 +1,233 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod, Garret Rieger + */ + +#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH +#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH + +#include "RangeRecord.hh" + +namespace OT { +namespace Layout { +namespace Common { + +template <typename Types> +struct CoverageFormat2_4 +{ + friend struct Coverage; + + protected: + HBUINT16 coverageFormat; /* Format identifier--format = 2 */ + SortedArray16Of<RangeRecord<Types>> + rangeRecord; /* Array of glyph ranges--ordered by + * Start GlyphID. rangeCount entries + * long */ + public: + DEFINE_SIZE_ARRAY (4, rangeRecord); + + private: + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (rangeRecord.sanitize (c)); + } + + unsigned int get_coverage (hb_codepoint_t glyph_id) const + { + const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id); + return likely (range.first <= range.last) + ? (unsigned int) range.value + (glyph_id - range.first) + : NOT_COVERED; + } + + unsigned get_population () const + { + typename Types::large_int ret = 0; + for (const auto &r : rangeRecord) + ret += r.get_population (); + return ret > UINT_MAX ? UINT_MAX : (unsigned) ret; + } + + template <typename Iterator, + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> + bool serialize (hb_serialize_context_t *c, Iterator glyphs) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (this))) return_trace (false); + + /* TODO(iter) Write more efficiently? */ + + unsigned num_ranges = 0; + hb_codepoint_t last = (hb_codepoint_t) -2; + for (auto g: glyphs) + { + if (last + 1 != g) + num_ranges++; + last = g; + } + + if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false); + if (!num_ranges) return_trace (true); + + unsigned count = 0; + unsigned range = (unsigned) -1; + last = (hb_codepoint_t) -2; + for (auto g: glyphs) + { + if (last + 1 != g) + { + range++; + rangeRecord[range].first = g; + rangeRecord[range].value = count; + } + rangeRecord[range].last = g; + last = g; + count++; + } + + return_trace (true); + } + + bool intersects (const hb_set_t *glyphs) const + { + return hb_any (+ hb_iter (rangeRecord) + | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); })); + } + bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const + { + auto cmp = [] (const void *pk, const void *pr) -> int + { + unsigned index = * (const unsigned *) pk; + const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr; + if (index < range.value) return -1; + if (index > (unsigned int) range.value + (range.last - range.first)) return +1; + return 0; + }; + + auto arr = rangeRecord.as_array (); + unsigned idx; + if (hb_bsearch_impl (&idx, index, + arr.arrayZ, arr.length, sizeof (arr[0]), + (int (*)(const void *_key, const void *_item)) cmp)) + return arr.arrayZ[idx].intersects (*glyphs); + return false; + } + + template <typename IterableOut, + hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))> + void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const + { + for (const auto& range : rangeRecord) + { + hb_codepoint_t last = range.last; + for (hb_codepoint_t g = range.first - 1; + glyphs.next (&g) && g <= last;) + intersect_glyphs << g; + } + } + + template <typename set_t> + bool collect_coverage (set_t *glyphs) const + { + for (const auto& range: rangeRecord) + if (unlikely (!range.collect_coverage (glyphs))) + return false; + return true; + } + + public: + /* Older compilers need this to be public. */ + struct iter_t + { + void init (const CoverageFormat2_4 &c_) + { + c = &c_; + coverage = 0; + i = 0; + j = c->rangeRecord.len ? c->rangeRecord[0].first : 0; + if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last)) + { + /* Broken table. Skip. */ + i = c->rangeRecord.len; + j = 0; + } + } + bool __more__ () const { return i < c->rangeRecord.len; } + void __next__ () + { + if (j >= c->rangeRecord[i].last) + { + i++; + if (__more__ ()) + { + unsigned int old = coverage; + j = c->rangeRecord[i].first; + coverage = c->rangeRecord[i].value; + if (unlikely (coverage != old + 1)) + { + /* Broken table. Skip. Important to avoid DoS. + * Also, our callers depend on coverage being + * consecutive and monotonically increasing, + * ie. iota(). */ + i = c->rangeRecord.len; + j = 0; + return; + } + } + else + j = 0; + return; + } + coverage++; + j++; + } + hb_codepoint_t get_glyph () const { return j; } + bool operator != (const iter_t& o) const + { return i != o.i || j != o.j; } + iter_t __end__ () const + { + iter_t it; + it.init (*c); + it.i = c->rangeRecord.len; + it.j = 0; + return it; + } + + private: + const struct CoverageFormat2_4 *c; + unsigned int i, coverage; + hb_codepoint_t j; + }; + private: +}; + +} +} +} + +#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh new file mode 100644 index 0000000000..a62629fad3 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh @@ -0,0 +1,85 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod, Garret Rieger + */ + +#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH +#define OT_LAYOUT_COMMON_RANGERECORD_HH + +namespace OT { +namespace Layout { +namespace Common { + +template <typename Types> +struct RangeRecord +{ + typename Types::HBGlyphID first; /* First GlyphID in the range */ + typename Types::HBGlyphID last; /* Last GlyphID in the range */ + HBUINT16 value; /* Value */ + + DEFINE_SIZE_STATIC (2 + 2 * Types::size); + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + int cmp (hb_codepoint_t g) const + { return g < first ? -1 : g <= last ? 0 : +1; } + + unsigned get_population () const + { + if (unlikely (last < first)) return 0; + return (last - first + 1); + } + + bool intersects (const hb_set_t &glyphs) const + { return glyphs.intersects (first, last); } + + template <typename set_t> + bool collect_coverage (set_t *glyphs) const + { return glyphs->add_range (first, last); } +}; + +} +} +} + +// TODO(garretrieger): This was previously implemented using +// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9); +// but that only works when there is only a single namespace level. +// The macro should probably be fixed so it can work in this situation. +extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9]; +template <typename Spec> +struct Null<OT::Layout::Common::RangeRecord<Spec>> { + static OT::Layout::Common::RangeRecord<Spec> const & get_null () { + return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord); + } +}; + + +#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh index e212fab976..7f58fac8b8 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh @@ -140,7 +140,14 @@ struct CursivePosFormat1 unsigned int i = skippy_iter.idx; unsigned int j = buffer->idx; - buffer->unsafe_to_break (i, j); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "cursive attaching glyph at %d to glyph at %d", + i, j); + } + + buffer->unsafe_to_break (i, j + 1); float entry_x, entry_y, exit_x, exit_y; (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); @@ -223,7 +230,20 @@ struct CursivePosFormat1 * https://github.com/harfbuzz/harfbuzz/issues/2469 */ if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain())) + { pos[parent].attach_chain() = 0; + if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) + pos[parent].y_offset = 0; + else + pos[parent].x_offset = 0; + } + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "cursive attached glyph at %d to glyph at %d", + i, j); + } buffer->idx++; return_trace (true); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh index 224d6b746b..72829377a6 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh @@ -1,12 +1,15 @@ -#ifndef OT_LAYOUT_GPOS_HH -#define OT_LAYOUT_GPOS_HH +#ifndef OT_LAYOUT_GPOS_GPOS_HH +#define OT_LAYOUT_GPOS_GPOS_HH -#include "../../hb-ot-layout-common.hh" -#include "../../hb-ot-layout-gsubgpos.hh" -#include "GPOS/Common.hh" -#include "GPOS/PosLookup.hh" +#include "../../../hb-ot-layout-common.hh" +#include "../../../hb-ot-layout-gsubgpos.hh" +#include "Common.hh" +#include "PosLookup.hh" namespace OT { + +using Layout::GPOS_impl::PosLookup; + namespace Layout { static void @@ -25,10 +28,10 @@ struct GPOS : GSUBGPOS { static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS; - using Lookup = GPOS_impl::PosLookup; + using Lookup = PosLookup; - const GPOS_impl::PosLookup& get_lookup (unsigned int i) const - { return static_cast<const GPOS_impl::PosLookup &> (GSUBGPOS::get_lookup (i)); } + const PosLookup& get_lookup (unsigned int i) const + { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); } static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer); @@ -37,11 +40,14 @@ struct GPOS : GSUBGPOS bool subset (hb_subset_context_t *c) const { hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features); - return GSUBGPOS::subset<GPOS_impl::PosLookup> (&l); + return GSUBGPOS::subset<PosLookup> (&l); } bool sanitize (hb_sanitize_context_t *c) const - { return GSUBGPOS::sanitize<GPOS_impl::PosLookup> (c); } + { + TRACE_SANITIZE (this); + return_trace (GSUBGPOS::sanitize<PosLookup> (c)); + } HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, hb_face_t *face) const; @@ -51,7 +57,7 @@ struct GPOS : GSUBGPOS for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++) { if (!c->gpos_lookups->has (i)) continue; - const GPOS_impl::PosLookup &l = get_lookup (i); + const PosLookup &l = get_lookup (i); l.dispatch (c); } } @@ -59,7 +65,7 @@ struct GPOS : GSUBGPOS void closure_lookups (hb_face_t *face, const hb_set_t *glyphs, hb_set_t *lookup_indexes /* IN/OUT */) const - { GSUBGPOS::closure_lookups<GPOS_impl::PosLookup> (face, glyphs, lookup_indexes); } + { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); } typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t; }; @@ -162,4 +168,4 @@ struct GPOS_accelerator_t : Layout::GPOS::accelerator_t { } -#endif /* OT_LAYOUT_GPOS_HH */ +#endif /* OT_LAYOUT_GPOS_GPOS_HH */ diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh new file mode 100644 index 0000000000..a2d807cc32 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh @@ -0,0 +1,56 @@ +#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH +#define OT_LAYOUT_GPOS_LIGATUREARRAY_HH + +namespace OT { +namespace Layout { +namespace GPOS_impl { + + +typedef AnchorMatrix LigatureAttach; /* component-major-- + * in order of writing direction--, + * mark-minor-- + * ordered by class--zero-based. */ + +/* Array of LigatureAttach tables ordered by LigatureCoverage Index */ +struct LigatureArray : List16OfOffset16To<LigatureAttach> +{ + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + Iterator coverage, + unsigned class_count, + const hb_map_t *klass_mapping) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + for (const auto _ : + hb_zip (coverage, *this) + | hb_filter (glyphset, hb_first)) + { + auto *matrix = out->serialize_append (c->serializer); + if (unlikely (!matrix)) return_trace (false); + + const LigatureAttach& src = (this + _.second); + auto indexes = + + hb_range (src.rows * class_count) + | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) + ; + matrix->serialize_subset (c, + _.second, + this, + src.rows, + indexes); + } + return_trace (this->len); + } +}; + + +} +} +} + +#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_HH */ diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh index f8cddd1991..cb5e8b2689 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh @@ -39,6 +39,13 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "attaching mark glyph at %d to glyph at %d", + c->buffer->idx, glyph_pos); + } + hb_glyph_position_t &o = buffer->cur_pos(); o.x_offset = roundf (base_x - mark_x); o.y_offset = roundf (base_y - mark_y); @@ -46,6 +53,13 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove o.attach_chain() = (int) glyph_pos - (int) buffer->idx; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "attached mark glyph at %d to glyph at %d", + c->buffer->idx, glyph_pos); + } + buffer->idx++; return_trace (true); } @@ -83,10 +97,11 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove } }; -static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, - const MarkArray &mark_array, - const hb_set_t &glyphset, - hb_map_t* klass_mapping /* INOUT */) +HB_INTERNAL inline +void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, + const MarkArray &mark_array, + const hb_set_t &glyphset, + hb_map_t* klass_mapping /* INOUT */) { hb_set_t orig_classes; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh index e99e13ff84..c99b6b2e4b 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh @@ -11,8 +11,11 @@ struct MarkBasePos { protected: union { - HBUINT16 format; /* Format identifier */ - MarkBasePosFormat1 format1; + HBUINT16 format; /* Format identifier */ + MarkBasePosFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + MarkBasePosFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -23,6 +26,9 @@ struct MarkBasePos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh index a10b806fe5..ebb8c31c67 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh @@ -12,26 +12,27 @@ typedef AnchorMatrix BaseArray; /* base-major-- * mark-minor-- * ordered by class--zero-based. */ -struct MarkBasePosFormat1 +template <typename Types> +struct MarkBasePosFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> markCoverage; /* Offset to MarkCoverage table--from * beginning of MarkBasePos subtable */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> baseCoverage; /* Offset to BaseCoverage table--from * beginning of MarkBasePos subtable */ HBUINT16 classCount; /* Number of classes defined for marks */ - Offset16To<MarkArray> + typename Types::template OffsetTo<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkBasePos subtable */ - Offset16To<BaseArray> + typename Types::template OffsetTo<BaseArray> baseArray; /* Offset to BaseArray table--from * beginning of MarkBasePos subtable */ public: - DEFINE_SIZE_STATIC (12); + DEFINE_SIZE_STATIC (4 + 4 * Types::size); bool sanitize (hb_sanitize_context_t *c) const { @@ -117,6 +118,7 @@ struct MarkBasePosFormat1 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || (skippy_iter.idx == 0 || _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) || + !_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) || _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh index 7e74aa73e0..8a4de9ffaa 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh @@ -11,8 +11,11 @@ struct MarkLigPos { protected: union { - HBUINT16 format; /* Format identifier */ - MarkLigPosFormat1 format1; + HBUINT16 format; /* Format identifier */ + MarkLigPosFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + MarkLigPosFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -23,6 +26,9 @@ struct MarkLigPos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh index 4382aa6c6c..1a8021237e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh @@ -1,72 +1,34 @@ #ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH #define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH +#include "LigatureArray.hh" + namespace OT { namespace Layout { namespace GPOS_impl { -typedef AnchorMatrix LigatureAttach; /* component-major-- - * in order of writing direction--, - * mark-minor-- - * ordered by class--zero-based. */ - -/* Array of LigatureAttach tables ordered by LigatureCoverage Index */ -struct LigatureArray : List16OfOffset16To<LigatureAttach> -{ - template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - bool subset (hb_subset_context_t *c, - Iterator coverage, - unsigned class_count, - const hb_map_t *klass_mapping) const - { - TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); - - auto *out = c->serializer->start_embed (this); - if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - - for (const auto _ : + hb_zip (coverage, *this) - | hb_filter (glyphset, hb_first)) - { - auto *matrix = out->serialize_append (c->serializer); - if (unlikely (!matrix)) return_trace (false); - - const LigatureAttach& src = (this + _.second); - auto indexes = - + hb_range (src.rows * class_count) - | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) - ; - matrix->serialize_subset (c, - _.second, - this, - src.rows, - indexes); - } - return_trace (this->len); - } -}; -struct MarkLigPosFormat1 +template <typename Types> +struct MarkLigPosFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> markCoverage; /* Offset to Mark Coverage table--from * beginning of MarkLigPos subtable */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> ligatureCoverage; /* Offset to Ligature Coverage * table--from beginning of MarkLigPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - Offset16To<MarkArray> + typename Types::template OffsetTo<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkLigPos subtable */ - Offset16To<LigatureArray> + typename Types::template OffsetTo<LigatureArray> ligatureArray; /* Offset to LigatureArray table--from * beginning of MarkLigPos subtable */ public: - DEFINE_SIZE_STATIC (12); + DEFINE_SIZE_STATIC (4 + 4 * Types::size); bool sanitize (hb_sanitize_context_t *c) const { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh index c0eee6d54c..74b5105c42 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh @@ -11,8 +11,11 @@ struct MarkMarkPos { protected: union { - HBUINT16 format; /* Format identifier */ - MarkMarkPosFormat1 format1; + HBUINT16 format; /* Format identifier */ + MarkMarkPosFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + MarkMarkPosFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -23,6 +26,9 @@ struct MarkMarkPos if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index c48a74f773..fbcebb8044 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -12,27 +12,28 @@ typedef AnchorMatrix Mark2Array; /* mark2-major-- * mark1-minor-- * ordered by class--zero-based. */ -struct MarkMarkPosFormat1 +template <typename Types> +struct MarkMarkPosFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> mark1Coverage; /* Offset to Combining Mark1 Coverage * table--from beginning of MarkMarkPos * subtable */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> mark2Coverage; /* Offset to Combining Mark2 Coverage * table--from beginning of MarkMarkPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - Offset16To<MarkArray> + typename Types::template OffsetTo<MarkArray> mark1Array; /* Offset to Mark1Array table--from * beginning of MarkMarkPos subtable */ - Offset16To<Mark2Array> + typename Types::template OffsetTo<Mark2Array> mark2Array; /* Offset to Mark2Array table--from * beginning of MarkMarkPos subtable */ public: - DEFINE_SIZE_STATIC (12); + DEFINE_SIZE_STATIC (4 + 4 * Types::size); bool sanitize (hb_sanitize_context_t *c) const { @@ -100,7 +101,7 @@ struct MarkMarkPosFormat1 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); - skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); + skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); unsigned unsafe_from; if (!skippy_iter.prev (&unsafe_from)) { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh index 8479178d38..72bfc43dc4 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh @@ -12,9 +12,13 @@ struct PairPos { protected: union { - HBUINT16 format; /* Format identifier */ - PairPosFormat1 format1; - PairPosFormat2 format2; + HBUINT16 format; /* Format identifier */ + PairPosFormat1_3<SmallTypes> format1; + PairPosFormat2_4<SmallTypes> format2; +#ifndef HB_NO_BORING_EXPANSION + PairPosFormat1_3<MediumTypes> format3; + PairPosFormat2_4<MediumTypes> format4; +#endif } u; public: @@ -26,6 +30,10 @@ struct PairPos switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh index 35a2db2d45..3cb207281d 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -1,248 +1,22 @@ #ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH #define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH +#include "PairSet.hh" + namespace OT { namespace Layout { namespace GPOS_impl { -struct PairValueRecord -{ - friend struct PairSet; - - int cmp (hb_codepoint_t k) const - { return secondGlyph.cmp (k); } - - struct context_t - { - const void *base; - const ValueFormat *valueFormats; - const ValueFormat *newFormats; - unsigned len1; /* valueFormats[0].get_len() */ - const hb_map_t *glyph_map; - const hb_map_t *layout_variation_idx_map; - }; - - bool subset (hb_subset_context_t *c, - context_t *closure) const - { - TRACE_SERIALIZE (this); - auto *s = c->serializer; - auto *out = s->start_embed (*this); - if (unlikely (!s->extend_min (out))) return_trace (false); - - out->secondGlyph = (*closure->glyph_map)[secondGlyph]; - - closure->valueFormats[0].copy_values (s, - closure->newFormats[0], - closure->base, &values[0], - closure->layout_variation_idx_map); - closure->valueFormats[1].copy_values (s, - closure->newFormats[1], - closure->base, - &values[closure->len1], - closure->layout_variation_idx_map); - - return_trace (true); - } - - void collect_variation_indices (hb_collect_variation_indices_context_t *c, - const ValueFormat *valueFormats, - const void *base) const - { - unsigned record1_len = valueFormats[0].get_len (); - unsigned record2_len = valueFormats[1].get_len (); - const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len); - - if (valueFormats[0].has_device ()) - valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len)); - - if (valueFormats[1].has_device ()) - valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len)); - } - - bool intersects (const hb_set_t& glyphset) const - { - return glyphset.has(secondGlyph); - } - - const Value* get_values_1 () const - { - return &values[0]; - } - - const Value* get_values_2 (ValueFormat format1) const - { - return &values[format1.get_len ()]; - } - protected: - HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the - * pair--first glyph is listed in the - * Coverage table */ - ValueRecord values; /* Positioning data for the first glyph - * followed by for second glyph */ - public: - DEFINE_SIZE_ARRAY (2, values); -}; - -struct PairSet +template <typename Types> +struct PairPosFormat1_3 { - friend struct PairPosFormat1; - - bool intersects (const hb_set_t *glyphs, - const ValueFormat *valueFormats) const - { - unsigned int len1 = valueFormats[0].get_len (); - unsigned int len2 = valueFormats[1].get_len (); - unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); - - const PairValueRecord *record = &firstPairValueRecord; - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - { - if (glyphs->has (record->secondGlyph)) - return true; - record = &StructAtOffset<const PairValueRecord> (record, record_size); - } - return false; - } - - void collect_glyphs (hb_collect_glyphs_context_t *c, - const ValueFormat *valueFormats) const - { - unsigned int len1 = valueFormats[0].get_len (); - unsigned int len2 = valueFormats[1].get_len (); - unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); - - const PairValueRecord *record = &firstPairValueRecord; - c->input->add_array (&record->secondGlyph, len, record_size); - } - - void collect_variation_indices (hb_collect_variation_indices_context_t *c, - const ValueFormat *valueFormats) const - { - unsigned len1 = valueFormats[0].get_len (); - unsigned len2 = valueFormats[1].get_len (); - unsigned record_size = HBUINT16::static_size * (1 + len1 + len2); - - const PairValueRecord *record = &firstPairValueRecord; - unsigned count = len; - for (unsigned i = 0; i < count; i++) - { - if (c->glyph_set->has (record->secondGlyph)) - { record->collect_variation_indices (c, valueFormats, this); } - - record = &StructAtOffset<const PairValueRecord> (record, record_size); - } - } + using PairSet = GPOS_impl::PairSet<Types>; + using PairValueRecord = GPOS_impl::PairValueRecord<Types>; - bool apply (hb_ot_apply_context_t *c, - const ValueFormat *valueFormats, - unsigned int pos) const - { - TRACE_APPLY (this); - hb_buffer_t *buffer = c->buffer; - unsigned int len1 = valueFormats[0].get_len (); - unsigned int len2 = valueFormats[1].get_len (); - unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); - - const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint, - &firstPairValueRecord, - len, - record_size); - if (record) - { - bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); - bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); - if (applied_first || applied_second) - buffer->unsafe_to_break (buffer->idx, pos + 1); - if (len2) - pos++; - buffer->idx = pos; - return_trace (true); - } - buffer->unsafe_to_concat (buffer->idx, pos + 1); - return_trace (false); - } - - bool subset (hb_subset_context_t *c, - const ValueFormat valueFormats[2], - const ValueFormat newFormats[2]) const - { - TRACE_SUBSET (this); - auto snap = c->serializer->snapshot (); - - auto *out = c->serializer->start_embed (*this); - if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - out->len = 0; - - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); - const hb_map_t &glyph_map = *c->plan->glyph_map; - - unsigned len1 = valueFormats[0].get_len (); - unsigned len2 = valueFormats[1].get_len (); - unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); - - PairValueRecord::context_t context = - { - this, - valueFormats, - newFormats, - len1, - &glyph_map, - c->plan->layout_variation_idx_map - }; - - const PairValueRecord *record = &firstPairValueRecord; - unsigned count = len, num = 0; - for (unsigned i = 0; i < count; i++) - { - if (glyphset.has (record->secondGlyph) - && record->subset (c, &context)) num++; - record = &StructAtOffset<const PairValueRecord> (record, record_size); - } - - out->len = num; - if (!num) c->serializer->revert (snap); - return_trace (num); - } - - struct sanitize_closure_t - { - const ValueFormat *valueFormats; - unsigned int len1; /* valueFormats[0].get_len() */ - unsigned int stride; /* 1 + len1 + len2 */ - }; - - bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const - { - TRACE_SANITIZE (this); - if (!(c->check_struct (this) - && c->check_range (&firstPairValueRecord, - len, - HBUINT16::static_size, - closure->stride))) return_trace (false); - - unsigned int count = len; - const PairValueRecord *record = &firstPairValueRecord; - return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && - closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); - } - - protected: - HBUINT16 len; /* Number of PairValueRecords */ - PairValueRecord firstPairValueRecord; - /* Array of PairValueRecords--ordered - * by GlyphID of the second glyph */ - public: - DEFINE_SIZE_MIN (2); -}; - -struct PairPosFormat1 -{ protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat[2]; /* [0] Defines the types of data in @@ -251,11 +25,11 @@ struct PairPosFormat1 /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ - Array16OfOffset16To<PairSet> + Array16Of<typename Types::template OffsetTo<PairSet>> pairSet; /* Array of PairSet tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (10, pairSet); + DEFINE_SIZE_ARRAY (8 + Types::size, pairSet); bool sanitize (hb_sanitize_context_t *c) const { @@ -265,7 +39,7 @@ struct PairPosFormat1 unsigned int len1 = valueFormat[0].get_len (); unsigned int len2 = valueFormat[1].get_len (); - PairSet::sanitize_closure_t closure = + typename PairSet::sanitize_closure_t closure = { valueFormat, len1, @@ -275,14 +49,13 @@ struct PairPosFormat1 return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure)); } - bool intersects (const hb_set_t *glyphs) const { return + hb_zip (this+coverage, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([glyphs, this] (const Offset16To<PairSet> &_) + | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_) { return (this+_).intersects (glyphs, valueFormat); }) | hb_any ; @@ -358,7 +131,7 @@ struct PairPosFormat1 + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const Offset16To<PairSet>& _) + | hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _) { auto snap = c->serializer->snapshot (); auto *o = out->pairSet.serialize_append (c->serializer); @@ -391,7 +164,7 @@ struct PairPosFormat1 unsigned format1 = 0; unsigned format2 = 0; - for (const Offset16To<PairSet>& _ : + for (const auto & _ : + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) { const PairSet& set = (this + _); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh index 3f5f9959c4..a80fe0c226 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -7,11 +7,12 @@ namespace OT { namespace Layout { namespace GPOS_impl { -struct PairPosFormat2 +template <typename Types> +struct PairPosFormat2_4 { protected: HBUINT16 format; /* Format identifier--format = 2 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat1; /* ValueRecord definition--for the @@ -20,11 +21,11 @@ struct PairPosFormat2 ValueFormat valueFormat2; /* ValueRecord definition--for the * second glyph of the pair--may be * zero (0) */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> classDef1; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the first glyph of the pair */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> classDef2; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the second glyph of the pair */ @@ -36,7 +37,7 @@ struct PairPosFormat2 * class1-major, class2-minor, * Each entry has value1 and value2 */ public: - DEFINE_SIZE_ARRAY (16, values); + DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values); bool sanitize (hb_sanitize_context_t *c) const { @@ -216,10 +217,23 @@ struct PairPosFormat2 } bail: + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerning glyphs at %d,%d", + c->buffer->idx, skippy_iter.idx); + } applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerned glyphs at %d,%d", + c->buffer->idx, skippy_iter.idx); + } + success: if (applied_first || applied_second) buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh new file mode 100644 index 0000000000..4578fbd1d6 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh @@ -0,0 +1,189 @@ +#ifndef OT_LAYOUT_GPOS_PAIRSET_HH +#define OT_LAYOUT_GPOS_PAIRSET_HH + +#include "PairValueRecord.hh" + +namespace OT { +namespace Layout { +namespace GPOS_impl { + + +template <typename Types> +struct PairSet +{ + template <typename Types2> + friend struct PairPosFormat1_3; + + using PairValueRecord = GPOS_impl::PairValueRecord<Types>; + + protected: + HBUINT16 len; /* Number of PairValueRecords */ + PairValueRecord firstPairValueRecord; + /* Array of PairValueRecords--ordered + * by GlyphID of the second glyph */ + public: + DEFINE_SIZE_MIN (2); + + struct sanitize_closure_t + { + const ValueFormat *valueFormats; + unsigned int len1; /* valueFormats[0].get_len() */ + unsigned int stride; /* 1 + len1 + len2 */ + }; + + bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const + { + TRACE_SANITIZE (this); + if (!(c->check_struct (this) + && c->check_range (&firstPairValueRecord, + len, + HBUINT16::static_size, + closure->stride))) return_trace (false); + + unsigned int count = len; + const PairValueRecord *record = &firstPairValueRecord; + return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && + closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); + } + + bool intersects (const hb_set_t *glyphs, + const ValueFormat *valueFormats) const + { + unsigned int len1 = valueFormats[0].get_len (); + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); + + const PairValueRecord *record = &firstPairValueRecord; + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + if (glyphs->has (record->secondGlyph)) + return true; + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + return false; + } + + void collect_glyphs (hb_collect_glyphs_context_t *c, + const ValueFormat *valueFormats) const + { + unsigned int len1 = valueFormats[0].get_len (); + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); + + const PairValueRecord *record = &firstPairValueRecord; + c->input->add_array (&record->secondGlyph, len, record_size); + } + + void collect_variation_indices (hb_collect_variation_indices_context_t *c, + const ValueFormat *valueFormats) const + { + unsigned len1 = valueFormats[0].get_len (); + unsigned len2 = valueFormats[1].get_len (); + unsigned record_size = HBUINT16::static_size * (1 + len1 + len2); + + const PairValueRecord *record = &firstPairValueRecord; + unsigned count = len; + for (unsigned i = 0; i < count; i++) + { + if (c->glyph_set->has (record->secondGlyph)) + { record->collect_variation_indices (c, valueFormats, this); } + + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + } + + bool apply (hb_ot_apply_context_t *c, + const ValueFormat *valueFormats, + unsigned int pos) const + { + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int len1 = valueFormats[0].get_len (); + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); + + const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint, + &firstPairValueRecord, + len, + record_size); + if (record) + { + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerning glyphs at %d,%d", + c->buffer->idx, pos); + } + + bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "kerned glyphs at %d,%d", + c->buffer->idx, pos); + } + + if (applied_first || applied_second) + buffer->unsafe_to_break (buffer->idx, pos + 1); + if (len2) + pos++; + + buffer->idx = pos; + return_trace (true); + } + buffer->unsafe_to_concat (buffer->idx, pos + 1); + return_trace (false); + } + + bool subset (hb_subset_context_t *c, + const ValueFormat valueFormats[2], + const ValueFormat newFormats[2]) const + { + TRACE_SUBSET (this); + auto snap = c->serializer->snapshot (); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->len = 0; + + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + unsigned len1 = valueFormats[0].get_len (); + unsigned len2 = valueFormats[1].get_len (); + unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); + + typename PairValueRecord::context_t context = + { + this, + valueFormats, + newFormats, + len1, + &glyph_map, + c->plan->layout_variation_idx_map + }; + + const PairValueRecord *record = &firstPairValueRecord; + unsigned count = len, num = 0; + for (unsigned i = 0; i < count; i++) + { + if (glyphset.has (record->secondGlyph) + && record->subset (c, &context)) num++; + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + + out->len = num; + if (!num) c->serializer->revert (snap); + return_trace (num); + } +}; + + +} +} +} + +#endif // OT_LAYOUT_GPOS_PAIRSET_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh new file mode 100644 index 0000000000..bd95abde16 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh @@ -0,0 +1,99 @@ +#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH +#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH + +#include "ValueFormat.hh" + +namespace OT { +namespace Layout { +namespace GPOS_impl { + + +template <typename Types> +struct PairValueRecord +{ + template <typename Types2> + friend struct PairSet; + + protected: + typename Types::HBGlyphID + secondGlyph; /* GlyphID of second glyph in the + * pair--first glyph is listed in the + * Coverage table */ + ValueRecord values; /* Positioning data for the first glyph + * followed by for second glyph */ + public: + DEFINE_SIZE_ARRAY (Types::size, values); + + int cmp (hb_codepoint_t k) const + { return secondGlyph.cmp (k); } + + struct context_t + { + const void *base; + const ValueFormat *valueFormats; + const ValueFormat *newFormats; + unsigned len1; /* valueFormats[0].get_len() */ + const hb_map_t *glyph_map; + const hb_map_t *layout_variation_idx_map; + }; + + bool subset (hb_subset_context_t *c, + context_t *closure) const + { + TRACE_SERIALIZE (this); + auto *s = c->serializer; + auto *out = s->start_embed (*this); + if (unlikely (!s->extend_min (out))) return_trace (false); + + out->secondGlyph = (*closure->glyph_map)[secondGlyph]; + + closure->valueFormats[0].copy_values (s, + closure->newFormats[0], + closure->base, &values[0], + closure->layout_variation_idx_map); + closure->valueFormats[1].copy_values (s, + closure->newFormats[1], + closure->base, + &values[closure->len1], + closure->layout_variation_idx_map); + + return_trace (true); + } + + void collect_variation_indices (hb_collect_variation_indices_context_t *c, + const ValueFormat *valueFormats, + const void *base) const + { + unsigned record1_len = valueFormats[0].get_len (); + unsigned record2_len = valueFormats[1].get_len (); + const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len); + + if (valueFormats[0].has_device ()) + valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len)); + + if (valueFormats[1].has_device ()) + valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len)); + } + + bool intersects (const hb_set_t& glyphset) const + { + return glyphset.has(secondGlyph); + } + + const Value* get_values_1 () const + { + return &values[0]; + } + + const Value* get_values_2 (ValueFormat format1) const + { + return &values[format1.get_len ()]; + } +}; + + +} +} +} + +#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_HH diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh index 57e146befd..702f578b3c 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh @@ -45,10 +45,7 @@ struct SinglePos ValueFormat new_format = src->get_value_format (); if (glyph_val_iter_pairs) - { format = get_format (glyph_val_iter_pairs); - new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second)); - } u.format = format; switch (u.format) { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh index 8b7840ed0e..7cbdf6dc6c 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -39,12 +39,10 @@ struct SinglePosFormat1 { if (!valueFormat.has_device ()) return; - auto it = - + hb_iter (this+coverage) - | hb_filter (c->glyph_set) - ; + hb_set_t intersection; + (this+coverage).intersect_set (*c->glyph_set, intersection); + if (!intersection) return; - if (!it) return; valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ())); } @@ -62,8 +60,22 @@ struct SinglePosFormat1 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "positioning glyph at %d", + c->buffer->idx); + } + valueFormat.apply_value (c, this, values, buffer->cur_pos()); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "positioned glyph at %d", + c->buffer->idx); + } + buffer->idx++; return_trace (true); } @@ -104,9 +116,11 @@ struct SinglePosFormat1 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_set_t intersection; + (this+coverage).intersect_set (glyphset, intersection); + auto it = - + hb_iter (this+coverage) - | hb_filter (glyphset) + + hb_iter (intersection) | hb_map_retains_sorting (glyph_map) | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ()))) ; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh index 0d038b4422..518fa9dcb0 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -70,10 +70,24 @@ struct SinglePosFormat2 if (likely (index >= valueCount)) return_trace (false); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "positioning glyph at %d", + c->buffer->idx); + } + valueFormat.apply_value (c, this, &values[index * valueFormat.get_len ()], buffer->cur_pos()); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "positioned glyph at %d", + c->buffer->idx); + } + buffer->idx++; return_trace (true); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh index 484f347468..4a9e9672eb 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh @@ -5,12 +5,13 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { +template <typename Types> struct AlternateSet { protected: - Array16Of<HBGlyphID16> + Array16Of<typename Types::HBGlyphID> alternates; /* Array of alternate GlyphIDs--in * arbitrary order */ public: @@ -56,8 +57,23 @@ struct AlternateSet if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "replacing glyph at %d (alternate substitution)", + c->buffer->idx); + } + c->replace_glyph (alternates[alt_index - 1]); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (alternate substitution)", + c->buffer->idx - 1); + } + return_trace (true); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh index e5d999261f..37406179a2 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh @@ -6,14 +6,17 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct AlternateSubst { protected: union { - HBUINT16 format; /* Format identifier */ - AlternateSubstFormat1 format1; + HBUINT16 format; /* Format identifier */ + AlternateSubstFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + AlternateSubstFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -24,10 +27,15 @@ struct AlternateSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } + /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using + * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */ bool serialize (hb_serialize_context_t *c, hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> alternate_len_list, @@ -42,6 +50,9 @@ struct AlternateSubst default:return_trace (false); } } + + /* TODO subset() should choose format. */ + }; } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh index af1cd7bedb..adec65d586 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh @@ -6,20 +6,21 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { -struct AlternateSubstFormat1 +template <typename Types> +struct AlternateSubstFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - Array16OfOffset16To<AlternateSet> + Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>> alternateSet; /* Array of AlternateSet tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, alternateSet); + DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet); bool sanitize (hb_sanitize_context_t *c) const { @@ -39,9 +40,8 @@ struct AlternateSubstFormat1 | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) + | hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); }) ; - } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -52,7 +52,7 @@ struct AlternateSubstFormat1 + hb_zip (this+coverage, alternateSet) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); }) + | hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); }) ; } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh index bbb88b222f..08fd779f73 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh @@ -7,7 +7,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct ChainContextSubst : ChainContext {}; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh index f4c78a9f02..968bba0481 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh @@ -6,7 +6,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh index 2af54e8ff4..9f8cb46b5e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh @@ -7,7 +7,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct ContextSubst : Context {}; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh index 40a3ff439f..831a7dfa2d 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh @@ -7,7 +7,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct ExtensionSubst : Extension<ExtensionSubst> { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh index 3f0c4b2ad9..c0ff098f49 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh @@ -1,16 +1,15 @@ #ifndef OT_LAYOUT_GSUB_GSUB_HH #define OT_LAYOUT_GSUB_GSUB_HH -// TODO(garretrieger): move to new layout. #include "../../../hb-ot-layout-gsubgpos.hh" #include "Common.hh" #include "SubstLookup.hh" -using OT::Layout::GSUB::SubstLookup; - namespace OT { + +using Layout::GSUB_impl::SubstLookup; + namespace Layout { -namespace GSUB { /* * GSUB -- Glyph Substitution @@ -33,7 +32,10 @@ struct GSUB : GSUBGPOS } bool sanitize (hb_sanitize_context_t *c) const - { return GSUBGPOS::sanitize<SubstLookup> (c); } + { + TRACE_SANITIZE (this); + return_trace (GSUBGPOS::sanitize<SubstLookup> (c)); + } HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, hb_face_t *face) const; @@ -48,10 +50,9 @@ struct GSUB : GSUBGPOS } -} -struct GSUB_accelerator_t : Layout::GSUB::GSUB::accelerator_t { - GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::GSUB::accelerator_t (face) {} +struct GSUB_accelerator_t : Layout::GSUB::accelerator_t { + GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::accelerator_t (face) {} }; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh index 0448d925d1..f373d921b5 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh @@ -5,18 +5,20 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { +template <typename Types> struct Ligature { protected: - HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf<HBGlyphID16> - component; /* Array of component GlyphIDs--start + typename Types::HBGlyphID + ligGlyph; /* GlyphID of ligature to substitute */ + HeadlessArrayOf<typename Types::HBGlyphID> + component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ public: - DEFINE_SIZE_ARRAY (4, component); + DEFINE_SIZE_ARRAY (Types::size + 2, component); bool sanitize (hb_sanitize_context_t *c) const { @@ -62,7 +64,24 @@ struct Ligature * as a "ligated" substitution. */ if (unlikely (count == 1)) { + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "replacing glyph at %d (ligature substitution)", + c->buffer->idx); + } + c->replace_glyph (ligGlyph); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (ligature substitution)", + c->buffer->idx - 1); + } + return_trace (true); } @@ -83,6 +102,31 @@ struct Ligature return_trace (false); } + unsigned pos = 0; + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + unsigned delta = c->buffer->sync_so_far (); + + pos = c->buffer->idx; + + char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0}; + char *p = buf; + + match_end += delta; + for (unsigned i = 0; i < count; i++) + { + match_positions[i] += delta; + if (i) + *p++ = ','; + sprintf (p, "%u", match_positions[i]); + p += strlen(p); + } + + c->buffer->message (c->font, + "ligating glyphs at %s", + buf); + } + ligate_input (c, count, match_positions, @@ -90,6 +134,14 @@ struct Ligature ligGlyph, total_component_count); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "ligated glyph at %d", + pos); + } + return_trace (true); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh index 185b324b35..637cec7137 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh @@ -6,12 +6,13 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { +template <typename Types> struct LigatureSet { protected: - Array16OfOffset16To<Ligature> + Array16OfOffset16To<Ligature<Types>> ligature; /* Array LigatureSet tables * ordered by preference */ public: @@ -28,7 +29,7 @@ struct LigatureSet return + hb_iter (ligature) | hb_map (hb_add (this)) - | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); }) + | hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); }) | hb_any ; } @@ -37,7 +38,7 @@ struct LigatureSet { + hb_iter (ligature) | hb_map (hb_add (this)) - | hb_apply ([c] (const Ligature &_) { _.closure (c); }) + | hb_apply ([c] (const Ligature<Types> &_) { _.closure (c); }) ; } @@ -45,7 +46,7 @@ struct LigatureSet { + hb_iter (ligature) | hb_map (hb_add (this)) - | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); }) + | hb_apply ([c] (const Ligature<Types> &_) { _.collect_glyphs (c); }) ; } @@ -54,7 +55,7 @@ struct LigatureSet return + hb_iter (ligature) | hb_map (hb_add (this)) - | hb_map ([c] (const Ligature &_) { return _.would_apply (c); }) + | hb_map ([c] (const Ligature<Types> &_) { return _.would_apply (c); }) | hb_any ; } @@ -65,7 +66,7 @@ struct LigatureSet unsigned int num_ligs = ligature.len; for (unsigned int i = 0; i < num_ligs; i++) { - const Ligature &lig = this+ligature[i]; + const auto &lig = this+ligature[i]; if (lig.apply (c)) return_trace (true); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh index a029bf5e9f..63707972a8 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh @@ -6,14 +6,17 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct LigatureSubst { protected: union { - HBUINT16 format; /* Format identifier */ - LigatureSubstFormat1 format1; + HBUINT16 format; /* Format identifier */ + LigatureSubstFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + LigatureSubstFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -24,10 +27,16 @@ struct LigatureSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } + /* TODO This function is only used by small GIDs, and not updated to 24bit GIDs. Should + * be done by using iterators. While at it perhaps using iterator of arrays of hb_codepoint_t + * instead. */ bool serialize (hb_serialize_context_t *c, hb_sorted_array_t<const HBGlyphID16> first_glyphs, hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, @@ -49,6 +58,9 @@ struct LigatureSubst default:return_trace (false); } } + + /* TODO subset() should choose format. */ + }; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh index 19dfe98469..32b642c38a 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh @@ -6,20 +6,21 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { -struct LigatureSubstFormat1 +template <typename Types> +struct LigatureSubstFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - Array16OfOffset16To<LigatureSet> + Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>> ligatureSet; /* Array LigatureSet tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, ligatureSet); + DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet); bool sanitize (hb_sanitize_context_t *c) const { @@ -33,7 +34,7 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_) + | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_) { return (this+_).intersects (glyphs); }) | hb_any ; @@ -48,7 +49,7 @@ struct LigatureSubstFormat1 | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) + | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); }) ; } @@ -62,7 +63,7 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); }) + | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); }) ; } @@ -73,7 +74,7 @@ struct LigatureSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); if (likely (index == NOT_COVERED)) return false; - const LigatureSet &lig_set = this+ligatureSet[index]; + const auto &lig_set = this+ligatureSet[index]; return lig_set.would_apply (c); } @@ -84,7 +85,7 @@ struct LigatureSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const LigatureSet &lig_set = this+ligatureSet[index]; + const auto &lig_set = this+ligatureSet[index]; return_trace (lig_set.apply (c)); } @@ -128,7 +129,7 @@ struct LigatureSubstFormat1 hb_set_t new_coverage; + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this))) | hb_filter (glyphset, hb_first) - | hb_filter ([&] (const LigatureSet& _) { + | hb_filter ([&] (const LigatureSet<Types>& _) { return _.intersects (&glyphset); }, hb_second) | hb_map (hb_first) diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh index b289175504..98f2f5fe7a 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh @@ -6,14 +6,17 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct MultipleSubst { protected: union { - HBUINT16 format; /* Format identifier */ - MultipleSubstFormat1 format1; + HBUINT16 format; /* Format identifier */ + MultipleSubstFormat1_2<SmallTypes> format1; +#ifndef HB_NO_BORING_EXPANSION + MultipleSubstFormat1_2<MediumTypes> format2; +#endif } u; public: @@ -25,10 +28,15 @@ struct MultipleSubst if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } + /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using + * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */ bool serialize (hb_serialize_context_t *c, hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> substitute_len_list, @@ -43,6 +51,9 @@ struct MultipleSubst default:return_trace (false); } } + + /* TODO subset() should choose format. */ + }; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh index 54c6dc8478..89a04ec3b1 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh @@ -6,20 +6,21 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { -struct MultipleSubstFormat1 +template <typename Types> +struct MultipleSubstFormat1_2 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - Array16OfOffset16To<Sequence> + Array16Of<typename Types::template OffsetTo<Sequence<Types>>> sequence; /* Array of Sequence tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, sequence); + DEFINE_SIZE_ARRAY (4 + Types::size, sequence); bool sanitize (hb_sanitize_context_t *c) const { @@ -39,7 +40,7 @@ struct MultipleSubstFormat1 | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const Sequence &_) { _.closure (c); }) + | hb_apply ([c] (const Sequence<Types> &_) { _.closure (c); }) ; } @@ -51,7 +52,7 @@ struct MultipleSubstFormat1 + hb_zip (this+coverage, sequence) | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); }) + | hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); }) ; } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh index 435d80fd31..48e208efb9 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh @@ -6,7 +6,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct ReverseChainSingleSubst { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh index 7a79a9df25..a23e92028e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh @@ -5,7 +5,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct ReverseChainSingleSubstFormat1 { @@ -33,10 +33,10 @@ struct ReverseChainSingleSubstFormat1 TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) return_trace (false); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); - const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + const auto &substitute = StructAfter<decltype (substituteX)> (lookahead); return_trace (substitute.sanitize (c)); } @@ -45,7 +45,7 @@ struct ReverseChainSingleSubstFormat1 if (!(this+coverage).intersects (glyphs)) return false; - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); unsigned int count; @@ -69,8 +69,8 @@ struct ReverseChainSingleSubstFormat1 { if (!intersects (c->glyphs)) return; - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); + const auto &substitute = StructAfter<decltype (substituteX)> (lookahead); + hb_zip (this+coverage, substitute) | hb_filter (c->parent_active_glyphs (), hb_first) @@ -91,12 +91,12 @@ struct ReverseChainSingleSubstFormat1 for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return; - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); count = lookahead.len; for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return; - const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + const auto &substitute = StructAfter<decltype (substituteX)> (lookahead); count = substitute.len; c->output->add_array (substitute.arrayZ, substitute.len); } @@ -115,8 +115,8 @@ struct ReverseChainSingleSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); + const auto &substitute = StructAfter<decltype (substituteX)> (lookahead); if (unlikely (index >= substitute.len)) return_trace (false); @@ -131,7 +131,23 @@ struct ReverseChainSingleSubstFormat1 c->buffer->idx + 1, &end_index)) { c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replacing glyph at %d (reverse chaining substitution)", + c->buffer->idx); + } + c->replace_glyph_inplace (substitute[index]); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (reverse chaining substitution)", + c->buffer->idx); + } + /* Note: We DON'T decrease buffer->idx. The main loop does it * for us. This is useful for preventing surprises if someone * calls us through a Context lookup. */ @@ -206,8 +222,8 @@ struct ReverseChainSingleSubstFormat1 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack); + const auto &substitute = StructAfter<decltype (substituteX)> (lookahead); auto it = + hb_zip (this+coverage, substitute) diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh index ebd451e6ba..3d84a5e6ea 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh @@ -5,12 +5,13 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { +template <typename Types> struct Sequence { protected: - Array16Of<HBGlyphID16> + Array16Of<typename Types::HBGlyphID> substitute; /* String of GlyphIDs to substitute */ public: DEFINE_SIZE_ARRAY (2, substitute); @@ -39,17 +40,58 @@ struct Sequence * as a "multiplied" substitution. */ if (unlikely (count == 1)) { + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "replacing glyph at %d (multiple substitution)", + c->buffer->idx); + } + c->replace_glyph (substitute.arrayZ[0]); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (multiple subtitution)", + c->buffer->idx - 1); + } + return_trace (true); } /* Spec disallows this, but Uniscribe allows it. * https://github.com/harfbuzz/harfbuzz/issues/253 */ else if (unlikely (count == 0)) { + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "deleting glyph at %d (multiple substitution)", + c->buffer->idx); + } + c->buffer->delete_glyph (); + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "deleted glyph at %d (multiple substitution)", + c->buffer->idx); + } + return_trace (true); } + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "multiplying glyph at %d", + c->buffer->idx); + } + unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur()); @@ -64,6 +106,26 @@ struct Sequence } c->buffer->skip_glyph (); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + + char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0}; + char *p = buf; + + for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++) + { + if (buf < p) + *p++ = ','; + sprintf (p, "%u", i); + p += strlen(p); + } + + c->buffer->message (c->font, + "multiplied glyphs at %s", + buf); + } + return_trace (true); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh index 786428fe45..6942e6997f 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh @@ -7,15 +7,19 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct SingleSubst { protected: union { - HBUINT16 format; /* Format identifier */ - SingleSubstFormat1 format1; - SingleSubstFormat2 format2; + HBUINT16 format; /* Format identifier */ + SingleSubstFormat1_3<SmallTypes> format1; + SingleSubstFormat2_4<SmallTypes> format2; +#ifndef HB_NO_BORING_EXPANSION + SingleSubstFormat1_3<MediumTypes> format3; + SingleSubstFormat2_4<MediumTypes> format4; +#endif } u; public: @@ -28,6 +32,10 @@ struct SingleSubst switch (u.format) { case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BORING_EXPANSION + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } @@ -45,11 +53,24 @@ struct SingleSubst if (glyphs) { format = 1; + hb_codepoint_t mask = 0xFFFFu; + +#ifndef HB_NO_BORING_EXPANSION + if (+ glyphs + | hb_map_retains_sorting (hb_first) + | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; })) + { + format += 2; + mask = 0xFFFFFFu; + } +#endif + auto get_delta = [=] (hb_codepoint_pair_t _) - { return (unsigned) (_.second - _.first) & 0xFFFF; }; + { return (unsigned) (_.second - _.first) & mask; }; delta = get_delta (*glyphs); - if (!hb_all (++(+glyphs), delta, get_delta)) format = 2; + if (!hb_all (++(+glyphs), delta, get_delta)) format += 1; } + u.format = format; switch (u.format) { case 1: return_trace (u.format1.serialize (c, @@ -57,6 +78,13 @@ struct SingleSubst | hb_map_retains_sorting (hb_first), delta)); case 2: return_trace (u.format2.serialize (c, glyphs)); +#ifndef HB_NO_BORING_EXPANSION + case 3: return_trace (u.format3.serialize (c, + + glyphs + | hb_map_retains_sorting (hb_first), + delta)); + case 4: return_trace (u.format4.serialize (c, glyphs)); +#endif default:return_trace (false); } } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh index 3c6b2954ce..4b17243d81 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh @@ -5,20 +5,22 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { -struct SingleSubstFormat1 +template <typename Types> +struct SingleSubstFormat1_3 { protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - HBUINT16 deltaGlyphID; /* Add to original GlyphID to get + typename Types::HBUINT + deltaGlyphID; /* Add to original GlyphID to get * substitute GlyphID, modulo 0x10000 */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_STATIC (2 + 2 * Types::size); bool sanitize (hb_sanitize_context_t *c) const { @@ -26,6 +28,9 @@ struct SingleSubstFormat1 return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); } + hb_codepoint_t get_mask () const + { return (1 << (8 * Types::size)) - 1; } + bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } @@ -34,14 +39,28 @@ struct SingleSubstFormat1 void closure (hb_closure_context_t *c) const { - unsigned d = deltaGlyphID; - - + hb_iter (this+coverage) - | hb_filter (c->parent_active_glyphs ()) - | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) + hb_codepoint_t d = deltaGlyphID; + hb_codepoint_t mask = get_mask (); + + hb_set_t intersection; + (this+coverage).intersect_set (c->parent_active_glyphs (), intersection); + + /* In degenerate fuzzer-found fonts, but not real fonts, + * this table can keep adding new glyphs in each round of closure. + * Refuse to close-over, if it maps glyph range to overlapping range. */ + hb_codepoint_t min_before = intersection.get_min (); + hb_codepoint_t max_before = intersection.get_max (); + hb_codepoint_t min_after = (min_before + d) & mask; + hb_codepoint_t max_after = (max_before + d) & mask; + if ((this+coverage).get_population () >= max_before - min_before && + ((min_before <= min_after && min_after <= max_before) || + (min_before <= max_after && max_after <= max_before))) + return; + + + hb_iter (intersection) + | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; }) | hb_sink (c->output) ; - } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -49,9 +68,11 @@ struct SingleSubstFormat1 void collect_glyphs (hb_collect_glyphs_context_t *c) const { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; - unsigned d = deltaGlyphID; + hb_codepoint_t d = deltaGlyphID; + hb_codepoint_t mask = get_mask (); + + hb_iter (this+coverage) - | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) + | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; }) | hb_sink (c->output) ; } @@ -68,11 +89,28 @@ struct SingleSubstFormat1 unsigned int index = (this+coverage).get_coverage (glyph_id); if (likely (index == NOT_COVERED)) return_trace (false); - /* According to the Adobe Annotated OpenType Suite, result is always - * limited to 16bit. */ - glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu; + hb_codepoint_t d = deltaGlyphID; + hb_codepoint_t mask = get_mask (); + + glyph_id = (glyph_id + d) & mask; + + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "replacing glyph at %d (single substitution)", + c->buffer->idx); + } + c->replace_glyph (glyph_id); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (single substitution)", + c->buffer->idx - 1); + } + return_trace (true); } @@ -95,14 +133,17 @@ struct SingleSubstFormat1 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_codepoint_t delta = deltaGlyphID; + hb_codepoint_t d = deltaGlyphID; + hb_codepoint_t mask = get_mask (); + + hb_set_t intersection; + (this+coverage).intersect_set (glyphset, intersection); auto it = - + hb_iter (this+coverage) - | hb_filter (glyphset) - | hb_map_retains_sorting ([&] (hb_codepoint_t g) { + + hb_iter (intersection) + | hb_map_retains_sorting ([d, mask] (hb_codepoint_t g) { return hb_codepoint_pair_t (g, - (g + delta) & 0xFFFF); }) + (g + d) & mask); }) | hb_filter (glyphset, hb_second) | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh index df75bb52bb..fb1e90d03e 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh @@ -5,21 +5,22 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { -struct SingleSubstFormat2 +template <typename Types> +struct SingleSubstFormat2_4 { protected: HBUINT16 format; /* Format identifier--format = 2 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - Array16Of<HBGlyphID16> + Array16Of<typename Types::HBGlyphID> substitute; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, substitute); + DEFINE_SIZE_ARRAY (4 + Types::size, substitute); bool sanitize (hb_sanitize_context_t *c) const { @@ -67,8 +68,23 @@ struct SingleSubstFormat2 if (unlikely (index >= substitute.len)) return_trace (false); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "replacing glyph at %d (single substitution)", + c->buffer->idx); + } + c->replace_glyph (substitute[index]); + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + c->buffer->message (c->font, + "replaced glyph at %d (single substitution)", + c->buffer->idx - 1); + } + return_trace (true); } @@ -103,7 +119,7 @@ struct SingleSubstFormat2 + hb_zip (this+coverage, substitute) | hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t + | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) ; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh index 8fb3b55097..320685b868 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh @@ -6,7 +6,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct SubstLookup : Lookup { @@ -25,7 +25,7 @@ struct SubstLookup : Lookup { unsigned int type = get_type (); if (unlikely (type == SubTable::Extension)) - return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse (); + return get_subtable (0).u.extension.is_reverse (); return lookup_type_is_reverse (type); } @@ -98,10 +98,15 @@ struct SubstLookup : Lookup return dispatch (c); } + template<typename Glyphs, typename Substitutes, + hb_requires (hb_is_sorted_source_of (Glyphs, + const hb_codepoint_t) && + hb_is_source_of (Substitutes, + const hb_codepoint_t))> bool serialize_single (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t<const HBGlyphID16> glyphs, - hb_array_t<const HBGlyphID16> substitutes) + Glyphs glyphs, + Substitutes substitutes) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh index 53e963e2a2..a525fba039 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh @@ -13,7 +13,7 @@ namespace OT { namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct SubstLookupSubTable { diff --git a/thirdparty/harfbuzz/src/OT/Layout/types.hh b/thirdparty/harfbuzz/src/OT/Layout/types.hh new file mode 100644 index 0000000000..6a43403e94 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Layout/types.hh @@ -0,0 +1,66 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod, Garret Rieger + */ + +#ifndef OT_LAYOUT_TYPES_HH +#define OT_LAYOUT_TYPES_HH + +namespace OT { +namespace Layout { + +struct SmallTypes { + static constexpr unsigned size = 2; + using large_int = uint32_t; + using HBUINT = HBUINT16; + using HBGlyphID = HBGlyphID16; + using Offset = Offset16; + template <typename Type, bool has_null=true> + using OffsetTo = OT::Offset16To<Type, has_null>; + template <typename Type> + using ArrayOf = OT::Array16Of<Type>; + template <typename Type> + using SortedArrayOf = OT::SortedArray16Of<Type>; +}; + +struct MediumTypes { + static constexpr unsigned size = 3; + using large_int = uint64_t; + using HBUINT = HBUINT24; + using HBGlyphID = HBGlyphID24; + using Offset = Offset24; + template <typename Type, bool has_null=true> + using OffsetTo = OT::Offset24To<Type, has_null>; + template <typename Type> + using ArrayOf = OT::Array24Of<Type>; + template <typename Type> + using SortedArrayOf = OT::SortedArray24Of<Type>; +}; + +} +} + +#endif /* OT_LAYOUT_TYPES_HH */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh index c145beaa49..98c2ee4e73 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh @@ -25,13 +25,20 @@ struct CompositeGlyphRecord USE_MY_METRICS = 0x0200, OVERLAP_COMPOUND = 0x0400, SCALED_COMPONENT_OFFSET = 0x0800, - UNSCALED_COMPONENT_OFFSET = 0x1000 + UNSCALED_COMPONENT_OFFSET = 0x1000, +#ifndef HB_NO_BEYOND_64K + GID_IS_24BIT = 0x2000 +#endif }; public: unsigned int get_size () const { unsigned int size = min_size; + /* glyphIndex is 24bit instead of 16bit */ +#ifndef HB_NO_BEYOND_64K + if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size; +#endif /* arg1 and 2 are int16 */ if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; /* arg1 and 2 are int8 */ @@ -60,7 +67,13 @@ struct CompositeGlyphRecord bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); } void get_anchor_points (unsigned int &point1, unsigned int &point2) const { - const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex); + const auto *p = &StructAfter<const HBUINT8> (flags); +#ifndef HB_NO_BEYOND_64K + if (flags & GID_IS_24BIT) + p += HBGlyphID24::static_size; + else +#endif + p += HBGlyphID16::static_size; if (flags & ARG_1_AND_2_ARE_WORDS) { point1 = ((const HBUINT16 *) p)[0]; @@ -101,8 +114,14 @@ struct CompositeGlyphRecord matrix[0] = matrix[3] = 1.f; matrix[1] = matrix[2] = 0.f; + const auto *p = &StructAfter<const HBINT8> (flags); +#ifndef HB_NO_BEYOND_64K + if (flags & GID_IS_24BIT) + p += HBGlyphID24::static_size; + else +#endif + p += HBGlyphID16::static_size; int tx, ty; - const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex); if (flags & ARG_1_AND_2_ARE_WORDS) { tx = *(const HBINT16 *) p; @@ -145,8 +164,29 @@ struct CompositeGlyphRecord } public: + hb_codepoint_t get_gid () const + { +#ifndef HB_NO_BEYOND_64K + if (flags & GID_IS_24BIT) + return StructAfter<const HBGlyphID24> (flags); + else +#endif + return StructAfter<const HBGlyphID16> (flags); + } + void set_gid (hb_codepoint_t gid) + { +#ifndef HB_NO_BEYOND_64K + if (flags & GID_IS_24BIT) + StructAfter<HBGlyphID24> (flags) = gid; + else +#endif + /* TODO assert? */ + StructAfter<HBGlyphID16> (flags) = gid; + } + + protected: HBUINT16 flags; - HBGlyphID16 glyphIndex; + HBUINT24 pad; public: DEFINE_SIZE_MIN (4); }; diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh index 2199d2c48b..3efe538f37 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh @@ -105,19 +105,21 @@ struct Glyph if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); { - int h_delta = (int) header->xMin - - glyf_accelerator.hmtx->get_side_bearing (gid); + int lsb = 0; + int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ? + (int) header->xMin - lsb : 0; + int tsb = 0; int v_orig = (int) header->yMax + #ifndef HB_NO_VERTICAL - glyf_accelerator.vmtx->get_side_bearing (gid) + ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb) #else 0 #endif ; - unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid); + unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid); unsigned v_adv = #ifndef HB_NO_VERTICAL - glyf_accelerator.vmtx->get_advance (gid) + glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid) #else - font->face->get_upem () #endif @@ -144,7 +146,7 @@ struct Glyph for (auto &item : get_composite_iterator ()) { comp_points.reset (); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.glyphIndex) + if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, comp_points, phantom_only, depth + 1))) return false; @@ -198,11 +200,11 @@ struct Glyph return !all_points.in_error (); } - bool get_extents (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator, - hb_glyph_extents_t *extents) const + bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator, + hb_glyph_extents_t *extents) const { if (type == EMPTY) return true; /* Empty glyph; zero extents. */ - return header->get_extents (font, glyf_accelerator, gid, extents); + return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents); } hb_bytes_t get_bytes () const { return bytes; } diff --git a/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh index 792bd5478f..e4a9168b79 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh @@ -14,12 +14,14 @@ struct GlyphHeader bool has_data () const { return numberOfContours; } template <typename accelerator_t> - bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator, - hb_codepoint_t gid, hb_glyph_extents_t *extents) const + bool get_extents_without_var_scaled (hb_font_t *font, const accelerator_t &glyf_accelerator, + hb_codepoint_t gid, hb_glyph_extents_t *extents) const { /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */ /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */ - extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid)); + int lsb = hb_min (xMin, xMax); + (void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb); + extents->x_bearing = font->em_scale_x (lsb); extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax)); extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax)); extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax)); diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh index ebe4372047..7ae8fe3078 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh @@ -42,8 +42,8 @@ struct SubsetGlyph for (auto &_ : Glyph (dest_glyph).get_composite_iterator ()) { hb_codepoint_t new_gid; - if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid)) - const_cast<CompositeGlyphRecord &> (_).glyphIndex = new_gid; + if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid)) + const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid); } if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh index f74513cb96..bcaf44fc1e 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh @@ -194,6 +194,7 @@ struct glyf_accelerator_t hb_font_t *font; hb_glyph_extents_t *extents; contour_point_t *phantoms; + bool scaled; struct contour_bounds_t { @@ -209,7 +210,7 @@ struct glyf_accelerator_t bool empty () const { return (min_x >= max_x) || (min_y >= max_y); } - void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) + void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scaled) { if (unlikely (empty ())) { @@ -219,26 +220,37 @@ struct glyf_accelerator_t extents->y_bearing = 0; return; } - extents->x_bearing = font->em_scalef_x (min_x); - extents->width = font->em_scalef_x (max_x) - extents->x_bearing; - extents->y_bearing = font->em_scalef_y (max_y); - extents->height = font->em_scalef_y (min_y) - extents->y_bearing; + if (scaled) + { + extents->x_bearing = font->em_scalef_x (min_x); + extents->width = font->em_scalef_x (max_x) - extents->x_bearing; + extents->y_bearing = font->em_scalef_y (max_y); + extents->height = font->em_scalef_y (min_y) - extents->y_bearing; + } + else + { + extents->x_bearing = roundf (min_x); + extents->width = roundf (max_x - extents->x_bearing); + extents->y_bearing = roundf (max_y); + extents->height = roundf (min_y - extents->y_bearing); + } } protected: float min_x, min_y, max_x, max_y; } bounds; - points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_) + points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_, bool scaled_) { font = font_; extents = extents_; phantoms = phantoms_; + scaled = scaled_; if (extents) bounds = contour_bounds_t (); } void consume_point (const contour_point_t &point) { bounds.add (point); } - void points_end () { bounds.get_extents (font, extents); } + void points_end () { bounds.get_extents (font, extents, scaled); } bool is_consuming_contour_points () { return extents; } contour_point_t *get_phantoms_sink () { return phantoms; } @@ -246,22 +258,22 @@ struct glyf_accelerator_t public: unsigned - get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const + get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const { if (unlikely (gid >= num_glyphs)) return 0; bool success = false; contour_point_t phantoms[glyf_impl::PHANTOM_COUNT]; - if (likely (font->num_coords == gvar->get_axis_count ())) - success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms)); + if (font->num_coords) + success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false)); if (unlikely (!success)) return #ifndef HB_NO_VERTICAL - is_vertical ? vmtx->get_advance (gid) : + is_vertical ? vmtx->get_advance_without_var_unscaled (gid) : #endif - hmtx->get_advance (gid); + hmtx->get_advance_without_var_unscaled (gid); float result = is_vertical ? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y @@ -269,23 +281,20 @@ struct glyf_accelerator_t return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2); } - int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const + bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const { - if (unlikely (gid >= num_glyphs)) return 0; + if (unlikely (gid >= num_glyphs)) return false; hb_glyph_extents_t extents; contour_point_t phantoms[glyf_impl::PHANTOM_COUNT]; - if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms)))) - return -#ifndef HB_NO_VERTICAL - is_vertical ? vmtx->get_side_bearing (gid) : -#endif - hmtx->get_side_bearing (gid); + if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false)))) + return false; - return is_vertical - ? ceilf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing - : floorf (phantoms[glyf_impl::PHANTOM_LEFT].x); + *lsb = is_vertical + ? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing + : roundf (phantoms[glyf_impl::PHANTOM_LEFT].x); + return true; } #endif @@ -296,9 +305,9 @@ struct glyf_accelerator_t #ifndef HB_NO_VAR if (font->num_coords) - return get_points (font, gid, points_aggregator_t (font, extents, nullptr)); + return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true)); #endif - return glyph_for_gid (gid).get_extents (font, *this, extents); + return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents); } const glyf_impl::Glyph diff --git a/thirdparty/harfbuzz/src/graph/coverage-graph.hh b/thirdparty/harfbuzz/src/graph/coverage-graph.hh new file mode 100644 index 0000000000..1d9fd0eb5b --- /dev/null +++ b/thirdparty/harfbuzz/src/graph/coverage-graph.hh @@ -0,0 +1,80 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "graph.hh" +#include "../OT/Layout/Common/Coverage.hh" + +#ifndef GRAPH_COVERAGE_GRAPH_HH +#define GRAPH_COVERAGE_GRAPH_HH + +namespace graph { + +struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes> +{ + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size; + if (vertex_len < min_size) return false; + return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size (); + } +}; + +struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes> +{ + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size; + if (vertex_len < min_size) return false; + return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size (); + } +}; + +struct Coverage : public OT::Layout::Common::Coverage +{ + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + if (vertex_len < OT::Layout::Common::Coverage::min_size) return false; + switch (u.format) + { + case 1: return ((CoverageFormat1*)this)->sanitize (vertex); + case 2: return ((CoverageFormat2*)this)->sanitize (vertex); +#ifndef HB_NO_BORING_EXPANSION + // Not currently supported + case 3: + case 4: +#endif + default: return false; + } + } +}; + + +} + +#endif // GRAPH_COVERAGE_GRAPH_HH diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh index 52ca9dd142..b3aef558a2 100644 --- a/thirdparty/harfbuzz/src/graph/graph.hh +++ b/thirdparty/harfbuzz/src/graph/graph.hh @@ -24,6 +24,10 @@ * Google Author(s): Garret Rieger */ +#include "../hb-set.hh" +#include "../hb-priority-queue.hh" +#include "../hb-serialize.hh" + #ifndef GRAPH_GRAPH_HH #define GRAPH_GRAPH_HH @@ -76,6 +80,22 @@ struct graph_t } } + void remove_real_link (unsigned child_index, const void* offset) + { + for (unsigned i = 0; i < obj.real_links.length; i++) + { + auto& link = obj.real_links[i]; + if (link.objidx != child_index) + continue; + + if ((obj.head + link.position) != offset) + continue; + + obj.real_links.remove (i); + return; + } + } + void remap_parents (const hb_vector_t<unsigned>& id_map) { for (unsigned i = 0; i < parents.length; i++) @@ -107,6 +127,10 @@ struct graph_t return priority >= 3; } + size_t table_size () const { + return obj.tail - obj.head; + } + int64_t modified_distance (unsigned order) const { // TODO(garretrieger): once priority is high enough, should try @@ -199,13 +223,24 @@ struct graph_t return vertices_.length - 1; } - const hb_serialize_context_t::object_t& object(unsigned i) const + const hb_serialize_context_t::object_t& object (unsigned i) const { return vertices_[i].obj; } /* * Generates a new topological sorting of graph ordered by the shortest + * distance to each node if positions are marked as invalid. + */ + void sort_shortest_distance_if_needed () + { + if (!positions_invalid) return; + sort_shortest_distance (); + } + + + /* + * Generates a new topological sorting of graph ordered by the shortest * distance to each node. */ void sort_shortest_distance () @@ -256,37 +291,91 @@ struct graph_t check_success (!queue.in_error ()); check_success (!sorted_graph.in_error ()); - if (!check_success (new_id == -1)) - print_orphaned_nodes (); remap_all_obj_indices (id_map, &sorted_graph); - hb_swap (vertices_, sorted_graph); + + if (!check_success (new_id == -1)) + print_orphaned_nodes (); } /* - * Assign unique space numbers to each connected subgraph of 32 bit offset(s). + * Finds the set of nodes (placed into roots) that should be assigned unique spaces. + * More specifically this looks for the top most 24 bit or 32 bit links in the graph. + * Some special casing is done that is specific to the layout of GSUB/GPOS tables. */ - bool assign_32bit_spaces () + void find_space_roots (hb_set_t& visited, hb_set_t& roots) { - unsigned root_index = root_idx (); - hb_set_t visited; - hb_set_t roots; - for (unsigned i = 0; i <= root_index; i++) + int root_index = (int) root_idx (); + for (int i = root_index; i >= 0; i--) { + if (visited.has (i)) continue; + // Only real links can form 32 bit spaces for (auto& l : vertices_[i].obj.real_links) { - if (l.width == 4 && !l.is_signed) + if (l.is_signed || l.width < 3) + continue; + + if (i == root_index && l.width == 3) + // Ignore 24bit links from the root node, this skips past the single 24bit + // pointer to the lookup list. + continue; + + if (l.width == 3) { - roots.add (l.objidx); - find_subgraph (l.objidx, visited); + // A 24bit offset forms a root, unless there is 32bit offsets somewhere + // in it's subgraph, then those become the roots instead. This is to make sure + // that extension subtables beneath a 24bit lookup become the spaces instead + // of the offset to the lookup. + hb_set_t sub_roots; + find_32bit_roots (l.objidx, sub_roots); + if (sub_roots) { + for (unsigned sub_root_idx : sub_roots) { + roots.add (sub_root_idx); + find_subgraph (sub_root_idx, visited); + } + continue; + } } + + roots.add (l.objidx); + find_subgraph (l.objidx, visited); } } + } + + unsigned index_for_offset(unsigned node_idx, const void* offset) const + { + const auto& node = object (node_idx); + if (offset < node.head || offset >= node.tail) return -1; + + for (const auto& link : node.real_links) + { + if (offset != node.head + link.position) + continue; + return link.objidx; + } + + return -1; + } - // Mark everything not in the subgraphs of 32 bit roots as visited. - // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs. + + /* + * Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s). + * Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB + * (including with 24bit offsets) table. + */ + bool assign_spaces () + { + update_parents (); + + hb_set_t visited; + hb_set_t roots; + find_space_roots (visited, roots); + + // Mark everything not in the subgraphs of the roots as visited. This prevents + // subgraphs from being connected via nodes not in those subgraphs. visited.invert (); if (!roots) return false; @@ -422,6 +511,68 @@ struct graph_t find_subgraph (link.objidx, subgraph); } + size_t find_subgraph_size (unsigned node_idx, hb_set_t& subgraph, unsigned max_depth = -1) + { + if (subgraph.has (node_idx)) return 0; + subgraph.add (node_idx); + + const auto& o = vertices_[node_idx].obj; + size_t size = o.tail - o.head; + if (max_depth == 0) + return size; + + for (const auto& link : o.all_links ()) + size += find_subgraph_size (link.objidx, subgraph, max_depth - 1); + return size; + } + + /* + * Finds the topmost children of 32bit offsets in the subgraph starting + * at node_idx. Found indices are placed into 'found'. + */ + void find_32bit_roots (unsigned node_idx, hb_set_t& found) + { + for (const auto& link : vertices_[node_idx].obj.all_links ()) + { + if (!link.is_signed && link.width == 4) { + found.add (link.objidx); + continue; + } + find_32bit_roots (link.objidx, found); + } + } + + /* + * Moves the child of old_parent_idx pointed to by old_offset to a new + * vertex at the new_offset. + */ + template<typename O> + void move_child (unsigned old_parent_idx, + const O* old_offset, + unsigned new_parent_idx, + const O* new_offset) + { + distance_invalid = true; + positions_invalid = true; + + auto& old_v = vertices_[old_parent_idx]; + auto& new_v = vertices_[new_parent_idx]; + + unsigned child_id = index_for_offset (old_parent_idx, + old_offset); + + auto* new_link = new_v.obj.real_links.push (); + new_link->width = O::static_size; + new_link->objidx = child_id; + new_link->position = (const char*) new_offset - (const char*) new_v.obj.head; + + auto& child = vertices_[child_id]; + child.parents.push (new_parent_idx); + + old_v.remove_real_link (child_id, old_offset); + child.remove_parent (old_parent_idx); + } + /* * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign * links. index_map is updated with mappings from old id to new id. If a duplication has already @@ -529,6 +680,39 @@ struct graph_t return true; } + + /* + * Adds a new node to the graph, not connected to anything. + */ + unsigned new_node (char* head, char* tail) + { + positions_invalid = true; + distance_invalid = true; + + auto* clone = vertices_.push (); + if (vertices_.in_error ()) { + return -1; + } + + clone->obj.head = head; + clone->obj.tail = tail; + clone->distance = 0; + clone->space = 0; + + unsigned clone_idx = vertices_.length - 2; + + // The last object is the root of the graph, so swap back the root to the end. + // The root's obj idx does change, however since it's root nothing else refers to it. + // all other obj idx's will be unaffected. + hb_swap (vertices_[vertices_.length - 2], *clone); + + // Since the root moved, update the parents arrays of all children on the root. + for (const auto& l : root ().obj.all_links ()) + vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ()); + + return clone_idx; + } + /* * Raises the sorting priority of all children. */ @@ -622,7 +806,7 @@ struct graph_t private: /* - * Returns the numbers of incoming edges that are 32bits wide. + * Returns the numbers of incoming edges that are 24 or 32 bits wide. */ unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const { @@ -636,7 +820,9 @@ struct graph_t // Only real links can be wide for (const auto& l : vertices_[p].obj.real_links) { - if (l.objidx == node_idx && l.width == 4 && !l.is_signed) + if (l.objidx == node_idx + && (l.width == 3 || l.width == 4) + && !l.is_signed) { count++; parents.add (p); diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc new file mode 100644 index 0000000000..e0ff6ff85f --- /dev/null +++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc @@ -0,0 +1,71 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "gsubgpos-graph.hh" + +namespace graph { + +gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_, + graph_t& graph_) + : table_tag (table_tag_), + graph (graph_), + lookup_list_index (0), + lookups (), + buffers () +{ + if (table_tag_ != HB_OT_TAG_GPOS + && table_tag_ != HB_OT_TAG_GSUB) + return; + + GSTAR* gstar = graph::GSTAR::graph_to_gstar (graph_); + if (gstar) { + gstar->find_lookups (graph, lookups); + lookup_list_index = gstar->get_lookup_list_index (graph_); + } +} + +unsigned gsubgpos_graph_context_t::create_node (unsigned size) +{ + char* buffer = (char*) hb_calloc (1, size); + if (!buffer) + return -1; + + buffers.push (buffer); + + return graph.new_node (buffer, buffer + size); +} + +unsigned gsubgpos_graph_context_t::num_non_ext_subtables () { + unsigned count = 0; + for (auto l : lookups.values ()) + { + if (l->is_extension (table_tag)) continue; + count += l->number_of_subtables (); + } + return count; +} + +} diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh new file mode 100644 index 0000000000..49b24198ff --- /dev/null +++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh @@ -0,0 +1,67 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "graph.hh" +#include "../hb-ot-layout-gsubgpos.hh" + +#ifndef GRAPH_GSUBGPOS_CONTEXT_HH +#define GRAPH_GSUBGPOS_CONTEXT_HH + +namespace graph { + +struct Lookup; + +struct gsubgpos_graph_context_t +{ + hb_tag_t table_tag; + graph_t& graph; + unsigned lookup_list_index; + hb_hashmap_t<unsigned, graph::Lookup*> lookups; + hb_vector_t<char*> buffers; + + HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_, + graph_t& graph_); + + ~gsubgpos_graph_context_t () + { + for (char* b : buffers) + hb_free (b); + } + + HB_INTERNAL unsigned create_node (unsigned size); + + void add_buffer (char* buffer) + { + buffers.push (buffer); + } + + private: + HB_INTERNAL unsigned num_non_ext_subtables (); +}; + +} + +#endif // GRAPH_GSUBGPOS_CONTEXT diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh new file mode 100644 index 0000000000..afa1152c44 --- /dev/null +++ b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh @@ -0,0 +1,351 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "graph.hh" +#include "../hb-ot-layout-gsubgpos.hh" +#include "../OT/Layout/GSUB/ExtensionSubst.hh" +#include "gsubgpos-context.hh" +#include "pairpos-graph.hh" + +#ifndef GRAPH_GSUBGPOS_GRAPH_HH +#define GRAPH_GSUBGPOS_GRAPH_HH + +namespace graph { + +struct Lookup; + +template<typename T> +struct ExtensionFormat1 : public OT::ExtensionFormat1<T> +{ + void reset(unsigned type) + { + this->format = 1; + this->extensionLookupType = type; + this->extensionOffset = 0; + } + + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + return vertex_len >= OT::ExtensionFormat1<T>::static_size; + } + + unsigned get_lookup_type () const + { + return this->extensionLookupType; + } + + unsigned get_subtable_index (graph_t& graph, unsigned this_index) const + { + return graph.index_for_offset (this_index, &this->extensionOffset); + } +}; + +struct Lookup : public OT::Lookup +{ + unsigned number_of_subtables () const + { + return subTable.len; + } + + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + if (vertex_len < OT::Lookup::min_size) return false; + return vertex_len >= this->get_size (); + } + + bool is_extension (hb_tag_t table_tag) const + { + return lookupType == extension_type (table_tag); + } + + bool make_extension (gsubgpos_graph_context_t& c, + unsigned this_index) + { + unsigned type = lookupType; + unsigned ext_type = extension_type (c.table_tag); + if (!ext_type || is_extension (c.table_tag)) + { + // NOOP + return true; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Promoting lookup type %u (obj %u) to extension.", + type, + this_index); + + for (unsigned i = 0; i < subTable.len; i++) + { + unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]); + if (!make_subtable_extension (c, + this_index, + subtable_index)) + return false; + } + + lookupType = ext_type; + return true; + } + + bool split_subtables_if_needed (gsubgpos_graph_context_t& c, + unsigned this_index) + { + unsigned type = lookupType; + bool is_ext = is_extension (c.table_tag); + + if (c.table_tag != HB_OT_TAG_GPOS) + return true; + + if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair) + return true; + + hb_vector_t<unsigned> all_new_subtables; + for (unsigned i = 0; i < subTable.len; i++) + { + unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]); + if (is_ext) { + unsigned ext_subtable_index = subtable_index; + ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension = + (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) + c.graph.object (ext_subtable_index).head; + if (!extension->sanitize (c.graph.vertices_[ext_subtable_index])) + continue; + + subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index); + type = extension->get_lookup_type (); + if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair) + continue; + } + + PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head; + if (!pairPos->sanitize (c.graph.vertices_[subtable_index])) continue; + + hb_vector_t<unsigned> new_sub_tables = pairPos->split_subtables (c, subtable_index); + if (new_sub_tables.in_error ()) return false; + + new_sub_tables.iter() | hb_sink (all_new_subtables); + } + + if (all_new_subtables) + add_sub_tables (c, this_index, type, all_new_subtables); + + return true; + } + + void add_sub_tables (gsubgpos_graph_context_t& c, + unsigned this_index, + unsigned type, + hb_vector_t<unsigned>& subtable_indices) + { + bool is_ext = is_extension (c.table_tag); + auto& v = c.graph.vertices_[this_index]; + + size_t new_size = v.table_size () + + subtable_indices.length * OT::Offset16::static_size; + char* buffer = (char*) hb_calloc (1, new_size); + c.add_buffer (buffer); + memcpy (buffer, v.obj.head, v.table_size()); + + v.obj.head = buffer; + v.obj.tail = buffer + new_size; + + Lookup* new_lookup = (Lookup*) buffer; + + new_lookup->subTable.len = subTable.len + subtable_indices.length; + unsigned offset_index = subTable.len; + for (unsigned subtable_id : subtable_indices) + { + if (is_ext) + { + unsigned ext_id = create_extension_subtable (c, subtable_id, type); + c.graph.vertices_[subtable_id].parents.push (ext_id); + subtable_id = ext_id; + } + + auto* link = v.obj.real_links.push (); + link->width = 2; + link->objidx = subtable_id; + link->position = (char*) &new_lookup->subTable[offset_index++] - + (char*) new_lookup; + c.graph.vertices_[subtable_id].parents.push (this_index); + } + + // The head location of the lookup has changed, invalidating the lookups map entry + // in the context. Update the map. + c.lookups.set (this_index, new_lookup); + } + + unsigned create_extension_subtable (gsubgpos_graph_context_t& c, + unsigned subtable_index, + unsigned type) + { + unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size; + + unsigned ext_index = c.create_node (extension_size); + if (ext_index == (unsigned) -1) + return -1; + + auto& ext_vertex = c.graph.vertices_[ext_index]; + ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension = + (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head; + extension->reset (type); + + // Make extension point at the subtable. + auto* l = ext_vertex.obj.real_links.push (); + + l->width = 4; + l->objidx = subtable_index; + l->position = 4; + + return ext_index; + } + + bool make_subtable_extension (gsubgpos_graph_context_t& c, + unsigned lookup_index, + unsigned subtable_index) + { + unsigned type = lookupType; + + unsigned ext_index = create_extension_subtable(c, subtable_index, type); + if (ext_index == (unsigned) -1) + return false; + + auto& lookup_vertex = c.graph.vertices_[lookup_index]; + for (auto& l : lookup_vertex.obj.real_links.writer ()) + { + if (l.objidx == subtable_index) + // Change lookup to point at the extension. + l.objidx = ext_index; + } + + // Make extension point at the subtable. + auto& ext_vertex = c.graph.vertices_[ext_index]; + auto& subtable_vertex = c.graph.vertices_[subtable_index]; + ext_vertex.parents.push (lookup_index); + subtable_vertex.remap_parent (lookup_index, ext_index); + + return true; + } + + private: + unsigned extension_type (hb_tag_t table_tag) const + { + switch (table_tag) + { + case HB_OT_TAG_GPOS: return 9; + case HB_OT_TAG_GSUB: return 7; + default: return 0; + } + } +}; + +template <typename T> +struct LookupList : public OT::LookupList<T> +{ + bool sanitize (const graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + if (vertex_len < OT::LookupList<T>::min_size) return false; + return vertex_len >= OT::LookupList<T>::item_size * this->len; + } +}; + +struct GSTAR : public OT::GSUBGPOS +{ + static GSTAR* graph_to_gstar (graph_t& graph) + { + const auto& r = graph.root (); + + GSTAR* gstar = (GSTAR*) r.obj.head; + if (!gstar->sanitize (r)) + return nullptr; + + return gstar; + } + + const void* get_lookup_list_field_offset () const + { + switch (u.version.major) { + case 1: return u.version1.get_lookup_list_offset (); +#ifndef HB_NO_BORING_EXPANSION + case 2: return u.version2.get_lookup_list_offset (); +#endif + default: return 0; + } + } + + bool sanitize (const graph_t::vertex_t& vertex) + { + int64_t len = vertex.obj.tail - vertex.obj.head; + if (len < OT::GSUBGPOS::min_size) return false; + return len >= get_size (); + } + + void find_lookups (graph_t& graph, + hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */) + { + switch (u.version.major) { + case 1: find_lookups<SmallTypes> (graph, lookups); break; +#ifndef HB_NO_BORING_EXPANSION + case 2: find_lookups<MediumTypes> (graph, lookups); break; +#endif + } + } + + unsigned get_lookup_list_index (graph_t& graph) + { + return graph.index_for_offset (graph.root_idx (), + get_lookup_list_field_offset()); + } + + template<typename Types> + void find_lookups (graph_t& graph, + hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */) + { + unsigned lookup_list_idx = get_lookup_list_index (graph); + + const LookupList<Types>* lookupList = + (const LookupList<Types>*) graph.object (lookup_list_idx).head; + if (!lookupList->sanitize (graph.vertices_[lookup_list_idx])) + return; + + for (unsigned i = 0; i < lookupList->len; i++) + { + unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i])); + Lookup* lookup = (Lookup*) graph.object (lookup_idx).head; + if (!lookup->sanitize (graph.vertices_[lookup_idx])) continue; + lookups.set (lookup_idx, lookup); + } + } +}; + + + + +} + +#endif /* GRAPH_GSUBGPOS_GRAPH_HH */ diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh new file mode 100644 index 0000000000..3ca4fc701c --- /dev/null +++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh @@ -0,0 +1,299 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef GRAPH_PAIRPOS_GRAPH_HH +#define GRAPH_PAIRPOS_GRAPH_HH + +#include "coverage-graph.hh" +#include "../OT/Layout/GPOS/PairPos.hh" +#include "../OT/Layout/GPOS/PosLookupSubTable.hh" + +namespace graph { + +struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes> +{ + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size; + if (vertex_len < min_size) return false; + + return vertex_len >= + min_size + pairSet.get_size () - pairSet.len.get_size(); + } + + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + { + hb_set_t visited; + + const unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage); + const unsigned coverage_size = c.graph.vertices_[coverage_id].table_size (); + const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size + + coverage_size; + + unsigned accumulated = base_size; + hb_vector_t<unsigned> split_points; + for (unsigned i = 0; i < pairSet.len; i++) + { + unsigned pair_set_index = pair_set_graph_index (c, this_index, i); + accumulated += c.graph.find_subgraph_size (pair_set_index, visited); + accumulated += SmallTypes::size; // for PairSet offset. + + // TODO(garretrieger): don't count the size of the largest pairset against the limit, since + // it will be packed last in the order and does not contribute to + // the 64kb limit. + + if (accumulated > (1 << 16)) + { + split_points.push (i); + accumulated = base_size; + visited.clear (); // Pretend node sharing isn't allowed between splits. + } + } + + return do_split (c, this_index, split_points); + } + + private: + + // Split this PairPos into two or more PairPos's. split_points defines + // the indices (first index to include in the new table) to split at. + // Returns the object id's of the newly created PairPos subtables. + hb_vector_t<unsigned> do_split (gsubgpos_graph_context_t& c, + unsigned this_index, + const hb_vector_t<unsigned> split_points) + { + hb_vector_t<unsigned> new_objects; + if (!split_points) + return new_objects; + + for (unsigned i = 0; i < split_points.length; i++) + { + unsigned start = split_points[i]; + unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len; + unsigned id = clone_range (c, this_index, start, end); + + if (id == (unsigned) -1) + { + new_objects.reset (); + new_objects.allocated = -1; // mark error + return new_objects; + } + new_objects.push (id); + } + + if (!shrink (c, this_index, split_points[0])) + { + new_objects.reset (); + new_objects.allocated = -1; // mark error + } + + return new_objects; + } + + bool shrink (gsubgpos_graph_context_t& c, + unsigned this_index, + unsigned count) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + " Shrinking PairPosFormat1 (%u) to [0, %u).", + this_index, + count); + unsigned old_count = pairSet.len; + if (count >= old_count) + return true; + + pairSet.len = count; + c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size; + + unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage); + unsigned coverage_size = c.graph.vertices_[coverage_id].table_size (); + auto& coverage_v = c.graph.vertices_[coverage_id]; + Coverage* coverage_table = (Coverage*) coverage_v.obj.head; + if (!coverage_table->sanitize (coverage_v)) + return false; + + auto new_coverage = + + hb_zip (coverage_table->iter (), hb_range ()) + | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) { + return p.second < count; + }) + | hb_map_retains_sorting (hb_first) + ; + + return make_coverage (c, new_coverage, coverage_id, coverage_size); + } + + // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive). + // Returns object id of the new object. + unsigned clone_range (gsubgpos_graph_context_t& c, + unsigned this_index, + unsigned start, unsigned end) const + { + DEBUG_MSG (SUBSET_REPACK, nullptr, + " Cloning PairPosFormat1 (%u) range [%u, %u).", this_index, start, end); + + unsigned num_pair_sets = end - start; + unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size + + num_pair_sets * SmallTypes::size; + + unsigned pair_pos_prime_id = c.create_node (prime_size); + if (pair_pos_prime_id == (unsigned) -1) return -1; + + PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head; + pair_pos_prime->format = this->format; + pair_pos_prime->valueFormat[0] = this->valueFormat[0]; + pair_pos_prime->valueFormat[1] = this->valueFormat[1]; + pair_pos_prime->pairSet.len = num_pair_sets; + + for (unsigned i = start; i < end; i++) + { + c.graph.move_child<> (this_index, + &pairSet[i], + pair_pos_prime_id, + &pair_pos_prime->pairSet[i - start]); + } + + unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage); + unsigned coverage_size = c.graph.vertices_[coverage_id].table_size (); + auto& coverage_v = c.graph.vertices_[coverage_id]; + Coverage* coverage_table = (Coverage*) coverage_v.obj.head; + if (!coverage_table->sanitize (coverage_v)) + return false; + + auto new_coverage = + + hb_zip (coverage_table->iter (), hb_range ()) + | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) { + return p.second >= start && p.second < end; + }) + | hb_map_retains_sorting (hb_first) + ; + + unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr); + auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id]; + if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size)) + return -1; + + auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push (); + coverage_link->width = SmallTypes::size; + coverage_link->objidx = coverage_prime_id; + coverage_link->position = 2; + coverage_prime_vertex.parents.push (pair_pos_prime_id); + + return pair_pos_prime_id; + } + + template<typename It> + bool make_coverage (gsubgpos_graph_context_t& c, + It glyphs, + unsigned dest_obj, + unsigned max_size) const + { + char* buffer = (char*) hb_calloc (1, max_size); + hb_serialize_context_t serializer (buffer, max_size); + Coverage_serialize (&serializer, glyphs); + serializer.end_serialize (); + if (serializer.in_error ()) + { + hb_free (buffer); + return false; + } + + hb_bytes_t coverage_copy = serializer.copy_bytes (); + c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + + auto& obj = c.graph.vertices_[dest_obj].obj; + obj.head = (char *) coverage_copy.arrayZ; + obj.tail = obj.head + coverage_copy.length; + + hb_free (buffer); + return true; + } + + unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const + { + return c.graph.index_for_offset (this_index, &pairSet[i]); + } +}; + +struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes> +{ + bool sanitize (graph_t::vertex_t& vertex) const + { + // TODO(garretrieger): implement me! + return true; + } + + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + { + // TODO(garretrieger): implement me! + return hb_vector_t<unsigned> (); + } +}; + +struct PairPos : public OT::Layout::GPOS_impl::PairPos +{ + hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) + { + switch (u.format) { + case 1: + return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index); + case 2: + return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index); +#ifndef HB_NO_BORING_EXPANSION + case 3: HB_FALLTHROUGH; + case 4: HB_FALLTHROUGH; + // Don't split 24bit PairPos's. +#endif + default: + return hb_vector_t<unsigned> (); + } + } + + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + if (vertex_len < u.format.get_size ()) return false; + + switch (u.format) { + case 1: + return ((PairPosFormat1*)(&u.format1))->sanitize (vertex); + case 2: + return ((PairPosFormat2*)(&u.format2))->sanitize (vertex); +#ifndef HB_NO_BORING_EXPANSION + case 3: HB_FALLTHROUGH; + case 4: HB_FALLTHROUGH; +#endif + default: + // We don't handle format 3 and 4 here. + return false; + } + } +}; + +} + +#endif // GRAPH_PAIRPOS_GRAPH_HH diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh index b52844e75d..bf12d2e699 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh @@ -42,7 +42,7 @@ struct BaselineTableFormat0Part bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -78,7 +78,7 @@ struct BaselineTableFormat2Part bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index 1db0f1df92..6cbed82692 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -415,18 +415,7 @@ struct Lookup public: DEFINE_SIZE_UNION (2, format); }; -/* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined - * special NULL objects for Lookup<> objects, but since it's template our macros - * don't work. So we have to hand-code them here. UGLY. */ -} /* Close namespace. */ -/* Ugly hand-coded null objects for template Lookup<> :(. */ -extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2]; -template <typename T> -struct Null<AAT::Lookup<T>> { - static AAT::Lookup<T> const & get_null () - { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); } -}; -namespace AAT { +DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2); enum { DELETED_GLYPH = 0xFFFF }; @@ -681,6 +670,13 @@ struct ObsoleteTypes const void *base, const T *array) { + /* https://github.com/harfbuzz/harfbuzz/issues/3483 */ + /* If offset is less than base, return an offset that would + * result in an address half a 32bit address-space away, + * to make sure sanitize fails even on 32bit builds. */ + if (unlikely (offset < unsigned ((const char *) array - (const char *) base))) + return INT_MAX / T::static_size; + /* https://github.com/harfbuzz/harfbuzz/issues/2816 */ return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size; } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh index 573f0cf9f6..815a1fd2aa 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh @@ -62,7 +62,7 @@ struct SettingName bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index 0bf9bd2912..57c105967d 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -48,7 +48,7 @@ struct ActionSubrecordHeader bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } HBUINT16 actionClass; /* The JustClass value associated with this @@ -65,7 +65,7 @@ struct DecompositionAction bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } ActionSubrecordHeader @@ -112,7 +112,7 @@ struct ConditionalAddGlyphAction bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -137,7 +137,7 @@ struct DuctileGlyphAction bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -163,7 +163,7 @@ struct RepeatedAddGlyphAction bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -294,7 +294,7 @@ struct WidthDeltaPair bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh index 6a24c90c31..995492cd5a 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh @@ -751,7 +751,7 @@ struct KerxSubTableHeader bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } public: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index 3d053cb13e..aa4ad4cf3c 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -980,6 +980,15 @@ struct Chain setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS; goto retry; } +#ifndef HB_NO_AAT + else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting && + /* TODO: Rudimentary language matching. */ + hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language)) + { + flags &= feature.disableFlags; + flags |= feature.enableFlags; + } +#endif } } return flags; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh index b1a1512821..51b650fc33 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh @@ -42,7 +42,7 @@ struct OpticalBounds bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } FWORD leftSide; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc index caff204d67..e06d286ff0 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.cc +++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc @@ -229,7 +229,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, * * <note>Note: does not examine the `GSUB` table.</note> * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.3.0 */ @@ -300,7 +300,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) * * <note>Note: does not examine the `GPOS` table.</note> * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.3.0 */ @@ -333,7 +333,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, * Tests whether the specified face includes any tracking information * in the `trak` table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.3.0 */ diff --git a/thirdparty/harfbuzz/src/hb-aat-map.hh b/thirdparty/harfbuzz/src/hb-aat-map.hh index 5a0fa70544..c914f58d70 100644 --- a/thirdparty/harfbuzz/src/hb-aat-map.hh +++ b/thirdparty/harfbuzz/src/hb-aat-map.hh @@ -52,8 +52,9 @@ struct hb_aat_map_builder_t public: HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_, - const hb_segment_properties_t *props_ HB_UNUSED) : - face (face_) {} + const hb_segment_properties_t props_) : + face (face_), + props (props_) {} HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1); @@ -87,6 +88,7 @@ struct hb_aat_map_builder_t public: hb_face_t *face; + hb_segment_properties_t props; public: hb_sorted_vector_t<feature_info_t> features; diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index f1633d886a..cc37c073da 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -109,15 +109,16 @@ struct BEInt<Type, 2> struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; constexpr operator Type () const { -#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ +#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ + ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ defined(__BYTE_ORDER) && \ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN) /* Spoon-feed the compiler a big-endian integer with alignment 1. * https://github.com/harfbuzz/harfbuzz/pull/1398 */ #if __BYTE_ORDER == __LITTLE_ENDIAN - return __builtin_bswap16 (((packed_uint16_t *) this)->v); + return __builtin_bswap16 (((packed_uint16_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ - return ((packed_uint16_t *) this)->v; + return ((packed_uint16_t *) v)->v; #endif #else return (v[0] << 8) @@ -153,15 +154,16 @@ struct BEInt<Type, 4> struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; constexpr operator Type () const { -#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ +#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ + ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ defined(__BYTE_ORDER) && \ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN) /* Spoon-feed the compiler a big-endian integer with alignment 1. * https://github.com/harfbuzz/harfbuzz/pull/1398 */ #if __BYTE_ORDER == __LITTLE_ENDIAN - return __builtin_bswap32 (((packed_uint32_t *) this)->v); + return __builtin_bswap32 (((packed_uint32_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ - return ((packed_uint32_t *) this)->v; + return ((packed_uint32_t *) v)->v; #endif #else return (v[0] << 24) @@ -525,7 +527,6 @@ struct hb_pair_t T1 first; T2 second; }; -#define hb_pair_t(T1,T2) hb_pair_t<T1, T2> template <typename T1, typename T2> static inline hb_pair_t<T1, T2> hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); } @@ -551,14 +552,14 @@ struct { template <typename T, typename T2> constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a <= b ? std::forward<T> (a) : std::forward<T2> (b)) + (a <= b ? a : b) } HB_FUNCOBJ (hb_min); struct { template <typename T, typename T2> constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a >= b ? std::forward<T> (a) : std::forward<T2> (b)) + (a >= b ? a : b) } HB_FUNCOBJ (hb_max); struct @@ -972,7 +973,7 @@ void hb_qsort(void *base, size_t nel, size_t width, [void *arg]); */ -#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp)) +#define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp)) /* swap a and b */ /* a and b must not be equal! */ diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index 5baeb6f7fe..826a901819 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -100,10 +100,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> /* Ouch. The operator== compares the contents of the array. For range-based for loops, * it's best if we can just compare arrayZ, though comparing contents is still fast, * but also would require that Type has operator==. As such, we optimize this operator - * for range-based for loop and just compare arrayZ. No need to compare length, as we - * assume we're only compared to .end(). */ + * for range-based for loop and just compare arrayZ and length. */ bool operator != (const hb_array_t& o) const - { return arrayZ != o.arrayZ; } + { return this->arrayZ != o.arrayZ || this->length != o.length; } /* Extra operators. */ @@ -220,11 +219,8 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> if (end < start + 2) return; - for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) { - Type temp = arrayZ[rhs]; - arrayZ[rhs] = arrayZ[lhs]; - arrayZ[lhs] = temp; - } + for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) + hb_swap (arrayZ[rhs], arrayZ[lhs]); } hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const @@ -328,6 +324,8 @@ struct hb_sorted_array_t : { hb_array_t<Type> (*this) = o; return *this; } /* Iterator implementation. */ + + /* See comment in hb_array_of::operator != */ bool operator != (const hb_sorted_array_t& o) const { return this->arrayZ != o.arrayZ || this->length != o.length; } diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh index e640d1b586..d6dfb0f57a 100644 --- a/thirdparty/harfbuzz/src/hb-atomic.hh +++ b/thirdparty/harfbuzz/src/hb-atomic.hh @@ -111,6 +111,19 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) #endif +#ifndef _hb_compiler_memory_r_barrier +/* This we always use std::atomic for; and should never be disabled... + * except that MSVC gives me an internal compiler error on it. */ +#if !defined(_MSC_VER) +#include <atomic> +#define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire) +#else +#define _hb_compiler_memory_r_barrier() do {} while (0) +#endif +#endif + + + #ifndef _hb_memory_r_barrier #define _hb_memory_r_barrier() _hb_memory_barrier () #endif diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh index cbe918ee40..95ae1b7bf9 100644 --- a/thirdparty/harfbuzz/src/hb-bit-page.hh +++ b/thirdparty/harfbuzz/src/hb-bit-page.hh @@ -55,7 +55,7 @@ struct hb_bit_page_t void add (hb_codepoint_t g) { elt (g) |= mask (g); } void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } - void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); } + void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } void add_range (hb_codepoint_t a, hb_codepoint_t b) diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh index 438fb66a2c..4765af67ce 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set.hh @@ -465,12 +465,10 @@ struct hb_bit_set_t } public: - template <typename Op> - void process (const Op& op, const hb_bit_set_t &other) + void process_ (hb_bit_page_t::vector_t (*op) (const hb_bit_page_t::vector_t &, const hb_bit_page_t::vector_t &), + bool passthru_left, bool passthru_right, + const hb_bit_set_t &other) { - const bool passthru_left = op (1, 0); - const bool passthru_right = op (0, 1); - if (unlikely (!successful)) return; dirty (); @@ -590,6 +588,15 @@ struct hb_bit_set_t assert (!count); resize (newCount); } + template <typename Op> + static hb_bit_page_t::vector_t + op_ (const hb_bit_page_t::vector_t &a, const hb_bit_page_t::vector_t &b) + { return Op{} (a, b); } + template <typename Op> + void process (const Op& op, const hb_bit_set_t &other) + { + process_ (op_<Op>, op (1, 0), op (0, 1), other); + } void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); } void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); } diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index b561a9374e..9bc12ea3fa 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -99,7 +99,7 @@ hb_blob_create (const char *data, * is zero. This is in contrast to hb_blob_create(), which returns the singleton * empty blob (as returned by hb_blob_get_empty()) if @length is zero. * - * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy(). + * Return value: New blob, or `NULL` if failed. Destroy with hb_blob_destroy(). * * Since: 2.8.2 **/ @@ -263,8 +263,6 @@ hb_blob_destroy (hb_blob_t *blob) { if (!hb_object_destroy (blob)) return; - blob->fini_shallow (); - hb_free (blob); } @@ -278,7 +276,7 @@ hb_blob_destroy (hb_blob_t *blob) * * Attaches a user-data key/data pair to the specified blob. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -305,7 +303,7 @@ hb_blob_set_user_data (hb_blob_t *blob, * Since: 0.9.2 **/ void * -hb_blob_get_user_data (hb_blob_t *blob, +hb_blob_get_user_data (const hb_blob_t *blob, hb_user_data_key_t *key) { return hb_object_get_user_data (blob, key); @@ -335,7 +333,7 @@ hb_blob_make_immutable (hb_blob_t *blob) * * Tests whether a blob is immutable. * - * Return value: %true if @blob is immutable, %false otherwise + * Return value: `true` if @blob is immutable, `false` otherwise * * Since: 0.9.2 **/ @@ -394,7 +392,7 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length) * fails. * * Returns: (transfer none) (array length=length): Writable blob data, - * or %NULL if failed. + * or `NULL` if failed. * * Since: 0.9.2 **/ @@ -620,7 +618,7 @@ hb_blob_create_from_file (const char *file_name) * specified binary font file. * * Returns: An #hb_blob_t pointer with the content of the file, - * or %NULL if failed. + * or `NULL` if failed. * * Since: 2.8.2 **/ diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h index 203f9e19dd..4eb42314da 100644 --- a/thirdparty/harfbuzz/src/hb-blob.h +++ b/thirdparty/harfbuzz/src/hb-blob.h @@ -135,7 +135,7 @@ hb_blob_set_user_data (hb_blob_t *blob, HB_EXTERN void * -hb_blob_get_user_data (hb_blob_t *blob, +hb_blob_get_user_data (const hb_blob_t *blob, hb_user_data_key_t *key); diff --git a/thirdparty/harfbuzz/src/hb-blob.hh b/thirdparty/harfbuzz/src/hb-blob.hh index a3683a681e..b1b3b94d3d 100644 --- a/thirdparty/harfbuzz/src/hb-blob.hh +++ b/thirdparty/harfbuzz/src/hb-blob.hh @@ -38,7 +38,7 @@ struct hb_blob_t { - void fini_shallow () { destroy_user_data (); } + ~hb_blob_t () { destroy_user_data (); } void destroy_user_data () { @@ -61,12 +61,12 @@ struct hb_blob_t public: hb_object_header_t header; - const char *data; - unsigned int length; - hb_memory_mode_t mode; + const char *data = nullptr; + unsigned int length = 0; + hb_memory_mode_t mode = (hb_memory_mode_t) 0; - void *user_data; - hb_destroy_func_t destroy; + void *user_data = nullptr; + hb_destroy_func_t destroy = nullptr; }; diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh index e80cfea6e7..44c802a00c 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh @@ -32,15 +32,16 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-json.hh" +#line 33 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { 0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, - 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, - 34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, - 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, + 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u, + 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 93u, + 9u, 123u, 0u, 0u, 0 }; static const char _deserialize_json_key_spans[] = { @@ -48,9 +49,10 @@ static const char _deserialize_json_key_spans[] = { 10, 117, 117, 117, 1, 50, 49, 10, 117, 117, 1, 1, 50, 49, 117, 117, 2, 1, 50, 49, 10, 117, 117, 1, - 50, 49, 10, 117, 117, 1, 50, 49, - 59, 117, 59, 117, 117, 1, 50, 49, - 117, 85, 115, 0 + 50, 49, 10, 117, 117, 1, 1, 50, + 49, 117, 117, 1, 50, 49, 59, 117, + 59, 117, 117, 1, 50, 49, 117, 85, + 115, 0 }; static const short _deserialize_json_index_offsets[] = { @@ -58,9 +60,10 @@ static const short _deserialize_json_index_offsets[] = { 271, 282, 400, 518, 636, 638, 689, 739, 750, 868, 986, 988, 990, 1041, 1091, 1209, 1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680, - 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083, - 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660, - 2710, 2828, 2914, 3030 + 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2034, + 2085, 2135, 2253, 2371, 2373, 2424, 2474, 2534, + 2652, 2712, 2830, 2948, 2950, 3001, 3051, 3169, + 3255, 3371 }; static const char _deserialize_json_indicies[] = { @@ -82,28 +85,28 @@ static const char _deserialize_json_indicies[] = { 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, - 5, 1, 6, 7, 1, 1, 8, 1, + 5, 1, 6, 7, 1, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 9, 1, 10, 11, - 1, 12, 1, 12, 12, 12, 12, 12, + 1, 1, 1, 1, 10, 1, 11, 12, + 1, 13, 1, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 12, 1, 1, 1, 1, 1, + 1, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 13, 1, 13, 13, - 13, 13, 13, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 14, 1, 14, 14, + 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 13, 1, 1, + 1, 1, 1, 1, 1, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 14, 1, 1, 15, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 1, - 17, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 1, 19, 19, 19, 19, 19, + 1, 1, 15, 1, 1, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 1, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 20, 20, 20, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 19, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 20, 1, + 1, 1, 20, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -113,11 +116,11 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 21, - 1, 22, 22, 22, 22, 22, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 23, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 22, 1, 1, 1, 1, 1, 1, 1, + 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -128,41 +131,58 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 23, 1, 19, - 19, 19, 19, 19, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 24, 1, 20, + 20, 20, 20, 20, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 20, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 21, 1, 1, 1, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 22, 1, 25, 1, 25, + 25, 25, 25, 25, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 25, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 20, 1, 1, 1, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, + 26, 1, 26, 26, 26, 26, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 26, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 27, 1, + 1, 28, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 1, 30, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 1, 32, + 32, 32, 32, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 21, 1, 24, 1, 24, - 24, 24, 24, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 25, 1, 25, 25, 25, 25, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 34, 1, 32, 32, 32, + 32, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 25, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 26, 1, - 1, 27, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 1, 29, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 1, 31, - 31, 31, 31, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 31, 1, + 33, 1, 1, 1, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -170,41 +190,41 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 34, 1, 35, 1, 36, 1, 36, + 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 33, 1, 31, 31, 31, - 31, 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 32, 1, 1, 1, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 1, 1, + 37, 1, 37, 37, 37, 37, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 38, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 1, 40, 40, 40, 40, + 40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 33, 1, 34, 1, 35, 1, 35, - 35, 35, 35, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 36, 1, 36, 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 36, 1, 1, 1, 1, 1, 1, + 42, 1, 40, 40, 40, 40, 40, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 37, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 1, 39, 39, 39, 39, - 39, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 39, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 40, + 1, 40, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 41, 1, 1, + 1, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -212,137 +232,130 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 42, 1, + 44, 45, 1, 46, 1, 46, 46, 46, + 46, 46, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 46, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 41, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 1, 1, 1, 47, 1, + 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 39, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 40, 1, 1, - 1, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 48, 1, 1, 49, + 50, 50, 50, 50, 50, 50, 50, 50, + 50, 1, 51, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 1, 53, 53, 53, + 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 41, 1, - 43, 44, 1, 45, 1, 45, 45, 45, - 45, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 46, 1, - 46, 46, 46, 46, 46, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 46, + 1, 55, 1, 53, 53, 53, 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 47, 1, 1, 48, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 1, 50, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 1, 52, 52, 52, - 52, 52, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 53, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 54, 1, + 1, 1, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 55, + 1, 56, 1, 56, 56, 56, 56, 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 54, 1, 52, 52, 52, 52, 52, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 57, 1, 57, 57, + 57, 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 52, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 53, 1, - 1, 1, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 58, 1, 1, 59, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 1, + 61, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 1, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 63, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 54, - 1, 55, 1, 55, 55, 55, 55, 55, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 55, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 56, 1, 56, 56, - 56, 56, 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 56, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 65, + 1, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 57, 1, 1, 58, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 1, - 60, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 1, 62, 62, 62, 62, 62, 1, 1, 1, 1, 1, 1, 1, 1, + 63, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 64, 1, 1, 1, + 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 62, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 65, 1, 66, + 1, 67, 1, 67, 67, 67, 67, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 64, - 1, 62, 62, 62, 62, 62, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 68, 1, 68, 68, + 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 62, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 63, 1, 1, 1, - 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 69, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 1, + 71, 71, 71, 71, 71, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 71, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 64, 1, 65, - 1, 65, 65, 65, 65, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 66, 1, 66, 66, 66, 66, - 66, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 66, 1, 67, 1, 1, + 1, 1, 1, 1, 73, 1, 71, 71, + 71, 71, 71, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 68, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 1, 71, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 72, 70, 73, 73, 73, 73, 73, 1, + 1, 1, 1, 1, 1, 71, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 72, 1, 1, 1, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 73, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -350,21 +363,33 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 73, 1, 75, 1, 75, 75, + 75, 75, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 75, 1, - 70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 76, + 1, 76, 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 76, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 78, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 1, 81, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 82, 80, 83, + 83, 83, 83, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 70, 1, 76, 76, 76, 76, - 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 76, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -373,67 +398,85 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 85, 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 78, 1, 76, 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 76, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 77, 1, 1, - 1, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 80, + 1, 86, 86, 86, 86, 86, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 86, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 87, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 78, 1, - 80, 1, 80, 80, 80, 80, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 88, 1, 86, + 86, 86, 86, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 81, 1, 81, 81, 81, - 81, 81, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 81, 1, 1, 1, + 1, 1, 87, 1, 1, 1, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 82, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 1, 76, - 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 77, 1, 1, 1, 84, 84, - 84, 84, 84, 84, 84, 84, 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 88, 1, 90, 1, 90, + 90, 90, 90, 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 78, 1, 85, 85, 85, - 85, 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 85, 1, 1, 1, + 91, 1, 91, 91, 91, 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 91, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 92, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 1, 86, 86, 86, 86, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 86, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 87, + 1, 1, 1, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 88, 1, 95, 95, 95, 95, 95, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 95, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 87, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 97, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -442,46 +485,52 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, - 0 + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 0 }; static const char _deserialize_json_trans_targs[] = { 1, 0, 2, 2, 3, 4, 18, 24, - 37, 45, 5, 12, 6, 7, 8, 9, - 11, 9, 11, 10, 2, 49, 10, 49, - 13, 14, 15, 16, 17, 16, 17, 10, - 2, 49, 19, 20, 21, 22, 23, 10, - 2, 49, 23, 25, 31, 26, 27, 28, - 29, 30, 29, 30, 10, 2, 49, 32, - 33, 34, 35, 36, 35, 36, 10, 2, - 49, 38, 39, 40, 43, 44, 40, 41, - 42, 10, 2, 49, 10, 2, 49, 44, - 46, 47, 43, 48, 48, 49, 50, 51 + 37, 43, 51, 5, 12, 6, 7, 8, + 9, 11, 9, 11, 10, 2, 55, 10, + 55, 13, 14, 15, 16, 17, 16, 17, + 10, 2, 55, 19, 20, 21, 22, 23, + 10, 2, 55, 23, 25, 31, 26, 27, + 28, 29, 30, 29, 30, 10, 2, 55, + 32, 33, 34, 35, 36, 35, 36, 10, + 2, 55, 38, 39, 40, 41, 42, 10, + 2, 55, 42, 44, 45, 46, 49, 50, + 46, 47, 48, 10, 2, 55, 10, 2, + 55, 50, 52, 53, 49, 54, 54, 55, + 56, 57 }; static const char _deserialize_json_trans_actions[] = { 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2, 2, - 2, 0, 0, 3, 3, 4, 0, 5, - 0, 0, 2, 2, 2, 0, 0, 6, - 6, 7, 0, 0, 0, 2, 2, 8, - 8, 9, 0, 0, 0, 0, 0, 2, - 2, 2, 0, 0, 10, 10, 11, 0, - 0, 2, 2, 2, 0, 0, 12, 12, - 13, 0, 0, 2, 14, 14, 0, 15, - 0, 16, 16, 17, 18, 18, 19, 15, - 0, 0, 20, 20, 21, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 0, 0, 3, 3, 4, 0, + 5, 0, 0, 2, 2, 2, 0, 0, + 6, 6, 7, 0, 0, 0, 2, 2, + 8, 8, 9, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 0, 10, 10, 11, + 0, 0, 2, 2, 2, 0, 0, 12, + 12, 13, 0, 0, 0, 2, 2, 14, + 14, 15, 0, 0, 0, 2, 16, 16, + 0, 17, 0, 18, 18, 19, 20, 20, + 21, 17, 0, 0, 22, 22, 23, 0, + 0, 0 }; static const int deserialize_json_start = 1; -static const int deserialize_json_first_final = 49; +static const int deserialize_json_first_final = 55; static const int deserialize_json_error = 0; static const int deserialize_json_en_main = 1; -#line 108 "hb-buffer-deserialize-json.rl" +#line 111 "hb-buffer-deserialize-json.rl" static hb_bool_t @@ -508,12 +557,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 512 "hb-buffer-deserialize-json.hh" +#line 554 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 517 "hb-buffer-deserialize-json.hh" +#line 557 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -561,25 +610,25 @@ _resume: tok = p; } break; - case 15: + case 17: #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 21: + case 23: #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 16: + case 18: #line 58 "hb-buffer-deserialize-json.rl" { /* TODO Unescape \" and \\ if found. */ if (!hb_font_glyph_from_string (font, - tok, p - tok, + tok+1, p - tok - 2, /* Skip "" */ &info.codepoint)) return false; } break; - case 18: + case 20: #line 66 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } break; @@ -604,6 +653,10 @@ _resume: { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; case 14: +#line 72 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } + break; + case 16: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -611,7 +664,7 @@ _resume: #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 20: + case 22: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -619,12 +672,12 @@ _resume: #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 17: + case 19: #line 58 "hb-buffer-deserialize-json.rl" { /* TODO Unescape \" and \\ if found. */ if (!hb_font_glyph_from_string (font, - tok, p - tok, + tok+1, p - tok - 2, /* Skip "" */ &info.codepoint)) return false; } @@ -637,7 +690,7 @@ _resume: *end_ptr = p; } break; - case 19: + case 21: #line 66 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } #line 43 "hb-buffer-deserialize-json.rl" @@ -709,7 +762,19 @@ _resume: *end_ptr = p; } break; -#line 713 "hb-buffer-deserialize-json.hh" + case 15: +#line 72 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 735 "hb-buffer-deserialize-json.hh" } _again: @@ -721,7 +786,7 @@ _again: _out: {} } -#line 136 "hb-buffer-deserialize-json.rl" +#line 139 "hb-buffer-deserialize-json.rl" *end_ptr = p; diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh index 06a605e225..8fbcdcc18c 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh @@ -32,29 +32,32 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-text.hh" +#line 33 "hb-buffer-deserialize-text.hh" static const unsigned char _deserialize_text_trans_keys[] = { 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, - 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, - 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, + 48u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, + 44u, 57u, 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0 + 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 0 }; static const char _deserialize_text_key_spans[] = { 0, 83, 1, 1, 55, 77, 10, 13, - 10, 10, 13, 10, 1, 13, 10, 14, - 82, 13, 10, 116, 116, 0, 77, 116, + 10, 10, 10, 13, 10, 1, 13, 10, + 14, 82, 13, 10, 116, 116, 0, 77, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, - 116, 116, 116, 116, 116 + 116, 116, 116 }; static const short _deserialize_text_index_offsets[] = { 0, 0, 84, 86, 88, 144, 222, 233, - 247, 258, 269, 283, 294, 296, 310, 321, - 336, 419, 433, 444, 561, 678, 679, 757, - 874, 991, 1108, 1225, 1342, 1459, 1576, 1693, - 1810, 1927, 2044, 2161, 2278 + 247, 258, 269, 280, 294, 305, 307, 321, + 332, 347, 430, 444, 455, 572, 689, 690, + 768, 885, 1002, 1119, 1236, 1353, 1470, 1587, + 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523, + 2640, 2757, 2874 }; static const char _deserialize_text_indicies[] = { @@ -91,50 +94,52 @@ static const char _deserialize_text_indicies[] = { 12, 12, 12, 12, 12, 12, 12, 1, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 1, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 1, 17, 1, - 1, 18, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 1, 20, 21, 21, 21, + 16, 16, 16, 16, 16, 1, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 1, 19, 1, 1, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 22, - 1, 23, 1, 1, 24, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 1, 26, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 1, 24, 1, 25, 1, 1, 26, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 1, 22, 1, 1, 1, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 1, 28, 28, 1, 1, 1, 1, 1, + 27, 1, 28, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 1, 24, 1, 1, + 1, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 1, 30, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 28, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 30, 1, + 1, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 30, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 28, 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 30, 1, 31, + 1, 1, 32, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 1, 34, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 1, + 36, 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 28, 1, 29, 1, 1, 30, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 1, 32, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 1, 34, 34, 34, - 34, 34, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 36, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 34, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 37, + 37, 37, 37, 37, 37, 37, 37, 37, + 37, 1, 1, 1, 38, 39, 1, 1, + 37, 37, 37, 37, 37, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 1, 1, - 1, 36, 37, 1, 1, 35, 35, 35, - 35, 35, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 35, 35, 35, - 35, 35, 35, 1, 1, 1, 1, 1, + 37, 37, 37, 37, 37, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 38, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 40, 1, 41, 41, 41, + 41, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 39, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -142,24 +147,23 @@ static const char _deserialize_text_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 41, 1, 1, - 7, 7, 7, 7, 7, 1, 1, 1, + 43, 1, 1, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 4, 1, 42, 42, - 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, + 1, 44, 44, 44, 44, 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 43, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -167,68 +171,83 @@ static const char _deserialize_text_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 44, 1, 42, 42, 42, 42, 42, + 1, 1, 1, 1, 46, 1, 44, 44, + 44, 44, 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 1, + 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 1, 1, 1, 1, - 43, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 44, 1, - 47, 47, 47, 47, 47, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 47, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 48, 1, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 49, 46, 46, 50, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 51, 52, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 53, 46, 54, 54, 54, - 54, 54, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 54, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 55, - 1, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 56, 28, 28, 57, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 58, 59, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 60, 28, 61, 61, 61, 61, 61, 1, + 1, 46, 1, 49, 49, 49, 49, 49, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 49, 48, 48, 50, 48, 48, + 48, 48, 48, 48, 48, 51, 1, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 52, + 48, 48, 53, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 54, 55, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 56, 48, + 57, 57, 57, 57, 57, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 57, + 30, 30, 58, 30, 30, 30, 30, 30, + 30, 30, 59, 1, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 60, 30, 30, 61, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 62, 63, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 64, 30, 57, 57, 57, + 57, 57, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 57, 30, 30, 58, + 30, 30, 30, 30, 30, 30, 30, 59, + 1, 30, 30, 30, 65, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 30, 30, + 30, 60, 30, 30, 61, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 62, 63, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 64, 30, 67, 67, 67, 67, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 61, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 62, 1, 1, + 1, 67, 1, 1, 68, 1, 1, 1, + 1, 1, 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 63, 1, + 1, 1, 1, 1, 1, 1, 70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 64, 1, 65, - 65, 65, 65, 65, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 71, 1, 72, + 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 65, 1, + 1, 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -236,172 +255,238 @@ static const char _deserialize_text_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 66, 1, 67, 67, 67, 67, - 67, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 67, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 48, 1, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 49, 46, 46, 50, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 51, - 52, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 53, - 46, 68, 68, 68, 68, 68, 1, 1, + 1, 1, 73, 1, 74, 74, 74, 74, + 74, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 74, 48, 48, 50, 48, + 48, 48, 48, 48, 48, 48, 51, 1, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 52, 48, 48, 53, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 54, + 55, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 56, + 48, 75, 75, 75, 75, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 68, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 69, 1, 1, 1, 1, + 75, 1, 1, 76, 1, 1, 1, 1, + 1, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 70, 1, 1, 1, 1, 1, 1, 1, + 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 71, 1, 72, 72, - 72, 72, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 79, 1, 80, 80, + 80, 80, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 72, 1, 1, + 1, 1, 1, 1, 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 75, 1, 72, 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 82, 1, 80, 80, 80, 80, 80, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 72, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 73, 1, 1, - 1, 1, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 75, 1, - 68, 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 68, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 69, 1, 1, 1, 1, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 1, 1, 1, 1, 1, 1, 70, + 1, 1, 1, 1, 1, 1, 82, 1, + 84, 84, 84, 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 84, + 1, 1, 85, 1, 1, 1, 1, 1, + 1, 1, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 43, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 71, 1, 77, 77, 77, - 77, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 87, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 88, 1, 84, 84, 84, + 84, 84, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 84, 1, 1, 85, + 1, 1, 1, 1, 1, 1, 1, 86, + 1, 1, 1, 1, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 88, 1, 75, 75, 75, 75, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 75, 1, 1, 76, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 1, 1, 1, 1, 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 79, 1, 77, 77, 77, 77, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 79, 1, 90, + 90, 90, 90, 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 90, 1, + 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 79, 1, 61, - 61, 61, 61, 61, 1, 1, 1, 1, + 1, 1, 1, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 61, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 62, 1, 1, 1, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 93, 1, 90, 90, 90, 90, + 90, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 90, 1, 1, 91, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 63, 1, 1, 1, 1, + 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 93, + 1, 67, 67, 67, 67, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 64, 1, 0 + 1, 1, 1, 1, 1, 1, 1, 1, + 67, 1, 1, 68, 1, 1, 1, 1, + 1, 1, 1, 1, 69, 1, 1, 1, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 70, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 71, 1, 94, 94, + 94, 94, 94, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 94, 30, 30, + 58, 30, 30, 30, 30, 30, 30, 30, + 59, 1, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 60, 30, 30, 61, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 62, 95, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 96, 30, 94, 94, 94, 94, 94, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 94, 30, 30, 58, 30, 30, + 30, 30, 30, 30, 30, 59, 1, 30, + 30, 30, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 30, 30, 30, 60, + 30, 30, 61, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 62, 95, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 96, 30, + 0 }; static const char _deserialize_text_trans_targs[] = { - 1, 0, 2, 25, 3, 4, 19, 5, - 23, 24, 8, 27, 36, 27, 36, 30, - 33, 11, 12, 15, 12, 15, 13, 14, - 31, 32, 31, 32, 26, 18, 34, 35, - 34, 35, 20, 19, 6, 21, 22, 20, - 21, 22, 20, 21, 22, 24, 26, 26, - 7, 9, 10, 16, 21, 29, 26, 7, - 9, 10, 16, 21, 29, 28, 17, 21, - 29, 28, 29, 29, 28, 7, 10, 29, - 28, 7, 21, 29, 33, 28, 21, 29 + 1, 0, 2, 26, 3, 4, 20, 5, + 24, 25, 8, 29, 40, 29, 40, 32, + 37, 33, 34, 12, 13, 16, 13, 16, + 14, 15, 35, 36, 35, 36, 27, 19, + 38, 39, 38, 39, 21, 20, 6, 22, + 23, 21, 22, 23, 21, 22, 23, 25, + 27, 27, 28, 7, 9, 11, 17, 22, + 31, 27, 28, 7, 9, 11, 17, 22, + 31, 41, 42, 30, 10, 18, 22, 31, + 30, 31, 31, 30, 10, 7, 11, 31, + 30, 22, 31, 34, 30, 10, 7, 22, + 31, 37, 30, 10, 22, 31, 27, 22, + 31, 42 }; static const char _deserialize_text_trans_actions[] = { 0, 0, 0, 0, 1, 0, 2, 0, 2, 2, 3, 4, 4, 5, 5, 4, - 4, 3, 3, 3, 0, 0, 6, 3, - 4, 4, 5, 5, 5, 3, 4, 4, - 5, 5, 7, 8, 9, 7, 7, 0, - 0, 0, 10, 10, 10, 8, 12, 13, - 14, 14, 14, 15, 11, 11, 17, 18, - 18, 18, 0, 16, 16, 19, 20, 19, - 19, 0, 0, 13, 10, 21, 21, 10, - 22, 23, 22, 22, 5, 24, 24, 24 + 4, 4, 4, 3, 3, 3, 0, 0, + 6, 3, 4, 4, 5, 5, 5, 3, + 4, 4, 5, 5, 7, 8, 9, 7, + 7, 0, 0, 0, 10, 10, 10, 8, + 12, 13, 14, 15, 15, 15, 16, 11, + 11, 18, 19, 20, 20, 20, 0, 17, + 17, 4, 4, 21, 22, 22, 21, 21, + 0, 0, 13, 10, 23, 23, 23, 10, + 24, 24, 24, 5, 25, 26, 26, 25, + 25, 5, 27, 28, 27, 27, 30, 29, + 29, 5 }; static const char _deserialize_text_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 7, 0, 0, 0, 10, - 10, 11, 16, 19, 0, 11, 10, 22, - 22, 10, 24, 24, 19 + 0, 0, 0, 0, 7, 0, 0, 0, + 10, 10, 11, 17, 17, 21, 0, 11, + 10, 24, 24, 25, 25, 10, 27, 27, + 21, 29, 29 }; static const int deserialize_text_start = 1; -static const int deserialize_text_first_final = 19; +static const int deserialize_text_first_final = 20; static const int deserialize_text_error = 0; static const int deserialize_text_en_main = 1; -#line 114 "hb-buffer-deserialize-text.rl" +#line 117 "hb-buffer-deserialize-text.rl" static hb_bool_t @@ -424,12 +509,12 @@ _hb_buffer_deserialize_text (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 428 "hb-buffer-deserialize-text.hh" +#line 506 "hb-buffer-deserialize-text.hh" { cs = deserialize_text_start; } -#line 433 "hb-buffer-deserialize-text.hh" +#line 509 "hb-buffer-deserialize-text.hh" { int _slen; int _trans; @@ -475,7 +560,7 @@ _resume: #line 56 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 18: + case 20: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -489,7 +574,7 @@ _resume: #line 66 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } break; - case 21: + case 23: #line 68 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; @@ -497,15 +582,19 @@ _resume: #line 69 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 23: + case 26: #line 70 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 20: + case 22: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 15: + case 28: +#line 72 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 16: #line 38 "hb-buffer-deserialize-text.rl" { memset (&info, 0, sizeof (info)); @@ -532,7 +621,7 @@ _resume: #line 56 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 16: + case 17: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -550,6 +639,18 @@ _resume: *end_ptr = p; } break; + case 19: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; case 7: #line 66 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } @@ -574,7 +675,7 @@ _resume: *end_ptr = p; } break; - case 22: + case 25: #line 70 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -586,7 +687,7 @@ _resume: *end_ptr = p; } break; - case 19: + case 21: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -598,7 +699,7 @@ _resume: *end_ptr = p; } break; - case 24: + case 27: #line 72 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -610,6 +711,18 @@ _resume: *end_ptr = p; } break; + case 24: +#line 73 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; case 12: #line 38 "hb-buffer-deserialize-text.rl" { @@ -623,7 +736,7 @@ _resume: #line 55 "hb-buffer-deserialize-text.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 14: + case 15: #line 38 "hb-buffer-deserialize-text.rl" { memset (&info, 0, sizeof (info)); @@ -642,7 +755,7 @@ _resume: return false; } break; - case 17: + case 18: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -662,6 +775,26 @@ _resume: *end_ptr = p; } break; + case 29: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 73 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; case 11: #line 38 "hb-buffer-deserialize-text.rl" { @@ -689,6 +822,49 @@ _resume: *end_ptr = p; } break; + case 14: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 30: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 73 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; case 13: #line 38 "hb-buffer-deserialize-text.rl" { @@ -718,7 +894,7 @@ _resume: *end_ptr = p; } break; -#line 722 "hb-buffer-deserialize-text.hh" +#line 826 "hb-buffer-deserialize-text.hh" } _again: @@ -730,7 +906,7 @@ _again: if ( p == eof ) { switch ( _deserialize_text_eof_actions[cs] ) { - case 16: + case 17: #line 58 "hb-buffer-deserialize-text.rl" { /* TODO Unescape delimiters. */ @@ -772,7 +948,7 @@ _again: *end_ptr = p; } break; - case 22: + case 25: #line 70 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -784,7 +960,7 @@ _again: *end_ptr = p; } break; - case 19: + case 21: #line 71 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -796,7 +972,7 @@ _again: *end_ptr = p; } break; - case 24: + case 27: #line 72 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" @@ -808,6 +984,38 @@ _again: *end_ptr = p; } break; + case 24: +#line 73 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 29: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 73 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; case 11: #line 38 "hb-buffer-deserialize-text.rl" { @@ -835,14 +1043,14 @@ _again: *end_ptr = p; } break; -#line 839 "hb-buffer-deserialize-text.hh" +#line 953 "hb-buffer-deserialize-text.hh" } } _out: {} } -#line 138 "hb-buffer-deserialize-text.rl" +#line 141 "hb-buffer-deserialize-text.rl" *end_ptr = p; diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc index 3f619a113e..d1e1775430 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc @@ -56,7 +56,7 @@ hb_buffer_serialize_list_formats () /** * hb_buffer_serialize_format_from_string: * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is %NULL terminated + * @len: length of @str, or -1 if string is `NULL` terminated * * Parses a string into an #hb_buffer_serialize_format_t. Does not check if * @str is a valid buffer serialization format, use @@ -78,11 +78,11 @@ hb_buffer_serialize_format_from_string (const char *str, int len) * hb_buffer_serialize_format_to_string: * @format: an #hb_buffer_serialize_format_t to convert. * - * Converts @format to the string corresponding it, or %NULL if it is not a valid + * Converts @format to the string corresponding it, or `NULL` if it is not a valid * #hb_buffer_serialize_format_t. * * Return value: (transfer none): - * A %NULL terminated string corresponding to @format. Should not be freed. + * A `NULL` terminated string corresponding to @format. Should not be freed. * * Since: 0.9.7 **/ @@ -400,9 +400,9 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. + * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. * @font: (nullable): the #hb_font_t used to shape this buffer, needed to - * read glyph names and extents. If %NULL, an empty font will be used. + * read glyph names and extents. If `NULL`, an empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. @@ -514,7 +514,7 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. + * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. @@ -637,9 +637,9 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. + * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. * @font: (nullable): the #hb_font_t used to shape this buffer, needed to - * read glyph names and extents. If %NULL, an empty font will be used. + * read glyph names and extents. If `NULL`, an empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. @@ -727,7 +727,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv) * hb_buffer_deserialize_glyphs: * @buffer: an #hb_buffer_t buffer. * @buf: (array length=buf_len): string to deserialize - * @buf_len: the size of @buf, or -1 if it is %NULL-terminated + * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated * @end_ptr: (out) (optional): output pointer to the character after last * consumed one. * @font: (nullable): font for getting glyph IDs @@ -736,7 +736,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv) * Deserializes glyphs @buffer from textual representation in the format * produced by hb_buffer_serialize_glyphs(). * - * Return value: %true if @buf is not fully consumed, %false otherwise. + * Return value: `true` if @buf is not fully consumed, `false` otherwise. * * Since: 0.9.7 **/ @@ -800,7 +800,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, * hb_buffer_deserialize_unicode: * @buffer: an #hb_buffer_t buffer. * @buf: (array length=buf_len): string to deserialize - * @buf_len: the size of @buf, or -1 if it is %NULL-terminated + * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated * @end_ptr: (out) (optional): output pointer to the character after last * consumed one. * @format: the #hb_buffer_serialize_format_t of the input @buf @@ -808,7 +808,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, * Deserializes Unicode @buffer from textual representation in the format * produced by hb_buffer_serialize_unicode(). * - * Return value: %true if @buf is not fully consumed, %false otherwise. + * Return value: `true` if @buf is not fully consumed, `false` otherwise. * * Since: 2.7.3 **/ diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index 2272ecf09b..57a5ae03ed 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -51,7 +51,7 @@ * Checks the equality of two #hb_segment_properties_t's. * * Return value: - * %true if all properties of @a equal those of @b, %false otherwise. + * `true` if all properties of @a equal those of @b, `false` otherwise. * * Since: 0.9.7 **/ @@ -387,9 +387,11 @@ hb_buffer_t::clear_positions () hb_memset (pos, 0, sizeof (pos[0]) * len); } -void +bool hb_buffer_t::sync () { + bool ret = false; + assert (have_output); assert (idx <= len); @@ -403,12 +405,39 @@ hb_buffer_t::sync () info = out_info; } len = out_len; + ret = true; reset: have_output = false; out_len = 0; out_info = info; idx = 0; + + return ret; +} + +int +hb_buffer_t::sync_so_far () +{ + bool had_output = have_output; + unsigned out_i = out_len; + unsigned i = idx; + unsigned old_idx = idx; + + if (sync ()) + idx = out_i; + else + idx = i; + + if (had_output) + { + have_output = true; + out_len = idx; + } + + assert (idx <= len); + + return idx - old_idx; } bool @@ -643,9 +672,9 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = * Return value: (transfer full): * A newly allocated #hb_buffer_t with a reference count of 1. The initial * reference count should be released with hb_buffer_destroy() when you are done - * using the #hb_buffer_t. This function never returns %NULL. If memory cannot + * using the #hb_buffer_t. This function never returns `NULL`. If memory cannot * be allocated, a special #hb_buffer_t object will be returned on which - * hb_buffer_allocation_successful() returns %false. + * hb_buffer_allocation_successful() returns `false`. * * Since: 0.9.2 **/ @@ -775,7 +804,7 @@ hb_buffer_destroy (hb_buffer_t *buffer) * * Attaches a user-data key/data pair to the specified buffer. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -802,7 +831,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, * Since: 0.9.2 **/ void * -hb_buffer_get_user_data (hb_buffer_t *buffer, +hb_buffer_get_user_data (const hb_buffer_t *buffer, hb_user_data_key_t *key) { return hb_object_get_user_data (buffer, key); @@ -1278,7 +1307,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer) * Pre allocates memory for @buffer to fit at least @size number of items. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise + * `true` if @buffer memory allocation succeeded, `false` otherwise * * Since: 0.9.2 **/ @@ -1295,7 +1324,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) * Check if allocating memory for the buffer succeeded. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise. + * `true` if @buffer memory allocation succeeded, `false` otherwise. * * Since: 0.9.2 **/ @@ -1340,7 +1369,7 @@ hb_buffer_add (hb_buffer_t *buffer, * end. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise. + * `true` if @buffer memory allocation succeeded, `false` otherwise. * * Since: 0.9.2 **/ @@ -1426,7 +1455,7 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, * If buffer did not have positions before, the positions will be * initialized to zeros, unless this function is called from * within a buffer message callback (see hb_buffer_set_message_func()), - * in which case %NULL is returned. + * in which case `NULL` is returned. * * Return value: (transfer none) (array length=length): * The @buffer glyph position array. @@ -1461,7 +1490,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, * and cleared of position data when hb_buffer_clear_contents() is called. * * Return value: - * %true if the @buffer has position array, %false otherwise. + * `true` if the @buffer has position array, `false` otherwise. * * Since: 2.7.3 **/ @@ -1645,10 +1674,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer, * @buffer: An #hb_buffer_t * @text: (array length=text_length) (element-type uint8_t): An array of UTF-8 * characters to append. - * @text_length: The length of the @text, or -1 if it is %NULL terminated. + * @text_length: The length of the @text, or -1 if it is `NULL` terminated. * @item_offset: The offset of the first character to add to the @buffer. * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated). + * end of @text (assuming it is `NULL` terminated). * * See hb_buffer_add_codepoints(). * @@ -1671,10 +1700,10 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer, * hb_buffer_add_utf16: * @buffer: An #hb_buffer_t * @text: (array length=text_length): An array of UTF-16 characters to append - * @text_length: The length of the @text, or -1 if it is %NULL terminated + * @text_length: The length of the @text, or -1 if it is `NULL` terminated * @item_offset: The offset of the first character to add to the @buffer * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * See hb_buffer_add_codepoints(). * @@ -1697,10 +1726,10 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer, * hb_buffer_add_utf32: * @buffer: An #hb_buffer_t * @text: (array length=text_length): An array of UTF-32 characters to append - * @text_length: The length of the @text, or -1 if it is %NULL terminated + * @text_length: The length of the @text, or -1 if it is `NULL` terminated * @item_offset: The offset of the first character to add to the @buffer * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * See hb_buffer_add_codepoints(). * @@ -1724,10 +1753,10 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer, * @buffer: An #hb_buffer_t * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 * characters to append - * @text_length: the length of the @text, or -1 if it is %NULL terminated + * @text_length: the length of the @text, or -1 if it is `NULL` terminated * @item_offset: the offset of the first character to add to the @buffer * @item_length: the number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 * Unicode code points that can fit in 8-bit strings. @@ -1750,10 +1779,10 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer, * hb_buffer_add_codepoints: * @buffer: a #hb_buffer_t to append characters to. * @text: (array length=text_length): an array of Unicode code points to append. - * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @text_length: the length of the @text, or -1 if it is `NULL` terminated. * @item_offset: the offset of the first code point to add to the @buffer. * @item_length: the number of code points to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated). + * end of @text (assuming it is `NULL` terminated). * * Appends characters from @text array to @buffer. The @item_offset is the * position of the first character from @text that will be appended, and @@ -2090,8 +2119,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, bool hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) { + assert (!have_output || (out_info == info && out_len == idx)); + + message_depth++; + char buf[100]; vsnprintf (buf, sizeof (buf), fmt, ap); - return (bool) this->message_func (this, font, buf, this->message_data); + bool ret = (bool) this->message_func (this, font, buf, this->message_data); + + message_depth--; + + return ret; } #endif diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index 22fb3496f2..c6af759fb9 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -142,6 +142,15 @@ typedef struct hb_glyph_info_t { * shaping, otherwise the buffer flag will not be * reliably produced. * Since: 4.0.0 + * @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL: In scripts that use elongation (Arabic, + Mongolian, Syriac, etc.), this flag signifies + that it is safe to insert a U+0640 TATWEEL + character *before* this cluster for elongation. + This flag does not determine the + script-specific elongation places, but only + when it is safe to do the elongation without + interrupting text shaping. + Since: 5.1.0 * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * * Flags for #hb_glyph_info_t. @@ -149,10 +158,11 @@ typedef struct hb_glyph_info_t { * Since: 1.5.0 */ typedef enum { /*< flags >*/ - HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, - HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002, + HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002, + HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004, - HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */ + HB_GLYPH_FLAG_DEFINED = 0x00000007 /* OR of all defined flags */ } hb_glyph_flags_t; HB_EXTERN hb_glyph_flags_t @@ -266,7 +276,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, hb_bool_t replace); HB_EXTERN void * -hb_buffer_get_user_data (hb_buffer_t *buffer, +hb_buffer_get_user_data (const hb_buffer_t *buffer, hb_user_data_key_t *key); @@ -373,6 +383,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer); * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT * glyph-flag should be produced by the shaper. By default * it will not be produced since it incurs a cost. Since: 4.0.0 + * @HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL: + * flag indicating that the @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL + * glyph-flag should be produced by the shaper. By default + * it will not be produced. Since: 5.1.0 * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0 * * Flags for #hb_buffer_t. @@ -388,8 +402,9 @@ typedef enum { /*< flags >*/ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u, HB_BUFFER_FLAG_VERIFY = 0x00000020u, HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u, + HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x00000080u, - HB_BUFFER_FLAG_DEFINED = 0x0000007Fu + HB_BUFFER_FLAG_DEFINED = 0x000000FFu } hb_buffer_flags_t; HB_EXTERN void @@ -755,16 +770,16 @@ hb_buffer_diff (hb_buffer_t *buffer, * hb_buffer_message_func_t: * @buffer: An #hb_buffer_t to work upon * @font: The #hb_font_t the @buffer is shaped with - * @message: %NULL-terminated message passed to the function + * @message: `NULL`-terminated message passed to the function * @user_data: User data pointer passed by the caller * * A callback method for #hb_buffer_t. The method gets called with the * #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a * message describing what step of the shaping process will be performed. - * Returning %false from this method will skip this shaping step and move to + * Returning `false` from this method will skip this shaping step and move to * the next one. * - * Return value: %true to perform the shaping step, %false to skip it. + * Return value: `true` to perform the shaping step, `false` to skip it. * * Since: 1.1.3 */ diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 6ca78f28d4..26c3f0fac8 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -288,7 +288,8 @@ struct hb_buffer_t HB_INTERNAL void guess_segment_properties (); - HB_INTERNAL void sync (); + HB_INTERNAL bool sync (); + HB_INTERNAL int sync_so_far (); HB_INTERNAL void clear_output (); HB_INTERNAL void clear_positions (); @@ -461,6 +462,17 @@ struct hb_buffer_t start, end, true); } + void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1) + { + if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0) + { + unsafe_to_break (start, end); + return; + } + _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL, + start, end, + true); + } void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) { if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) @@ -555,15 +567,11 @@ struct hb_buffer_t if (likely (!messaging ())) return true; - message_depth++; - va_list ap; va_start (ap, fmt); bool ret = message_impl (font, fmt, ap); va_end (ap); - message_depth--; - return ret; #endif } diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh index 2983ae54a1..f93c83ab45 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh @@ -57,6 +57,7 @@ struct call_context_t /* call stack */ const unsigned int kMaxCallLimit = 10; +const unsigned int kMaxOps = 10000; struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {}; template <typename SUBRS> @@ -881,7 +882,13 @@ struct cs_interpreter_t : interpreter_t<ENV> { SUPER::env.set_endchar (false); + unsigned max_ops = kMaxOps; for (;;) { + if (unlikely (!--max_ops)) + { + SUPER::env.set_error (); + break; + } OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); if (unlikely (SUPER::env.in_error ())) return false; diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index 7266d9b01f..e6512872e8 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -108,7 +108,7 @@ _hb_options_init () /** * hb_tag_from_string: * @str: (array length=len) (element-type uint8_t): String to convert - * @len: Length of @str, or -1 if it is %NULL-terminated + * @len: Length of @str, or -1 if it is `NULL`-terminated * * Converts a string into an #hb_tag_t. Valid tags * are four characters. Shorter input strings will be @@ -170,7 +170,7 @@ static const char direction_strings[][4] = { /** * hb_direction_from_string: * @str: (array length=len) (element-type uint8_t): String to convert - * @len: Length of @str, or -1 if it is %NULL-terminated + * @len: Length of @str, or -1 if it is `NULL`-terminated * * Converts a string to an #hb_direction_t. * @@ -357,7 +357,7 @@ retry: * hb_language_from_string: * @str: (array length=len) (element-type uint8_t): a string representing * a BCP 47 language tag - * @len: length of the @str, or -1 if it is %NULL-terminated. + * @len: length of the @str, or -1 if it is `NULL`-terminated. * * Converts @str representing a BCP 47 language tag to the corresponding * #hb_language_t. @@ -396,7 +396,7 @@ hb_language_from_string (const char *str, int len) * Converts an #hb_language_t to a string. * * Return value: (transfer none): - * A %NULL-terminated string representing the @language. Must not be freed by + * A `NULL`-terminated string representing the @language. Must not be freed by * the caller. * * Since: 0.9.2 @@ -441,6 +441,38 @@ hb_language_get_default () return language; } +/** + * hb_language_matches: + * @language: The #hb_language_t to work on + * @specific: Another #hb_language_t + * + * Check whether a second language tag is the same or a more + * specific version of the provided language tag. For example, + * "fa_IR.utf8" is a more specific tag for "fa" or for "fa_IR". + * + * Return value: `true` if languages match, `false` otherwise. + * + * Since: 5.0.0 + **/ +hb_bool_t +hb_language_matches (hb_language_t language, + hb_language_t specific) +{ + if (language == specific) return true; + if (!language || !specific) return false; + + const char *l = language->s; + const char *s = specific->s; + unsigned ll = strlen (l); + unsigned sl = strlen (s); + + if (ll > sl) + return false; + + return strncmp (l, s, ll) == 0 && + (s[ll] == '\0' || s[ll] == '-'); +} + /* hb_script_t */ @@ -498,7 +530,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag) * hb_script_from_string: * @str: (array length=len) (element-type uint8_t): a string representing an * ISO 15924 tag. - * @len: length of the @str, or -1 if it is %NULL-terminated. + * @len: length of the @str, or -1 if it is `NULL`-terminated. * * Converts a string @str representing an ISO 15924 script tag to a * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then @@ -693,8 +725,8 @@ hb_version_string () * Tests the library version against a minimum value, * as three integer components. * - * Return value: %true if the library is equal to or greater than - * the test value, %false otherwise + * Return value: `true` if the library is equal to or greater than + * the test value, `false` otherwise * * Since: 0.9.30 **/ @@ -881,7 +913,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) /** * hb_feature_from_string: * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is %NULL terminated + * @len: length of @str, or -1 if string is `NULL` terminated * @feature: (out): the #hb_feature_t to initialize with the parsed values * * Parses a string into a #hb_feature_t. @@ -923,7 +955,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) * </informaltable> * * Return value: - * %true if @str is successfully parsed, %false otherwise + * `true` if @str is successfully parsed, `false` otherwise * * Since: 0.9.5 **/ @@ -954,7 +986,7 @@ hb_feature_from_string (const char *str, int len, * @buf: (array length=size) (out): output string * @size: the allocated size of @buf * - * Converts a #hb_feature_t into a %NULL-terminated string in the format + * Converts a #hb_feature_t into a `NULL`-terminated string in the format * understood by hb_feature_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * @@ -1022,7 +1054,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation /** * hb_variation_from_string: * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is %NULL terminated + * @len: length of @str, or -1 if string is `NULL` terminated * @variation: (out): the #hb_variation_t to initialize with the parsed values * * Parses a string into a #hb_variation_t. @@ -1035,7 +1067,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation * number. For example `wght=500`, or `slnt=-7.5`. * * Return value: - * %true if @str is successfully parsed, %false otherwise + * `true` if @str is successfully parsed, `false` otherwise * * Since: 1.4.2 */ @@ -1107,7 +1139,7 @@ get_C_locale () * @buf: (array length=size) (out): output string * @size: the allocated size of @buf * - * Converts an #hb_variation_t into a %NULL-terminated string in the format + * Converts an #hb_variation_t into a `NULL`-terminated string in the format * understood by hb_variation_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index 7b897a6c51..7c7ad87c7c 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -326,6 +326,9 @@ hb_language_to_string (hb_language_t language); HB_EXTERN hb_language_t hb_language_get_default (void); +HB_EXTERN hb_bool_t +hb_language_matches (hb_language_t language, + hb_language_t specific); /** * hb_script_t: diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh index 2578231d23..db8ec0e908 100644 --- a/thirdparty/harfbuzz/src/hb-config.hh +++ b/thirdparty/harfbuzz/src/hb-config.hh @@ -98,6 +98,11 @@ /* Closure of options. */ +#ifdef HB_NO_BORING_EXPANSION +#define HB_NO_BEYOND_64K +#define HB_NO_VARIATIONS2 +#endif + #ifdef HB_DISABLE_DEPRECATED #define HB_IF_NOT_DEPRECATED(x) #else diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh index 86d0452080..c4d9d29e23 100644 --- a/thirdparty/harfbuzz/src/hb-cplusplus.hh +++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh @@ -130,7 +130,7 @@ template <typename T, void *, hb_destroy_func_t, hb_bool_t), - void * (*_get_user_data) (T *, + void * (*_get_user_data) (const T *, hb_user_data_key_t *)> struct vtable_t { @@ -164,10 +164,37 @@ HB_DEFINE_VTABLE (unicode_funcs); #undef HB_DEFINE_VTABLE +#ifdef HB_SUBSET_H + +#define HB_DEFINE_VTABLE(name) \ + template<> \ + struct vtable<hb_##name##_t> \ + : vtable_t<hb_##name##_t, \ + nullptr, \ + &hb_##name##_reference, \ + &hb_##name##_destroy, \ + &hb_##name##_set_user_data, \ + &hb_##name##_get_user_data> {} + + +HB_DEFINE_VTABLE (subset_input); +HB_DEFINE_VTABLE (subset_plan); + +#undef HB_DEFINE_VTABLE + +#endif + + } // namespace hb +/* Workaround for GCC < 7, see: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 + * https://stackoverflow.com/a/25594741 */ +namespace std { + + template<typename T> -struct std::hash<hb::shared_ptr<T>> +struct hash<hb::shared_ptr<T>> { std::size_t operator()(const hb::shared_ptr<T>& v) const noexcept { @@ -177,7 +204,7 @@ struct std::hash<hb::shared_ptr<T>> }; template<typename T> -struct std::hash<hb::unique_ptr<T>> +struct hash<hb::unique_ptr<T>> { std::size_t operator()(const hb::unique_ptr<T>& v) const noexcept { @@ -187,6 +214,8 @@ struct std::hash<hb::unique_ptr<T>> }; +} // namespace std + #endif /* __cplusplus */ #endif /* HB_CPLUSPLUS_HH */ diff --git a/thirdparty/harfbuzz/src/hb-debug.hh b/thirdparty/harfbuzz/src/hb-debug.hh index 3ac7440e80..905a46a087 100644 --- a/thirdparty/harfbuzz/src/hb-debug.hh +++ b/thirdparty/harfbuzz/src/hb-debug.hh @@ -460,4 +460,9 @@ struct hb_no_trace_t { #endif +#ifndef HB_BUFFER_MESSAGE_MORE +#define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+1) +#endif + + #endif /* HB_DEBUG_HH */ diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h index a130d77f77..333dc3cd4c 100644 --- a/thirdparty/harfbuzz/src/hb-deprecated.h +++ b/thirdparty/harfbuzz/src/hb-deprecated.h @@ -93,7 +93,7 @@ HB_BEGIN_DECLS * This method should retrieve the glyph ID for a specified Unicode code point * font, with an optional variation selector. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * Deprecated: 1.2.3 * **/ diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index ce04f5bab1..de05b7d871 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -43,6 +43,14 @@ * Functions for using HarfBuzz with DirectWrite fonts. **/ +/* Declare object creator for dynamic support of DWRITE */ +typedef HRESULT (WINAPI *t_DWriteCreateFactory)( + DWRITE_FACTORY_TYPE factoryType, + REFIID iid, + IUnknown **factory +); + + /* * DirectWrite font stream helpers */ @@ -137,6 +145,7 @@ public: struct hb_directwrite_face_data_t { + HMODULE dwrite_dll; IDWriteFactory *dwriteFactory; IDWriteFontFile *fontFile; DWriteFontFileStream *fontFileStream; @@ -158,12 +167,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) return nullptr; \ } HB_STMT_END + data->dwrite_dll = LoadLibrary (TEXT ("DWRITE")); + if (unlikely (!data->dwrite_dll)) + FAIL ("Cannot find DWrite.DLL"); + + t_DWriteCreateFactory p_DWriteCreateFactory; + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + + p_DWriteCreateFactory = (t_DWriteCreateFactory) + GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + + if (unlikely (!p_DWriteCreateFactory)) + FAIL ("Cannot find DWriteCreateFactory()."); + HRESULT hr; // TODO: factory and fontFileLoader should be cached separately IDWriteFactory* dwriteFactory; - hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); + hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory); if (unlikely (hr != S_OK)) FAIL ("Failed to run DWriteCreateFactory()."); @@ -227,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); + if (data->dwrite_dll) + FreeLibrary (data->dwrite_dll); if (data) delete data; } diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc index fdc71102d6..46797e64e6 100644 --- a/thirdparty/harfbuzz/src/hb-draw.cc +++ b/thirdparty/harfbuzz/src/hb-draw.cc @@ -120,6 +120,7 @@ hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \ if (dfuncs->destroy) \ dfuncs->destroy->name = nullptr; \ } \ + return; \ \ fail: \ if (destroy) \ @@ -137,7 +138,7 @@ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS * Return value: (transfer full): * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial * reference count should be released with hb_draw_funcs_destroy when you are - * done using the #hb_draw_funcs_t. This function never returns %NULL. If + * done using the #hb_draw_funcs_t. This function never returns `NULL`. If * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will * be returned. * @@ -208,6 +209,9 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs) #undef HB_DRAW_FUNC_IMPLEMENT } + hb_free (dfuncs->destroy); + hb_free (dfuncs->user_data); + hb_free (dfuncs); } @@ -234,7 +238,7 @@ hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs) * * Checks whether @dfuncs is immutable. * - * Return value: %true if @dfuncs is immutable, %false otherwise + * Return value: `true` if @dfuncs is immutable, `false` otherwise * * Since: 4.0.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index 7cdd6cb49f..61adbdd503 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -315,7 +315,7 @@ hb_face_destroy (hb_face_t *face) * * Attaches a user-data key/data pair to the given face object. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -342,7 +342,7 @@ hb_face_set_user_data (hb_face_t *face, * Since: 0.9.2 **/ void * -hb_face_get_user_data (hb_face_t *face, +hb_face_get_user_data (const hb_face_t *face, hb_user_data_key_t *key) { return hb_object_get_user_data (face, key); @@ -371,7 +371,7 @@ hb_face_make_immutable (hb_face_t *face) * * Tests whether the given face object is immutable. * - * Return value: %true is @face is immutable, %false otherwise + * Return value: `true` is @face is immutable, `false` otherwise * * Since: 0.9.2 **/ diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h index 3b7477a76c..6ef2f8b886 100644 --- a/thirdparty/harfbuzz/src/hb-face.h +++ b/thirdparty/harfbuzz/src/hb-face.h @@ -96,7 +96,7 @@ hb_face_set_user_data (hb_face_t *face, hb_bool_t replace); HB_EXTERN void * -hb_face_get_user_data (hb_face_t *face, +hb_face_get_user_data (const hb_face_t *face, hb_user_data_key_t *key); HB_EXTERN void diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index 8c4fe863b6..856bbdda32 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -754,7 +754,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) * * Attaches a user-data key/data pair to the specified font-functions structure. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -781,8 +781,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, * Since: 0.9.2 **/ void * -hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, - hb_user_data_key_t *key) +hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key) { return hb_object_get_user_data (ffuncs, key); } @@ -811,7 +811,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) * * Tests whether a font-functions structure is immutable. * - * Return value: %true if @ffuncs is immutable, %false otherwise + * Return value: `true` if @ffuncs is immutable, `false` otherwise * * Since: 0.9.2 **/ @@ -903,7 +903,7 @@ hb_font_t::has_func (unsigned int i) * Fetches the extents for a specified font, for horizontal * text segments. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 1.1.3 **/ @@ -922,7 +922,7 @@ hb_font_get_h_extents (hb_font_t *font, * Fetches the extents for a specified font, for vertical * text segments. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 1.1.3 **/ @@ -946,7 +946,7 @@ hb_font_get_v_extents (hb_font_t *font, * If @variation_selector is 0, calls hb_font_get_nominal_glyph(); * otherwise calls hb_font_get_variation_glyph(). * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -974,7 +974,7 @@ hb_font_get_glyph (hb_font_t *font, * for code points modified by variation selectors. For variation-selector * support, user hb_font_get_variation_glyph() or use hb_font_get_glyph(). * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 1.2.3 **/ @@ -1026,7 +1026,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font, * by the specified variation-selector code point, in the specified * font. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 1.2.3 **/ @@ -1136,7 +1136,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font, * Fetches the (X,Y) coordinates of the origin for a glyph ID * in the specified font, for horizontal text segments. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1159,7 +1159,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font, * Fetches the (X,Y) coordinates of the origin for a glyph ID * in the specified font, for vertical text segments. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1232,7 +1232,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font, * Fetches the #hb_glyph_extents_t data for a glyph ID * in the specified font. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1255,7 +1255,7 @@ hb_font_get_glyph_extents (hb_font_t *font, * Fetches the (x,y) coordinates of a specified contour-point index * in the specified glyph, within the specified font. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1278,7 +1278,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font, * * Fetches the glyph-name string for a glyph ID in the specified @font. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1302,7 +1302,7 @@ hb_font_get_glyph_name (hb_font_t *font, * * <note>Note: @len == -1 means the name string is null-terminated.</note> * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1537,7 +1537,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font, * Calls the appropriate direction-specific variant (horizontal * or vertical) depending on the value of @direction. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1566,7 +1566,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font, * Calls the appropriate direction-specific variant (horizontal * or vertical) depending on the value of @direction. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1617,7 +1617,7 @@ hb_font_glyph_to_string (hb_font_t *font, * * <note>Note: @len == -1 means the string is null-terminated.</note> * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.2 **/ @@ -1675,6 +1675,7 @@ _hb_font_create (hb_face_t *face) if (unlikely (!face)) face = hb_face_get_empty (); + if (!(font = hb_object_create<hb_font_t> ())) return hb_font_get_empty (); @@ -1866,7 +1867,7 @@ hb_font_destroy (hb_font_t *font) * * Attaches a user-data key/data pair to the specified font object. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -1896,7 +1897,7 @@ hb_font_set_user_data (hb_font_t *font, * Since: 0.9.2 **/ void * -hb_font_get_user_data (hb_font_t *font, +hb_font_get_user_data (const hb_font_t *font, hb_user_data_key_t *key) { return hb_object_get_user_data (font, key); @@ -1928,7 +1929,7 @@ hb_font_make_immutable (hb_font_t *font) * * Tests whether a font object is immutable. * - * Return value: %true if @font is immutable, %false otherwise + * Return value: `true` if @font is immutable, `false` otherwise * * Since: 0.9.2 **/ @@ -1948,7 +1949,7 @@ hb_font_is_immutable (hb_font_t *font) * * Return value: serial number * - * Since: 4.4.0. + * Since: 4.4.0 **/ unsigned int hb_font_get_serial (hb_font_t *font) @@ -1964,7 +1965,7 @@ hb_font_get_serial (hb_font_t *font) * This has the effect of increasing the serial as returned * by hb_font_get_serial(), which invalidates internal caches. * - * Since: 4.4.0. + * Since: 4.4.0 **/ void hb_font_changed (hb_font_t *font) @@ -2386,6 +2387,10 @@ hb_font_set_variations (hb_font_t *font, return; } + /* Initialize design coords to default from fvar. */ + for (unsigned int i = 0; i < coords_length; i++) + design_coords[i] = axes[i].get_default (); + for (unsigned int i = 0; i < variations_length; i++) { const auto tag = variations[i].tag; diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h index ca6ecf7963..e2c3df4a5a 100644 --- a/thirdparty/harfbuzz/src/hb-font.h +++ b/thirdparty/harfbuzz/src/hb-font.h @@ -86,8 +86,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, HB_EXTERN void * -hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, - hb_user_data_key_t *key); +hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key); HB_EXTERN void @@ -198,7 +198,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; * This method should retrieve the nominal glyph ID for a specified Unicode code * point. Glyph IDs must be returned in a #hb_codepoint_t output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data, @@ -221,7 +221,7 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo * followed by a specified Variation Selector code point. Glyph IDs must be * returned in a #hb_codepoint_t output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data, @@ -362,7 +362,7 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t; * origin for a glyph. Each coordinate must be returned in an #hb_position_t * output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, @@ -434,7 +434,7 @@ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; * This method should retrieve the extents for a specified glyph. Extents must be * returned in an #hb_glyph_extents output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, @@ -458,7 +458,7 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo * specified contour point in a glyph. Each coordinate must be returned as * an #hb_position_t output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data, @@ -481,7 +481,7 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo * This method should retrieve the glyph name that corresponds to a * glyph ID. The name should be returned in a string output parameter. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data, @@ -503,7 +503,7 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_ * This method should retrieve the glyph ID that corresponds to a glyph-name * string. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data, @@ -993,7 +993,7 @@ hb_font_set_user_data (hb_font_t *font, HB_EXTERN void * -hb_font_get_user_data (hb_font_t *font, +hb_font_get_user_data (const hb_font_t *font, hb_user_data_key_t *key); HB_EXTERN void diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index b526a82865..ef073475cb 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -136,32 +136,56 @@ _hb_ft_font_destroy (void *data) /* hb_font changed, update FT_Face. */ static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face) { + float x_mult = 1.f, y_mult = 1.f; - FT_Set_Char_Size (ft_face, - abs (font->x_scale), abs (font->y_scale), - 0, 0); + if (font->x_scale < 0) x_mult = -x_mult; + if (font->y_scale < 0) y_mult = -y_mult; + + if (FT_Set_Char_Size (ft_face, + abs (font->x_scale), abs (font->y_scale), + 0, 0 #if 0 font->x_ppem * 72 * 64 / font->x_scale, - font->y_ppem * 72 * 64 / font->y_scale); + font->y_ppem * 72 * 64 / font->y_scale #endif - if (font->x_scale < 0 || font->y_scale < 0) + ) && ft_face->num_fixed_sizes) { - FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, - 0, font->y_scale < 0 ? -1 : +1}; +#ifdef HAVE_FT_GET_TRANSFORM + /* Bitmap font, eg. bitmap color emoji. */ + /* TODO Pick largest size? */ + int x_scale = ft_face->available_sizes[0].x_ppem; + int y_scale = ft_face->available_sizes[0].y_ppem; + FT_Set_Char_Size (ft_face, + x_scale, y_scale, + 0, 0); + + /* This contains the sign that was previously in x_mult/y_mult. */ + x_mult = (float) font->x_scale / x_scale; + y_mult = (float) font->y_scale / y_scale; +#endif + } + else + { /* Shrug */ } + + + if (x_mult != 1.f || y_mult != 1.f) + { + FT_Matrix matrix = { (int) roundf (x_mult * (1<<16)), 0, + 0, (int) roundf (y_mult * (1<<16))}; FT_Set_Transform (ft_face, &matrix, nullptr); } #if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR) unsigned int num_coords; - const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + const float *coords = hb_font_get_var_coords_design (font, &num_coords); if (num_coords) { FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed)); if (ft_coords) { for (unsigned int i = 0; i < num_coords; i++) - ft_coords[i] = coords[i] * 4; - FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + ft_coords[i] = coords[i] * 65536.f; + FT_Set_Var_Design_Coordinates (ft_face, num_coords, ft_coords); hb_free (ft_coords); } } @@ -241,7 +265,7 @@ hb_ft_font_get_load_flags (hb_font_t *font) * Fetches the FT_Face associated with the specified #hb_font_t * font object. * - * Return value: (nullable): the FT_Face found or %NULL + * Return value: (nullable): the FT_Face found or `NULL` * * Since: 0.9.2 **/ @@ -263,7 +287,7 @@ hb_ft_font_get_face (hb_font_t *font) * Gets the FT_Face associated with @font, This face will be kept around until * you call hb_ft_font_unlock_face(). * - * Return value: (nullable): the FT_Face associated with @font or %NULL + * Return value: (nullable) (transfer none): the FT_Face associated with @font or `NULL` * Since: 2.6.5 **/ FT_Face @@ -280,7 +304,7 @@ hb_ft_font_lock_face (hb_font_t *font) } /** - * hb_ft_font_unlock_face: + * hb_ft_font_unlock_face: (skip) * @font: #hb_font_t to work upon * * Releases an FT_Face previously obtained with hb_ft_font_lock_face(). @@ -404,7 +428,13 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; int load_flags = ft_font->load_flags; - int mult = font->x_scale < 0 ? -1 : +1; +#ifdef HAVE_FT_GET_TRANSFORM + FT_Matrix matrix; + FT_Get_Transform (ft_face, &matrix, nullptr); + float mult = matrix.xx / 65536.f; +#else + float mult = font->x_scale < 0 ? -1 : +1; +#endif for (unsigned int i = 0; i < count; i++) { @@ -420,7 +450,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, ft_font->advance_cache.set (glyph, v); } - *first_advance = (v * mult + (1<<9)) >> 10; + *first_advance = (int) (v * mult + (1<<9)) >> 10; first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); } @@ -436,12 +466,18 @@ hb_ft_get_glyph_v_advance (hb_font_t *font, const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; hb_lock_t lock (ft_font->lock); FT_Fixed v; +#ifdef HAVE_FT_GET_TRANSFORM + FT_Matrix matrix; + FT_Get_Transform (ft_font->ft_face, &matrix, nullptr); + float y_mult = matrix.yy / 65536.f; +#else + float y_mult = font->y_scale < 0 ? -1 : +1; +#endif if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) return 0; - if (font->y_scale < 0) - v = -v; + v = (int) (y_mult * v); /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates * have a Y growing upward. Hence the extra negation. */ @@ -462,6 +498,15 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; +#ifdef HAVE_FT_GET_TRANSFORM + FT_Matrix matrix; + FT_Get_Transform (ft_face, &matrix, nullptr); + float x_mult = matrix.xx / 65536.f; + float y_mult = matrix.yy / 65536.f; +#else + float x_mult = font->x_scale < 0 ? -1 : +1; + float y_mult = font->y_scale < 0 ? -1 : +1; +#endif if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; @@ -471,10 +516,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX; *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY); - if (font->x_scale < 0) - *x = -*x; - if (font->y_scale < 0) - *y = -*y; + *x = (hb_position_t) (x_mult * *x); + *y = (hb_position_t) (y_mult * *y); return true; } @@ -510,24 +553,24 @@ hb_ft_get_glyph_extents (hb_font_t *font, const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; +#ifdef HAVE_FT_GET_TRANSFORM + FT_Matrix matrix; + FT_Get_Transform (ft_face, &matrix, nullptr); + float x_mult = matrix.xx / 65536.f; + float y_mult = matrix.yy / 65536.f; +#else + float x_mult = font->x_scale < 0 ? -1 : +1; + float y_mult = font->y_scale < 0 ? -1 : +1; +#endif if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; - extents->x_bearing = ft_face->glyph->metrics.horiBearingX; - extents->y_bearing = ft_face->glyph->metrics.horiBearingY; - extents->width = ft_face->glyph->metrics.width; - extents->height = -ft_face->glyph->metrics.height; - if (font->x_scale < 0) - { - extents->x_bearing = -extents->x_bearing; - extents->width = -extents->width; - } - if (font->y_scale < 0) - { - extents->y_bearing = -extents->y_bearing; - extents->height = -extents->height; - } + extents->x_bearing = (hb_position_t) (x_mult * ft_face->glyph->metrics.horiBearingX); + extents->y_bearing = (hb_position_t) (y_mult * ft_face->glyph->metrics.horiBearingY); + extents->width = (hb_position_t) (x_mult * ft_face->glyph->metrics.width); + extents->height = (hb_position_t) (y_mult * -ft_face->glyph->metrics.height); + return true; } @@ -620,16 +663,32 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; +#ifdef HAVE_FT_GET_TRANSFORM + FT_Matrix matrix; + FT_Get_Transform (ft_face, &matrix, nullptr); + float y_mult = matrix.yy / 65536.f; +#else + float y_mult = font->y_scale < 0 ? -1 : +1; +#endif - metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale); - metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale); - metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender); - if (font->y_scale < 0) + if (ft_face->units_per_EM != 0) { - metrics->ascender = -metrics->ascender; - metrics->descender = -metrics->descender; - metrics->line_gap = -metrics->line_gap; + metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale); + metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale); + metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender); } + else + { + /* Bitmap-only font, eg. color bitmap font. */ + metrics->ascender = ft_face->size->metrics.ascender; + metrics->descender = ft_face->size->metrics.descender; + metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender); + } + + metrics->ascender = (hb_position_t) (y_mult * metrics->ascender); + metrics->descender = (hb_position_t) (y_mult * metrics->descender); + metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap); + return true; } @@ -684,8 +743,6 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED, hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; - _hb_ft_hb_font_check_changed (font, ft_font); - if (unlikely (FT_Load_Glyph (ft_face, glyph, FT_LOAD_NO_BITMAP | ft_font->load_flags))) return; @@ -1028,6 +1085,9 @@ hb_ft_font_changed (hb_font_t *font) #endif } #endif + + ft_font->advance_cache.clear (); + ft_font->cached_serial = font->serial; } /** diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc index 63dc18b466..4d0e687c75 100644 --- a/thirdparty/harfbuzz/src/hb-graphite2.cc +++ b/thirdparty/harfbuzz/src/hb-graphite2.cc @@ -158,7 +158,7 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data) } /** - * hb_graphite2_face_get_gr_face: + * hb_graphite2_face_get_gr_face: (skip) * @face: @hb_face_t to query * * Fetches the Graphite2 gr_face corresponding to the specified @@ -195,10 +195,10 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED #ifndef HB_DISABLE_DEPRECATED /** - * hb_graphite2_font_get_gr_font: + * hb_graphite2_font_get_gr_font: (skip) * @font: An #hb_font_t * - * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead. + * Always returns `NULL`. Use hb_graphite2_face_get_gr_face() instead. * * Return value: (nullable): Graphite2 font associated with @font. * @@ -223,7 +223,7 @@ struct hb_graphite2_cluster_t { unsigned int base_glyph; unsigned int num_glyphs; unsigned int cluster; - unsigned int advance; + int advance; }; hb_bool_t diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index d4461f166c..1a3ab43de0 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -253,6 +253,8 @@ struct hb_is_iterator_of }; #define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value #define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t) +#define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator) +#define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t) /* hb_is_iterable() */ diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc index 089615c72a..5c5f5de59e 100644 --- a/thirdparty/harfbuzz/src/hb-map.cc +++ b/thirdparty/harfbuzz/src/hb-map.cc @@ -56,8 +56,6 @@ hb_map_create () if (!(map = hb_object_create<hb_map_t> ())) return hb_map_get_empty (); - map->init_shallow (); - return map; } @@ -107,8 +105,6 @@ hb_map_destroy (hb_map_t *map) { if (!hb_object_destroy (map)) return; - map->fini_shallow (); - hb_free (map); } @@ -122,7 +118,7 @@ hb_map_destroy (hb_map_t *map) * * Attaches a user-data key/data pair to the specified map. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 1.7.7 **/ @@ -149,7 +145,7 @@ hb_map_set_user_data (hb_map_t *map, * Since: 1.7.7 **/ void * -hb_map_get_user_data (hb_map_t *map, +hb_map_get_user_data (const hb_map_t *map, hb_user_data_key_t *key) { return hb_object_get_user_data (map, key); @@ -162,7 +158,7 @@ hb_map_get_user_data (hb_map_t *map, * * Tests whether memory allocation for a set was successful. * - * Return value: %true if allocation succeeded, %false otherwise + * Return value: `true` if allocation succeeded, `false` otherwise * * Since: 1.7.7 **/ @@ -251,7 +247,7 @@ hb_map_del (hb_map_t *map, * * Tests whether @key is an element of @map. * - * Return value: %true if @key is found in @map, %false otherwise + * Return value: `true` if @key is found in @map, `false` otherwise * * Since: 1.7.7 **/ @@ -283,7 +279,7 @@ hb_map_clear (hb_map_t *map) * * Tests whether @map is empty (contains no elements). * - * Return value: %true if @map is empty + * Return value: `true` if @map is empty * * Since: 1.7.7 **/ @@ -317,7 +313,7 @@ hb_map_get_population (const hb_map_t *map) * Tests whether @map and @other are equal (contain the same * elements). * - * Return value: %true if the two maps are equal, %false otherwise. + * Return value: `true` if the two maps are equal, `false` otherwise. * * Since: 4.3.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-map.h b/thirdparty/harfbuzz/src/hb-map.h index 41d877d6a1..3a067c5c73 100644 --- a/thirdparty/harfbuzz/src/hb-map.h +++ b/thirdparty/harfbuzz/src/hb-map.h @@ -74,7 +74,7 @@ hb_map_set_user_data (hb_map_t *map, hb_bool_t replace); HB_EXTERN void * -hb_map_get_user_data (hb_map_t *map, +hb_map_get_user_data (const hb_map_t *map, hb_user_data_key_t *key); diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 5efad8d20c..8302e3f8c7 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -124,21 +124,20 @@ struct hb_hashmap_t hb_swap (a.prime, b.prime); hb_swap (a.items, b.items); } - void init_shallow () + void init () { + hb_object_init (this); + successful = true; population = occupancy = 0; mask = 0; prime = 0; items = nullptr; } - void init () - { - hb_object_init (this); - init_shallow (); - } - void fini_shallow () + void fini () { + hb_object_fini (this); + if (likely (items)) { unsigned size = mask + 1; for (unsigned i = 0; i < size; i++) @@ -148,11 +147,6 @@ struct hb_hashmap_t } population = occupancy = 0; } - void fini () - { - hb_object_fini (this); - fini_shallow (); - } void reset () { @@ -219,13 +213,11 @@ struct hb_hashmap_t /* Has interface. */ typedef const V& value_t; value_t operator [] (K k) const { return get (k); } - bool has (K key, const V **vp = nullptr) const + template <typename VV=V> + bool has (K key, VV **vp = nullptr) const { if (unlikely (!items)) - { - if (vp) *vp = &item_t::default_value (); return false; - } unsigned int i = bucket_for (key); if (items[i].is_real () && items[i] == key) { @@ -233,10 +225,7 @@ struct hb_hashmap_t return true; } else - { - if (vp) *vp = &item_t::default_value (); return false; - } } /* Projection. */ V operator () (K k) const { return get (k); } @@ -301,6 +290,12 @@ struct hb_hashmap_t | hb_map (&item_t::key) | hb_map (hb_ridentity) ) + auto keys_ref () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::key) + ) auto values () const HB_AUTO_RETURN ( + hb_array (items, mask ? mask + 1 : 0) @@ -308,6 +303,12 @@ struct hb_hashmap_t | hb_map (&item_t::value) | hb_map (hb_ridentity) ) + auto values_ref () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::value) + ) /* Sink interface. */ hb_hashmap_t& operator << (const hb_pair_t<K, V>& v) @@ -443,4 +444,37 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t, hb_map_t (const Iterable &o) : hashmap (o) {} }; +template <typename K, typename V> +static inline +hb_hashmap_t<K, V>* hb_hashmap_create () +{ + using hashmap = hb_hashmap_t<K, V>; + hashmap* map; + if (!(map = hb_object_create<hashmap> ())) + return nullptr; + + return map; +} + +template <typename K, typename V> +static inline +void hb_hashmap_destroy (hb_hashmap_t<K, V>* map) +{ + if (!hb_object_destroy (map)) + return; + + hb_free (map); +} + +namespace hb { + +template <typename K, typename V> +struct vtable<hb_hashmap_t<K, V>> +{ + static constexpr auto destroy = hb_hashmap_destroy<K,V>; +}; + +} + + #endif /* HB_MAP_HH */ diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index e97d790fc3..1921ccbb6d 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -188,7 +188,7 @@ template <> struct hb_int_max<signed long long> : hb_integral_constant<signed l template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigned long long, ULLONG_MAX> {}; #define hb_int_max(T) hb_int_max<T>::value -#if defined(__GNUC__) && __GNUC__ < 5 +#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) #define hb_is_trivially_copyable(T) __has_trivial_copy(T) #define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T) #define hb_is_trivially_constructible(T) __has_trivial_constructor(T) diff --git a/thirdparty/harfbuzz/src/hb-null.hh b/thirdparty/harfbuzz/src/hb-null.hh index 78eb6474d5..0d7f4da79e 100644 --- a/thirdparty/harfbuzz/src/hb-null.hh +++ b/thirdparty/harfbuzz/src/hb-null.hh @@ -39,6 +39,24 @@ #define HB_NULL_POOL_SIZE 448 +template <typename T, typename> +struct _hb_has_min_size : hb_false_type {}; +template <typename T> +struct _hb_has_min_size<T, hb_void_t<decltype (T::min_size)>> + : hb_true_type {}; +template <typename T> +using hb_has_min_size = _hb_has_min_size<T, void>; +#define hb_has_min_size(T) hb_has_min_size<T>::value + +template <typename T, typename> +struct _hb_has_null_size : hb_false_type {}; +template <typename T> +struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>> + : hb_true_type {}; +template <typename T> +using hb_has_null_size = _hb_has_null_size<T, void>; +#define hb_has_null_size(T) hb_has_null_size<T>::value + /* Use SFINAE to sniff whether T has min_size; in which case return the larger * of sizeof(T) and T::null_size, otherwise return sizeof(T). * @@ -117,8 +135,19 @@ struct NullHelper }; \ namespace Namespace { \ static_assert (true, "") /* Require semicolon after. */ +#define DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1(Namespace, Type, Size) \ + } /* Close namespace. */ \ + extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Size]; \ + template <typename Spec> \ + struct Null<Namespace::Type<Spec>> { \ + static Namespace::Type<Spec> const & get_null () { \ + return *reinterpret_cast<const Namespace::Type<Spec> *> (_hb_Null_##Namespace##_##Type); \ + } \ + }; \ + namespace Namespace { \ + static_assert (true, "") /* Require semicolon after. */ #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \ - const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)] + const unsigned char _hb_Null_##Namespace##_##Type[sizeof (_hb_Null_##Namespace##_##Type)] /* Specializations for arbitrary-content Null objects expressed as struct initializer. */ #define DECLARE_NULL_INSTANCE(Type) \ diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index 4b5bc32ade..f6c7a56991 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -222,8 +222,11 @@ static inline Type *hb_object_create () if (unlikely (!obj)) return obj; + new (obj) Type; + hb_object_init (obj); hb_object_trace (obj, HB_FUNC); + return obj; } template <typename Type> @@ -269,6 +272,9 @@ static inline bool hb_object_destroy (Type *obj) return false; hb_object_fini (obj); + + obj->~Type (); + return true; } template <typename Type> @@ -280,7 +286,7 @@ static inline void hb_object_fini (Type *obj) { user_data->fini (); hb_free (user_data); - user_data = nullptr; + obj->header.user_data.set_relaxed (nullptr); } } template <typename Type> diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index aee7064be3..d0d01a68c5 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -105,7 +105,7 @@ struct IntType bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: BEInt<Type, Size> v; @@ -170,7 +170,7 @@ struct LONGDATETIME bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: HBINT32 major; @@ -196,6 +196,10 @@ struct HBGlyphID16 : HBUINT16 { HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } }; +struct HBGlyphID24 : HBUINT24 +{ + HBGlyphID24& operator = (uint32_t i) { HBUINT24::operator= (i); return *this; } +}; /* Script/language-system/feature index */ struct Index : HBUINT16 { @@ -300,6 +304,10 @@ struct _hb_has_null<Type, true> template <typename Type, typename OffsetType, bool has_null=true> struct OffsetTo : Offset<OffsetType, has_null> { + // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time. + static_assert (has_null == false || + (hb_has_null_size (Type) || !hb_has_min_size (Type)), ""); + HB_DELETE_COPY_ASSIGN (OffsetTo); OffsetTo () = default; @@ -450,14 +458,16 @@ struct UnsizedArrayOf { unsigned int i = (unsigned int) i_; const Type *p = &arrayZ[i]; - if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */ + if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */ + _hb_compiler_memory_r_barrier (); return *p; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; Type *p = &arrayZ[i]; - if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */ + if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */ + _hb_compiler_memory_r_barrier (); return *p; } @@ -550,14 +560,16 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_ { unsigned int i = (unsigned int) i_; const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i]; - if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */ + if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */ + _hb_compiler_memory_r_barrier (); return this+*p; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i]; - if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */ + if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */ + _hb_compiler_memory_r_barrier (); return this+*p; } @@ -608,12 +620,14 @@ struct ArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= len)) return Null (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= len)) return Crap (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i]; } @@ -729,6 +743,7 @@ struct ArrayOf DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>; +template <typename Type> using Array24Of = ArrayOf<Type, HBUINT24>; template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>; using PString = ArrayOf<HBUINT8, HBUINT8>; @@ -738,26 +753,28 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>; /* Array of offsets relative to the beginning of the array itself. */ -template <typename Type> -struct List16OfOffset16To : Array16OfOffset16To<Type> +template <typename Type, typename OffsetType> +struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16> { const Type& operator [] (int i_) const { unsigned int i = (unsigned int) i_; if (unlikely (i >= this->len)) return Null (Type); + _hb_compiler_memory_r_barrier (); return this+this->arrayZ[i]; } const Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= this->len)) return Crap (Type); + _hb_compiler_memory_r_barrier (); return this+this->arrayZ[i]; } bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct List16OfOffset16To<Type> *out = c->serializer->embed (*this); + struct List16OfOffsetTo *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) @@ -769,10 +786,13 @@ struct List16OfOffset16To : Array16OfOffset16To<Type> bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...)); + return_trace ((Array16Of<OffsetTo<Type, OffsetType>>::sanitize (c, this, std::forward<Ts> (ds)...))); } }; +template <typename Type> +using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>; + /* An array starting at second element. */ template <typename Type, typename LenType=HBUINT16> struct HeadlessArrayOf @@ -785,12 +805,14 @@ struct HeadlessArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= lenP1 || !i)) return Null (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i-1]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= lenP1 || !i)) return Crap (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i-1]; } unsigned int get_size () const @@ -869,12 +891,14 @@ struct ArrayOfM1 { unsigned int i = (unsigned int) i_; if (unlikely (i > lenM1)) return Null (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i > lenM1)) return Crap (Type); + _hb_compiler_memory_r_barrier (); return arrayZ[i]; } unsigned int get_size () const @@ -961,6 +985,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType> }; template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>; +template <typename Type> using SortedArray24Of = SortedArrayOf<Type, HBUINT24>; template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>; /* @@ -1053,12 +1078,14 @@ struct VarSizedBinSearchArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= get_length ())) return Null (Type); + _hb_compiler_memory_r_barrier (); return StructAtOffset<Type> (&bytesZ, i * header.unitSize); } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= get_length ())) return Crap (Type); + _hb_compiler_memory_r_barrier (); return StructAtOffset<Type> (&bytesZ, i * header.unitSize); } unsigned int get_length () const diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index dac755c02c..f01d383bdc 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -145,7 +145,7 @@ struct BaseGlyphRecord bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } public: @@ -524,6 +524,7 @@ struct PaintSweepGradient }; struct Paint; + // Paint a non-COLR glyph, filled as indicated by paint. struct PaintGlyph { @@ -1152,6 +1153,8 @@ struct Paint Variable<PaintSkewAroundCenter> paintformat31; PaintComposite paintformat32; } u; + public: + DEFINE_SIZE_MIN (2); }; struct BaseGlyphPaintRecord diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc index 16077765bd..a9ae013682 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.cc +++ b/thirdparty/harfbuzz/src/hb-ot-color.cc @@ -61,7 +61,7 @@ * * Tests whether a face includes a `CPAL` color-palette table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.1.0 */ @@ -192,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face, * * Tests whether a face includes any `COLR` color layers. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.1.0 */ @@ -239,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, * * Tests whether a face includes any `SVG` glyph images. * - * Return value: %true if data found, %false otherwise. + * Return value: `true` if data found, `false` otherwise. * * Since: 2.1.0 */ @@ -279,7 +279,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) * * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables). * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.1.0 */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color.h b/thirdparty/harfbuzz/src/hb-ot-color.h index c23ce4de44..d11e07e230 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.h +++ b/thirdparty/harfbuzz/src/hb-ot-color.h @@ -102,6 +102,10 @@ hb_ot_color_has_layers (hb_face_t *face); * * Pairs of glyph and color index. * + * A color index of 0xFFFF does not refer to a palette + * color, but indicates that the foreground color should + * be used. + * * Since: 2.1.0 **/ typedef struct hb_ot_color_layer_t { diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index af1bc86d48..3f13b9994a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.cc +++ b/thirdparty/harfbuzz/src/hb-ot-font.cc @@ -151,7 +151,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; #ifndef HB_NO_VAR - const OT::HVARVVAR &HVAR = *hmtx.var_table; + const OT::HVAR &HVAR = *hmtx.var_table; const OT::VariationStore &varStore = &HVAR + HVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; @@ -190,7 +190,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, { for (unsigned int i = 0; i < count; i++) { - *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, varStore_cache)); + *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache)); first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); } @@ -211,7 +211,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, v = cv; else { - v = hmtx.get_advance (*first_glyph, font, varStore_cache); + v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache); ot_font->advance_cache->set (*first_glyph, v); } *first_advance = font->em_scale_x (v); @@ -242,7 +242,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, if (vmtx.has_data ()) { #ifndef HB_NO_VAR - const OT::HVARVVAR &VVAR = *vmtx.var_table; + const OT::VVAR &VVAR = *vmtx.var_table; const OT::VariationStore &varStore = &VVAR + VVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; #else @@ -251,7 +251,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, for (unsigned int i = 0; i < count; i++) { - *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font, varStore_cache)); + *first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache)); first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); } @@ -293,17 +293,28 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, const OT::VORG &VORG = *ot_face->VORG; if (VORG.has_data ()) { - *y = font->em_scale_y (VORG.get_y_origin (glyph)); + float delta = 0; + +#ifndef HB_NO_VAR + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + const OT::VVAR &VVAR = *vmtx.var_table; + if (font->num_coords) + VVAR.get_vorg_delta_unscaled (glyph, + font->coords, font->num_coords, + &delta); +#endif + + *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta); return true; } hb_glyph_extents_t extents = {0}; if (ot_face->glyf->get_extents (font, glyph, &extents)) { - if (ot_face->vmtx->has_data ()) + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + int tsb = 0; + if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb)) { - const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - hb_position_t tsb = vmtx.get_side_bearing (font, glyph); *y = extents.y_bearing + font->em_scale_y (tsb); return true; } @@ -503,16 +514,17 @@ hb_ot_font_set_funcs (hb_font_t *font) } #ifndef HB_NO_VAR -int -_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical) +bool +_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, + int *lsb) { - return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical); + return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb); } unsigned -_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical) +_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical) { - return font->face->table.glyf->get_advance_var (font, glyph, is_vertical); + return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical); } #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index d0e46e0b0f..50e4b54fde 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -43,11 +43,11 @@ #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') -HB_INTERNAL int -_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); +HB_INTERNAL bool +_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb); HB_INTERNAL unsigned -_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); +_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); namespace OT { @@ -62,7 +62,7 @@ struct LongMetric }; -template <typename T, typename H> +template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/> struct hmtxvmtx { bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const @@ -135,9 +135,9 @@ struct hmtxvmtx auto& plan = c->plan; num_long_metrics = plan->num_output_glyphs (); hb_codepoint_t old_gid = 0; - unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0; + unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0; while (num_long_metrics > 1 && - last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0)) + last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0)) { num_long_metrics--; } @@ -150,7 +150,9 @@ struct hmtxvmtx hb_codepoint_t old_gid; if (!c->plan->old_gid_for_new_gid (_, &old_gid)) return hb_pair (0u, 0); - return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid)); + int lsb = 0; + (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb); + return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb); }) ; @@ -173,7 +175,7 @@ struct hmtxvmtx accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); - var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag); + var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag); default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face); @@ -221,36 +223,46 @@ struct hmtxvmtx bool has_data () const { return (bool) num_bearings; } - int get_side_bearing (hb_codepoint_t glyph) const + bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph, + int *lsb) const { if (glyph < num_long_metrics) - return table->longMetricZ[glyph].sb; + { + *lsb = table->longMetricZ[glyph].sb; + return true; + } if (unlikely (glyph >= num_bearings)) - return 0; + return false; const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; - return bearings[glyph - num_long_metrics]; + *lsb = bearings[glyph - num_long_metrics]; + return true; } - int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const + bool get_leading_bearing_with_var_unscaled (hb_font_t *font, + hb_codepoint_t glyph, + int *lsb) const { - int side_bearing = get_side_bearing (glyph); + if (!font->num_coords) + return get_leading_bearing_without_var_unscaled (glyph, lsb); #ifndef HB_NO_VAR - if (unlikely (glyph >= num_bearings) || !font->num_coords) - return side_bearing; - - if (var_table.get_length ()) - return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); + float delta; + if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) && + get_leading_bearing_without_var_unscaled (glyph, lsb)) + { + *lsb += roundf (delta); + return true; + } - return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); + return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb); #else - return side_bearing; + return false; #endif } - unsigned int get_advance (hb_codepoint_t glyph) const + unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const { /* OpenType case. */ if (glyph < num_bearings) @@ -262,7 +274,7 @@ struct hmtxvmtx if (unlikely (!num_advances)) return default_advance; -#ifdef HB_NO_BORING_EXPANSION +#ifdef HB_NO_BEYOND_64K return 0; #endif @@ -275,7 +287,7 @@ struct hmtxvmtx /* TODO Optimize */ if (num_bearings == num_advances) - return get_advance (num_bearings - 1); + return get_advance_without_var_unscaled (num_bearings - 1); const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics]; @@ -283,20 +295,22 @@ struct hmtxvmtx return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)]; } - unsigned int get_advance (hb_codepoint_t glyph, - hb_font_t *font, - VariationStore::cache_t *store_cache = nullptr) const + unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph, + hb_font_t *font, + VariationStore::cache_t *store_cache = nullptr) const { - unsigned int advance = get_advance (glyph); + unsigned int advance = get_advance_without_var_unscaled (glyph); #ifndef HB_NO_VAR if (unlikely (glyph >= num_bearings) || !font->num_coords) return advance; if (var_table.get_length ()) - return advance + roundf (var_table->get_advance_var (glyph, font, store_cache)); // TODO Optimize?! + return advance + roundf (var_table->get_advance_delta_unscaled (glyph, + font->coords, font->num_coords, + store_cache)); // TODO Optimize?! - return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); + return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx); #else return advance; #endif @@ -313,7 +327,7 @@ struct hmtxvmtx public: hb_blob_ptr_t<hmtxvmtx> table; - hb_blob_ptr_t<HVARVVAR> var_table; + hb_blob_ptr_t<V> var_table; }; protected: @@ -346,12 +360,12 @@ struct hmtxvmtx DEFINE_SIZE_ARRAY (0, longMetricZ); }; -struct hmtx : hmtxvmtx<hmtx, hhea> { +struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> { static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; static constexpr bool is_horizontal = true; }; -struct vmtx : hmtxvmtx<vmtx, vhea> { +struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> { static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; static constexpr bool is_horizontal = false; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index 1b9dfcd3f5..8179e5acd5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -49,7 +49,7 @@ struct BaseCoordFormat1 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index d343805346..0532039aad 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -35,6 +35,14 @@ #include "hb-set.hh" #include "hb-bimap.hh" +#include "OT/Layout/Common/Coverage.hh" +#include "OT/Layout/types.hh" + +// TODO(garretrieger): cleanup these after migration. +using OT::Layout::Common::Coverage; +using OT::Layout::Common::RangeRecord; +using OT::Layout::SmallTypes; +using OT::Layout::MediumTypes; #ifndef HB_MAX_NESTING_LEVEL #define HB_MAX_NESTING_LEVEL 64 @@ -46,10 +54,10 @@ /* * The maximum number of times a lookup can be applied during shaping. * Used to limit the number of iterations of the closure algorithm. - * This must be larger than the number of times add_pause() is + * This must be larger than the number of times add_gsub_pause() is * called in a collect_features call of any shaper. */ -#define HB_CLOSURE_MAX_STAGES 32 +#define HB_CLOSURE_MAX_STAGES 12 #endif #ifndef HB_MAX_SCRIPTS @@ -64,10 +72,6 @@ #define HB_MAX_LANGSYS_FEATURE_COUNT 50000 #endif -#ifndef HB_MAX_FEATURES -#define HB_MAX_FEATURES 750 -#endif - #ifndef HB_MAX_FEATURE_INDICES #define HB_MAX_FEATURE_INDICES 1500 #endif @@ -79,14 +83,6 @@ namespace OT { - -#define NOT_COVERED ((unsigned int) -1) - - -template<typename Iterator> -static inline void Coverage_serialize (hb_serialize_context_t *c, - Iterator it); - template<typename Iterator> static inline void ClassDef_serialize (hb_serialize_context_t *c, Iterator it); @@ -377,6 +373,51 @@ HB_FUNCOBJ (serialize_math_record_array); * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList */ +struct IndexArray : Array16Of<Index> +{ + bool intersects (const hb_map_t *indexes) const + { return hb_any (*this, indexes); } + + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + void serialize (hb_serialize_context_t *c, + hb_subset_layout_context_t *l, + Iterator it) + { + if (!it) return; + if (unlikely (!c->extend_min ((*this)))) return; + + for (const auto _ : it) + { + if (!l->visitLookupIndex()) break; + + Index i; + i = _; + c->copy (i); + this->len++; + } + } + + unsigned int get_indexes (unsigned int start_offset, + unsigned int *_count /* IN/OUT */, + unsigned int *_indexes /* OUT */) const + { + if (_count) + { + + this->sub_array (start_offset, _count) + | hb_sink (hb_array (_indexes, *_count)) + ; + } + return this->len; + } + + void add_indexes_to (hb_set_t* output /* OUT */) const + { + output->add_array (as_array ()); + } +}; + + struct Record_sanitize_closure_t { hb_tag_t tag; const void *list_base; @@ -465,363 +506,6 @@ struct RecordListOf : RecordArrayOf<Type> } }; -struct Feature; - -struct RecordListOfFeature : RecordListOf<Feature> -{ - bool subset (hb_subset_context_t *c, - hb_subset_layout_context_t *l) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - - unsigned count = this->len; - + hb_zip (*this, hb_range (count)) - | hb_filter (l->feature_index_map, hb_second) - | hb_map (hb_first) - | hb_apply (subset_record_array (l, out, this)) - ; - return_trace (true); - } -}; - -struct Script; -struct RecordListOfScript : RecordListOf<Script> -{ - bool subset (hb_subset_context_t *c, - hb_subset_layout_context_t *l) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - - unsigned count = this->len; - for (auto _ : + hb_zip (*this, hb_range (count))) - { - auto snap = c->serializer->snapshot (); - l->cur_script_index = _.second; - bool ret = _.first.subset (l, this); - if (!ret) c->serializer->revert (snap); - else out->len++; - } - - return_trace (true); - } -}; - -struct RangeRecord -{ - int cmp (hb_codepoint_t g) const - { return g < first ? -1 : g <= last ? 0 : +1; } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - bool intersects (const hb_set_t *glyphs) const - { return glyphs->intersects (first, last); } - - template <typename set_t> - bool collect_coverage (set_t *glyphs) const - { return glyphs->add_range (first, last); } - - HBGlyphID16 first; /* First GlyphID in the range */ - HBGlyphID16 last; /* Last GlyphID in the range */ - HBUINT16 value; /* Value */ - public: - DEFINE_SIZE_STATIC (6); -}; -DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord); - - -struct IndexArray : Array16Of<Index> -{ - bool intersects (const hb_map_t *indexes) const - { return hb_any (*this, indexes); } - - template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - void serialize (hb_serialize_context_t *c, - hb_subset_layout_context_t *l, - Iterator it) - { - if (!it) return; - if (unlikely (!c->extend_min ((*this)))) return; - - for (const auto _ : it) - { - if (!l->visitLookupIndex()) break; - - Index i; - i = _; - c->copy (i); - this->len++; - } - } - - unsigned int get_indexes (unsigned int start_offset, - unsigned int *_count /* IN/OUT */, - unsigned int *_indexes /* OUT */) const - { - if (_count) - { - + this->sub_array (start_offset, _count) - | hb_sink (hb_array (_indexes, *_count)) - ; - } - return this->len; - } - - void add_indexes_to (hb_set_t* output /* OUT */) const - { - output->add_array (as_array ()); - } -}; - - -struct LangSys -{ - unsigned int get_feature_count () const - { return featureIndex.len; } - hb_tag_t get_feature_index (unsigned int i) const - { return featureIndex[i]; } - unsigned int get_feature_indexes (unsigned int start_offset, - unsigned int *feature_count /* IN/OUT */, - unsigned int *feature_indexes /* OUT */) const - { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); } - void add_feature_indexes_to (hb_set_t *feature_indexes) const - { featureIndex.add_indexes_to (feature_indexes); } - - bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; } - unsigned int get_required_feature_index () const - { - if (reqFeatureIndex == 0xFFFFu) - return Index::NOT_FOUND_INDEX; - return reqFeatureIndex; - } - - LangSys* copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - return_trace (c->embed (*this)); - } - - bool compare (const LangSys& o, const hb_map_t *feature_index_map) const - { - if (reqFeatureIndex != o.reqFeatureIndex) - return false; - - auto iter = - + hb_iter (featureIndex) - | hb_filter (feature_index_map) - | hb_map (feature_index_map) - ; - - auto o_iter = - + hb_iter (o.featureIndex) - | hb_filter (feature_index_map) - | hb_map (feature_index_map) - ; - - for (; iter && o_iter; iter++, o_iter++) - { - unsigned a = *iter; - unsigned b = *o_iter; - if (a != b) return false; - } - - if (iter || o_iter) return false; - - return true; - } - - void collect_features (hb_prune_langsys_context_t *c) const - { - if (!has_required_feature () && !get_feature_count ()) return; - if (has_required_feature () && - c->duplicate_feature_map->has (reqFeatureIndex)) - c->new_feature_indexes->add (get_required_feature_index ()); - - + hb_iter (featureIndex) - | hb_filter (c->duplicate_feature_map) - | hb_sink (c->new_feature_indexes) - ; - } - - bool subset (hb_subset_context_t *c, - hb_subset_layout_context_t *l, - const Tag *tag = nullptr) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - - const unsigned *v; - out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; - - if (!l->visitFeatureIndex (featureIndex.len)) - return_trace (false); - - auto it = - + hb_iter (featureIndex) - | hb_filter (l->feature_index_map) - | hb_map (l->feature_index_map) - ; - - bool ret = bool (it); - out->featureIndex.serialize (c->serializer, l, it); - return_trace (ret); - } - - bool sanitize (hb_sanitize_context_t *c, - const Record_sanitize_closure_t * = nullptr) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && featureIndex.sanitize (c)); - } - - Offset16 lookupOrderZ; /* = Null (reserved for an offset to a - * reordering table) */ - HBUINT16 reqFeatureIndex;/* Index of a feature required for this - * language system--if no required features - * = 0xFFFFu */ - IndexArray featureIndex; /* Array of indices into the FeatureList */ - public: - DEFINE_SIZE_ARRAY_SIZED (6, featureIndex); -}; -DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys); - -struct Script -{ - unsigned int get_lang_sys_count () const - { return langSys.len; } - const Tag& get_lang_sys_tag (unsigned int i) const - { return langSys.get_tag (i); } - unsigned int get_lang_sys_tags (unsigned int start_offset, - unsigned int *lang_sys_count /* IN/OUT */, - hb_tag_t *lang_sys_tags /* OUT */) const - { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); } - const LangSys& get_lang_sys (unsigned int i) const - { - if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys (); - return this+langSys[i].offset; - } - bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const - { return langSys.find_index (tag, index); } - - bool has_default_lang_sys () const { return defaultLangSys != 0; } - const LangSys& get_default_lang_sys () const { return this+defaultLangSys; } - - void prune_langsys (hb_prune_langsys_context_t *c, - unsigned script_index) const - { - if (!has_default_lang_sys () && !get_lang_sys_count ()) return; - if (!c->visitScript ()) return; - - if (!c->script_langsys_map->has (script_index)) - { - if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()}))) - return; - } - - unsigned langsys_count = get_lang_sys_count (); - if (has_default_lang_sys ()) - { - //only collect features from non-redundant langsys - const LangSys& d = get_default_lang_sys (); - if (c->visitLangsys (d.get_feature_count ())) { - d.collect_features (c); - } - - for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) - { - const LangSys& l = this+_.first.offset; - if (!c->visitLangsys (l.get_feature_count ())) continue; - if (l.compare (d, c->duplicate_feature_map)) continue; - - l.collect_features (c); - c->script_langsys_map->get (script_index)->add (_.second); - } - } - else - { - for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) - { - const LangSys& l = this+_.first.offset; - if (!c->visitLangsys (l.get_feature_count ())) continue; - l.collect_features (c); - c->script_langsys_map->get (script_index)->add (_.second); - } - } - } - - bool subset (hb_subset_context_t *c, - hb_subset_layout_context_t *l, - const Tag *tag) const - { - TRACE_SUBSET (this); - if (!l->visitScript ()) return_trace (false); - - auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - - bool defaultLang = false; - if (has_default_lang_sys ()) - { - c->serializer->push (); - const LangSys& ls = this+defaultLangSys; - bool ret = ls.subset (c, l); - if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T')) - { - c->serializer->pop_discard (); - out->defaultLangSys = 0; - } - else - { - c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ()); - defaultLang = true; - } - } - - const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index); - if (active_langsys) - { - unsigned count = langSys.len; - + hb_zip (langSys, hb_range (count)) - | hb_filter (active_langsys, hb_second) - | hb_map (hb_first) - | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); }) - | hb_apply (subset_record_array (l, &(out->langSys), this)) - ; - } - - return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB); - } - - bool sanitize (hb_sanitize_context_t *c, - const Record_sanitize_closure_t * = nullptr) const - { - TRACE_SANITIZE (this); - return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); - } - - protected: - Offset16To<LangSys> - defaultLangSys; /* Offset to DefaultLangSys table--from - * beginning of Script table--may be Null */ - RecordArrayOf<LangSys> - langSys; /* Array of LangSysRecords--listed - * alphabetically by LangSysTag */ - public: - DEFINE_SIZE_ARRAY_SIZED (4, langSys); -}; - -typedef RecordListOfScript ScriptList; - - /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ struct FeatureParamsSize { @@ -1104,6 +788,7 @@ struct FeatureParams DEFINE_SIZE_MIN (0); }; + struct Feature { unsigned int get_lookup_count () const @@ -1199,9 +884,294 @@ struct Feature DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex); }; +struct RecordListOfFeature : RecordListOf<Feature> +{ + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + unsigned count = this->len; + + hb_zip (*this, hb_range (count)) + | hb_filter (l->feature_index_map, hb_second) + | hb_map (hb_first) + | hb_apply (subset_record_array (l, out, this)) + ; + return_trace (true); + } +}; + typedef RecordListOf<Feature> FeatureList; +struct LangSys +{ + unsigned int get_feature_count () const + { return featureIndex.len; } + hb_tag_t get_feature_index (unsigned int i) const + { return featureIndex[i]; } + unsigned int get_feature_indexes (unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_indexes /* OUT */) const + { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); } + void add_feature_indexes_to (hb_set_t *feature_indexes) const + { featureIndex.add_indexes_to (feature_indexes); } + + bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; } + unsigned int get_required_feature_index () const + { + if (reqFeatureIndex == 0xFFFFu) + return Index::NOT_FOUND_INDEX; + return reqFeatureIndex; + } + + LangSys* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (*this)); + } + + bool compare (const LangSys& o, const hb_map_t *feature_index_map) const + { + if (reqFeatureIndex != o.reqFeatureIndex) + return false; + + auto iter = + + hb_iter (featureIndex) + | hb_filter (feature_index_map) + | hb_map (feature_index_map) + ; + + auto o_iter = + + hb_iter (o.featureIndex) + | hb_filter (feature_index_map) + | hb_map (feature_index_map) + ; + + for (; iter && o_iter; iter++, o_iter++) + { + unsigned a = *iter; + unsigned b = *o_iter; + if (a != b) return false; + } + + if (iter || o_iter) return false; + + return true; + } + + void collect_features (hb_prune_langsys_context_t *c) const + { + if (!has_required_feature () && !get_feature_count ()) return; + if (has_required_feature () && + c->duplicate_feature_map->has (reqFeatureIndex)) + c->new_feature_indexes->add (get_required_feature_index ()); + + + hb_iter (featureIndex) + | hb_filter (c->duplicate_feature_map) + | hb_sink (c->new_feature_indexes) + ; + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + const Tag *tag = nullptr) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + const unsigned *v; + out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; + + if (!l->visitFeatureIndex (featureIndex.len)) + return_trace (false); + + auto it = + + hb_iter (featureIndex) + | hb_filter (l->feature_index_map) + | hb_map (l->feature_index_map) + ; + + bool ret = bool (it); + out->featureIndex.serialize (c->serializer, l, it); + return_trace (ret); + } + + bool sanitize (hb_sanitize_context_t *c, + const Record_sanitize_closure_t * = nullptr) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && featureIndex.sanitize (c)); + } + + Offset16 lookupOrderZ; /* = Null (reserved for an offset to a + * reordering table) */ + HBUINT16 reqFeatureIndex;/* Index of a feature required for this + * language system--if no required features + * = 0xFFFFu */ + IndexArray featureIndex; /* Array of indices into the FeatureList */ + public: + DEFINE_SIZE_ARRAY_SIZED (6, featureIndex); +}; +DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys); + +struct Script +{ + unsigned int get_lang_sys_count () const + { return langSys.len; } + const Tag& get_lang_sys_tag (unsigned int i) const + { return langSys.get_tag (i); } + unsigned int get_lang_sys_tags (unsigned int start_offset, + unsigned int *lang_sys_count /* IN/OUT */, + hb_tag_t *lang_sys_tags /* OUT */) const + { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); } + const LangSys& get_lang_sys (unsigned int i) const + { + if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys (); + return this+langSys[i].offset; + } + bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const + { return langSys.find_index (tag, index); } + + bool has_default_lang_sys () const { return defaultLangSys != 0; } + const LangSys& get_default_lang_sys () const { return this+defaultLangSys; } + + void prune_langsys (hb_prune_langsys_context_t *c, + unsigned script_index) const + { + if (!has_default_lang_sys () && !get_lang_sys_count ()) return; + if (!c->visitScript ()) return; + + if (!c->script_langsys_map->has (script_index)) + { + if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()}))) + return; + } + + unsigned langsys_count = get_lang_sys_count (); + if (has_default_lang_sys ()) + { + //only collect features from non-redundant langsys + const LangSys& d = get_default_lang_sys (); + if (c->visitLangsys (d.get_feature_count ())) { + d.collect_features (c); + } + + for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + { + const LangSys& l = this+_.first.offset; + if (!c->visitLangsys (l.get_feature_count ())) continue; + if (l.compare (d, c->duplicate_feature_map)) continue; + + l.collect_features (c); + c->script_langsys_map->get (script_index)->add (_.second); + } + } + else + { + for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + { + const LangSys& l = this+_.first.offset; + if (!c->visitLangsys (l.get_feature_count ())) continue; + l.collect_features (c); + c->script_langsys_map->get (script_index)->add (_.second); + } + } + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + const Tag *tag) const + { + TRACE_SUBSET (this); + if (!l->visitScript ()) return_trace (false); + if (tag && !c->plan->layout_scripts->has (*tag)) + return false; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + bool defaultLang = false; + if (has_default_lang_sys ()) + { + c->serializer->push (); + const LangSys& ls = this+defaultLangSys; + bool ret = ls.subset (c, l); + if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T')) + { + c->serializer->pop_discard (); + out->defaultLangSys = 0; + } + else + { + c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ()); + defaultLang = true; + } + } + + const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index); + if (active_langsys) + { + unsigned count = langSys.len; + + hb_zip (langSys, hb_range (count)) + | hb_filter (active_langsys, hb_second) + | hb_map (hb_first) + | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); }) + | hb_apply (subset_record_array (l, &(out->langSys), this)) + ; + } + + return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB); + } + + bool sanitize (hb_sanitize_context_t *c, + const Record_sanitize_closure_t * = nullptr) const + { + TRACE_SANITIZE (this); + return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); + } + + protected: + Offset16To<LangSys> + defaultLangSys; /* Offset to DefaultLangSys table--from + * beginning of Script table--may be Null */ + RecordArrayOf<LangSys> + langSys; /* Array of LangSysRecords--listed + * alphabetically by LangSysTag */ + public: + DEFINE_SIZE_ARRAY_SIZED (4, langSys); +}; + +struct RecordListOfScript : RecordListOf<Script> +{ + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + unsigned count = this->len; + for (auto _ : + hb_zip (*this, hb_range (count))) + { + auto snap = c->serializer->snapshot (); + l->cur_script_index = _.second; + bool ret = _.first.subset (l, this); + if (!ret) c->serializer->revert (snap); + else out->len++; + } + + return_trace (true); + } +}; + +typedef RecordListOfScript ScriptList; + + + struct LookupFlag : HBUINT16 { enum Flags { @@ -1343,7 +1313,7 @@ struct Lookup if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ()))) return_trace (false); - if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ())) + if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ())) { /* The spec says all subtables of an Extension lookup should * have the same type, which shall not be the Extension type @@ -1363,7 +1333,7 @@ struct Lookup return_trace (true); } - private: + protected: HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */ HBUINT16 lookupFlag; /* Lookup qualifiers */ Array16Of<Offset16> @@ -1375,10 +1345,11 @@ struct Lookup DEFINE_SIZE_ARRAY (6, subTable); }; -typedef List16OfOffset16To<Lookup> LookupList; +template <typename Types> +using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>; -template <typename TLookup> -struct LookupOffsetList : List16OfOffset16To<TLookup> +template <typename TLookup, typename OffsetType> +struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType> { bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l) const @@ -1408,470 +1379,6 @@ struct LookupOffsetList : List16OfOffset16To<TLookup> * Coverage Table */ -struct CoverageFormat1 -{ - friend struct Coverage; - - private: - unsigned int get_coverage (hb_codepoint_t glyph_id) const - { - unsigned int i; - glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED); - return i; - } - - template <typename Iterator, - hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> - bool serialize (hb_serialize_context_t *c, Iterator glyphs) - { - TRACE_SERIALIZE (this); - return_trace (glyphArray.serialize (c, glyphs)); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (glyphArray.sanitize (c)); - } - - bool intersects (const hb_set_t *glyphs) const - { - /* TODO Speed up, using hb_set_next() and bsearch()? */ - for (const auto& g : glyphArray.as_array ()) - if (glyphs->has (g)) - return true; - return false; - } - bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const - { return glyphs->has (glyphArray[index]); } - - void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const - { - unsigned count = glyphArray.len; - for (unsigned i = 0; i < count; i++) - if (glyphs->has (glyphArray[i])) - intersect_glyphs->add (glyphArray[i]); - } - - template <typename set_t> - bool collect_coverage (set_t *glyphs) const - { return glyphs->add_sorted_array (glyphArray.as_array ()); } - - public: - /* Older compilers need this to be public. */ - struct iter_t - { - void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; } - void fini () {} - bool more () const { return i < c->glyphArray.len; } - void next () { i++; } - hb_codepoint_t get_glyph () const { return c->glyphArray[i]; } - bool operator != (const iter_t& o) const - { return i != o.i; } - iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; } - - private: - const struct CoverageFormat1 *c; - unsigned int i; - }; - private: - - protected: - HBUINT16 coverageFormat; /* Format identifier--format = 1 */ - SortedArray16Of<HBGlyphID16> - glyphArray; /* Array of GlyphIDs--in numerical order */ - public: - DEFINE_SIZE_ARRAY (4, glyphArray); -}; - -struct CoverageFormat2 -{ - friend struct Coverage; - - private: - unsigned int get_coverage (hb_codepoint_t glyph_id) const - { - const RangeRecord &range = rangeRecord.bsearch (glyph_id); - return likely (range.first <= range.last) - ? (unsigned int) range.value + (glyph_id - range.first) - : NOT_COVERED; - } - - template <typename Iterator, - hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> - bool serialize (hb_serialize_context_t *c, Iterator glyphs) - { - TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (this))) return_trace (false); - - /* TODO(iter) Write more efficiently? */ - - unsigned num_ranges = 0; - hb_codepoint_t last = (hb_codepoint_t) -2; - for (auto g: glyphs) - { - if (last + 1 != g) - num_ranges++; - last = g; - } - - if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false); - if (!num_ranges) return_trace (true); - - unsigned count = 0; - unsigned range = (unsigned) -1; - last = (hb_codepoint_t) -2; - for (auto g: glyphs) - { - if (last + 1 != g) - { - range++; - rangeRecord[range].first = g; - rangeRecord[range].value = count; - } - rangeRecord[range].last = g; - last = g; - count++; - } - - return_trace (true); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (rangeRecord.sanitize (c)); - } - - bool intersects (const hb_set_t *glyphs) const - { - return hb_any (+ hb_iter (rangeRecord.as_array ()) - | hb_map ([glyphs] (const RangeRecord &range) { return range.intersects (glyphs); })); - } - bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const - { - auto cmp = [] (const void *pk, const void *pr) -> int - { - unsigned index = * (const unsigned *) pk; - const RangeRecord &range = * (const RangeRecord *) pr; - if (index < range.value) return -1; - if (index > (unsigned int) range.value + (range.last - range.first)) return +1; - return 0; - }; - - auto arr = rangeRecord.as_array (); - unsigned idx; - if (hb_bsearch_impl (&idx, index, - arr.arrayZ, arr.length, sizeof (arr[0]), - (int (*)(const void *_key, const void *_item)) cmp)) - return arr.arrayZ[idx].intersects (glyphs); - return false; - } - - void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const - { - for (const auto& range : rangeRecord.as_array ()) - { - if (!range.intersects (glyphs)) continue; - unsigned last = range.last; - for (hb_codepoint_t g = range.first - 1; - glyphs->next (&g) && g <= last;) - intersect_glyphs->add (g); - } - } - - template <typename set_t> - bool collect_coverage (set_t *glyphs) const - { - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) - if (unlikely (!rangeRecord[i].collect_coverage (glyphs))) - return false; - return true; - } - - public: - /* Older compilers need this to be public. */ - struct iter_t - { - void init (const CoverageFormat2 &c_) - { - c = &c_; - coverage = 0; - i = 0; - j = c->rangeRecord.len ? c->rangeRecord[0].first : 0; - if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last)) - { - /* Broken table. Skip. */ - i = c->rangeRecord.len; - } - } - void fini () {} - bool more () const { return i < c->rangeRecord.len; } - void next () - { - if (j >= c->rangeRecord[i].last) - { - i++; - if (more ()) - { - unsigned int old = coverage; - j = c->rangeRecord[i].first; - coverage = c->rangeRecord[i].value; - if (unlikely (coverage != old + 1)) - { - /* Broken table. Skip. Important to avoid DoS. - * Also, our callers depend on coverage being - * consecutive and monotonically increasing, - * ie. iota(). */ - i = c->rangeRecord.len; - return; - } - } - else - j = 0; - return; - } - coverage++; - j++; - } - hb_codepoint_t get_glyph () const { return j; } - bool operator != (const iter_t& o) const - { return i != o.i || j != o.j; } - iter_t __end__ () const - { - iter_t it; - it.init (*c); - it.i = c->rangeRecord.len; - it.j = 0; - return it; - } - - private: - const struct CoverageFormat2 *c; - unsigned int i, coverage; - hb_codepoint_t j; - }; - private: - - protected: - HBUINT16 coverageFormat; /* Format identifier--format = 2 */ - SortedArray16Of<RangeRecord> - rangeRecord; /* Array of glyph ranges--ordered by - * Start GlyphID. rangeCount entries - * long */ - public: - DEFINE_SIZE_ARRAY (4, rangeRecord); -}; - -struct Coverage -{ - /* Has interface. */ - static constexpr unsigned SENTINEL = NOT_COVERED; - typedef unsigned int value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } - /* Predicate. */ - bool operator () (hb_codepoint_t k) const { return has (k); } - - unsigned int get (hb_codepoint_t k) const { return get_coverage (k); } - unsigned int get_coverage (hb_codepoint_t glyph_id) const - { - switch (u.format) { - case 1: return u.format1.get_coverage (glyph_id); - case 2: return u.format2.get_coverage (glyph_id); - default:return NOT_COVERED; - } - } - - template <typename Iterator, - hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> - bool serialize (hb_serialize_context_t *c, Iterator glyphs) - { - TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (this))) return_trace (false); - - unsigned count = 0; - unsigned num_ranges = 0; - hb_codepoint_t last = (hb_codepoint_t) -2; - for (auto g: glyphs) - { - if (last + 1 != g) - num_ranges++; - last = g; - count++; - } - u.format = count <= num_ranges * 3 ? 1 : 2; - - switch (u.format) - { - case 1: return_trace (u.format1.serialize (c, glyphs)); - case 2: return_trace (u.format2.serialize (c, glyphs)); - default:return_trace (false); - } - } - - bool subset (hb_subset_context_t *c) const - { - TRACE_SUBSET (this); - auto it = - + iter () - | hb_filter (c->plan->glyph_map_gsub) - | hb_map_retains_sorting (c->plan->glyph_map_gsub) - ; - - // Cache the iterator result as it will be iterated multiple times - // by the serialize code below. - hb_sorted_vector_t<hb_codepoint_t> glyphs (it); - Coverage_serialize (c->serializer, glyphs.iter ()); - return_trace (bool (glyphs)); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (!u.format.sanitize (c)) return_trace (false); - switch (u.format) - { - case 1: return_trace (u.format1.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - default:return_trace (true); - } - } - - bool intersects (const hb_set_t *glyphs) const - { - switch (u.format) - { - case 1: return u.format1.intersects (glyphs); - case 2: return u.format2.intersects (glyphs); - default:return false; - } - } - bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const - { - switch (u.format) - { - case 1: return u.format1.intersects_coverage (glyphs, index); - case 2: return u.format2.intersects_coverage (glyphs, index); - default:return false; - } - } - - /* Might return false if array looks unsorted. - * Used for faster rejection of corrupt data. */ - template <typename set_t> - bool collect_coverage (set_t *glyphs) const - { - switch (u.format) - { - case 1: return u.format1.collect_coverage (glyphs); - case 2: return u.format2.collect_coverage (glyphs); - default:return false; - } - } - - void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const - { - switch (u.format) - { - case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs); - case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs); - default:return ; - } - } - - struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> - { - static constexpr bool is_sorted_iterator = true; - iter_t (const Coverage &c_ = Null (Coverage)) - { - memset (this, 0, sizeof (*this)); - format = c_.u.format; - switch (format) - { - case 1: u.format1.init (c_.u.format1); return; - case 2: u.format2.init (c_.u.format2); return; - default: return; - } - } - bool __more__ () const - { - switch (format) - { - case 1: return u.format1.more (); - case 2: return u.format2.more (); - default:return false; - } - } - void __next__ () - { - switch (format) - { - case 1: u.format1.next (); break; - case 2: u.format2.next (); break; - default: break; - } - } - typedef hb_codepoint_t __item_t__; - __item_t__ __item__ () const { return get_glyph (); } - - hb_codepoint_t get_glyph () const - { - switch (format) - { - case 1: return u.format1.get_glyph (); - case 2: return u.format2.get_glyph (); - default:return 0; - } - } - bool operator != (const iter_t& o) const - { - if (unlikely (format != o.format)) return true; - switch (format) - { - case 1: return u.format1 != o.u.format1; - case 2: return u.format2 != o.u.format2; - default:return false; - } - } - iter_t __end__ () const - { - iter_t it = {}; - it.format = format; - switch (format) - { - case 1: it.u.format1 = u.format1.__end__ (); break; - case 2: it.u.format2 = u.format2.__end__ (); break; - default: break; - } - return it; - } - - private: - unsigned int format; - union { - CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */ - CoverageFormat1::iter_t format1; - } u; - }; - iter_t iter () const { return iter_t (*this); } - - protected: - union { - HBUINT16 format; /* Format identifier */ - CoverageFormat1 format1; - CoverageFormat2 format2; - } u; - public: - DEFINE_SIZE_UNION (2, format); -}; - -template<typename Iterator> -static inline void -Coverage_serialize (hb_serialize_context_t *c, - Iterator it) -{ c->start_embed<Coverage> ()->serialize (c, it); } static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_set_t &klasses, @@ -1913,7 +1420,8 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, * Class Definition Table */ -struct ClassDefFormat1 +template <typename Types> +struct ClassDefFormat1_3 { friend struct ClassDef; @@ -1924,7 +1432,7 @@ struct ClassDefFormat1 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator it) { @@ -2118,14 +1626,16 @@ struct ClassDefFormat1 protected: HBUINT16 classFormat; /* Format identifier--format = 1 */ - HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */ - Array16Of<HBUINT16> + typename Types::HBGlyphID + startGlyph; /* First GlyphID of the classValueArray */ + typename Types::template ArrayOf<HBUINT16> classValue; /* Array of Class Values--one per GlyphID */ public: - DEFINE_SIZE_ARRAY (6, classValue); + DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue); }; -struct ClassDefFormat2 +template <typename Types> +struct ClassDefFormat2_4 { friend struct ClassDef; @@ -2136,7 +1646,7 @@ struct ClassDefFormat2 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator it) { @@ -2154,12 +1664,12 @@ struct ClassDefFormat2 hb_codepoint_t prev_gid = (*it).first; unsigned prev_klass = (*it).second; - RangeRecord range_rec; + RangeRecord<Types> range_rec; range_rec.first = prev_gid; range_rec.last = prev_gid; range_rec.value = prev_klass; - RangeRecord *record = c->copy (range_rec); + auto *record = c->copy (range_rec); if (unlikely (!record)) return_trace (false); for (const auto gid_klass_pair : + (++it)) @@ -2202,13 +1712,14 @@ struct ClassDefFormat2 hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass; hb_set_t orig_klasses; + unsigned num_source_glyphs = c->plan->source->get_num_glyphs (); unsigned count = rangeRecord.len; for (unsigned i = 0; i < count; i++) { unsigned klass = rangeRecord[i].value; if (!klass) continue; hb_codepoint_t start = rangeRecord[i].first; - hb_codepoint_t end = rangeRecord[i].last + 1; + hb_codepoint_t end = hb_min (rangeRecord[i].last + 1, num_source_glyphs); for (hb_codepoint_t g = start; g < end; g++) { hb_codepoint_t new_gid = glyph_map[g]; @@ -2272,7 +1783,7 @@ struct ClassDefFormat2 for (unsigned int i = 0; i < count; i++) { const auto& range = rangeRecord[i]; - if (range.intersects (glyphs) && range.value) + if (range.intersects (*glyphs) && range.value) return true; } return false; @@ -2296,11 +1807,8 @@ struct ClassDefFormat2 return true; /* Fall through. */ } - /* TODO Speed up, using set overlap first? */ - /* TODO(iter) Rewrite as dagger. */ - const RangeRecord *arr = rangeRecord.arrayZ; - for (unsigned int i = 0; i < count; i++) - if (arr[i].value == klass && arr[i].intersects (glyphs)) + for (const auto &range : rangeRecord) + if (range.value == klass && range.intersects (*glyphs)) return true; return false; } @@ -2374,18 +1882,18 @@ struct ClassDefFormat2 if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) intersect_classes->add (0); - for (const RangeRecord& record : rangeRecord.iter ()) - if (record.intersects (glyphs)) + for (const auto& record : rangeRecord.iter ()) + if (record.intersects (*glyphs)) intersect_classes->add (record.value); } protected: HBUINT16 classFormat; /* Format identifier--format = 2 */ - SortedArray16Of<RangeRecord> + typename Types::template SortedArrayOf<RangeRecord<Types>> rangeRecord; /* Array of glyph ranges--ordered by * Start GlyphID */ public: - DEFINE_SIZE_ARRAY (4, rangeRecord); + DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord); }; struct ClassDef @@ -2404,12 +1912,16 @@ struct ClassDef switch (u.format) { case 1: return u.format1.get_class (glyph_id); case 2: return u.format2.get_class (glyph_id); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.get_class (glyph_id); + case 4: return u.format4.get_class (glyph_id); +#endif default:return 0; } } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero) { TRACE_SERIALIZE (this); @@ -2418,10 +1930,11 @@ struct ClassDef auto it = + it_with_class_zero | hb_filter (hb_second); unsigned format = 2; + hb_codepoint_t glyph_max = 0; if (likely (it)) { hb_codepoint_t glyph_min = (*it).first; - hb_codepoint_t glyph_max = glyph_min; + glyph_max = glyph_min; unsigned num_glyphs = 0; unsigned num_ranges = 1; @@ -2446,12 +1959,22 @@ struct ClassDef if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) format = 1; } + +#ifndef HB_NO_BEYOND_64K + if (glyph_max > 0xFFFFu) + format += 2; +#endif + u.format = format; switch (u.format) { case 1: return_trace (u.format1.serialize (c, it)); case 2: return_trace (u.format2.serialize (c, it)); +#ifndef HB_NO_BEYOND_64K + case 3: return_trace (u.format3.serialize (c, it)); + case 4: return_trace (u.format4.serialize (c, it)); +#endif default:return_trace (false); } } @@ -2466,6 +1989,10 @@ struct ClassDef switch (u.format) { case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); +#ifndef HB_NO_BEYOND_64K + case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); +#endif default:return_trace (false); } } @@ -2477,6 +2004,10 @@ struct ClassDef switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); +#ifndef HB_NO_BEYOND_64K + case 3: return_trace (u.format3.sanitize (c)); + case 4: return_trace (u.format4.sanitize (c)); +#endif default:return_trace (true); } } @@ -2486,6 +2017,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.cost (); case 2: return u.format2.cost (); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.cost (); + case 4: return u.format4.cost (); +#endif default:return 0u; } } @@ -2498,6 +2033,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.collect_coverage (glyphs); case 2: return u.format2.collect_coverage (glyphs); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.collect_coverage (glyphs); + case 4: return u.format4.collect_coverage (glyphs); +#endif default:return false; } } @@ -2510,6 +2049,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.collect_class (glyphs, klass); case 2: return u.format2.collect_class (glyphs, klass); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.collect_class (glyphs, klass); + case 4: return u.format4.collect_class (glyphs, klass); +#endif default:return false; } } @@ -2519,6 +2062,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.intersects (glyphs); case 2: return u.format2.intersects (glyphs); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.intersects (glyphs); + case 4: return u.format4.intersects (glyphs); +#endif default:return false; } } @@ -2527,6 +2074,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.intersects_class (glyphs, klass); case 2: return u.format2.intersects_class (glyphs, klass); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.intersects_class (glyphs, klass); + case 4: return u.format4.intersects_class (glyphs, klass); +#endif default:return false; } } @@ -2536,6 +2087,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs); case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs); +#endif default:return; } } @@ -2545,6 +2100,10 @@ struct ClassDef switch (u.format) { case 1: return u.format1.intersected_classes (glyphs, intersect_classes); case 2: return u.format2.intersected_classes (glyphs, intersect_classes); +#ifndef HB_NO_BEYOND_64K + case 3: return u.format3.intersected_classes (glyphs, intersect_classes); + case 4: return u.format4.intersected_classes (glyphs, intersect_classes); +#endif default:return; } } @@ -2552,9 +2111,13 @@ struct ClassDef protected: union { - HBUINT16 format; /* Format identifier */ - ClassDefFormat1 format1; - ClassDefFormat2 format2; + HBUINT16 format; /* Format identifier */ + ClassDefFormat1_3<SmallTypes> format1; + ClassDefFormat2_4<SmallTypes> format2; +#ifndef HB_NO_BEYOND_64K + ClassDefFormat1_3<MediumTypes>format3; + ClassDefFormat2_4<MediumTypes>format4; +#endif } u; public: DEFINE_SIZE_UNION (2, format); @@ -2940,6 +2503,9 @@ struct VariationStore cache_t *create_cache () const { +#ifdef HB_NO_VAR + return nullptr; +#endif auto &r = this+regions; unsigned count = r.regionCount; @@ -3000,6 +2566,10 @@ struct VariationStore const hb_array_t <hb_inc_bimap_t> &inner_maps) { TRACE_SERIALIZE (this); +#ifdef HB_NO_VAR + return_trace (false); +#endif + if (unlikely (!c->extend_min (this))) return_trace (false); unsigned int set_count = 0; @@ -3051,6 +2621,9 @@ struct VariationStore bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); +#ifdef HB_NO_VAR + return_trace (false); +#endif VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> (); if (unlikely (!varstore_prime)) return_trace (false); @@ -3078,7 +2651,12 @@ struct VariationStore } unsigned int get_region_index_count (unsigned int major) const - { return (this+dataSets[major]).get_region_index_count (); } + { +#ifdef HB_NO_VAR + return 0; +#endif + return (this+dataSets[major]).get_region_index_count (); + } void get_region_scalars (unsigned int major, const int *coords, unsigned int coord_count, @@ -3096,7 +2674,13 @@ struct VariationStore &scalars[0], num_scalars); } - unsigned int get_sub_table_count () const { return dataSets.len; } + unsigned int get_sub_table_count () const + { +#ifdef HB_NO_VAR + return 0; +#endif + return dataSets.len; + } protected: HBUINT16 format; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh index 9d47bac2b9..5bc26d9182 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -510,6 +510,101 @@ struct MarkGlyphSets */ +template <typename Types> +struct GDEFVersion1_2 +{ + friend struct GDEF; + + protected: + FixedVersion<>version; /* Version of the GDEF table--currently + * 0x00010003u */ + typename Types::template OffsetTo<ClassDef> + glyphClassDef; /* Offset to class definition table + * for glyph type--from beginning of + * GDEF header (may be Null) */ + typename Types::template OffsetTo<AttachList> + attachList; /* Offset to list of glyphs with + * attachment points--from beginning + * of GDEF header (may be Null) */ + typename Types::template OffsetTo<LigCaretList> + ligCaretList; /* Offset to list of positioning points + * for ligature carets--from beginning + * of GDEF header (may be Null) */ + typename Types::template OffsetTo<ClassDef> + markAttachClassDef; /* Offset to class definition table for + * mark attachment type--from beginning + * of GDEF header (may be Null) */ + typename Types::template OffsetTo<MarkGlyphSets> + markGlyphSetsDef; /* Offset to the table of mark set + * definitions--from beginning of GDEF + * header (may be NULL). Introduced + * in version 0x00010002. */ + Offset32To<VariationStore> + varStore; /* Offset to the table of Item Variation + * Store--from beginning of GDEF + * header (may be NULL). Introduced + * in version 0x00010003. */ + public: + DEFINE_SIZE_MIN (4 + 4 * Types::size); + + unsigned int get_size () const + { + return min_size + + (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + + (version.to_int () >= 0x00010003u ? varStore.static_size : 0); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + glyphClassDef.sanitize (c, this) && + attachList.sanitize (c, this) && + ligCaretList.sanitize (c, this) && + markAttachClassDef.sanitize (c, this) && + (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && + (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); + bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); + bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); + bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); + + bool subset_markglyphsetsdef = false; + if (version.to_int () >= 0x00010002u) + { + subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); + } + + bool subset_varstore = false; + if (version.to_int () >= 0x00010003u) + { + subset_varstore = out->varStore.serialize_subset (c, varStore, this); + } + + if (subset_varstore) + { + out->version.minor = 3; + } else if (subset_markglyphsetsdef) { + out->version.minor = 2; + } else { + out->version.minor = 0; + } + + return_trace (subset_glyphclassdef || subset_attachlist || + subset_ligcaretlist || subset_markattachclassdef || + (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || + (out->version.to_int () >= 0x00010003u && subset_varstore)); + } +}; + struct GDEF { static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; @@ -522,42 +617,190 @@ struct GDEF ComponentGlyph = 4 }; - bool has_data () const { return version.to_int (); } - bool has_glyph_classes () const { return glyphClassDef != 0; } + unsigned int get_size () const + { + switch (u.version.major) { + case 1: return u.version1.get_size (); +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.get_size (); +#endif + default: return u.version.static_size; + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!u.version.sanitize (c))) return_trace (false); + switch (u.version.major) { + case 1: return_trace (u.version1.sanitize (c)); +#ifndef HB_NO_BEYOND_64K + case 2: return_trace (u.version2.sanitize (c)); +#endif + default: return_trace (true); + } + } + + bool subset (hb_subset_context_t *c) const + { + switch (u.version.major) { + case 1: return u.version1.subset (c); +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.subset (c); +#endif + default: return false; + } + } + + bool has_glyph_classes () const + { + switch (u.version.major) { + case 1: return u.version1.glyphClassDef != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.glyphClassDef != 0; +#endif + default: return false; + } + } + const ClassDef &get_glyph_class_def () const + { + switch (u.version.major) { + case 1: return this+u.version1.glyphClassDef; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.glyphClassDef; +#endif + default: return Null(ClassDef); + } + } + bool has_attach_list () const + { + switch (u.version.major) { + case 1: return u.version1.attachList != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.attachList != 0; +#endif + default: return false; + } + } + const AttachList &get_attach_list () const + { + switch (u.version.major) { + case 1: return this+u.version1.attachList; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.attachList; +#endif + default: return Null(AttachList); + } + } + bool has_lig_carets () const + { + switch (u.version.major) { + case 1: return u.version1.ligCaretList != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.ligCaretList != 0; +#endif + default: return false; + } + } + const LigCaretList &get_lig_caret_list () const + { + switch (u.version.major) { + case 1: return this+u.version1.ligCaretList; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.ligCaretList; +#endif + default: return Null(LigCaretList); + } + } + bool has_mark_attachment_types () const + { + switch (u.version.major) { + case 1: return u.version1.markAttachClassDef != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.markAttachClassDef != 0; +#endif + default: return false; + } + } + const ClassDef &get_mark_attach_class_def () const + { + switch (u.version.major) { + case 1: return this+u.version1.markAttachClassDef; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.markAttachClassDef; +#endif + default: return Null(ClassDef); + } + } + bool has_mark_glyph_sets () const + { + switch (u.version.major) { + case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.markGlyphSetsDef != 0; +#endif + default: return false; + } + } + const MarkGlyphSets &get_mark_glyph_sets () const + { + switch (u.version.major) { + case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.markGlyphSetsDef; +#endif + default: return Null(MarkGlyphSets); + } + } + bool has_var_store () const + { + switch (u.version.major) { + case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0; +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.varStore != 0; +#endif + default: return false; + } + } + const VariationStore &get_var_store () const + { + switch (u.version.major) { + case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore); +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.varStore; +#endif + default: return Null(VariationStore); + } + } + + + bool has_data () const { return u.version.to_int (); } unsigned int get_glyph_class (hb_codepoint_t glyph) const - { return (this+glyphClassDef).get_class (glyph); } + { return get_glyph_class_def ().get_class (glyph); } void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const - { (this+glyphClassDef).collect_class (glyphs, klass); } + { get_glyph_class_def ().collect_class (glyphs, klass); } - bool has_mark_attachment_types () const { return markAttachClassDef != 0; } unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const - { return (this+markAttachClassDef).get_class (glyph); } + { return get_mark_attach_class_def ().get_class (glyph); } - bool has_attach_points () const { return attachList != 0; } unsigned int get_attach_points (hb_codepoint_t glyph_id, unsigned int start_offset, unsigned int *point_count /* IN/OUT */, unsigned int *point_array /* OUT */) const - { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); } + { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); } - bool has_lig_carets () const { return ligCaretList != 0; } unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const - { return (this+ligCaretList).get_lig_carets (font, - direction, glyph_id, get_var_store(), - start_offset, caret_count, caret_array); } + { return get_lig_caret_list ().get_lig_carets (font, + direction, glyph_id, get_var_store(), + start_offset, caret_count, caret_array); } - bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const - { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } - - bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; } - const VariationStore &get_var_store () const - { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); } + { return get_mark_glyph_sets ().covers (set_index, glyph_id); } /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing * glyph class and other bits, and high 8-bit the mark attachment type (if any). @@ -599,20 +842,13 @@ struct GDEF hb_blob_ptr_t<GDEF> table; }; - unsigned int get_size () const - { - return min_size + - (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + - (version.to_int () >= 0x00010003u ? varStore.static_size : 0); - } - void collect_variation_indices (hb_collect_variation_indices_context_t *c) const - { (this+ligCaretList).collect_variation_indices (c); } + { get_lig_caret_list ().collect_variation_indices (c); } void remap_layout_variation_indices (const hb_set_t *layout_variation_indices, hb_map_t *layout_variation_idx_map /* OUT */) const { - if (version.to_int () < 0x00010003u || !varStore) return; + if (!has_var_store ()) return; if (layout_variation_indices->is_empty ()) return; unsigned new_major = 0, new_minor = 0; @@ -620,7 +856,7 @@ struct GDEF for (unsigned idx : layout_variation_indices->iter ()) { uint16_t major = idx >> 16; - if (major >= (this+varStore).get_sub_table_count ()) break; + if (major >= get_var_store ().get_sub_table_count ()) break; if (major != last_major) { new_minor = 0; @@ -634,84 +870,16 @@ struct GDEF } } - bool subset (hb_subset_context_t *c) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->embed (*this); - if (unlikely (!out)) return_trace (false); - - bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); - bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); - bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); - bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); - - bool subset_markglyphsetsdef = true; - if (version.to_int () >= 0x00010002u) - { - subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); - if (!subset_markglyphsetsdef && - version.to_int () == 0x00010002u) - out->version.minor = 0; - } - - bool subset_varstore = true; - if (version.to_int () >= 0x00010003u) - { - subset_varstore = out->varStore.serialize_subset (c, varStore, this); - if (!subset_varstore && version.to_int () == 0x00010003u) - out->version.minor = 2; - } - - return_trace (subset_glyphclassdef || subset_attachlist || - subset_ligcaretlist || subset_markattachclassdef || - (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || - (out->version.to_int () >= 0x00010003u && subset_varstore)); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (version.sanitize (c) && - likely (version.major == 1) && - glyphClassDef.sanitize (c, this) && - attachList.sanitize (c, this) && - ligCaretList.sanitize (c, this) && - markAttachClassDef.sanitize (c, this) && - (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && - (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); - } - protected: - FixedVersion<>version; /* Version of the GDEF table--currently - * 0x00010003u */ - Offset16To<ClassDef> - glyphClassDef; /* Offset to class definition table - * for glyph type--from beginning of - * GDEF header (may be Null) */ - Offset16To<AttachList> - attachList; /* Offset to list of glyphs with - * attachment points--from beginning - * of GDEF header (may be Null) */ - Offset16To<LigCaretList> - ligCaretList; /* Offset to list of positioning points - * for ligature carets--from beginning - * of GDEF header (may be Null) */ - Offset16To<ClassDef> - markAttachClassDef; /* Offset to class definition table for - * mark attachment type--from beginning - * of GDEF header (may be Null) */ - Offset16To<MarkGlyphSets> - markGlyphSetsDef; /* Offset to the table of mark set - * definitions--from beginning of GDEF - * header (may be NULL). Introduced - * in version 0x00010002. */ - Offset32To<VariationStore> - varStore; /* Offset to the table of Item Variation - * Store--from beginning of GDEF - * header (may be NULL). Introduced - * in version 0x00010003. */ + union { + FixedVersion<> version; /* Version identifier */ + GDEFVersion1_2<SmallTypes> version1; +#ifndef HB_NO_BEYOND_64K + GDEFVersion1_2<MediumTypes> version2; +#endif + } u; public: - DEFINE_SIZE_MIN (12); + DEFINE_SIZE_MIN (4); }; struct GDEF_accelerator_t : GDEF::accelerator_t { diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh index 064d31cdff..8fe987fc50 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -29,11 +29,11 @@ #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH #define HB_OT_LAYOUT_GPOS_TABLE_HH -#include "OT/Layout/GPOS.hh" +#include "OT/Layout/GPOS/GPOS.hh" namespace OT { - -using Layout::GPOS_impl::PosLookup; +namespace Layout { +namespace GPOS_impl { // TODO(garretrieger): Move into new layout directory. /* Out-of-class implementation for methods recursing */ @@ -68,6 +68,8 @@ inline bool PosLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply } #endif +} /* namespace GPOS_impl */ +} /* namespace Layout */ } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh index 462542025b..50301ff1d9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -32,9 +32,8 @@ #include "OT/Layout/GSUB/GSUB.hh" namespace OT { - -using Layout::GSUB::SubstLookup; -using Layout::GSUB::ExtensionSubst; +namespace Layout { +namespace GSUB_impl { // TODO(garretrieger): Move into the new layout directory. /* Out-of-class implementation for methods recursing */ @@ -82,7 +81,8 @@ inline bool SubstLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_app } #endif - +} /* namespace GSUB_impl */ +} /* namespace Layout */ } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 31da498652..c77ec12fbe 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -150,7 +150,7 @@ struct hb_closure_context_t : bool pop_cur_done_glyphs () { - if (active_glyphs_stack.length < 1) + if (!active_glyphs_stack) return false; active_glyphs_stack.pop (); @@ -409,7 +409,7 @@ struct hb_ot_apply_context_t : match_func (nullptr), match_data (nullptr) {} - typedef bool (*match_func_t) (hb_glyph_info_t &info, const HBUINT16 &value, const void *data); + typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data); void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } @@ -428,14 +428,14 @@ struct hb_ot_apply_context_t : }; may_match_t may_match (hb_glyph_info_t &info, - const HBUINT16 *glyph_data) const + hb_codepoint_t glyph_data) const { if (!(info.mask & mask) || (syllable && syllable != info.syllable ())) return MATCH_NO; if (match_func) - return match_func (info, *glyph_data, match_data) ? MATCH_YES : MATCH_NO; + return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO; return MATCH_MAYBE; } @@ -476,7 +476,10 @@ struct hb_ot_apply_context_t : void init (hb_ot_apply_context_t *c_, bool context_match = false) { c = c_; - match_glyph_data = nullptr; + match_glyph_data16 = nullptr; +#ifndef HB_NO_BEYOND_64K + match_glyph_data24 = nullptr; +#endif matcher.set_match_func (nullptr, nullptr); matcher.set_lookup_props (c->lookup_props); /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */ @@ -491,12 +494,24 @@ struct hb_ot_apply_context_t : matcher.set_lookup_props (lookup_props); } void set_match_func (matcher_t::match_func_t match_func_, - const void *match_data_, - const HBUINT16 glyph_data[]) + const void *match_data_) { matcher.set_match_func (match_func_, match_data_); - match_glyph_data = glyph_data; } + void set_glyph_data (const HBUINT16 glyph_data[]) + { + match_glyph_data16 = glyph_data; +#ifndef HB_NO_BEYOND_64K + match_glyph_data24 = nullptr; +#endif + } +#ifndef HB_NO_BEYOND_64K + void set_glyph_data (const HBUINT24 glyph_data[]) + { + match_glyph_data16 = nullptr; + match_glyph_data24 = glyph_data; + } +#endif void reset (unsigned int start_index_, unsigned int num_items_) @@ -510,7 +525,7 @@ struct hb_ot_apply_context_t : void reject () { num_items++; - if (match_glyph_data) match_glyph_data--; + backup_glyph_data (); } matcher_t::may_skip_t @@ -529,13 +544,13 @@ struct hb_ot_apply_context_t : if (unlikely (skip == matcher_t::SKIP_YES)) continue; - matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); + matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ()); if (match == matcher_t::MATCH_YES || (match == matcher_t::MATCH_MAYBE && skip == matcher_t::SKIP_NO)) { num_items--; - if (match_glyph_data) match_glyph_data++; + advance_glyph_data (); return true; } @@ -562,13 +577,13 @@ struct hb_ot_apply_context_t : if (unlikely (skip == matcher_t::SKIP_YES)) continue; - matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); + matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ()); if (match == matcher_t::MATCH_YES || (match == matcher_t::MATCH_MAYBE && skip == matcher_t::SKIP_NO)) { num_items--; - if (match_glyph_data) match_glyph_data++; + advance_glyph_data (); return true; } @@ -584,11 +599,43 @@ struct hb_ot_apply_context_t : return false; } + hb_codepoint_t + get_glyph_data () + { + if (match_glyph_data16) return *match_glyph_data16; +#ifndef HB_NO_BEYOND_64K + else + if (match_glyph_data24) return *match_glyph_data24; +#endif + return 0; + } + void + advance_glyph_data () + { + if (match_glyph_data16) match_glyph_data16++; +#ifndef HB_NO_BEYOND_64K + else + if (match_glyph_data24) match_glyph_data24++; +#endif + } + void + backup_glyph_data () + { + if (match_glyph_data16) match_glyph_data16--; +#ifndef HB_NO_BEYOND_64K + else + if (match_glyph_data24) match_glyph_data24--; +#endif + } + unsigned int idx; protected: hb_ot_apply_context_t *c; matcher_t matcher; - const HBUINT16 *match_glyph_data; + const HBUINT16 *match_glyph_data16; +#ifndef HB_NO_BEYOND_64K + const HBUINT24 *match_glyph_data24; +#endif unsigned int num_items; unsigned int end; @@ -941,10 +988,10 @@ struct hb_accelerate_subtables_context_t : }; -typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data); +typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data); typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs); -typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data); -typedef bool (*match_func_t) (hb_glyph_info_t &info, const HBUINT16 &value, const void *data); +typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data); +typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data); struct ContextClosureFuncs { @@ -965,18 +1012,19 @@ struct ChainContextApplyFuncs }; -static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED) +static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED) { return glyphs->has (value); } -static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data) +static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); return class_def.intersects_class (glyphs, value); } -static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data) +static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data) { - const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; + Offset16To<Coverage> coverage; + coverage = value; return (data+coverage).intersects (glyphs); } @@ -995,60 +1043,63 @@ static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const vo { Offset16To<Coverage> coverage; coverage = value; - (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs); + (data+coverage).intersect_set (*glyphs, *intersected_glyphs); } +template <typename HBUINT> static inline bool array_is_subset_of (const hb_set_t *glyphs, unsigned int count, - const HBUINT16 values[], + const HBUINT values[], intersects_func_t intersects_func, const void *intersects_data) { - for (const HBUINT16 &_ : + hb_iter (values, count)) + for (const auto &_ : + hb_iter (values, count)) if (!intersects_func (glyphs, _, intersects_data)) return false; return true; } -static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED) +static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED) { glyphs->add (value); } -static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data) +static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); class_def.collect_class (glyphs, value); } -static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data) +static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data) { - const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; + Offset16To<Coverage> coverage; + coverage = value; (data+coverage).collect_coverage (glyphs); } +template <typename HBUINT> static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED, hb_set_t *glyphs, unsigned int count, - const HBUINT16 values[], + const HBUINT values[], collect_glyphs_func_t collect_func, const void *collect_data) { return + hb_iter (values, count) - | hb_apply ([&] (const HBUINT16 &_) { collect_func (glyphs, _, collect_data); }) + | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); }) ; } -static inline bool match_glyph (hb_glyph_info_t &info, const HBUINT16 &value, const void *data HB_UNUSED) +static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED) { return info.codepoint == value; } -static inline bool match_class (hb_glyph_info_t &info, const HBUINT16 &value, const void *data) +static inline bool match_class (hb_glyph_info_t &info, unsigned value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); return class_def.get_class (info.codepoint) == value; } -static inline bool match_class_cached (hb_glyph_info_t &info, const HBUINT16 &value, const void *data) +static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data) { unsigned klass = info.syllable(); if (klass < 255) @@ -1059,15 +1110,17 @@ static inline bool match_class_cached (hb_glyph_info_t &info, const HBUINT16 &va info.syllable() = klass; return klass == value; } -static inline bool match_coverage (hb_glyph_info_t &info, const HBUINT16 &value, const void *data) +static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data) { - const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; + Offset16To<Coverage> coverage; + coverage = value; return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED; } +template <typename HBUINT> static inline bool would_match_input (hb_would_apply_context_t *c, unsigned int count, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data) { @@ -1084,9 +1137,10 @@ static inline bool would_match_input (hb_would_apply_context_t *c, return true; } +template <typename HBUINT> static inline bool match_input (hb_ot_apply_context_t *c, unsigned int count, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, unsigned int *end_position, @@ -1101,7 +1155,8 @@ static inline bool match_input (hb_ot_apply_context_t *c, hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, count - 1); - skippy_iter.set_match_func (match_func, match_data, input); + skippy_iter.set_match_func (match_func, match_data); + skippy_iter.set_glyph_data (input); /* * This is perhaps the trickiest part of OpenType... Remarks: @@ -1322,9 +1377,10 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, return_trace (true); } +template <typename HBUINT> static inline bool match_backtrack (hb_ot_apply_context_t *c, unsigned int count, - const HBUINT16 backtrack[], + const HBUINT backtrack[], match_func_t match_func, const void *match_data, unsigned int *match_start) @@ -1333,7 +1389,8 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c, hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->backtrack_len (), count); - skippy_iter.set_match_func (match_func, match_data, backtrack); + skippy_iter.set_match_func (match_func, match_data); + skippy_iter.set_glyph_data (backtrack); for (unsigned int i = 0; i < count; i++) { @@ -1349,9 +1406,10 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c, return_trace (true); } +template <typename HBUINT> static inline bool match_lookahead (hb_ot_apply_context_t *c, unsigned int count, - const HBUINT16 lookahead[], + const HBUINT lookahead[], match_func_t match_func, const void *match_data, unsigned int start_index, @@ -1361,7 +1419,8 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c, hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (start_index - 1, count); - skippy_iter.set_match_func (match_func, match_data, lookahead); + skippy_iter.set_match_func (match_func, match_data); + skippy_iter.set_glyph_data (lookahead); for (unsigned int i = 0; i < count; i++) { @@ -1425,8 +1484,9 @@ static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c, enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 }; +template <typename HBUINT> static void context_closure_recurse_lookups (hb_closure_context_t *c, - unsigned inputCount, const HBUINT16 input[], + unsigned inputCount, const HBUINT input[], unsigned lookupCount, const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */, unsigned value, @@ -1542,9 +1602,28 @@ static inline void apply_lookup (hb_ot_apply_context_t *c, if (unlikely (buffer->max_ops <= 0)) break; + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + if (buffer->have_output) + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "recursing to lookup %u at %d", + (unsigned) lookupRecord[i].lookupListIndex, + buffer->idx); + } + if (!c->recurse (lookupRecord[i].lookupListIndex)) continue; + if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) + { + if (buffer->have_output) + c->buffer->sync_so_far (); + c->buffer->message (c->font, + "recursed to lookup %u", + (unsigned) lookupRecord[i].lookupListIndex); + } + unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); int delta = new_len - orig_len; @@ -1645,9 +1724,10 @@ struct ContextApplyLookupContext const void *match_data; }; +template <typename HBUINT> static inline bool context_intersects (const hb_set_t *glyphs, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ ContextClosureLookupContext &lookup_context) { return array_is_subset_of (glyphs, @@ -1655,9 +1735,10 @@ static inline bool context_intersects (const hb_set_t *glyphs, lookup_context.funcs.intersects, lookup_context.intersects_data); } +template <typename HBUINT> static inline void context_closure_lookup (hb_closure_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */ @@ -1675,9 +1756,10 @@ static inline void context_closure_lookup (hb_closure_context_t *c, lookup_context.funcs.intersected_glyphs); } +template <typename HBUINT> static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], ContextCollectGlyphsLookupContext &lookup_context) @@ -1689,9 +1771,10 @@ static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c lookupCount, lookupRecord); } +template <typename HBUINT> static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, ContextApplyLookupContext &lookup_context) @@ -1700,9 +1783,11 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data); } + +template <typename HBUINT> static inline bool context_apply_lookup (hb_ot_apply_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], ContextApplyLookupContext &lookup_context) @@ -1728,6 +1813,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c, } } +template <typename Types> struct Rule { bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const @@ -1741,8 +1827,8 @@ struct Rule { if (unlikely (c->lookup_limit_exceeded ())) return; - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); context_closure_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, @@ -1755,16 +1841,16 @@ struct Rule if (unlikely (c->lookup_limit_exceeded ())) return; if (!intersects (c->glyphs, lookup_context)) return; - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array (inputCount ? inputCount - 1 : 0)); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); recurse_lookups (c, lookupCount, lookupRecord.arrayZ); } void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const { - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array (inputCount ? inputCount - 1 : 0)); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); context_collect_glyphs_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, @@ -1774,8 +1860,8 @@ struct Rule bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array (inputCount ? inputCount - 1 : 0)); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, @@ -1786,8 +1872,8 @@ struct Rule ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array (inputCount ? inputCount - 1 : 0)); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context)); } @@ -1800,7 +1886,7 @@ struct Rule if (unlikely (!c->extend_min (out))) return_trace (false); out->inputCount = inputCount; - const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1); + const auto input = inputZ.as_array (inputCount - 1); for (const auto org : input) { HBUINT16 d; @@ -1808,8 +1894,8 @@ struct Rule c->copy (d); } - const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> - (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); + const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> + (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map); return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); @@ -1821,7 +1907,7 @@ struct Rule { TRACE_SUBSET (this); if (unlikely (!inputCount)) return_trace (false); - const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1); + const auto input = inputZ.as_array (inputCount - 1); const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map; if (!hb_all (input, mapping)) return_trace (false); @@ -1844,7 +1930,7 @@ struct Rule * glyph sequence--includes the first * glyph */ HBUINT16 lookupCount; /* Number of LookupRecords */ - UnsizedArrayOf<HBUINT16> + UnsizedArrayOf<typename Types::HBUINT> inputZ; /* Array of match inputs--start with * second glyph */ /*UnsizedArrayOf<LookupRecord> @@ -1854,8 +1940,11 @@ struct Rule DEFINE_SIZE_ARRAY (4, inputZ); }; +template <typename Types> struct RuleSet { + using Rule = OT::Rule<Types>; + bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const { @@ -1968,8 +2057,11 @@ struct RuleSet }; -struct ContextFormat1 +template <typename Types> +struct ContextFormat1_4 { + using RuleSet = OT::RuleSet<Types>; + bool intersects (const hb_set_t *glyphs) const { struct ContextClosureLookupContext lookup_context = { @@ -1993,9 +2085,8 @@ struct ContextFormat1 void closure (hb_closure_context_t *c) const { - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), - cur_active_glyphs); + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); struct ContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -2106,19 +2197,22 @@ struct ContextFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - Array16OfOffset16To<RuleSet> + Array16Of<typename Types::template OffsetTo<RuleSet>> ruleSet; /* Array of RuleSet tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, ruleSet); + DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet); }; -struct ContextFormat2 +template <typename Types> +struct ContextFormat2_5 { + using RuleSet = OT::RuleSet<SmallTypes>; + bool intersects (const hb_set_t *glyphs) const { if (!(this+coverage).intersects (glyphs)) @@ -2133,7 +2227,7 @@ struct ContextFormat2 }; hb_set_t retained_coverage_glyphs; - (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs); + (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs); hb_set_t coverage_glyph_classes; class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); @@ -2159,8 +2253,8 @@ struct ContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); const ClassDef &class_def = this+classDef; @@ -2175,7 +2269,7 @@ struct ContextFormat2 | hb_filter ([&] (unsigned _) { return class_def.intersects_class (&c->parent_active_glyphs (), _); }, hb_first) - | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _) + | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _) { const RuleSet& rule_set = this+_.second; rule_set.closure (c, _.first, lookup_context); @@ -2305,7 +2399,7 @@ struct ContextFormat2 const hb_set_t* glyphset = c->plan->glyphset_gsub (); hb_set_t retained_coverage_glyphs; - (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs); + (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs); hb_set_t coverage_glyph_classes; (this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); @@ -2351,22 +2445,24 @@ struct ContextFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> classDef; /* Offset to glyph ClassDef table--from * beginning of table */ - Array16OfOffset16To<RuleSet> + Array16Of<typename Types::template OffsetTo<RuleSet>> ruleSet; /* Array of RuleSet tables * ordered by class */ public: - DEFINE_SIZE_ARRAY (8, ruleSet); + DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet); }; struct ContextFormat3 { + using RuleSet = OT::RuleSet<SmallTypes>; + bool intersects (const hb_set_t *glyphs) const { if (!(this+coverageZ[0]).intersects (glyphs)) @@ -2390,8 +2486,8 @@ struct ContextFormat3 if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); @@ -2483,7 +2579,7 @@ struct ContextFormat3 if (!o->serialize_subset (c, offset, this)) return_trace (false); } - const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount)); + const auto& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount)); const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; @@ -2530,16 +2626,24 @@ struct Context case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BEYOND_64K + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } protected: union { - HBUINT16 format; /* Format identifier */ - ContextFormat1 format1; - ContextFormat2 format2; - ContextFormat3 format3; + HBUINT16 format; /* Format identifier */ + ContextFormat1_4<SmallTypes> format1; + ContextFormat2_5<SmallTypes> format2; + ContextFormat3 format3; +#ifndef HB_NO_BEYOND_64K + ContextFormat1_4<MediumTypes> format4; + ContextFormat2_5<MediumTypes> format5; +#endif } u; }; @@ -2565,13 +2669,14 @@ struct ChainContextApplyLookupContext const void *match_data[3]; }; +template <typename HBUINT> static inline bool chain_context_intersects (const hb_set_t *glyphs, unsigned int backtrackCount, - const HBUINT16 backtrack[], + const HBUINT backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const HBUINT16 lookahead[], + const HBUINT lookahead[], ChainContextClosureLookupContext &lookup_context) { return array_is_subset_of (glyphs, @@ -2585,13 +2690,14 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs, lookup_context.funcs.intersects, lookup_context.intersects_data[2]); } +template <typename HBUINT> static inline void chain_context_closure_lookup (hb_closure_context_t *c, unsigned int backtrackCount, - const HBUINT16 backtrack[], + const HBUINT backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const HBUINT16 lookahead[], + const HBUINT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], unsigned value, @@ -2611,13 +2717,14 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, lookup_context.funcs.intersected_glyphs); } +template <typename HBUINT> static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int backtrackCount, - const HBUINT16 backtrack[], + const HBUINT backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const HBUINT16 lookahead[], + const HBUINT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextCollectGlyphsLookupContext &lookup_context) @@ -2635,13 +2742,14 @@ static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex lookupCount, lookupRecord); } +template <typename HBUINT> static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c, unsigned int backtrackCount, - const HBUINT16 backtrack[] HB_UNUSED, + const HBUINT backtrack[] HB_UNUSED, unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const HBUINT16 lookahead[] HB_UNUSED, + const HBUINT lookahead[] HB_UNUSED, unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, ChainContextApplyLookupContext &lookup_context) @@ -2652,13 +2760,14 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c lookup_context.funcs.match[1], lookup_context.match_data[1]); } +template <typename HBUINT> static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c, unsigned int backtrackCount, - const HBUINT16 backtrack[], + const HBUINT backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const HBUINT16 input[], /* Array of input values--start with second glyph */ + const HBUINT input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const HBUINT16 lookahead[], + const HBUINT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) @@ -2697,12 +2806,13 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c, return true; } +template <typename Types> struct ChainRule { bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const { - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); return chain_context_intersects (glyphs, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2715,9 +2825,9 @@ struct ChainRule { if (unlikely (c->lookup_limit_exceeded ())) return; - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); chain_context_closure_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2733,18 +2843,18 @@ struct ChainRule if (unlikely (c->lookup_limit_exceeded ())) return; if (!intersects (c->glyphs, lookup_context)) return; - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); recurse_lookups (c, lookup.len, lookup.arrayZ); } void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const { - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); chain_context_collect_glyphs_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2756,9 +2866,9 @@ struct ChainRule bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); return chain_context_would_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2769,9 +2879,9 @@ struct ChainRule bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); return_trace (chain_context_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2804,22 +2914,22 @@ struct ChainRule serialize_array (c, backtrack.len, + backtrack.iter () | hb_map (mapping)); - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (input_map) mapping = input_map; serialize_array (c, input.lenP1, + input.iter () | hb_map (mapping)); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); if (lookahead_map) mapping = lookahead_map; serialize_array (c, lookahead.len, + lookahead.iter () | hb_map (mapping)); - const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); - HBUINT16* lookupCount = c->embed (&(lookupRecord.len)); + HBUINT16* lookupCount = c->embed (&(lookup.len)); if (!lookupCount) return_trace (false); - unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map); + unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map); return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } @@ -2831,8 +2941,8 @@ struct ChainRule { TRACE_SUBSET (this); - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); if (!backtrack_map) { @@ -2861,23 +2971,23 @@ struct ChainRule { TRACE_SANITIZE (this); if (!backtrack.sanitize (c)) return_trace (false); - const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (!input.sanitize (c)) return_trace (false); - const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); if (!lookahead.sanitize (c)) return_trace (false); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); return_trace (lookup.sanitize (c)); } protected: - Array16Of<HBUINT16> + Array16Of<typename Types::HBUINT> backtrack; /* Array of backtracking values * (to be matched before the input * sequence) */ - HeadlessArrayOf<HBUINT16> + HeadlessArrayOf<typename Types::HBUINT> inputX; /* Array of input values (start with * second glyph) */ - Array16Of<HBUINT16> + Array16Of<typename Types::HBUINT> lookaheadX; /* Array of lookahead values's (to be * matched after the input sequence) */ Array16Of<LookupRecord> @@ -2887,8 +2997,11 @@ struct ChainRule DEFINE_SIZE_MIN (8); }; +template <typename Types> struct ChainRuleSet { + using ChainRule = OT::ChainRule<Types>; + bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const { return @@ -3001,8 +3114,11 @@ struct ChainRuleSet DEFINE_SIZE_ARRAY (2, rule); }; -struct ChainContextFormat1 +template <typename Types> +struct ChainContextFormat1_4 { + using ChainRuleSet = OT::ChainRuleSet<Types>; + bool intersects (const hb_set_t *glyphs) const { struct ChainContextClosureLookupContext lookup_context = { @@ -3026,8 +3142,8 @@ struct ChainContextFormat1 void closure (hb_closure_context_t *c) const { - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); struct ChainContextClosureLookupContext lookup_context = { @@ -3138,18 +3254,21 @@ struct ChainContextFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - Array16OfOffset16To<ChainRuleSet> + Array16Of<typename Types::template OffsetTo<ChainRuleSet>> ruleSet; /* Array of ChainRuleSet tables * ordered by Coverage Index */ public: - DEFINE_SIZE_ARRAY (6, ruleSet); + DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet); }; -struct ChainContextFormat2 +template <typename Types> +struct ChainContextFormat2_5 { + using ChainRuleSet = OT::ChainRuleSet<SmallTypes>; + bool intersects (const hb_set_t *glyphs) const { if (!(this+coverage).intersects (glyphs)) @@ -3168,7 +3287,7 @@ struct ChainContextFormat2 }; hb_set_t retained_coverage_glyphs; - (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs); + (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs); hb_set_t coverage_glyph_classes; input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); @@ -3193,8 +3312,8 @@ struct ChainContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); @@ -3214,7 +3333,7 @@ struct ChainContextFormat2 | hb_filter ([&] (unsigned _) { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); }, hb_first) - | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _) + | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _) { const ChainRuleSet& chainrule_set = this+_.second; chainrule_set.closure (c, _.first, lookup_context); @@ -3330,7 +3449,7 @@ struct ChainContextFormat2 const ClassDef &input_class_def = this+inputClassDef; const ClassDef &lookahead_class_def = this+lookaheadClassDef; - /* For ChainContextFormat2 we cache the LookaheadClassDef instead of InputClassDef. + /* For ChainContextFormat2_5 we cache the LookaheadClassDef instead of InputClassDef. * The reason is that most heavy fonts want to identify a glyph in context and apply * a lookup to it. In this scenario, the length of the input sequence is one, whereas * the lookahead / backtrack are typically longer. The one glyph in input sequence is @@ -3378,7 +3497,7 @@ struct ChainContextFormat2 const hb_set_t* glyphset = c->plan->glyphset_gsub (); hb_set_t retained_coverage_glyphs; - (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs); + (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs); hb_set_t coverage_glyph_classes; (this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); @@ -3433,38 +3552,40 @@ struct ChainContextFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - Offset16To<Coverage> + typename Types::template OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> backtrackClassDef; /* Offset to glyph ClassDef table * containing backtrack sequence * data--from beginning of table */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> inputClassDef; /* Offset to glyph ClassDef * table containing input sequence * data--from beginning of table */ - Offset16To<ClassDef> + typename Types::template OffsetTo<ClassDef> lookaheadClassDef; /* Offset to glyph ClassDef table * containing lookahead sequence * data--from beginning of table */ - Array16OfOffset16To<ChainRuleSet> + Array16Of<typename Types::template OffsetTo<ChainRuleSet>> ruleSet; /* Array of ChainRuleSet tables * ordered by class */ public: - DEFINE_SIZE_ARRAY (12, ruleSet); + DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet); }; struct ChainContextFormat3 { + using RuleSet = OT::RuleSet<SmallTypes>; + bool intersects (const hb_set_t *glyphs) const { - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (!(this+input[0]).intersects (glyphs)) return false; - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); struct ChainContextClosureLookupContext lookup_context = { {intersects_coverage, intersected_coverage_glyphs}, ContextFormat::CoverageBasedContext, @@ -3482,18 +3603,18 @@ struct ChainContextFormat3 void closure (hb_closure_context_t *c) const { - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (!(this+input[0]).intersects (c->glyphs)) return; - hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); struct ChainContextClosureLookupContext lookup_context = { {intersects_coverage, intersected_coverage_glyphs}, ContextFormat::CoverageBasedContext, @@ -3514,9 +3635,9 @@ struct ChainContextFormat3 if (!intersects (c->glyphs)) return; - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); recurse_lookups (c, lookup.len, lookup.arrayZ); } @@ -3524,12 +3645,13 @@ struct ChainContextFormat3 void collect_glyphs (hb_collect_glyphs_context_t *c) const { - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); (this+input[0]).collect_coverage (c->input); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); + struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_coverage}, {this, this, this} @@ -3544,9 +3666,9 @@ struct ChainContextFormat3 bool would_apply (hb_would_apply_context_t *c) const { - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &input = StructAfter<decltype (inputX)> (backtrack); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {{match_coverage, match_coverage, match_coverage}}, {this, this, this} @@ -3560,20 +3682,20 @@ struct ChainContextFormat3 const Coverage &get_coverage () const { - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); return this+input[0]; } bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {{match_coverage, match_coverage, match_coverage}}, {this, this, this} @@ -3615,21 +3737,21 @@ struct ChainContextFormat3 if (!serialize_coverage_offsets (c, backtrack.iter (), this)) return_trace (false); - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (!serialize_coverage_offsets (c, input.iter (), this)) return_trace (false); - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); if (!serialize_coverage_offsets (c, lookahead.iter (), this)) return_trace (false); - const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; - HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len); + HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len); if (!lookupCount) return_trace (false); - unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map); + unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map); return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } @@ -3637,12 +3759,12 @@ struct ChainContextFormat3 { TRACE_SANITIZE (this); if (!backtrack.sanitize (c, this)) return_trace (false); - const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const auto &input = StructAfter<decltype (inputX)> (backtrack); if (!input.sanitize (c, this)) return_trace (false); if (!input.len) return_trace (false); /* To be consistent with Context. */ - const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); if (!lookahead.sanitize (c, this)) return_trace (false); - const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); + const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); return_trace (lookup.sanitize (c)); } @@ -3678,16 +3800,24 @@ struct ChainContext case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); +#ifndef HB_NO_BEYOND_64K + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); +#endif default:return_trace (c->default_return_value ()); } } protected: union { - HBUINT16 format; /* Format identifier */ - ChainContextFormat1 format1; - ChainContextFormat2 format2; - ChainContextFormat3 format3; + HBUINT16 format; /* Format identifier */ + ChainContextFormat1_4<SmallTypes> format1; + ChainContextFormat2_5<SmallTypes> format2; + ChainContextFormat3 format3; +#ifndef HB_NO_BEYOND_64K + ChainContextFormat1_4<MediumTypes> format4; + ChainContextFormat2_5<MediumTypes> format5; +#endif } u; }; @@ -3871,39 +4001,214 @@ struct hb_ot_layout_lookup_accelerator_t #endif }; +template <typename Types> +struct GSUBGPOSVersion1_2 +{ + friend struct GSUBGPOS; + + protected: + FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set + * to 0x00010000u */ + typename Types:: template OffsetTo<ScriptList> + scriptList; /* ScriptList table */ + typename Types::template OffsetTo<FeatureList> + featureList; /* FeatureList table */ + typename Types::template OffsetTo<LookupList<Types>> + lookupList; /* LookupList table */ + Offset32To<FeatureVariations> + featureVars; /* Offset to Feature Variations + table--from beginning of table + * (may be NULL). Introduced + * in version 0x00010001. */ + public: + DEFINE_SIZE_MIN (4 + 3 * Types::size); + + unsigned int get_size () const + { + return min_size + + (version.to_int () >= 0x00010001u ? featureVars.static_size : 0); + } + + const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const + { + return &lookupList; + } + + template <typename TLookup> + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList; + if (unlikely (!(scriptList.sanitize (c, this) && + featureList.sanitize (c, this) && + reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this)))) + return_trace (false); + +#ifndef HB_NO_VAR + if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this)))) + return_trace (false); +#endif + + return_trace (true); + } + + template <typename TLookup> + bool subset (hb_subset_layout_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->subset_context->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList; + reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList) + .serialize_subset (c->subset_context, + reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList), + this, + c); + + reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList) + .serialize_subset (c->subset_context, + reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList), + this, + c); + + out->scriptList.serialize_subset (c->subset_context, + scriptList, + this, + c); + +#ifndef HB_NO_VAR + if (version.to_int () >= 0x00010001u) + { + bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c); + if (!ret && version.major == 1) + { + out->version.major = 1; + out->version.minor = 0; + } + } +#endif + + return_trace (true); + } +}; + struct GSUBGPOS { - bool has_data () const { return version.to_int (); } + unsigned int get_size () const + { + switch (u.version.major) { + case 1: return u.version1.get_size (); +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.get_size (); +#endif + default: return u.version.static_size; + } + } + + template <typename TLookup> + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!u.version.sanitize (c))) return_trace (false); + switch (u.version.major) { + case 1: return_trace (u.version1.sanitize<TLookup> (c)); +#ifndef HB_NO_BEYOND_64K + case 2: return_trace (u.version2.sanitize<TLookup> (c)); +#endif + default: return_trace (true); + } + } + + template <typename TLookup> + bool subset (hb_subset_layout_context_t *c) const + { + switch (u.version.major) { + case 1: return u.version1.subset<TLookup> (c); +#ifndef HB_NO_BEYOND_64K + case 2: return u.version2.subset<TLookup> (c); +#endif + default: return false; + } + } + + const ScriptList &get_script_list () const + { + switch (u.version.major) { + case 1: return this+u.version1.scriptList; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.scriptList; +#endif + default: return Null (ScriptList); + } + } + const FeatureList &get_feature_list () const + { + switch (u.version.major) { + case 1: return this+u.version1.featureList; +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.featureList; +#endif + default: return Null (FeatureList); + } + } + unsigned int get_lookup_count () const + { + switch (u.version.major) { + case 1: return (this+u.version1.lookupList).len; +#ifndef HB_NO_BEYOND_64K + case 2: return (this+u.version2.lookupList).len; +#endif + default: return 0; + } + } + const Lookup& get_lookup (unsigned int i) const + { + switch (u.version.major) { + case 1: return (this+u.version1.lookupList)[i]; +#ifndef HB_NO_BEYOND_64K + case 2: return (this+u.version2.lookupList)[i]; +#endif + default: return Null (Lookup); + } + } + const FeatureVariations &get_feature_variations () const + { + switch (u.version.major) { + case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations)); +#ifndef HB_NO_BEYOND_64K + case 2: return this+u.version2.featureVars; +#endif + default: return Null (FeatureVariations); + } + } + + bool has_data () const { return u.version.to_int (); } unsigned int get_script_count () const - { return (this+scriptList).len; } + { return get_script_list ().len; } const Tag& get_script_tag (unsigned int i) const - { return (this+scriptList).get_tag (i); } + { return get_script_list ().get_tag (i); } unsigned int get_script_tags (unsigned int start_offset, unsigned int *script_count /* IN/OUT */, hb_tag_t *script_tags /* OUT */) const - { return (this+scriptList).get_tags (start_offset, script_count, script_tags); } + { return get_script_list ().get_tags (start_offset, script_count, script_tags); } const Script& get_script (unsigned int i) const - { return (this+scriptList)[i]; } + { return get_script_list ()[i]; } bool find_script_index (hb_tag_t tag, unsigned int *index) const - { return (this+scriptList).find_index (tag, index); } + { return get_script_list ().find_index (tag, index); } unsigned int get_feature_count () const - { return (this+featureList).len; } + { return get_feature_list ().len; } hb_tag_t get_feature_tag (unsigned int i) const - { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); } + { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); } unsigned int get_feature_tags (unsigned int start_offset, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */) const - { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); } + { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); } const Feature& get_feature (unsigned int i) const - { return (this+featureList)[i]; } + { return get_feature_list ()[i]; } bool find_feature_index (hb_tag_t tag, unsigned int *index) const - { return (this+featureList).find_index (tag, index); } - - unsigned int get_lookup_count () const - { return (this+lookupList).len; } - const Lookup& get_lookup (unsigned int i) const - { return (this+lookupList)[i]; } + { return get_feature_list ().find_index (tag, index); } bool find_variations_index (const int *coords, unsigned int num_coords, unsigned int *index) const @@ -3912,18 +4217,17 @@ struct GSUBGPOS *index = FeatureVariations::NOT_FOUND_INDEX; return false; #endif - return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations)) - .find_index (coords, num_coords, index); + return get_feature_variations ().find_index (coords, num_coords, index); } const Feature& get_feature_variation (unsigned int feature_index, unsigned int variations_index) const { #ifndef HB_NO_VAR if (FeatureVariations::NOT_FOUND_INDEX != variations_index && - version.to_int () >= 0x00010001u) + u.version.to_int () >= 0x00010001u) { - const Feature *feature = (this+featureVars).find_substitute (variations_index, - feature_index); + const Feature *feature = get_feature_variations ().find_substitute (variations_index, + feature_index); if (feature) return *feature; } @@ -3935,8 +4239,7 @@ struct GSUBGPOS hb_set_t *lookup_indexes /* OUT */) const { #ifndef HB_NO_VAR - if (version.to_int () >= 0x00010001u) - (this+featureVars).collect_lookups (feature_indexes, lookup_indexes); + get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes); #endif } @@ -3971,108 +4274,6 @@ struct GSUBGPOS } } - template <typename TLookup> - bool subset (hb_subset_layout_context_t *c) const - { - TRACE_SUBSET (this); - auto *out = c->subset_context->serializer->embed (*this); - if (unlikely (!out)) return_trace (false); - - typedef LookupOffsetList<TLookup> TLookupList; - reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList) - .serialize_subset (c->subset_context, - reinterpret_cast<const Offset16To<TLookupList> &> (lookupList), - this, - c); - - reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList) - .serialize_subset (c->subset_context, - reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList), - this, - c); - - out->scriptList.serialize_subset (c->subset_context, - scriptList, - this, - c); - -#ifndef HB_NO_VAR - if (version.to_int () >= 0x00010001u) - { - bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c); - if (!ret) - { - out->version.major = 1; - out->version.minor = 0; - } - } -#endif - - return_trace (true); - } - - void find_duplicate_features (const hb_map_t *lookup_indices, - const hb_set_t *feature_indices, - hb_map_t *duplicate_feature_map /* OUT */) const - { - if (feature_indices->is_empty ()) return; - hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features; - //find out duplicate features after subset - for (unsigned i : feature_indices->iter ()) - { - hb_tag_t t = get_feature_tag (i); - if (t == HB_MAP_VALUE_INVALID) continue; - if (!unique_features.has (t)) - { - if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()}))) - return; - if (unique_features.has (t)) - unique_features.get (t)->add (i); - duplicate_feature_map->set (i, i); - continue; - } - - bool found = false; - - hb_set_t* same_tag_features = unique_features.get (t); - for (unsigned other_f_index : same_tag_features->iter ()) - { - const Feature& f = get_feature (i); - const Feature& other_f = get_feature (other_f_index); - - auto f_iter = - + hb_iter (f.lookupIndex) - | hb_filter (lookup_indices) - ; - - auto other_f_iter = - + hb_iter (other_f.lookupIndex) - | hb_filter (lookup_indices) - ; - - bool is_equal = true; - for (; f_iter && other_f_iter; f_iter++, other_f_iter++) - { - unsigned a = *f_iter; - unsigned b = *other_f_iter; - if (a != b) { is_equal = false; break; } - } - - if (is_equal == false || f_iter || other_f_iter) continue; - - found = true; - duplicate_feature_map->set (i, other_f_index); - break; - } - - if (found == false) - { - same_tag_features->add (i); - duplicate_feature_map->set (i, i); - } - } - } - void prune_features (const hb_map_t *lookup_indices, /* IN */ hb_set_t *feature_indices /* IN/OUT */) const { @@ -4081,8 +4282,7 @@ struct GSUBGPOS // if the FeatureVariation's table and the alternate version(s) intersect the // set of lookup indices. hb_set_t alternate_feature_indices; - if (version.to_int () >= 0x00010001u) - (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices); + get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices); if (unlikely (alternate_feature_indices.in_error())) { feature_indices->err (); @@ -4115,32 +4315,6 @@ struct GSUBGPOS } } - unsigned int get_size () const - { - return min_size + - (version.to_int () >= 0x00010001u ? featureVars.static_size : 0); - } - - template <typename TLookup> - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - typedef List16OfOffset16To<TLookup> TLookupList; - if (unlikely (!(version.sanitize (c) && - likely (version.major == 1) && - scriptList.sanitize (c, this) && - featureList.sanitize (c, this) && - reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this)))) - return_trace (false); - -#ifndef HB_NO_VAR - if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this)))) - return_trace (false); -#endif - - return_trace (true); - } - template <typename T> struct accelerator_t { @@ -4180,21 +4354,15 @@ struct GSUBGPOS }; protected: - FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set - * to 0x00010000u */ - Offset16To<ScriptList> - scriptList; /* ScriptList table */ - Offset16To<FeatureList> - featureList; /* FeatureList table */ - Offset16To<LookupList> - lookupList; /* LookupList table */ - Offset32To<FeatureVariations> - featureVars; /* Offset to Feature Variations - table--from beginning of table - * (may be NULL). Introduced - * in version 0x00010001. */ + union { + FixedVersion<> version; /* Version identifier */ + GSUBGPOSVersion1_2<SmallTypes> version1; +#ifndef HB_NO_BEYOND_64K + GSUBGPOSVersion1_2<MediumTypes> version2; +#endif + } u; public: - DEFINE_SIZE_MIN (10); + DEFINE_SIZE_MIN (4); }; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 142c843dad..f9c0daa486 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -54,7 +54,7 @@ #include "hb-aat-layout-morx-table.hh" #include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise. -using OT::Layout::GSUB::GSUB; +using OT::Layout::GSUB; using OT::Layout::GPOS; /** @@ -79,7 +79,7 @@ using OT::Layout::GPOS; * Tests whether a face includes any kerning data in the 'kern' table. * Does NOT test for kerning lookups in the GPOS table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ bool @@ -95,7 +95,7 @@ hb_ot_layout_has_kerning (hb_face_t *face) * Tests whether a face includes any state-machine kerning in the 'kern' table. * Does NOT examine the GPOS table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ bool @@ -115,7 +115,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face) * * Does NOT examine the GPOS table. * - * Return value: %true is data found, %false otherwise + * Return value: `true` is data found, `false` otherwise * **/ bool @@ -272,7 +272,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font, * * Tests whether a face has any glyph classes defined in its GDEF table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ hb_bool_t @@ -461,7 +461,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face, * Fetches the index if a given script tag in the specified face's GSUB table * or GPOS table. * - * Return value: %true if the script is found, %false otherwise + * Return value: `true` if the script is found, `false` otherwise * **/ hb_bool_t @@ -535,7 +535,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face, * #HB_OT_LAYOUT_NO_SCRIPT_INDEX. * * Return value: - * %true if one of the requested scripts is selected, %false if a fallback + * `true` if one of the requested scripts is selected, `false` if a fallback * script is selected or if no scripts are selected. * * Since: 2.0.0 @@ -628,7 +628,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face, * Fetches the index for a given feature tag in the specified face's GSUB table * or GPOS table. * - * Return value: %true if the feature is found, %false otherwise + * Return value: `true` if the feature is found, `false` otherwise **/ bool hb_ot_layout_table_find_feature (hb_face_t *face, @@ -695,7 +695,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, * Fetches the index of a given language tag in the specified face's GSUB table * or GPOS table, underneath the specified script tag. * - * Return value: %true if the language tag is found, %false otherwise + * Return value: `true` if the language tag is found, `false` otherwise * * Since: 0.6.0 * Deprecated: 2.0.0 @@ -730,10 +730,10 @@ hb_ot_layout_script_find_language (hb_face_t *face, * in the specified face's GSUB or GPOS table, underneath the specified script * index. * - * If none of the given language tags is found, %false is returned and + * If none of the given language tags is found, `false` is returned and * @language_index is set to the default language index. * - * Return value: %true if one of the given language tags is found, %false otherwise + * Return value: `true` if one of the given language tags is found, `false` otherwise * * Since: 2.0.0 **/ @@ -776,7 +776,7 @@ hb_ot_layout_script_select_language (hb_face_t *face, * Fetches the index of a requested feature in the given face's GSUB or GPOS table, * underneath the specified script and language. * - * Return value: %true if the feature is found, %false otherwise + * Return value: `true` if the feature is found, `false` otherwise * **/ hb_bool_t @@ -807,7 +807,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, * Fetches the tag of a requested feature index in the given face's GSUB or GPOS table, * underneath the specified script and language. * - * Return value: %true if the feature is found, %false otherwise + * Return value: `true` if the feature is found, `false` otherwise * * Since: 0.9.30 **/ @@ -917,7 +917,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, * Fetches the index of a given feature tag in the specified face's GSUB table * or GPOS table, underneath the specified script and language. * - * Return value: %true if the feature is found, %false otherwise + * Return value: `true` if the feature is found, `false` otherwise * **/ hb_bool_t @@ -1314,7 +1314,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, * Fetches a list of feature variations in the specified face's GSUB table * or GPOS table, at the specified variation coordinates. * - * Return value: %true if feature variations were found, %false otherwise. + * Return value: `true` if feature variations were found, `false` otherwise. * **/ hb_bool_t @@ -1377,7 +1377,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, * * Tests whether the specified face includes any GSUB substitutions. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * **/ hb_bool_t @@ -1399,7 +1399,7 @@ hb_ot_layout_has_substitution (hb_face_t *face) * Tests whether a specified lookup in the specified face would * trigger a substitution on the given glyph sequence. * - * Return value: %true if a substitution would be triggered, %false otherwise + * Return value: `true` if a substitution would be triggered, `false` otherwise * * Since: 0.9.7 **/ @@ -1561,7 +1561,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, * * Tests whether the specified face includes any GPOS positioning. * - * Return value: %true if the face has GPOS data, %false otherwise + * Return value: `true` if the face has GPOS data, `false` otherwise * **/ hb_bool_t @@ -1634,7 +1634,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) * For more information on this distinction, see the [`size` feature documentation]( * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size). * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 0.9.10 **/ @@ -1698,7 +1698,7 @@ hb_ot_layout_get_size_params (hb_face_t *face, * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or * "Character Variant" ('cvXX') features. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.0.0 **/ @@ -2051,7 +2051,7 @@ hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script) * * Fetches a baseline value from the face. * - * Return value: %true if found baseline value in the font. + * Return value: `true` if found baseline value in the font. * * Since: 2.6.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index 6395f06670..de06610cb5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -110,7 +110,7 @@ namespace OT { struct hb_ot_apply_context_t; struct hb_ot_layout_lookup_accelerator_t; namespace Layout { -namespace GSUB { +namespace GSUB_impl { struct SubstLookup; } } @@ -118,7 +118,7 @@ namespace GSUB { HB_INTERNAL void hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, - const OT::Layout::GSUB::SubstLookup &lookup, + const OT::Layout::GSUB_impl::SubstLookup &lookup, const OT::hb_ot_layout_lookup_accelerator_t &accel); diff --git a/thirdparty/harfbuzz/src/hb-ot-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc index f085c78ff8..39215b335f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-map.cc +++ b/thirdparty/harfbuzz/src/hb-ot-map.cc @@ -43,7 +43,7 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_o hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, - const hb_segment_properties_t *props_) + const hb_segment_properties_t &props_) { memset (this, 0, sizeof (*this)); @@ -52,7 +52,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, stages[table_index].init (); face = face_; - props = *props_; + props = props_; /* Fetch script/language indices for GSUB/GPOS. We need these later to skip * features not available in either table and not waste precious bits for them. */ @@ -109,6 +109,21 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, info->stage[1] = current_stage[1]; } +bool hb_ot_map_builder_t::has_feature (hb_tag_t tag) +{ + for (unsigned int table_index = 0; table_index < 2; table_index++) + { + if (hb_ot_layout_language_find_feature (face, + table_tags[table_index], + script_index[table_index], + language_index[table_index], + tag, + nullptr)) + return true; + } + return false; +} + void hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, unsigned int table_index, diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh index f1cbf752fc..a7b5eec30d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-map.hh +++ b/thirdparty/harfbuzz/src/hb-ot-map.hh @@ -139,19 +139,15 @@ struct hb_ot_map_t return map ? map->stage[table_index] : UINT_MAX; } - void get_stage_lookups (unsigned int table_index, unsigned int stage, - const struct lookup_map_t **plookups, unsigned int *lookup_count) const + hb_array_t<const hb_ot_map_t::lookup_map_t> + get_stage_lookups (unsigned int table_index, unsigned int stage) const { if (unlikely (stage > stages[table_index].length)) - { - *plookups = nullptr; - *lookup_count = 0; - return; - } + return hb_array<const hb_ot_map_t::lookup_map_t> (nullptr, 0); + unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0; unsigned int end = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length; - *plookups = end == start ? nullptr : &lookups[table_index][start]; - *lookup_count = end - start; + return lookups[table_index].as_array ().sub_array (start, end - start); } HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const; @@ -167,7 +163,7 @@ struct hb_ot_map_t private: - hb_mask_t global_mask; + hb_mask_t global_mask = 0; hb_sorted_vector_t<feature_map_t> features; hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */ @@ -204,7 +200,7 @@ struct hb_ot_map_builder_t public: HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_, - const hb_segment_properties_t *props_); + const hb_segment_properties_t &props_); HB_INTERNAL ~hb_ot_map_builder_t (); @@ -212,6 +208,8 @@ struct hb_ot_map_builder_t hb_ot_map_feature_flags_t flags=F_NONE, unsigned int value=1); + HB_INTERNAL bool has_feature (hb_tag_t tag); + void add_feature (const hb_ot_map_feature_t &feat) { add_feature (feat.tag, feat.flags); } diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc index f44ac35849..c515867bdf 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math.cc +++ b/thirdparty/harfbuzz/src/hb-ot-math.cc @@ -56,7 +56,7 @@ * * Tests whether a face has a `MATH` table. * - * Return value: %true if the table is found, %false otherwise + * Return value: `true` if the table is found, `false` otherwise * * Since: 1.3.3 **/ @@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * * Tests whether the given glyph index is an extended shape in the face. * - * Return value: %true if the glyph is an extended shape, %false otherwise + * Return value: `true` if the glyph is an extended shape, `false` otherwise * * Since: 1.3.3 **/ diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc index f9c4b96fff..5b12482b97 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc @@ -71,12 +71,12 @@ _hb_ot_metrics_get_position_common (hb_font_t *font, #endif #define GET_METRIC_X(TABLE, ATTR) \ (face->table.TABLE->has_data () && \ - (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \ - face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true)) + ((void) (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \ + face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true)) #define GET_METRIC_Y(TABLE, ATTR) \ (face->table.TABLE->has_data () && \ - (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \ - face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true)) + ((void) (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \ + face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true)) case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER: return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) || @@ -154,10 +154,10 @@ hb_ot_metrics_get_position (hb_font_t *font, #endif #define GET_METRIC_X(TABLE, ATTR) \ (face->table.TABLE->has_data () && \ - (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true)) + ((void) (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR))), true)) #define GET_METRIC_Y(TABLE, ATTR) \ (face->table.TABLE->has_data () && \ - (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true)) + ((void) (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR))), true)) case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent); case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent); diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh index 01107aad67..1f2131ffcc 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh @@ -175,15 +175,11 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact) signed c = strcmp (astr, bstr); - if (!exact && c) - { - unsigned la = strlen (astr); - unsigned lb = strlen (bstr); - // 'a' is the user request, and 'b' is string in the font. - // If eg. user asks for "en-us" and font has "en", approve. - if (la > lb && astr[lb] == '-' && !strncmp (astr, bstr, lb)) - return 0; - } + // 'a' is the user request, and 'b' is string in the font. + // If eg. user asks for "en-us" and font has "en", approve. + if (!exact && c && + hb_language_matches (b->language, a->language)) + return 0; return c; } diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh index a4844e94bc..a4c0c4aa17 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh @@ -263,10 +263,10 @@ struct post bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (version.to_int () == 0x00010000 || - (version.to_int () == 0x00020000 && v2X.sanitize (c)) || - version.to_int () == 0x00030000))); + return_trace (c->check_struct (this) && + (version.to_int () == 0x00010000 || + (version.to_int () == 0x00020000 && v2X.sanitize (c)) || + version.to_int () == 0x00030000)); } public: diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 0806abb7dd..7f679cfd39 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -53,11 +53,11 @@ _hb_codepoint_is_regional_indicator (hb_codepoint_t u) #ifndef HB_NO_AAT_SHAPE static inline bool -_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props) +_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props) { /* https://github.com/harfbuzz/harfbuzz/issues/2124 */ return hb_aat_layout_has_substitution (face) && - (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face)); + (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face)); } #endif @@ -77,9 +77,9 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, unsigned int num_user_features); hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, - const hb_segment_properties_t *props) : + const hb_segment_properties_t &props) : face (face), - props (*props), + props (props), map (face, props), aat_map (face, props) #ifndef HB_NO_AAT_SHAPE @@ -225,7 +225,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face, #endif hb_ot_shape_planner_t planner (face, - &key->props); + key->props); hb_ot_shape_collect_features (&planner, key->user_features, @@ -1141,6 +1141,18 @@ hb_propagate_flags (hb_buffer_t *buffer) if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS)) return; + /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things: + * + * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL, + * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL, + * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK. + * + * We couldn't make this interaction earlier. It has to be done here. + */ + bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL; + + bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0; + hb_glyph_info_t *info = buffer->info; foreach_cluster (buffer, start, end) @@ -1148,9 +1160,20 @@ hb_propagate_flags (hb_buffer_t *buffer) unsigned int mask = 0; for (unsigned int i = start; i < end; i++) mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED; - if (mask) - for (unsigned int i = start; i < end; i++) - info[i].mask |= mask; + + if (flip_tatweel) + { + if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) + mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL; + if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) + mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT; + } + + if (clear_concat) + mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT; + + for (unsigned int i = start; i < end; i++) + info[i].mask = mask; } } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.hh b/thirdparty/harfbuzz/src/hb-ot-shape.hh index 17fa58b337..cd6f15cbe2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh @@ -60,6 +60,8 @@ struct hb_shape_plan_key_t; struct hb_ot_shape_plan_t { + ~hb_ot_shape_plan_t () { fini (); } + hb_segment_properties_t props; const struct hb_ot_shaper_t *shaper; hb_ot_map_t map; @@ -161,7 +163,7 @@ struct hb_ot_shape_planner_t const struct hb_ot_shaper_t *shaper; HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face, - const hb_segment_properties_t *props); + const hb_segment_properties_t &props); HB_INTERNAL void compile (hb_ot_shape_plan_t &plan, const hb_ot_shape_plan_key_t &key); diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc index e869d78509..ed2748b828 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc @@ -201,24 +201,21 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * work. However, testing shows that rlig and calt are applied * together for Mongolian in Uniscribe. As such, we only add a * pause for Arabic, not other scripts. - * - * A pause after calt is required to make KFGQPC Uthmanic Script HAFS - * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505 */ map->enable_feature (HB_TAG('s','t','c','h')); map->add_gsub_pause (record_stch); - map->enable_feature (HB_TAG('c','c','m','p')); - map->enable_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('c','c','m','p'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('l','o','c','l'), F_MANUAL_ZWJ); map->add_gsub_pause (nullptr); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]); - map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE); + map->add_feature (arabic_features[i], F_MANUAL_ZWJ | (has_fallback ? F_HAS_FALLBACK : F_NONE)); map->add_gsub_pause (nullptr); } map->add_gsub_pause (deallocate_buffer_var); @@ -232,10 +229,16 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) if (plan->props.script == HB_SCRIPT_ARABIC) map->add_gsub_pause (arabic_fallback_shape); - /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */ - map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ); - map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ); - map->add_gsub_pause (nullptr); + map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ); + /* https://github.com/harfbuzz/harfbuzz/issues/1573 */ + if (!map->has_feature (HB_TAG('r','c','l','t'))) + { + map->add_gsub_pause (nullptr); + map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ); + } + + map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ); /* The spec includes 'cswh'. Earlier versions of Windows * used to enable this by default, but testing suggests @@ -245,8 +248,8 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * Note that IranNastaliq uses this feature extensively * to fixup broken glyph sequences. Oh well... * Test case: U+0643,U+0640,U+0631. */ - //map->enable_feature (HB_TAG('c','s','w','h')); - map->enable_feature (HB_TAG('m','s','e','t')); + //map->enable_feature (HB_TAG('c','s','w','h'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('m','s','e','t'), F_MANUAL_ZWJ); } #include "hb-ot-shaper-arabic-fallback.hh" @@ -328,7 +331,7 @@ arabic_joining (hb_buffer_t *buffer) if (entry->prev_action != NONE && prev != UINT_MAX) { info[prev].arabic_shaping_action() = entry->prev_action; - buffer->unsafe_to_break (prev, i + 1); + buffer->safe_to_insert_tatweel (prev, i + 1); } else { @@ -362,7 +365,7 @@ arabic_joining (hb_buffer_t *buffer) if (entry->prev_action != NONE && prev != UINT_MAX) { info[prev].arabic_shaping_action() = entry->prev_action; - buffer->unsafe_to_break (prev, buffer->len); + buffer->safe_to_insert_tatweel (prev, buffer->len); } else if (2 <= state && state <= 5) /* States that have a possible prev_action. */ { @@ -735,12 +738,12 @@ const hb_ot_shaper_t _hb_ot_shaper_arabic = data_destroy_arabic, nullptr, /* preprocess_text */ postprocess_glyphs_arabic, - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, nullptr, /* decompose */ nullptr, /* compose */ setup_masks_arabic, - HB_TAG_NONE, /* gpos_tag */ reorder_marks_arabic, + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc index 25716aa81f..2f6f499eec 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc @@ -39,12 +39,12 @@ const hb_ot_shaper_t _hb_ot_shaper_default = nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; @@ -59,12 +59,12 @@ const hb_ot_shaper_t _hb_ot_shaper_dumber = nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc index aa507c75ca..c90476bc46 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc @@ -422,12 +422,12 @@ const hb_ot_shaper_t _hb_ot_shaper_hangul = data_destroy_hangul, preprocess_text_hangul, nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_NONE, nullptr, /* decompose */ nullptr, /* compose */ setup_masks_hangul, - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc index f3b6cde179..e18edd6b3f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc @@ -89,7 +89,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, found = true; } break; - case 0x05B7u: /* patah */ + case 0x05B7u: /* PATAH */ if (a == 0x05F2u) { /* YIDDISH YOD YOD */ *ab = 0xFB1Fu; found = true; @@ -162,6 +162,32 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, return found; } +static void +reorder_marks_hebrew (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_buffer_t *buffer, + unsigned int start, + unsigned int end) +{ + hb_glyph_info_t *info = buffer->info; + + for (unsigned i = start + 2; i < end; i++) + { + unsigned c0 = info_cc (info[i - 2]); + unsigned c1 = info_cc (info[i - 1]); + unsigned c2 = info_cc (info[i - 0]); + + if ((c0 == HB_MODIFIED_COMBINING_CLASS_CCC17 || c0 == HB_MODIFIED_COMBINING_CLASS_CCC18) /* patach or qamats */ && + (c1 == HB_MODIFIED_COMBINING_CLASS_CCC10 || c1 == HB_MODIFIED_COMBINING_CLASS_CCC14) /* sheva or hiriq */ && + (c2 == HB_MODIFIED_COMBINING_CLASS_CCC22 || c2 == HB_UNICODE_COMBINING_CLASS_BELOW) /* meteg or below */) + { + buffer->merge_clusters (i - 1, i + 1); + hb_swap (info[i - 1], info[i]); + break; + } + } + + +} const hb_ot_shaper_t _hb_ot_shaper_hebrew = { @@ -171,12 +197,12 @@ const hb_ot_shaper_t _hb_ot_shaper_hebrew = nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, nullptr, /* decompose */ compose_hebrew, nullptr, /* setup_masks */ + reorder_marks_hebrew, HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */ - nullptr, /* reorder_marks */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh index d52b13f616..d3a7cce3de 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 57 "hb-ot-shaper-indic-machine.hh" +#line 54 "hb-ot-shaper-indic-machine.hh" #define indic_syllable_machine_ex_A 9u #define indic_syllable_machine_ex_C 1u #define indic_syllable_machine_ex_CM 16u @@ -75,7 +75,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 79 "hb-ot-shaper-indic-machine.hh" +#line 74 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 12u, 4u, 12u, 8u, 8u, 5u, 7u, @@ -422,7 +422,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 426 "hb-ot-shaper-indic-machine.hh" +#line 415 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -438,7 +438,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 442 "hb-ot-shaper-indic-machine.hh" +#line 427 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -452,7 +452,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 456 "hb-ot-shaper-indic-machine.hh" +#line 439 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -555,7 +555,7 @@ _eof_trans: #line 113 "hb-ot-shaper-indic-machine.rl" {act = 6;} break; -#line 559 "hb-ot-shaper-indic-machine.hh" +#line 521 "hb-ot-shaper-indic-machine.hh" } _again: @@ -564,7 +564,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 568 "hb-ot-shaper-indic-machine.hh" +#line 528 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc index 48a3c74463..6eb400ab16 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc @@ -92,24 +92,22 @@ struct hb_indic_would_substitute_feature_t void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) { zero_context = zero_context_; - map->get_stage_lookups (0/*GSUB*/, - map->get_feature_stage (0/*GSUB*/, feature_tag), - &lookups, &count); + lookups = map->get_stage_lookups (0/*GSUB*/, + map->get_feature_stage (0/*GSUB*/, feature_tag)); } bool would_substitute (const hb_codepoint_t *glyphs, unsigned int glyphs_count, hb_face_t *face) const { - for (unsigned int i = 0; i < count; i++) - if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context)) + for (const auto &lookup : lookups) + if (hb_ot_layout_lookup_would_substitute (face, lookup.index, glyphs, glyphs_count, zero_context)) return true; return false; } private: - const hb_ot_map_t::lookup_map_t *lookups; - unsigned int count; + hb_array_t<const hb_ot_map_t::lookup_map_t> lookups; bool zero_context; }; @@ -1528,12 +1526,12 @@ const hb_ot_shaper_t _hb_ot_shaper_indic = data_destroy_indic, preprocess_text_indic, nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, compose_indic, setup_masks_indic, - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh index e18bd75ef1..2c40663bdd 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh @@ -48,7 +48,7 @@ enum khmer_syllable_type_t { }; -#line 52 "hb-ot-shaper-khmer-machine.hh" +#line 49 "hb-ot-shaper-khmer-machine.hh" #define khmer_syllable_machine_ex_C 1u #define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u #define khmer_syllable_machine_ex_H 4u @@ -66,7 +66,7 @@ enum khmer_syllable_type_t { #define khmer_syllable_machine_ex_ZWNJ 5u -#line 70 "hb-ot-shaper-khmer-machine.hh" +#line 65 "hb-ot-shaper-khmer-machine.hh" static const unsigned char _khmer_syllable_machine_trans_keys[] = { 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, @@ -294,7 +294,7 @@ find_syllables_khmer (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 298 "hb-ot-shaper-khmer-machine.hh" +#line 287 "hb-ot-shaper-khmer-machine.hh" { cs = khmer_syllable_machine_start; ts = 0; @@ -310,7 +310,7 @@ find_syllables_khmer (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 314 "hb-ot-shaper-khmer-machine.hh" +#line 299 "hb-ot-shaper-khmer-machine.hh" { int _slen; int _trans; @@ -324,7 +324,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 328 "hb-ot-shaper-khmer-machine.hh" +#line 311 "hb-ot-shaper-khmer-machine.hh" } _keys = _khmer_syllable_machine_trans_keys + (cs<<1); @@ -394,7 +394,7 @@ _eof_trans: #line 98 "hb-ot-shaper-khmer-machine.rl" {act = 3;} break; -#line 398 "hb-ot-shaper-khmer-machine.hh" +#line 368 "hb-ot-shaper-khmer-machine.hh" } _again: @@ -403,7 +403,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 407 "hb-ot-shaper-khmer-machine.hh" +#line 375 "hb-ot-shaper-khmer-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc index e04d633195..d9795589fa 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc @@ -368,12 +368,12 @@ const hb_ot_shaper_t _hb_ot_shaper_khmer = data_destroy_khmer, nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_khmer, compose_khmer, setup_masks_khmer, - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh index b109708937..464cf796d4 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh @@ -50,7 +50,7 @@ enum myanmar_syllable_type_t { }; -#line 54 "hb-ot-shaper-myanmar-machine.hh" +#line 51 "hb-ot-shaper-myanmar-machine.hh" #define myanmar_syllable_machine_ex_A 9u #define myanmar_syllable_machine_ex_As 32u #define myanmar_syllable_machine_ex_C 1u @@ -77,7 +77,7 @@ enum myanmar_syllable_type_t { #define myanmar_syllable_machine_ex_ZWNJ 5u -#line 81 "hb-ot-shaper-myanmar-machine.hh" +#line 76 "hb-ot-shaper-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { 1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u, 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u, @@ -443,7 +443,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 447 "hb-ot-shaper-myanmar-machine.hh" +#line 436 "hb-ot-shaper-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -459,7 +459,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 463 "hb-ot-shaper-myanmar-machine.hh" +#line 448 "hb-ot-shaper-myanmar-machine.hh" { int _slen; int _trans; @@ -473,7 +473,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 477 "hb-ot-shaper-myanmar-machine.hh" +#line 460 "hb-ot-shaper-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -519,7 +519,7 @@ _eof_trans: #line 113 "hb-ot-shaper-myanmar-machine.rl" {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }} break; -#line 523 "hb-ot-shaper-myanmar-machine.hh" +#line 498 "hb-ot-shaper-myanmar-machine.hh" } _again: @@ -528,7 +528,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 532 "hb-ot-shaper-myanmar-machine.hh" +#line 505 "hb-ot-shaper-myanmar-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc index 1ccafbca7e..78bd8de524 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc @@ -320,12 +320,12 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar = nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ nullptr, /* compose */ setup_masks_myanmar, - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; @@ -342,12 +342,12 @@ const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi = nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_NONE, nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc index 1280e7ed17..15349b1e64 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc @@ -379,12 +379,12 @@ const hb_ot_shaper_t _hb_ot_shaper_thai = nullptr, /* data_destroy */ preprocess_text_thai, nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh index 65e65ff39d..5b3ec05616 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh @@ -53,7 +53,7 @@ enum use_syllable_type_t { }; -#line 57 "hb-ot-shaper-use-machine.hh" +#line 54 "hb-ot-shaper-use-machine.hh" #define use_syllable_machine_ex_B 1u #define use_syllable_machine_ex_CGJ 6u #define use_syllable_machine_ex_CMAbv 31u @@ -97,7 +97,7 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_ZWNJ 14u -#line 101 "hb-ot-shaper-use-machine.hh" +#line 96 "hb-ot-shaper-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 53u, @@ -780,7 +780,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int act HB_UNUSED; int cs; -#line 784 "hb-ot-shaper-use-machine.hh" +#line 773 "hb-ot-shaper-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -793,7 +793,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 797 "hb-ot-shaper-use-machine.hh" +#line 782 "hb-ot-shaper-use-machine.hh" { int _slen; int _trans; @@ -807,7 +807,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 811 "hb-ot-shaper-use-machine.hh" +#line 794 "hb-ot-shaper-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -897,7 +897,7 @@ _eof_trans: #line 171 "hb-ot-shaper-use-machine.rl" {act = 2;} break; -#line 901 "hb-ot-shaper-use-machine.hh" +#line 866 "hb-ot-shaper-use-machine.hh" } _again: @@ -906,7 +906,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 910 "hb-ot-shaper-use-machine.hh" +#line 873 "hb-ot-shaper-use-machine.hh" } if ( ++p != pe ) diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh index 5aa025fb4c..e45ea30e60 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh @@ -89,1440 +89,265 @@ #define VMPre USE(VMPre) #pragma GCC diagnostic pop -static const uint8_t use_table[] = { - - -#define use_offset_0x0028u 0 - - - /* Basic Latin */ - O, O, O, O, O, GB, O, O, - /* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - -#define use_offset_0x00a0u 24 - - - /* Latin-1 Supplement */ - - /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, O, - /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O, - /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 00D0 */ O, O, O, O, O, O, O, GB, - -#define use_offset_0x0348u 80 - - - /* Combining Diacritical Marks */ - O, O, O, O, O, O, O, CGJ, - -#define use_offset_0x0640u 88 - - - /* Arabic */ - - /* 0640 */ B, O, O, O, O, O, O, O, - -#define use_offset_0x07c8u 96 - - - /* NKo */ - O, O, B, B, B, B, B, B, - /* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, - /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, WJ, WJ, VMAbv, O, O, - -#define use_offset_0x0840u 152 - - - /* Mandaic */ - - /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, WJ, WJ, O, WJ, - -#define use_offset_0x0900u 184 - - - /* Devanagari */ - - /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre, - /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst, - /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B, - /* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - - /* Bengali */ - - /* 0980 */ GB, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, - /* 0990 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 09A0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 09B0 */ B, WJ, B, WJ, WJ, WJ, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre, - /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, O, WJ, - /* 09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, B, B, WJ, B, - /* 09E0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, WJ, - - /* Gurmukhi */ - - /* 0A00 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, - /* 0A10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0A20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 0A30 */ B, WJ, B, B, WJ, B, B, WJ, B, B, WJ, WJ, CMBlw, WJ, VPst, VPre, - /* 0A40 */ VPst, VBlw, VBlw, WJ, WJ, WJ, WJ, VAbv, VAbv, WJ, WJ, VAbv, VAbv, H, WJ, WJ, - /* 0A50 */ WJ, VMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, WJ, B, WJ, - /* 0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Gujarati */ - - /* 0A80 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, B, B, B, WJ, B, - /* 0A90 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0AA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 0AB0 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre, - /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, WJ, VAbv, VAbv, VAbv, WJ, VPst, VPst, H, WJ, WJ, - /* 0AD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 0AE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0AF0 */ O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv, - - /* Oriya */ - - /* 0B00 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, - /* 0B10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0B20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 0B30 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv, - /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ, - /* 0B50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, B, B, WJ, B, - /* 0B60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0B70 */ O, B, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Tamil */ - - /* 0B80 */ WJ, WJ, VMAbv, O, WJ, B, B, B, B, B, B, WJ, WJ, WJ, B, B, - /* 0B90 */ B, WJ, B, B, B, B, WJ, WJ, WJ, B, B, WJ, B, WJ, B, B, - /* 0BA0 */ WJ, WJ, WJ, B, B, WJ, WJ, WJ, B, B, B, WJ, WJ, WJ, B, B, - /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, VPst, VPst, - /* 0BC0 */ VAbv, VPst, VPst, WJ, WJ, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, WJ, WJ, - /* 0BD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, - - /* Telugu */ - - /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, WJ, B, B, - /* 0C10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0C20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 0C30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, CMBlw, B, VAbv, VAbv, - /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ, - /* 0C50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VBlw, WJ, B, B, B, WJ, WJ, O, WJ, WJ, - /* 0C60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, O, O, O, O, - - /* Kannada */ - - /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, WJ, B, B, - /* 0C90 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0CA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 0CB0 */ B, B, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv, - /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ, - /* 0CD0 */ WJ, WJ, WJ, WJ, WJ, VPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, O, B, WJ, - /* 0CE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0CF0 */ WJ, CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Malayalam */ - - /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, WJ, B, B, - /* 0D10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst, - /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, R, O, - /* 0D50 */ WJ, WJ, WJ, WJ, O, O, O, VPst, O, O, O, O, O, O, O, B, - /* 0D60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - - /* Sinhala */ - - /* 0D80 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, B, B, B, - /* 0D90 */ B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, B, B, B, - /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0DB0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, WJ, B, WJ, WJ, - /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, HVM, WJ, WJ, WJ, WJ, VPst, - /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, WJ, VBlw, WJ, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, - /* 0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, - /* 0DF0 */ WJ, WJ, VPst, VPst, O, WJ, WJ, WJ, - -#define use_offset_0x0f00u 1456 - - - /* Tibetan */ - - /* 0F00 */ B, B, O, O, B, B, B, O, O, O, O, O, O, O, O, O, - /* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O, - /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre, - /* 0F40 */ B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, B, - /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, - /* 0F70 */ WJ, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O, - /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB, - /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, O, O, - /* 0FC0 */ O, O, O, O, O, O, FBlw, O, - -#define use_offset_0x1000u 1656 - - - /* Myanmar */ - - /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw, - /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, - /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O, - /* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw, - /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B, - /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B, - /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst, - /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O, - -#define use_offset_0x1700u 1816 - - - /* Tagalog */ - - /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, - - /* Hanunoo */ - - /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Buhid */ - - /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1750 */ B, B, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Tagbanwa */ - - /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, - /* 1770 */ B, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Khmer */ - - /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, - /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv, - /* 17D0 */ FMAbv, VAbv, IS, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ, - /* 17E0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - /* 17F0 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Mongolian */ - - /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, WJ, CGJ, - /* 1810 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, - /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1870 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B, - /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x1900u 2248 - - - /* Limbu */ - - /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, - /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, WJ, WJ, WJ, WJ, - /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, WJ, WJ, WJ, WJ, - /* 1940 */ O, WJ, WJ, WJ, O, O, B, B, B, B, B, B, B, B, B, B, - - /* Tai Le */ - - /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, - /* 1970 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* New Tai Lue */ - - /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, - /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, WJ, WJ, WJ, WJ, WJ, WJ, - /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, O, O, - /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - - /* Buginese */ - - /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, WJ, WJ, O, O, - - /* Tai Tham */ - - /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, WJ, - /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, WJ, WJ, VMBlw, - /* 1A80 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - /* 1A90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x1b00u 2664 - - - /* Balinese */ - - /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, - /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, - /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, WJ, WJ, WJ, - /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, - /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, WJ, - - /* Sundanese */ - - /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B, - /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - - /* Batak */ - - /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, - /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, - - /* Lepcha */ - - /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, - /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, WJ, WJ, WJ, O, O, O, O, O, - /* 1C40 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, - -#define use_offset_0x1cd0u 3000 - - - /* Vedic Extensions */ - - /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw, - /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, - /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x1df8u 3048 - - - /* Combining Diacritical Marks Supplement */ - O, O, O, FMAbv, O, O, O, O, - -#define use_offset_0x2008u 3056 - - - /* General Punctuation */ - O, O, O, WJ, ZWNJ, CGJ, WJ, WJ, - /* 2010 */ GB, GB, GB, GB, GB, O, O, O, O, O, O, O, O, O, O, O, - /* 2020 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, O, - /* 2030 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 2040 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 2050 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 2060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Superscripts and Subscripts */ - - /* 2070 */ O, O, WJ, WJ, FMPst, O, O, O, O, O, O, O, O, O, O, O, - /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O, - -#define use_offset_0x20f0u 3184 - - - /* Combining Diacritical Marks for Symbols */ - - /* 20F0 */ VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x25c8u 3192 - - - /* Geometric Shapes */ - O, O, O, O, B, O, O, O, - -#define use_offset_0x2d30u 3200 - - - /* Tifinagh */ - - /* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 2D60 */ B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, - /* 2D70 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, H, - -#define use_offset_0xa800u 3280 - - - /* Syloti Nagri */ - - /* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B, - /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, WJ, WJ, WJ, - /* A830 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Phags-pa */ - - /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A870 */ B, B, B, B, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Saurashtra */ - - /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, - /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, - /* A8D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Devanagari Extended */ - - /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, - /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, B, VAbv, - - /* Kayah Li */ - - /* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O, - - /* Rejang */ - - /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv, - /* A950 */ FAbv, FAbv, FPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, - /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, - - /* Javanese */ - - /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, - /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw, - /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, - /* A9D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O, - - /* Myanmar Extended-B */ - - /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B, - /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, - - /* Cham */ - - /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, - /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, WJ, WJ, - /* AA50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, O, O, O, - - /* Myanmar Extended-A */ - - /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B, - - /* Tai Viet */ - - /* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv, - /* AAC0 */ B, VMAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* AAD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, - - /* Meetei Mayek Extensions */ - - /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, - /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ, - -#define use_offset_0xabc0u 4040 - - - /* Meetei Mayek */ - - /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, WJ, WJ, - /* ABF0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0xfe00u 4104 - - - /* Variation Selectors */ - - /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - -#define use_offset_0xfef8u 4120 - - - /* Arabic Presentation Forms-B */ - O, O, O, O, O, WJ, WJ, WJ, - -#define use_offset_0xfff0u 4128 - - - /* Specials */ - - /* FFF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, WJ, WJ, - -#define use_offset_0x10570u 4144 - - - /* Vithkuqi */ - - /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, - /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, - /* 10590 */ B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, B, - /* 105A0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 105B0 */ B, B, WJ, B, B, B, B, B, B, B, WJ, B, B, WJ, WJ, WJ, - -#define use_offset_0x10a00u 4224 - - - /* Kharoshthi */ - - /* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv, - /* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B, - /* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMBlw, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS, - /* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x10ac0u 4304 - - - /* Manichaean */ - - /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, - /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, WJ, WJ, WJ, WJ, B, B, B, B, B, - -#define use_offset_0x10b80u 4352 - - - /* Psalter Pahlavi */ - - /* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10B90 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, WJ, WJ, WJ, - /* 10BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, O, - -#define use_offset_0x10d00u 4400 - - - /* Hanifi Rohingya */ - - /* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 10D30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x10e80u 4464 - - - /* Yezidi */ - - /* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, WJ, VAbv, VAbv, O, WJ, WJ, - /* 10EB0 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x10f30u 4520 - - - /* Sogdian */ - - /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, - /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, - /* 10F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Old Uyghur */ - - /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, - /* 10F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 10FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Chorasmian */ - - /* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B, - /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, WJ, WJ, WJ, WJ, - /* 10FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 10FF0 */ O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Brahmi */ - - /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B, - /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, - /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, WJ, WJ, - /* 11050 */ WJ, WJ, N, N, N, N, N, N, N, N, N, N, N, N, N, N, - /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B, - /* 11070 */ VAbv, B, B, VAbv, VAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, HN, - - /* Kaithi */ - - /* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, - /* 110C0 */ O, O, VBlw, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x11100u 4928 - - - /* Chakma */ - - /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv, - /* 11130 */ VBlw, VAbv, VAbv, IS, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B, - /* 11140 */ O, O, O, O, B, VPst, VPst, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Mahajani */ - - /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11170 */ B, B, B, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Sharada */ - - /* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, - /* 111C0 */ H, B, R, R, O, O, O, O, O, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv, - /* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, - - /* Sinhala Archaic Numbers */ - - /* 111E0 */ WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 111F0 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Khojki */ - - /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11210 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, - /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, WJ, - -#define use_offset_0x11280u 5248 - - - /* Multani */ - - /* 11280 */ B, B, B, B, B, B, B, WJ, B, WJ, B, B, B, B, WJ, B, - /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, - /* 112A0 */ B, B, B, B, B, B, B, B, B, O, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Khudawadi */ - - /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, - /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, WJ, WJ, WJ, WJ, WJ, - /* 112F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Grantha */ - - /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, - /* 11310 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11320 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 11330 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, CMBlw, CMBlw, B, VPst, VPst, - /* 11340 */ VAbv, VPst, VPst, VPst, VPst, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ, - /* 11350 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, O, B, B, - /* 11360 */ B, B, VPst, VPst, WJ, WJ, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ, - /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ, - -#define use_offset_0x11400u 5496 - - - /* Newa */ - - /* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, - /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O, - /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, WJ, O, FMAbv, B, - /* 11460 */ CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Tirhuta */ - - /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv, - /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 114D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x11580u 5720 - - - /* Siddham */ - - /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, - /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, - /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, WJ, WJ, - /* 115E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 115F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Modi */ - - /* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H, - /* 11640 */ VAbv, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11650 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, - /* 11670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Takri */ - - /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst, - /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, WJ, WJ, WJ, WJ, WJ, WJ, - /* 116C0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - /* 116D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 116E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 116F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Ahom */ - - /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, MBlw, MPre, MAbv, - /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, - /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, - /* 11740 */ B, B, B, B, B, B, B, WJ, - -#define use_offset_0x11800u 6176 - - - /* Dogra */ - - /* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw, - /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, WJ, WJ, WJ, WJ, - -#define use_offset_0x11900u 6240 - - - /* Dives Akuru */ - - /* 11900 */ B, B, B, B, B, B, B, WJ, WJ, B, WJ, WJ, B, B, B, B, - /* 11910 */ B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, - /* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, WJ, VPre, VPre, WJ, WJ, VMAbv, VMAbv, VPst, IS, R, - /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x119a0u 6336 - - - /* Nandinagari */ - - /* 119A0 */ B, B, B, B, B, B, B, B, WJ, WJ, B, B, B, B, B, B, - /* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VAbv, VAbv, VPst, VPst, VMPst, VMPst, - /* 119E0 */ H, B, O, O, VPre, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 119F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Zanabazar Square */ - - /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B, - /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, - /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Soyombo */ - - /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B, - /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, - /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O, - -#define use_offset_0x11c00u 6592 - - - /* Bhaiksuki */ - - /* 11C00 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, - /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, - /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H, - /* 11C40 */ B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, - - /* Marchen */ - - /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C90 */ WJ, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, WJ, - -#define use_offset_0x11d00u 6776 - - - /* Masaram Gondi */ - - /* 11D00 */ B, B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, - /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, WJ, WJ, WJ, VAbv, WJ, VAbv, VAbv, WJ, VAbv, - /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, IS, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11D50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Gunjala Gondi */ - - /* 11D60 */ B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, - /* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, WJ, - /* 11D90 */ VAbv, VAbv, WJ, VPst, VPst, VMAbv, VMPst, IS, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x11ee0u 6952 - - - /* Makasar */ - - /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O, - -#define use_offset_0x13000u 6976 - - - /* Egyptian Hieroglyphs */ - - /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, - - /* Egyptian Hieroglyph Format Controls */ - - /* 13430 */ H, H, H, H, H, H, H, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - -#define use_offset_0x16ac0u 8064 - - - /* Tangsa */ - - /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, - /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, - /* 16AF0 */ O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Pahawh Hmong */ - - /* 16B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, - -#define use_offset_0x16f00u 8184 - - - /* Miao */ - - /* 16F00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, CMBlw, - /* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, - /* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, - /* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, - /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, VMBlw, - /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O, - -#define use_offset_0x16fe0u 8336 - - - /* Ideographic Symbols and Punctuation */ - - /* 16FE0 */ O, O, O, O, B, WJ, WJ, WJ, - -#define use_offset_0x18b00u 8344 - - - /* Khitan Small Script */ - - /* 18B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18BF0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18C90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18CD0 */ B, B, B, B, B, B, WJ, WJ, - -#define use_offset_0x1bc00u 8816 - - - /* Duployan */ - - /* 1BC00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, - /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, - /* 1BC80 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, CMBlw, CMBlw, O, - -#define use_offset_0x1d170u 8976 - - - /* Musical Symbols */ - - /* 1D170 */ O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, - -#define use_offset_0x1e100u 8992 - - - /* Nyiakeng Puachue Hmong */ - - /* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, - /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, WJ, WJ, - /* 1E140 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, B, - -#define use_offset_0x1e290u 9072 - - - /* Toto */ - - /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, WJ, - /* 1E2B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Wancho */ - - /* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, - /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, O, - -#define use_offset_0x1e900u 9184 - - - /* Adlam */ - - /* 1E900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, WJ, WJ, WJ, WJ, - /* 1E950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O, - -#define use_offset_0xe0000u 9280 - - - /* Tags */ - - /* E0000 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0010 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0020 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0030 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0040 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0050 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0070 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* No_Block */ - - /* E0080 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0090 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E00F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - - /* Variation Selectors Supplement */ - - /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, - - /* No_Block */ - - /* E01F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0200 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0210 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0220 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0230 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0240 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0250 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0260 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0270 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0280 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0290 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E02F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0300 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0310 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0320 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0330 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0340 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0350 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0360 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0370 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0380 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0390 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E03F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0400 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0410 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0420 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0430 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0440 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0450 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0460 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0480 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0490 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E04F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0500 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0510 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0520 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0530 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0540 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0550 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0560 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0570 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0580 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0590 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E05F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0600 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0610 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0620 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0630 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0640 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0650 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0660 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0680 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0690 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E06F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0700 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0710 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0720 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0730 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0740 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0750 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0760 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0770 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0780 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0790 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E07F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0800 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0810 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0820 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0830 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0840 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0850 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0860 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0870 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0880 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0890 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E08F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0900 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0910 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0920 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0930 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0940 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0950 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0960 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0970 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0980 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0990 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E09F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0A90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0AF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0B90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0BF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0C90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0CF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0D90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0DF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0E90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0EA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0EB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0EC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0ED0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0EE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0EF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - /* E0FF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, - -}; /* Table items: 13376; occupancy: 84% */ - -static inline uint8_t -hb_use_get_category (hb_glyph_info_t info) +static const uint8_t +hb_use_u8[3083] = { - hb_codepoint_t u = info.codepoint; - switch (u >> 12) - { - case 0x0u: - if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; - if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u]; - if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u]; - if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u]; - if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u]; - if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; - if (hb_in_range<hb_codepoint_t> (u, 0x0F00u, 0x0FC7u)) return use_table[u - 0x0F00u + use_offset_0x0f00u]; - break; - - case 0x1u: - if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x18AFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u]; - break; - - case 0x2u: - if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2087u)) return use_table[u - 0x2008u + use_offset_0x2008u]; - if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u]; - if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u]; - break; - - case 0xAu: - if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; - if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; - break; - - case 0xFu: - if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; - if (hb_in_range<hb_codepoint_t> (u, 0xFEF8u, 0xFEFFu)) return use_table[u - 0xFEF8u + use_offset_0xfef8u]; - if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u]; - break; - - case 0x10u: - if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u]; - break; - - case 0x11u: - if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x11747u)) return use_table[u - 0x11580u + use_offset_0x11580u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11900u, 0x1195Fu)) return use_table[u - 0x11900u + use_offset_0x11900u]; - if (hb_in_range<hb_codepoint_t> (u, 0x119A0u, 0x11A9Fu)) return use_table[u - 0x119A0u + use_offset_0x119a0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11DAFu)) return use_table[u - 0x11D00u + use_offset_0x11d00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x11EE0u, 0x11EF7u)) return use_table[u - 0x11EE0u + use_offset_0x11ee0u]; - break; - - case 0x13u: - if (hb_in_range<hb_codepoint_t> (u, 0x13000u, 0x1343Fu)) return use_table[u - 0x13000u + use_offset_0x13000u]; - break; - - case 0x16u: - if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u]; - if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u]; - break; - - case 0x18u: - if (hb_in_range<hb_codepoint_t> (u, 0x18B00u, 0x18CD7u)) return use_table[u - 0x18B00u + use_offset_0x18b00u]; - break; - - case 0x1Bu: - if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u]; - break; - - case 0x1Du: - if (hb_in_range<hb_codepoint_t> (u, 0x1D170u, 0x1D17Fu)) return use_table[u - 0x1D170u + use_offset_0x1d170u]; - break; - - case 0x1Eu: - if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u]; - break; - - case 0xE0u: - if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u]; - break; - - case 0xE1u: - if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u]; - break; - - default: - break; - } - if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) - return WJ; - return O; + 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2, + 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17, + 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2, + 2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 38, 39, 40, 41, 42, 43, 2, 44, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 46, 2, + 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 49, 2, 2, 2, + 2, 2, 2, 2, 2, 50, 51, 2, 52, 2, 2, 53, 2, 2, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 2, 64, 65, 2, 66, 67, 68, 69, + 2, 70, 2, 71, 72, 73, 74, 2, 2, 75, 76, 77, 78, 2, 79, 2, + 2, 80, 80, 80, 80, 80, 80, 80, 80, 81, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 82, 83, 2, 2, 2, 2, 2, 2, 2, 84, + 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 80, 80, 80, 86, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 2, 2, 2, 2, 2, + 2, 2, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 90, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 93, 93, 94, 95, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10, + 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22, + 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7, + 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2, + 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32, + 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7, + 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35, + 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7, + 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0, + 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2, + 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22, + 0, 0, 0, 0, 0, 28, 9, 39, 42, 10, 27, 28, 2, 2, 2, 7, + 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2, + 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0, + 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0, + 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7, + 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15, + 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0, + 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15, + 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0, + 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51, + 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0, + 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2, + 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0, + 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18, + 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, + 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43, + 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0, + 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27, + 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76, + 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0, + 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0, + 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82, + 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79, + 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2, + 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0, + 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, + 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0, + 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59, + 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44, + 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20, + 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108, + 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2, + 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43, + 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111, + 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28, + 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38, + 0, 0, 0, 115, 116, 9, 3, 0, 0, 0, 0, 0, 0, 0, 117, 0, + 0, 0, 0, 0, 0, 0, 4, 118, 119, 40, 40, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119, + 119, 0, 0, 121, 0, 0, 0, 0, 0, 0, 5, 121, 0, 0, 0, 0, + 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, + 122, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29, + 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 123, 21, 21, 21, 21, 21, 21, 21, 124, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, + 50, 2, 2, 2, 20, 20, 125, 114, 0, 2, 2, 2, 126, 18, 57, 18, + 111, 100, 127, 0, 0, 0, 0, 0, 0, 9, 128, 2, 2, 2, 2, 2, + 2, 2, 129, 21, 20, 18, 46, 130, 131, 132, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57, + 97, 74, 133, 134, 135, 0, 0, 0, 0, 2, 136, 2, 2, 2, 2, 137, + 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 138, 50, 51, 2, 2, + 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 139, 19, + 23, 0, 0, 140, 141, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 142, + 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, + 4, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2, + 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7, + 0, 126, 18, 25, 29, 0, 0, 143, 144, 2, 2, 28, 2, 28, 2, 2, + 2, 2, 2, 2, 0, 12, 35, 0, 145, 2, 2, 11, 35, 0, 28, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2, + 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36, + 0, 2, 2, 2, 114, 114, 114, 114, 114, 146, 2, 7, 0, 0, 0, 0, + 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2, + 2, 28, 2, 7, 0, 28, 2, 0, 0, 147, 148, 149, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 132, 0, 0, 0, + 0, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 2, 2, 2, 2, + 2, 51, 50, 51, 0, 0, 0, 0, 151, 9, 72, 2, 2, 2, 2, 2, + 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0, + 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 18, 20, 152, + 20, 19, 153, 154, 2, 2, 2, 2, 2, 0, 0, 63, 155, 0, 0, 0, + 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20, + 20, 106, 156, 0, 0, 157, 158, 29, 159, 28, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 160, 42, 0, 0, 0, + 44, 2, 2, 2, 7, 7, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, + 28, 2, 2, 2, 2, 2, 2, 2, 8, 16, 17, 19, 20, 161, 29, 0, + 0, 9, 9, 28, 2, 2, 2, 7, 28, 7, 2, 28, 2, 2, 56, 15, + 21, 14, 21, 45, 30, 31, 30, 32, 0, 0, 0, 0, 33, 0, 0, 0, + 2, 2, 21, 0, 9, 9, 9, 44, 0, 9, 9, 44, 0, 0, 0, 0, + 0, 2, 2, 63, 23, 18, 18, 18, 20, 21, 124, 13, 15, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 0, 0, 162, 163, 0, 0, 0, 0, 0, 0, + 0, 16, 17, 18, 18, 64, 97, 23, 159, 9, 164, 7, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 63, 23, 18, 18, 0, 46, 46, 9, + 165, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18, + 0, 21, 17, 18, 18, 19, 14, 80, 165, 36, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 8, 166, 23, 18, 20, 20, 164, 7, 0, 0, + 0, 2, 2, 2, 2, 2, 7, 41, 134, 21, 20, 18, 74, 19, 20, 0, + 0, 2, 2, 2, 7, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 16, + 17, 18, 19, 20, 103, 165, 35, 0, 0, 2, 2, 2, 7, 28, 0, 2, + 2, 2, 2, 28, 7, 2, 2, 2, 2, 21, 21, 16, 30, 31, 10, 167, + 168, 169, 170, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, + 2, 63, 23, 18, 18, 0, 20, 21, 27, 106, 0, 31, 0, 0, 0, 0, + 0, 50, 18, 20, 20, 20, 138, 2, 2, 2, 171, 172, 9, 13, 173, 70, + 174, 0, 0, 1, 145, 0, 0, 0, 0, 50, 18, 20, 14, 17, 18, 2, + 2, 2, 2, 156, 156, 156, 175, 175, 175, 175, 175, 175, 13, 176, 0, 28, + 0, 20, 18, 18, 29, 20, 20, 9, 165, 0, 59, 59, 59, 59, 59, 59, + 59, 64, 19, 80, 44, 0, 0, 0, 0, 2, 2, 2, 7, 2, 28, 2, + 2, 50, 20, 20, 29, 0, 36, 20, 25, 9, 158, 177, 173, 0, 0, 0, + 0, 2, 2, 2, 28, 7, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, + 45, 20, 33, 80, 66, 0, 0, 0, 0, 2, 178, 64, 45, 0, 0, 0, + 0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56, + 35, 0, 4, 119, 119, 119, 120, 0, 0, 9, 9, 9, 47, 2, 2, 2, + 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0, + 0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B, + O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, + B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, + VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre, + O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv, + CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, + B, O, CS, CS, O, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O, + CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B, + VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst, + VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, + CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, + CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, + FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv, + VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, + FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, CS,VMPst, O,FMAbv, ZWNJ, CGJ, WJ, + WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, + VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, + O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst, + VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, + HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre, + VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, + VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw, + FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, H, H, O, VBlw, +}; +static const uint16_t +hb_use_u16[768] = +{ + 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11, + 0, 0, 0, 0, 9, 12, 0, 0, 13, 9, 9, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 17, 25, 26, 20, 21, 27, 28, 29, 30, 31, + 32, 33, 21, 34, 35, 0, 17, 36, 37, 20, 21, 38, 23, 39, 17, 40, + 41, 42, 43, 44, 45, 46, 30, 0, 47, 48, 21, 49, 50, 51, 17, 0, + 52, 48, 21, 53, 50, 54, 17, 55, 56, 48, 9, 57, 58, 59, 17, 0, + 60, 61, 9, 62, 63, 64, 30, 65, 66, 67, 9, 68, 69, 9, 70, 71, + 72, 73, 74, 75, 76, 0, 0, 0, 9, 9, 77, 78, 79, 80, 81, 82, + 83, 84, 0, 0, 0, 0, 0, 0, 9, 85, 9, 86, 9, 87, 88, 89, + 9, 9, 9, 90, 91, 92, 2, 0, 93, 0, 9, 9, 9, 9, 9, 94, + 95, 9, 96, 0, 0, 0, 0, 0, 97, 98, 99,100, 30, 9,101,102, + 9, 9,103, 9,104,105, 0, 0, 9,106, 9, 9, 9,107,108,109, + 2, 2, 0, 0, 0, 0, 0, 0,110, 9, 9,111,112, 2,113,114, + 115, 9,116, 9, 9, 9,117,118, 9, 9,119,120,121, 0, 0, 0, + 0, 0, 0, 0, 0,122,123,124, 0, 0, 0, 0, 0, 0, 0,125, + 126,127,128, 0, 0, 0,129,130,131, 0, 0, 0, 0, 0, 0,132, + 0, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 9, 9, 9,134,135, + 136, 9,137, 0, 9, 9, 9,138,139, 9, 9,140,141, 2,142,143, + 9, 9,144, 9,145,146, 0, 0,147, 9, 9,148,149, 2,150, 98, + 9, 9,151,152,153, 2, 9,154, 9, 9, 9,155,156, 0,157,158, + 0, 0, 0, 0, 9, 9,159, 2,160, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0,162, + 0, 0, 0, 0, 0, 0, 0,163,163,164, 33,165, 0, 0, 0, 0, + 166,167, 9,168, 94, 0, 0, 0, 0, 0, 0, 0, 69, 9,169, 0, + 9,170,171, 0, 0, 0, 0, 0, 9, 9,172, 2, 0, 0, 0, 0, + 9, 9,173,170, 0, 0, 0, 0, 0, 0, 0, 9,174,175, 0, 9, + 176, 0, 0,177,178, 0, 0, 0,179, 9, 9,180,181,182,183,184, + 185, 9, 9,186,187, 0, 0, 0,188, 9,189,190,191, 9, 9,192, + 185, 9, 9,193,194,105,195,102, 9, 33,196,197, 0, 0, 0, 0, + 198,199, 94, 9, 9,200,201, 2,202, 20, 21,203,204,205,206,207, + 9, 9, 9,208,209,210,211, 0,195, 9, 9,212,213, 2, 0, 0, + 9, 9,214,215,216,217, 0, 0, 9, 9, 9,218,219, 2, 0, 0, + 9, 9,220,221, 2, 0, 0, 0, 9,222,223,103,224, 0, 0, 0, + 9, 9,225,226, 0, 0, 0, 0,227,228, 9,229,230, 2, 0, 0, + 0, 0,231, 9, 9,232,233, 0,234, 9, 9,235,236,237, 9, 9, + 238,239, 0, 0, 0, 0, 0, 0, 21, 9,214,240, 7, 9, 70, 18, + 9,241, 73,242, 0, 0, 0, 0,243, 9, 9,244,245, 2,246, 9, + 247,248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,249, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 98,250, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 9, 9, 9,251, 0, 0, 0, 0, + 9, 9, 9, 9,252,253,254,254,255,256, 0, 0, 0, 0,257, 0, + 9, 9, 9, 9, 9,258, 0, 0, 9, 9, 9, 9, 9, 9,105, 70, + 94,259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,260, + 9, 9, 70,261,262, 0, 0, 0, 0, 9,263, 0, 9, 9,264, 2, + 9, 9, 9, 9,265, 2, 0, 0,129,129,129,129,129,129,129,129, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129, +}; + +static inline unsigned +hb_use_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline uint_fast8_t +hb_use_get_category (unsigned u) +{ + return u<921600u?hb_use_u8[2721+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; } #undef B @@ -1568,5 +393,26 @@ hb_use_get_category (hb_glyph_info_t info) #undef VMPre +#ifdef HB_USE_TABLE_MAIN +int main (int argc, char **argv) +{ + if (argc != 2) + { + for (unsigned u = 0; u < 0x10FFFFu; u++) + printf ("U+%04X %d\n", u, hb_use_get_category (u)); + return 0; + } + + hb_codepoint_t u; + sscanf (argv[1], "%x", &u); + + printf ("%d\n", hb_use_get_category (u)); + + return 0; +} + +#endif + + #endif /* HB_OT_SHAPER_USE_TABLE_HH */ /* == End of generated table == */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc index 60394ed4d8..c40ec52f9c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc @@ -206,7 +206,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - info[i].use_category() = hb_use_get_category (info[i]); + info[i].use_category() = hb_use_get_category (info[i].codepoint); } static void @@ -490,12 +490,12 @@ const hb_ot_shaper_t _hb_ot_shaper_use = data_destroy_use, preprocess_text_use, nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ compose_use, setup_masks_use, - HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ + HB_TAG_NONE, /* gpos_tag */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh index b823bf003c..e160987f83 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh @@ -117,8 +117,6 @@ struct hb_ot_shaper_t hb_font_t *font); - hb_ot_shape_normalization_mode_t normalization_preference; - /* decompose() * Called during shape()'s normalization. * May be NULL. @@ -147,12 +145,6 @@ struct hb_ot_shaper_t hb_buffer_t *buffer, hb_font_t *font); - /* gpos_tag() - * If not HB_TAG_NONE, then must match found GPOS script tag for - * GPOS to be applied. Otherwise, fallback positioning will be used. - */ - hb_tag_t gpos_tag; - /* reorder_marks() * Called during shape(). * Shapers can use to modify ordering of combining marks. @@ -163,6 +155,14 @@ struct hb_ot_shaper_t unsigned int start, unsigned int end); + /* gpos_tag() + * If not HB_TAG_NONE, then must match found GPOS script tag for + * GPOS to be applied. Otherwise, fallback positioning will be used. + */ + hb_tag_t gpos_tag; + + hb_ot_shape_normalization_mode_t normalization_preference; + hb_ot_shape_zero_width_marks_type_t zero_width_marks; bool fallback_position; diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh index 41d1734b39..d83bf14219 100644 --- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @@ -57,6 +57,31 @@ enum // Reserved = 0xFFFC /* Reserved for future use — set to zero. */ }; +struct StatAxisRecord +{ + int cmp (hb_tag_t key) const { return tag.cmp (key); } + + hb_ot_name_id_t get_name_id () const { return nameID; } + + hb_tag_t get_axis_tag () const { return tag; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + Tag tag; /* A tag identifying the axis of design variation. */ + NameID nameID; /* The name ID for entries in the 'name' table that + * provide a display string for this axis. */ + HBUINT16 ordering; /* A value that applications can use to determine + * primary sorting of face names, or for ordering + * of descriptors when composing family or face names. */ + public: + DEFINE_SIZE_STATIC (8); +}; + struct AxisValueFormat1 { unsigned int get_axis_index () const { return axisIndex; } @@ -64,10 +89,41 @@ struct AxisValueFormat1 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -92,10 +148,41 @@ struct AxisValueFormat2 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -124,10 +211,41 @@ struct AxisValueFormat3 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -155,7 +273,7 @@ struct AxisValueRecord bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -172,12 +290,47 @@ struct AxisValueFormat4 const AxisValueRecord &get_axis_record (unsigned int axis_index) const { return axisValues.as_array (axisCount)[axis_index]; } + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount); + + for (const auto& rec : axis_value_records) + { + unsigned axis_idx = rec.get_axis_index (); + float axis_value = rec.get_value (); + hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag (); + + if (user_axes_location->has (axis_tag) && + fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f) + return false; + } + + return true; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location; + if (!keep_axis_value (axis_records, user_axes_location)) + return_trace (false); + + unsigned total_size = min_size + axisCount * AxisValueRecord::static_size; + auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size); + if (unlikely (!out)) return_trace (false); + memcpy (out, this, total_size); + return_trace (true); + } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this) && + axisValues.sanitize (c, axisCount))); } protected: @@ -234,6 +387,33 @@ struct AxisValue } } + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + switch (u.format) + { + case 1: return u.format1.keep_axis_value (axis_records, user_axes_location); + case 2: return u.format2.keep_axis_value (axis_records, user_axes_location); + case 3: return u.format3.keep_axis_value (axis_records, user_axes_location); + case 4: return u.format4.keep_axis_value (axis_records, user_axes_location); + default:return false; + } + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -263,27 +443,35 @@ struct AxisValue DEFINE_SIZE_UNION (2, format); }; -struct StatAxisRecord +struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>> { - int cmp (hb_tag_t key) const { return tag.cmp (key); } + bool subset (hb_subset_context_t *c, + unsigned axisValueCount, + unsigned& count, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!out)) return_trace (false); - hb_ot_name_id_t get_name_id () const { return nameID; } + auto axisValueOffsets = as_array (axisValueCount); + count = 0; + for (const auto& offset : axisValueOffsets) + { + if (!offset) continue; + auto o_snap = c->serializer->snapshot (); + auto *o = c->serializer->embed (offset); + if (!o) return_trace (false); + if (!o->serialize_subset (c, offset, this, axis_records)) + { + c->serializer->revert (o_snap); + continue; + } + count++; + } - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (count); } - - protected: - Tag tag; /* A tag identifying the axis of design variation. */ - NameID nameID; /* The name ID for entries in the 'name' table that - * provide a display string for this axis. */ - HBUINT16 ordering; /* A value that applications can use to determine - * primary sorting of face names, or for ordering - * of descriptors when composing family or face names. */ - public: - DEFINE_SIZE_STATIC (8); }; struct STAT @@ -329,7 +517,8 @@ struct STAT return axis_value.get_value_name_id (); } - void collect_name_ids (hb_set_t *nameids_to_retain) const + void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, + hb_set_t *nameids_to_retain /* OUT */) const { if (!has_data ()) return; @@ -338,13 +527,38 @@ struct STAT | hb_sink (nameids_to_retain) ; + auto designAxes = get_design_axes (); + + get_axis_value_offsets () | hb_map (hb_add (&(this + offsetToAxisValueOffsets))) + | hb_filter ([&] (const AxisValue& _) + { return _.keep_axis_value (designAxes, user_axes_location); }) | hb_map (&AxisValue::get_value_name_id) | hb_sink (nameids_to_retain) ; } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + STAT *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + auto designAxes = get_design_axes (); + for (unsigned i = 0; i < (unsigned)designAxisCount; i++) + if (unlikely (!c->serializer->embed (designAxes[i]))) + return_trace (false); + + if (designAxisCount) + c->serializer->check_assign (out->designAxesOffset, this->get_size (), + HB_SERIALIZE_ERROR_INT_OVERFLOW); + + unsigned count = 0; + out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this, + axisValueCount, count, designAxes); + return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -381,7 +595,7 @@ struct STAT * set to zero; if designAxisCount is greater * than zero, must be greater than zero. */ HBUINT16 axisValueCount; /* The number of axis value tables. */ - NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>> + NNOffset32To<AxisValueOffsetArray> offsetToAxisValueOffsets; /* Offset in bytes from the beginning of * the STAT table to the start of the design diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc index ce5cdce98b..ceb3bf6df5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag.cc +++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc @@ -214,6 +214,8 @@ lang_matches (const char *lang_str, const char *spec, unsigned spec_len) { + /* Same as hb_language_matches(); duplicated. */ + if (likely ((unsigned) (limit - lang_str) < spec_len)) return false; diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh index 65f26c1d22..5946aef635 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh @@ -28,6 +28,8 @@ #define HB_OT_VAR_AVAR_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-var-common.hh" + /* * avar -- Axis Variations @@ -40,6 +42,28 @@ namespace OT { +/* "Spec": https://github.com/be-fonts/boring-expansion-spec/issues/14 */ +struct avarV2Tail +{ + friend struct avar; + + bool sanitize (hb_sanitize_context_t *c, + const void *base) const + { + TRACE_SANITIZE (this); + return_trace (varIdxMap.sanitize (c, base) && + varStore.sanitize (c, base)); + } + + protected: + Offset32To<DeltaSetIndexMap> varIdxMap; /* Offset from the beginning of 'avar' table. */ + Offset32To<VariationStore> varStore; /* Offset from the beginning of 'avar' table. */ + + public: + DEFINE_SIZE_STATIC (8); +}; + + struct AxisValueMap { bool sanitize (hb_sanitize_context_t *c) const @@ -106,12 +130,24 @@ struct avar { static constexpr hb_tag_t tableTag = HB_OT_TAG_avar; + bool has_data () const { return version.to_int (); } + + const SegmentMaps* get_segment_maps () const + { return &firstAxisSegmentMaps; } + + unsigned get_axis_count () const + { return axisCount; } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!(version.sanitize (c) && - version.major == 1 && - c->check_struct (this)))) + if (!(version.sanitize (c) && + (version.major == 1 +#ifndef HB_NO_VARIATIONS2 + || version.major == 2 +#endif + ) && + c->check_struct (this))) return_trace (false); const SegmentMaps *map = &firstAxisSegmentMaps; @@ -123,6 +159,15 @@ struct avar map = &StructAfter<SegmentMaps> (*map); } +#ifndef HB_NO_VARIATIONS2 + if (version.major < 2) + return_trace (true); + + const auto &v2 = * (const avarV2Tail *) map; + if (unlikely (!v2.sanitize (c, this))) + return_trace (false); +#endif + return_trace (true); } @@ -136,6 +181,37 @@ struct avar coords[i] = map->map (coords[i]); map = &StructAfter<SegmentMaps> (*map); } + +#ifndef HB_NO_VARIATIONS2 + if (version.major < 2) + return; + + for (; count < axisCount; count++) + map = &StructAfter<SegmentMaps> (*map); + + const auto &v2 = * (const avarV2Tail *) map; + + const auto &varidx_map = this+v2.varIdxMap; + const auto &var_store = this+v2.varStore; + auto *var_store_cache = var_store.create_cache (); + + hb_vector_t<int> out; + out.alloc (coords_length); + for (unsigned i = 0; i < coords_length; i++) + { + int v = coords[i]; + uint32_t varidx = varidx_map.map (i); + float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache); + v += roundf (delta); + v = hb_clamp (v, -(1<<14), +(1<<14)); + out.push (v); + } + + OT::VariationStore::destroy_cache (var_store_cache); + + for (unsigned i = 0; i < coords_length; i++) + coords[i] = out[i]; +#endif } void unmap_coords (int *coords, unsigned int coords_length) const diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh index 0eafb949d5..1d29e3e4f9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh @@ -31,12 +31,13 @@ namespace OT { -struct DeltaSetIndexMapFormat0 +template <typename MapCountT> +struct DeltaSetIndexMapFormat01 { friend struct DeltaSetIndexMap; private: - DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const + DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); auto *out = c->start_embed (this); @@ -128,56 +129,12 @@ struct DeltaSetIndexMapFormat0 HBUINT8 format; /* Format identifier--format = 0 */ HBUINT8 entryFormat; /* A packed field that describes the compressed * representation of delta-set indices. */ - HBUINT16 mapCount; /* The number of mapping entries. */ + MapCountT mapCount; /* The number of mapping entries. */ UnsizedArrayOf<HBUINT8> mapDataZ; /* The delta-set index mapping data. */ public: - DEFINE_SIZE_ARRAY (4, mapDataZ); -}; - -struct DeltaSetIndexMapFormat1 -{ - friend struct DeltaSetIndexMap; - - private: - DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (nullptr); - - unsigned total_size = min_size + mapCount * get_width (); - HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); - if (unlikely (!p)) return_trace (nullptr); - - memcpy (p, this, HBUINT8::static_size * total_size); - return_trace (out); - } - - unsigned get_map_count () const { return mapCount; } - unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } - unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - c->check_range (mapDataZ.arrayZ, - mapCount, - get_width ())); - } - - protected: - HBUINT8 format; /* Format identifier--format = 1 */ - HBUINT8 entryFormat; /* A packed field that describes the compressed - * representation of delta-set indices. */ - HBUINT32 mapCount; /* The number of mapping entries. */ - UnsizedArrayOf<HBUINT8> - mapDataZ; /* The delta-set index mapping data. */ - - public: - DEFINE_SIZE_ARRAY (6, mapDataZ); + DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ); }; struct DeltaSetIndexMap @@ -186,8 +143,11 @@ struct DeltaSetIndexMap bool serialize (hb_serialize_context_t *c, const T &plan) { TRACE_SERIALIZE (this); + unsigned length = plan.get_output_map ().length; + u.format = length <= 0xFFFF ? 0 : 1; switch (u.format) { case 0: return_trace (u.format0.serialize (c, plan)); + case 1: return_trace (u.format1.serialize (c, plan)); default:return_trace (false); } } @@ -196,6 +156,7 @@ struct DeltaSetIndexMap { switch (u.format) { case 0: return (u.format0.map (v)); + case 1: return (u.format1.map (v)); default:return v; } } @@ -250,9 +211,9 @@ struct DeltaSetIndexMap protected: union { - HBUINT8 format; /* Format identifier */ - DeltaSetIndexMapFormat0 format0; - DeltaSetIndexMapFormat1 format1; + HBUINT8 format; /* Format identifier */ + DeltaSetIndexMapFormat01<HBUINT16> format0; + DeltaSetIndexMapFormat01<HBUINT32> format1; } u; public: DEFINE_SIZE_UNION (1, format); diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh index c5c476bc0e..b9b49f2287 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh @@ -96,6 +96,8 @@ struct AxisRecord info->reserved = 0; } + hb_tag_t get_axis_tag () const { return axisTag; } + int normalize_axis_value (float v) const { float min_value, default_value, max_value; @@ -133,7 +135,6 @@ struct AxisRecord return_trace (c->check_struct (this)); } - protected: void get_coordinates (float &min, float &default_, float &max) const { default_ = defaultValue / 65536.f; @@ -142,6 +143,11 @@ struct AxisRecord max = hb_max (default_, maxValue / 65536.f); } + float get_default () const + { + return defaultValue / 65536.f; + } + public: Tag axisTag; /* Tag identifying the design variation for the axis. */ protected: @@ -270,24 +276,49 @@ struct fvar return axisCount; } - void collect_name_ids (hb_set_t *nameids) const + void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, + hb_set_t *nameids /* IN/OUT */) const { if (!has_data ()) return; + hb_map_t pinned_axes; - + get_axes () - | hb_map (&AxisRecord::get_name_id) - | hb_sink (nameids) - ; - - + hb_range ((unsigned) instanceCount) - | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); }) - | hb_sink (nameids) - ; + auto axis_records = get_axes (); + for (unsigned i = 0 ; i < (unsigned)axisCount; i++) + { + hb_tag_t axis_tag = axis_records[i].get_axis_tag (); + if (user_axes_location->has (axis_tag)) + { + pinned_axes.set (i, axis_tag); + continue; + } + + nameids->add (axis_records[i].get_name_id ()); + } - + hb_range ((unsigned) instanceCount) - | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); }) - | hb_sink (nameids) - ; + for (unsigned i = 0 ; i < (unsigned)instanceCount; i++) + { + const InstanceRecord *instance = get_instance (i); + + if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount)) + | hb_filter (pinned_axes, hb_second) + | hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _) + { + hb_tag_t axis_tag = pinned_axes.get (_.second); + float location = user_axes_location->get (axis_tag); + if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true; + return false; + }) + )) + continue; + + nameids->add (instance->subfamilyNameID); + + if (instanceSize >= axisCount * 4 + 6) + { + unsigned post_script_name_id = StructAfter<NameID> (instance->get_coordinates (axisCount)); + if (post_script_name_id != HB_OT_NAME_ID_INVALID) nameids->add (post_script_name_id); + } + } } public: diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh index 56efcdbee9..53355c5077 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh @@ -319,27 +319,26 @@ struct HVARVVAR hvar_plan.index_map_plans.as_array ())); } - float get_advance_var (hb_codepoint_t glyph, - hb_font_t *font, - VariationStore::cache_t *store_cache = nullptr) const + float get_advance_delta_unscaled (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count, + VariationStore::cache_t *store_cache = nullptr) const { uint32_t varidx = (this+advMap).map (glyph); return (this+varStore).get_delta (varidx, - font->coords, - font->num_coords, + coords, coord_count, store_cache); } - float get_side_bearing_var (hb_codepoint_t glyph, - const int *coords, unsigned int coord_count) const + bool get_lsb_delta_unscaled (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count, + float *lsb) const { - if (!has_side_bearing_deltas ()) return 0.f; + if (!lsbMap) return false; uint32_t varidx = (this+lsbMap).map (glyph); - return (this+varStore).get_delta (varidx, coords, coord_count); + *lsb = (this+varStore).get_delta (varidx, coords, coord_count); + return true; } - bool has_side_bearing_deltas () const { return lsbMap && rsbMap; } - public: FixedVersion<>version; /* Version of the metrics variation table * initially set to 0x00010000u */ @@ -392,6 +391,16 @@ struct VVAR : HVARVVAR { bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); } + bool get_vorg_delta_unscaled (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count, + float *delta) const + { + if (!vorgMap) return false; + uint32_t varidx = (this+vorgMap).map (glyph); + *delta = (this+varStore).get_delta (varidx, coords, coord_count); + return true; + } + protected: Offset32To<DeltaSetIndexMap> vorgMap; /* Offset to vertical-origin var-idx mapping. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc index 0376e26b4a..f000f27263 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var.cc +++ b/thirdparty/harfbuzz/src/hb-ot-var.cc @@ -56,7 +56,7 @@ * * Tests whether a face includes any OpenType variation data in the `fvar` table. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 1.4.2 **/ @@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face, * Fetches the variation-axis information corresponding to the specified axis tag * in the specified face. * - * Return value: %true if data found, %false otherwise + * Return value: `true` if data found, `false` otherwise * * Since: 2.2.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index 683a441ec3..61b142238e 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -29,10 +29,9 @@ #include "hb-open-type.hh" #include "hb-map.hh" -#include "hb-priority-queue.hh" -#include "hb-serialize.hh" #include "hb-vector.hh" #include "graph/graph.hh" +#include "graph/gsubgpos-graph.hh" #include "graph/serialize.hh" using graph::graph_t; @@ -42,6 +41,143 @@ using graph::graph_t; * docs/repacker.md */ +struct lookup_size_t +{ + unsigned lookup_index; + size_t size; + unsigned num_subtables; + + static int cmp (const void* a, const void* b) + { + return cmp ((const lookup_size_t*) a, + (const lookup_size_t*) b); + } + + static int cmp (const lookup_size_t* a, const lookup_size_t* b) + { + double subtables_per_byte_a = (double) a->num_subtables / (double) a->size; + double subtables_per_byte_b = (double) b->num_subtables / (double) b->size; + if (subtables_per_byte_a == subtables_per_byte_b) { + return b->lookup_index - a->lookup_index; + } + + double cmp = subtables_per_byte_b - subtables_per_byte_a; + if (cmp < 0) return -1; + if (cmp > 0) return 1; + return 0; + } +}; + +static inline +bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context) +{ + // For each lookup this will check the size of subtables and split them as needed + // so that no subtable is at risk of overflowing. (where we support splitting for + // that subtable type). + // + // TODO(grieger): de-dup newly added nodes as necessary. Probably just want a full de-dup + // pass after this processing is done. Not super necessary as splits are + // only done where overflow is likely, so de-dup probably will get undone + // later anyways. + for (unsigned lookup_index : ext_context.lookups.keys ()) + { + graph::Lookup* lookup = ext_context.lookups.get(lookup_index); + if (!lookup->split_subtables_if_needed (ext_context, lookup_index)) + return false; + } + + return true; +} + +/* + * Analyze the lookups in a GSUB/GPOS table and decide if any should be promoted + * to extension lookups. + */ +static inline +bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context) +{ + // Simple Algorithm (v1, current): + // 1. Calculate how many bytes each non-extension lookup consumes. + // 2. Select up to 64k of those to remain as non-extension (greedy, highest subtables per byte first) + // 3. Promote the rest. + // + // Advanced Algorithm (v2, not implemented): + // 1. Perform connected component analysis using lookups as roots. + // 2. Compute size of each connected component. + // 3. Select up to 64k worth of connected components to remain as non-extensions. + // (greedy, highest subtables per byte first) + // 4. Promote the rest. + + // TODO(garretrieger): support extension demotion, then consider all lookups. Requires advanced algo. + // TODO(garretrieger): also support extension promotion during iterative resolution phase, then + // we can use a less conservative threshold here. + // TODO(grieger): skip this for the 24 bit case. + if (!ext_context.lookups) return true; + + hb_vector_t<lookup_size_t> lookup_sizes; + lookup_sizes.alloc (ext_context.lookups.get_population ()); + + for (unsigned lookup_index : ext_context.lookups.keys ()) + { + const graph::Lookup* lookup = ext_context.lookups.get(lookup_index); + hb_set_t visited; + lookup_sizes.push (lookup_size_t { + lookup_index, + ext_context.graph.find_subgraph_size (lookup_index, visited), + lookup->number_of_subtables (), + }); + } + + lookup_sizes.qsort (); + + size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size (); + size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups + size_t l3_l4_size = 0; // Lookups + SubTables + size_t l4_plus_size = 0; // SubTables + their descendants + + // Start by assuming all lookups are using extension subtables, this size will be removed later + // if it's decided to not make a lookup extension. + for (auto p : lookup_sizes) + { + unsigned subtables_size = p.num_subtables * 8; + l3_l4_size += subtables_size; + l4_plus_size += subtables_size; + } + + bool layers_full = false; + for (auto p : lookup_sizes) + { + const graph::Lookup* lookup = ext_context.lookups.get(p.lookup_index); + if (lookup->is_extension (ext_context.table_tag)) + // already an extension so size is counted by the loop above. + continue; + + if (!layers_full) + { + size_t lookup_size = ext_context.graph.vertices_[p.lookup_index].table_size (); + hb_set_t visited; + size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size; + size_t remaining_size = p.size - subtables_size - lookup_size; + + l2_l3_size += lookup_size; + l3_l4_size += lookup_size + subtables_size; + l3_l4_size -= p.num_subtables * 8; + l4_plus_size += subtables_size + remaining_size; + + if (l2_l3_size < (1 << 16) + && l3_l4_size < (1 << 16) + && l4_plus_size < (1 << 16)) continue; // this lookup fits within all layers groups + + layers_full = true; + } + + if (!ext_context.lookups.get(p.lookup_index)->make_extension (ext_context, p.lookup_index)) + return false; + } + + return true; +} + static inline bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& overflows, graph_t& sorted_graph) @@ -157,7 +293,8 @@ template<typename T> inline hb_blob_t* hb_resolve_overflows (const T& packed, hb_tag_t table_tag, - unsigned max_rounds = 20) { + unsigned max_rounds = 20, + bool recalculate_extensions = false) { graph_t sorted_graph (packed); sorted_graph.sort_shortest_distance (); @@ -167,13 +304,31 @@ hb_resolve_overflows (const T& packed, return graph::serialize (sorted_graph); } + graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph); if ((table_tag == HB_OT_TAG_GPOS || table_tag == HB_OT_TAG_GSUB) && will_overflow) { + if (recalculate_extensions) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed."); + if (!_presplit_subtables_if_needed (ext_context)) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed."); + return nullptr; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed."); + if (!_promote_extensions_if_needed (ext_context)) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed."); + return nullptr; + } + } + DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs."); - if (sorted_graph.assign_32bit_spaces ()) + if (sorted_graph.assign_spaces ()) sorted_graph.sort_shortest_distance (); + else + sorted_graph.sort_shortest_distance_if_needed (); } unsigned round = 0; @@ -181,7 +336,7 @@ hb_resolve_overflows (const T& packed, // TODO(garretrieger): select a good limit for max rounds. while (!sorted_graph.in_error () && graph::will_overflow (sorted_graph, &overflows) - && round++ < max_rounds) { + && round < max_rounds) { DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round); print_overflows (sorted_graph, overflows); @@ -189,6 +344,9 @@ hb_resolve_overflows (const T& packed, if (!_try_isolating_subgraphs (overflows, sorted_graph)) { + // Don't count space isolation towards round limit. Only increment + // round counter if space isolation made no changes. + round++; if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :("); diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc index 2d458294f8..0270b21998 100644 --- a/thirdparty/harfbuzz/src/hb-set.cc +++ b/thirdparty/harfbuzz/src/hb-set.cc @@ -56,8 +56,6 @@ hb_set_create () if (!(set = hb_object_create<hb_set_t> ())) return hb_set_get_empty (); - set->init_shallow (); - return set; } @@ -107,8 +105,6 @@ hb_set_destroy (hb_set_t *set) { if (!hb_object_destroy (set)) return; - set->fini_shallow (); - hb_free (set); } @@ -122,7 +118,7 @@ hb_set_destroy (hb_set_t *set) * * Attaches a user-data key/data pair to the specified set. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -149,7 +145,7 @@ hb_set_set_user_data (hb_set_t *set, * Since: 0.9.2 **/ void * -hb_set_get_user_data (hb_set_t *set, +hb_set_get_user_data (const hb_set_t *set, hb_user_data_key_t *key) { return hb_object_get_user_data (set, key); @@ -162,7 +158,7 @@ hb_set_get_user_data (hb_set_t *set, * * Tests whether memory allocation for a set was successful. * - * Return value: %true if allocation succeeded, %false otherwise + * Return value: `true` if allocation succeeded, `false` otherwise * * Since: 0.9.2 **/ @@ -212,7 +208,7 @@ hb_set_clear (hb_set_t *set) * * Tests whether a set is empty (contains no elements). * - * Return value: %true if @set is empty + * Return value: `true` if @set is empty * * Since: 0.9.7 **/ @@ -229,7 +225,7 @@ hb_set_is_empty (const hb_set_t *set) * * Tests whether @codepoint belongs to @set. * - * Return value: %true if @codepoint is in @set, %false otherwise + * Return value: `true` if @codepoint is in @set, `false` otherwise * * Since: 0.9.2 **/ @@ -348,7 +344,7 @@ hb_set_del_range (hb_set_t *set, * Tests whether @set and @other are equal (contain the same * elements). * - * Return value: %true if the two sets are equal, %false otherwise. + * Return value: `true` if the two sets are equal, `false` otherwise. * * Since: 0.9.7 **/ @@ -383,7 +379,7 @@ hb_set_hash (const hb_set_t *set) * * Tests whether @set is a subset of @larger_set. * - * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise. + * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise. * * Since: 1.8.1 **/ @@ -553,7 +549,7 @@ hb_set_get_max (const hb_set_t *set) * * Set @codepoint to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a next value, %false otherwise + * Return value: `true` if there was a next value, `false` otherwise * * Since: 0.9.2 **/ @@ -574,7 +570,7 @@ hb_set_next (const hb_set_t *set, * * Set @codepoint to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a previous value, %false otherwise + * Return value: `true` if there was a previous value, `false` otherwise * * Since: 1.8.0 **/ @@ -597,7 +593,7 @@ hb_set_previous (const hb_set_t *set, * * Set @last to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a next range, %false otherwise + * Return value: `true` if there was a next range, `false` otherwise * * Since: 0.9.7 **/ @@ -621,7 +617,7 @@ hb_set_next_range (const hb_set_t *set, * * Set @first to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a previous range, %false otherwise + * Return value: `true` if there was a previous range, `false` otherwise * * Since: 1.8.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h index 56902c267e..93636ab5d7 100644 --- a/thirdparty/harfbuzz/src/hb-set.h +++ b/thirdparty/harfbuzz/src/hb-set.h @@ -77,7 +77,7 @@ hb_set_set_user_data (hb_set_t *set, hb_bool_t replace); HB_EXTERN void * -hb_set_get_user_data (hb_set_t *set, +hb_set_get_user_data (const hb_set_t *set, hb_user_data_key_t *key); diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index 7eb5e19a2a..5d5576cb9e 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -59,17 +59,15 @@ struct hb_sparseset_t hb_copy (o, *this); } - void init_shallow () { s.init (); } void init () { hb_object_init (this); - init_shallow (); + s.init (); } - void fini_shallow () { s.fini (); } void fini () { hb_object_fini (this); - fini_shallow (); + s.fini (); } explicit operator bool () const { return !is_empty (); } diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc index 0af07825fc..9e513c0458 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.cc +++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc @@ -117,7 +117,7 @@ hb_shape_plan_key_t::init (bool copy, } else { - const hb_shaper_entry_t *shapers = _hb_shapers_get (); + const HB_UNUSED hb_shaper_entry_t *shapers = _hb_shapers_get (); for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) if (false) ; @@ -318,10 +318,6 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) { if (!hb_object_destroy (shape_plan)) return; -#ifndef HB_NO_OT_SHAPE - shape_plan->ot.fini (); -#endif - shape_plan->key.fini (); hb_free (shape_plan); } @@ -335,7 +331,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) * * Attaches a user-data key/data pair to the given shaping plan. * - * Return value: %true if success, %false otherwise. + * Return value: `true` if success, `false` otherwise. * * Since: 0.9.7 **/ @@ -362,8 +358,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, * Since: 0.9.7 **/ void * -hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, - hb_user_data_key_t *key) +hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key) { return hb_object_get_user_data (shape_plan, key); } @@ -440,7 +436,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan, * Executes the given shaping plan on the specified buffer, using * the given @font and @features. * - * Return value: %true if success, %false otherwise. + * Return value: `true` if success, `false` otherwise. * * Since: 0.9.7 **/ diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.h b/thirdparty/harfbuzz/src/hb-shape-plan.h index fc7c041899..aaf5cf9c45 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.h +++ b/thirdparty/harfbuzz/src/hb-shape-plan.h @@ -102,8 +102,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, hb_bool_t replace); HB_EXTERN void * -hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, - hb_user_data_key_t *key); +hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key); HB_EXTERN hb_bool_t diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.hh b/thirdparty/harfbuzz/src/hb-shape-plan.hh index 8cb4ddb927..6fc73939b3 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.hh +++ b/thirdparty/harfbuzz/src/hb-shape-plan.hh @@ -55,7 +55,7 @@ struct hb_shape_plan_key_t unsigned int num_coords, const char * const *shaper_list); - HB_INTERNAL void fini () { hb_free ((void *) user_features); } + HB_INTERNAL void fini () { hb_free ((void *) user_features); user_features = nullptr; } HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other); @@ -64,6 +64,7 @@ struct hb_shape_plan_key_t struct hb_shape_plan_t { + ~hb_shape_plan_t () { key.fini (); } hb_object_header_t header; hb_face_t *face_unsafe; /* We don't carry a reference to face. */ hb_shape_plan_key_t key; diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc index 14ec92828f..547d0afc47 100644 --- a/thirdparty/harfbuzz/src/hb-shape.cc +++ b/thirdparty/harfbuzz/src/hb-shape.cc @@ -106,12 +106,12 @@ hb_shape_list_shapers () * @font: an #hb_font_t to use for shaping * @buffer: an #hb_buffer_t to shape * @features: (array length=num_features) (nullable): an array of user - * specified #hb_feature_t or %NULL + * specified #hb_feature_t or `NULL` * @num_features: the length of @features array - * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated - * array of shapers to use or %NULL + * @shaper_list: (array zero-terminated=1) (nullable): a `NULL`-terminated + * array of shapers to use or `NULL` * - * See hb_shape() for details. If @shaper_list is not %NULL, the specified + * See hb_shape() for details. If @shaper_list is not `NULL`, the specified * shapers will be used in the given order, otherwise the default shapers list * will be used. * @@ -173,11 +173,11 @@ hb_shape_full (hb_font_t *font, * @font: an #hb_font_t to use for shaping * @buffer: an #hb_buffer_t to shape * @features: (array length=num_features) (nullable): an array of user - * specified #hb_feature_t or %NULL + * specified #hb_feature_t or `NULL` * @num_features: the length of @features array * * Shapes @buffer using @font turning its Unicode characters content to - * positioned glyphs. If @features is not %NULL, it will be used to control the + * positioned glyphs. If @features is not `NULL`, it will be used to control the * features applied during shaping. If two @features have the same tag but * overlapping ranges the value of the feature with the higher index takes * precedence. diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc index da4253ed64..a900ac6991 100644 --- a/thirdparty/harfbuzz/src/hb-shaper.cc +++ b/thirdparty/harfbuzz/src/hb-shaper.cc @@ -64,7 +64,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t, if (!end) end = p + strlen (p); - for (unsigned int j = i; j < ARRAY_LENGTH (_hb_all_shapers); j++) + for (unsigned int j = i; j < ARRAY_LENGTH_CONST (_hb_all_shapers); j++) if (end - p == (int) strlen (shapers[j].name) && 0 == strncmp (shapers[j].name, p, end - p)) { diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc index 5c5ecce880..af95615c16 100644 --- a/thirdparty/harfbuzz/src/hb-static.cc +++ b/thirdparty/harfbuzz/src/hb-static.cc @@ -46,11 +46,10 @@ uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; -DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; +DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01}; DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF}; -/* Hand-coded because Lookup is a template. Sad. */ -const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF}; +DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF}; /* hb_map_t */ @@ -59,7 +58,7 @@ const hb_codepoint_t minus_1 = -1; /* hb_face_t */ -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K static inline unsigned load_num_glyphs_from_loca (const hb_face_t *face) { @@ -89,7 +88,7 @@ hb_face_t::load_num_glyphs () const { unsigned ret = 0; -#ifndef HB_NO_BORING_EXPANSION +#ifndef HB_NO_BEYOND_64K ret = hb_max (ret, load_num_glyphs_from_loca (this)); #endif diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc index 028ddf9035..7d19496275 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.cc +++ b/thirdparty/harfbuzz/src/hb-subset-input.cc @@ -32,7 +32,7 @@ * * Creates a new subset input object. * - * Return value: (transfer full): New subset input, or %NULL if failed. Destroy + * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy * with hb_subset_input_destroy(). * * Since: 1.8.0 @@ -48,7 +48,9 @@ hb_subset_input_create_or_fail (void) for (auto& set : input->sets_iter ()) set = hb_set_create (); - if (input->in_error ()) + input->axes_location = hb_hashmap_create<hb_tag_t, float> (); + + if (!input->axes_location || input->in_error ()) { hb_subset_input_destroy (input); return nullptr; @@ -96,7 +98,6 @@ hb_subset_input_create_or_fail (void) HB_TAG ('D', 'S', 'I', 'G'), HB_TAG ('M', 'V', 'A', 'R'), HB_TAG ('c', 'v', 'a', 'r'), - HB_TAG ('S', 'T', 'A', 'T'), }; input->sets.no_subset_tables->add_array (default_no_subset_tables, ARRAY_LENGTH (default_no_subset_tables)); @@ -203,6 +204,8 @@ hb_subset_input_create_or_fail (void) input->sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features)); + input->sets.layout_scripts->invert (); // Default to all scripts. + if (input->in_error ()) { hb_subset_input_destroy (input); @@ -244,6 +247,8 @@ hb_subset_input_destroy (hb_subset_input_t *input) for (hb_set_t* set : input->sets_iter ()) hb_set_destroy (set); + hb_hashmap_destroy (input->axes_location); + hb_free (input); } @@ -342,7 +347,7 @@ hb_subset_input_set_flags (hb_subset_input_t *input, * * Attaches a user-data key/data pair to the given subset input object. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 2.9.0 **/ @@ -374,3 +379,56 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input, { return hb_object_get_user_data (input, key); } + +#ifdef HB_EXPERIMENTAL_API +#ifndef HB_NO_VAR +/** + * hb_subset_input_pin_axis_to_default: (skip) + * @input: a #hb_subset_input_t object. + * @axis_tag: Tag of the axis to be pinned + * + * Pin an axis to its default location in the given subset input object. + * + * Return value: `true` if success, `false` otherwise + * + * Since: REPLACEME + **/ +hb_bool_t +hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag) +{ + hb_ot_var_axis_info_t axis_info; + if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) + return false; + + return input->axes_location->set (axis_tag, axis_info.default_value); +} + +/** + * hb_subset_input_pin_axis_location: (skip) + * @input: a #hb_subset_input_t object. + * @axis_tag: Tag of the axis to be pinned + * @axis_value: Location on the axis to be pinned at + * + * Pin an axis to a fixed location in the given subset input object. + * + * Return value: `true` if success, `false` otherwise + * + * Since: REPLACEME + **/ +hb_bool_t +hb_subset_input_pin_axis_location (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag, + float axis_value) +{ + hb_ot_var_axis_info_t axis_info; + if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) + return false; + + float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value); + return input->axes_location->set (axis_tag, val); +} +#endif +#endif diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh index 07c0e22676..2335f0634f 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.hh +++ b/thirdparty/harfbuzz/src/hb-subset-input.hh @@ -50,6 +50,7 @@ struct hb_subset_input_t hb_set_t *name_ids; hb_set_t *name_languages; hb_set_t *layout_features; + hb_set_t *layout_scripts; }; union { @@ -58,6 +59,7 @@ struct hb_subset_input_t }; unsigned flags; + hb_hashmap_t<hb_tag_t, float> *axes_location; inline unsigned num_sets () const { @@ -76,7 +78,8 @@ struct hb_subset_input_t if (unlikely (set_ptrs[i]->in_error ())) return true; } - return false; + + return axes_location->in_error (); } }; diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 4e3bb1d477..7ff66333a8 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -37,10 +37,11 @@ #include "hb-ot-color-colr-table.hh" #include "hb-ot-color-colrv1-closure.hh" #include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var-avar-table.hh" #include "hb-ot-stat-table.hh" #include "hb-ot-math-table.hh" -using OT::Layout::GSUB::GSUB; +using OT::Layout::GSUB; using OT::Layout::GPOS; typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map; @@ -91,100 +92,171 @@ _remap_indexes (const hb_set_t *indexes, typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */); +/* + * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates. + * Returns true if anything was removed (not including duplicates). + */ +static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */ + const hb_set_t* filter) +{ + hb_vector_t<hb_tag_t> out; + out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator. + + bool removed = false; + hb_set_t visited; + + for (hb_tag_t tag : *tags) + { + if (!tag) continue; + if (visited.has (tag)) continue; + + if (!filter->has (tag)) + { + removed = true; + continue; + } + + visited.add (tag); + out.push (tag); + } + + // The collect function needs a null element to signal end of the array. + out.push (HB_TAG_NONE); + + hb_swap (out, *tags); + return removed; +} + template <typename T> -static void _collect_layout_indices (hb_face_t *face, +static void _collect_layout_indices (hb_subset_plan_t *plan, const T& table, - const hb_set_t *layout_features_to_retain, layout_collect_func_t layout_collect_func, hb_set_t *indices /* OUT */) { + unsigned num_features = table.get_feature_count (); hb_vector_t<hb_tag_t> features; - if (!features.alloc (table.get_feature_count () + 1)) + if (!plan->check_success (features.resize (num_features))) return; + table.get_feature_tags (0, &num_features, features.arrayZ); + bool retain_all_features = !_filter_tag_list (&features, plan->layout_features); + + unsigned num_scripts = table.get_script_count (); + hb_vector_t<hb_tag_t> scripts; + if (!plan->check_success (scripts.resize (num_scripts))) return; + table.get_script_tags (0, &num_scripts, scripts.arrayZ); + bool retain_all_scripts = !_filter_tag_list (&scripts, plan->layout_scripts); + + if (!plan->check_success (!features.in_error ()) || !features + || !plan->check_success (!scripts.in_error ()) || !scripts) return; - hb_set_t visited_features; - bool retain_all_features = true; - for (unsigned i = 0; i < table.get_feature_count (); i++) + layout_collect_func (plan->source, + T::tableTag, + retain_all_scripts ? nullptr : scripts.arrayZ, + nullptr, + retain_all_features ? nullptr : features.arrayZ, + indices); +} + + +static inline void +_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, + const hb_map_t *lookup_indices, + const hb_set_t *feature_indices, + hb_map_t *duplicate_feature_map /* OUT */) +{ + if (feature_indices->is_empty ()) return; + hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features; + //find out duplicate features after subset + for (unsigned i : feature_indices->iter ()) { - hb_tag_t tag = table.get_feature_tag (i); - if (!tag) continue; - if (!layout_features_to_retain->has (tag)) + hb_tag_t t = g.get_feature_tag (i); + if (t == HB_MAP_VALUE_INVALID) continue; + if (!unique_features.has (t)) { - retain_all_features = false; + if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()}))) + return; + if (unique_features.has (t)) + unique_features.get (t)->add (i); + duplicate_feature_map->set (i, i); continue; } - if (visited_features.has (tag)) - continue; + bool found = false; - features.push (tag); - visited_features.add (tag); - } + hb_set_t* same_tag_features = unique_features.get (t); + for (unsigned other_f_index : same_tag_features->iter ()) + { + const OT::Feature& f = g.get_feature (i); + const OT::Feature& other_f = g.get_feature (other_f_index); - if (!features) - return; + auto f_iter = + + hb_iter (f.lookupIndex) + | hb_filter (lookup_indices) + ; - // The collect function needs a null element to signal end of the array. - features.push (0); + auto other_f_iter = + + hb_iter (other_f.lookupIndex) + | hb_filter (lookup_indices) + ; - if (retain_all_features) - { - // Looking for all features, trigger the faster collection method. - layout_collect_func (face, - T::tableTag, - nullptr, - nullptr, - nullptr, - indices); - return; - } + bool is_equal = true; + for (; f_iter && other_f_iter; f_iter++, other_f_iter++) + { + unsigned a = *f_iter; + unsigned b = *other_f_iter; + if (a != b) { is_equal = false; break; } + } - layout_collect_func (face, - T::tableTag, - nullptr, - nullptr, - features.arrayZ, - indices); + if (is_equal == false || f_iter || other_f_iter) continue; + + found = true; + duplicate_feature_map->set (i, other_f_index); + break; + } + + if (found == false) + { + same_tag_features->add (i); + duplicate_feature_map->set (i, i); + } + } } template <typename T> static inline void -_closure_glyphs_lookups_features (hb_face_t *face, +_closure_glyphs_lookups_features (hb_subset_plan_t *plan, hb_set_t *gids_to_retain, - const hb_set_t *layout_features_to_retain, hb_map_t *lookups, hb_map_t *features, script_langsys_map *langsys_map) { - hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face); + hb_blob_ptr_t<T> table = plan->source_table<T> (); hb_tag_t table_tag = table->tableTag; hb_set_t lookup_indices; - _collect_layout_indices<T> (face, + _collect_layout_indices<T> (plan, *table, - layout_features_to_retain, hb_ot_layout_collect_lookups, &lookup_indices); if (table_tag == HB_OT_TAG_GSUB) - hb_ot_layout_lookups_substitute_closure (face, - &lookup_indices, + hb_ot_layout_lookups_substitute_closure (plan->source, + &lookup_indices, gids_to_retain); - table->closure_lookups (face, + table->closure_lookups (plan->source, gids_to_retain, - &lookup_indices); + &lookup_indices); _remap_indexes (&lookup_indices, lookups); // Collect and prune features hb_set_t feature_indices; - _collect_layout_indices<T> (face, + _collect_layout_indices<T> (plan, *table, - layout_features_to_retain, hb_ot_layout_collect_features, &feature_indices); table->prune_features (lookups, &feature_indices); hb_map_t duplicate_feature_map; - table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map); + _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map); feature_indices.clear (); table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices); @@ -197,14 +269,14 @@ _closure_glyphs_lookups_features (hb_face_t *face, #ifndef HB_NO_VAR static inline void - _collect_layout_variation_indices (hb_face_t *face, - const hb_set_t *glyphset, - const hb_map_t *gpos_lookups, - hb_set_t *layout_variation_indices, - hb_map_t *layout_variation_idx_map) +_collect_layout_variation_indices (hb_subset_plan_t* plan, + const hb_set_t *glyphset, + const hb_map_t *gpos_lookups, + hb_set_t *layout_variation_indices, + hb_map_t *layout_variation_idx_map) { - hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face); - hb_blob_ptr_t<GPOS> gpos = hb_sanitize_context_t ().reference_table<GPOS> (face); + hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> (); + hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> (); if (!gdef->has_data ()) { @@ -215,7 +287,7 @@ static inline void OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups); gdef->collect_variation_indices (&c); - if (hb_ot_layout_has_positioning (face)) + if (hb_ot_layout_has_positioning (plan->source)) gpos->collect_variation_indices (&c); gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map); @@ -242,22 +314,16 @@ static void _colr_closure (hb_face_t *face, OT::COLR::accelerator_t colr (face); if (!colr.is_valid ()) return; - unsigned iteration_count = 0; hb_set_t palette_indices, layer_indices; - unsigned glyphs_num; - { - glyphs_num = glyphs_colred->get_population (); - // Collect all glyphs referenced by COLRv0 - hb_set_t glyphset_colrv0; - for (hb_codepoint_t gid : glyphs_colred->iter ()) - colr.closure_glyphs (gid, &glyphset_colrv0); + // Collect all glyphs referenced by COLRv0 + hb_set_t glyphset_colrv0; + for (hb_codepoint_t gid : *glyphs_colred) + colr.closure_glyphs (gid, &glyphset_colrv0); - glyphs_colred->union_ (glyphset_colrv0); + glyphs_colred->union_ (glyphset_colrv0); - //closure for COLRv1 - colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices); - } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && - glyphs_num != glyphs_colred->get_population ()); + //closure for COLRv1 + colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices); colr.closure_V0palette_indices (glyphs_colred, &palette_indices); _remap_indexes (&layer_indices, layers_map); @@ -265,10 +331,10 @@ static void _colr_closure (hb_face_t *face, } static inline void -_math_closure (hb_face_t *face, - hb_set_t *glyphset) +_math_closure (hb_subset_plan_t *plan, + hb_set_t *glyphset) { - hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face); + hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> (); if (math->has_data ()) math->closure_glyphs (glyphset); math.destroy (); @@ -368,7 +434,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ()) operation_count = _glyf_add_gid_and_children (glyf, - item.glyphIndex, + item.get_gid (), gids_to_retain, operation_count, depth); @@ -395,18 +461,16 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, if (close_over_gsub) // closure all glyphs/lookups/features needed for GSUB substitutions. _closure_glyphs_lookups_features<GSUB> ( - plan->source, + plan, plan->_glyphset_gsub, - plan->layout_features, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys); if (close_over_gpos) _closure_glyphs_lookups_features<GPOS> ( - plan->source, + plan, plan->_glyphset_gsub, - plan->layout_features, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys); @@ -414,7 +478,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub); - _math_closure (plan->source, plan->_glyphset_mathed); + _math_closure (plan, plan->_glyphset_mathed); _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ()); hb_set_t cur_glyphset = *plan->_glyphset_mathed; @@ -442,7 +506,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #ifndef HB_NO_VAR if (close_over_gdef) - _collect_layout_variation_indices (plan->source, + _collect_layout_variation_indices (plan, plan->_glyphset_gsub, plan->gpos_lookups, plan->layout_variation_indices, @@ -506,16 +570,62 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, static void _nameid_closure (hb_face_t *face, - hb_set_t *nameids) + hb_set_t *nameids, + bool all_axes_pinned, + hb_hashmap_t<hb_tag_t, float> *user_axes_location) { #ifndef HB_NO_STYLE - face->table.STAT->collect_name_ids (nameids); + face->table.STAT->collect_name_ids (user_axes_location, nameids); #endif #ifndef HB_NO_VAR - face->table.fvar->collect_name_ids (nameids); + if (!all_axes_pinned) + face->table.fvar->collect_name_ids (user_axes_location, nameids); #endif } +#ifndef HB_NO_VAR +static void +_normalize_axes_location (hb_face_t *face, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location, + hb_hashmap_t<hb_tag_t, int> *normalized_axes_location, /* OUT */ + bool &all_axes_pinned) +{ + if (user_axes_location->is_empty ()) + return; + + hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes (); + + bool has_avar = face->table.avar->has_data (); + const OT::SegmentMaps *seg_maps = nullptr; + if (has_avar) + seg_maps = face->table.avar->get_segment_maps (); + + bool axis_not_pinned = false; + unsigned axis_count = 0; + for (const auto& axis : axes) + { + hb_tag_t axis_tag = axis.get_axis_tag (); + if (!user_axes_location->has (axis_tag)) + { + axis_not_pinned = true; + } + else + { + int normalized_v = axis.normalize_axis_value (user_axes_location->get (axis_tag)); + if (has_avar && axis_count < face->table.avar->get_axis_count ()) + { + normalized_v = seg_maps->map (normalized_v); + } + normalized_axes_location->set (axis_tag, normalized_v); + } + if (has_avar) + seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps); + + axis_count++; + } + all_axes_pinned = !axis_not_pinned; +} +#endif /** * hb_subset_plan_create_or_fail: * @face: font face to create the plan for. @@ -546,9 +656,9 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->unicode_to_new_gid_list.init (); plan->name_ids = hb_set_copy (input->sets.name_ids); - _nameid_closure (face, plan->name_ids); plan->name_languages = hb_set_copy (input->sets.name_languages); plan->layout_features = hb_set_copy (input->sets.layout_features); + plan->layout_scripts = hb_set_copy (input->sets.layout_scripts); plan->glyphs_requested = hb_set_copy (input->sets.glyphs); plan->drop_tables = hb_set_copy (input->sets.drop_tables); plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables); @@ -566,10 +676,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->gsub_lookups = hb_map_create (); plan->gpos_lookups = hb_map_create (); - if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ())) - plan->gsub_langsys->init_shallow (); - if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ())) - plan->gpos_langsys->init_shallow (); + plan->check_success (plan->gsub_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ()); + plan->check_success (plan->gpos_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ()); plan->gsub_features = hb_map_create (); plan->gpos_features = hb_map_create (); @@ -578,6 +686,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->layout_variation_indices = hb_set_create (); plan->layout_variation_idx_map = hb_map_create (); + plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ()); + plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ()); + plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ()); + if (plan->user_axes_location && input->axes_location) + *plan->user_axes_location = *input->axes_location; + plan->all_axes_pinned = false; + if (unlikely (plan->in_error ())) { hb_subset_plan_destroy (plan); return nullptr; @@ -610,6 +725,14 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second); } +#ifndef HB_NO_VAR + _normalize_axes_location (face, + input->axes_location, + plan->axes_location, + plan->all_axes_pinned); +#endif + + _nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location); if (unlikely (plan->in_error ())) { hb_subset_plan_destroy (plan); return nullptr; @@ -632,10 +755,10 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) if (!hb_object_destroy (plan)) return; hb_set_destroy (plan->unicodes); - plan->unicode_to_new_gid_list.fini (); hb_set_destroy (plan->name_ids); hb_set_destroy (plan->name_languages); hb_set_destroy (plan->layout_features); + hb_set_destroy (plan->layout_scripts); hb_set_destroy (plan->glyphs_requested); hb_set_destroy (plan->drop_tables); hb_set_destroy (plan->no_subset_tables); @@ -658,18 +781,15 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_set_destroy (plan->layout_variation_indices); hb_map_destroy (plan->layout_variation_idx_map); - if (plan->gsub_langsys) - { - hb_object_destroy (plan->gsub_langsys); - plan->gsub_langsys->fini_shallow (); - hb_free (plan->gsub_langsys); - } + hb_hashmap_destroy (plan->gsub_langsys); + hb_hashmap_destroy (plan->gpos_langsys); + hb_hashmap_destroy (plan->axes_location); + hb_hashmap_destroy (plan->sanitized_table_cache); - if (plan->gpos_langsys) + if (plan->user_axes_location) { - hb_object_destroy (plan->gpos_langsys); - plan->gpos_langsys->fini_shallow (); - hb_free (plan->gpos_langsys); + hb_object_destroy (plan->user_axes_location); + hb_free (plan->user_axes_location); } hb_free (plan); @@ -755,7 +875,7 @@ hb_subset_plan_reference (hb_subset_plan_t *plan) * * Attaches a user-data key/data pair to the given subset plan object. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 4.0.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index 2aaf19c61d..8912ae70d5 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -55,6 +55,9 @@ struct hb_subset_plan_t //layout features which will be preserved hb_set_t *layout_features; + // layout scripts which will be preserved. + hb_set_t *layout_scripts; + //glyph ids requested to retain hb_set_t *glyphs_requested; @@ -103,8 +106,34 @@ struct hb_subset_plan_t //Old -> New layout item variation store delta set index mapping hb_map_t *layout_variation_idx_map; + hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache; + //normalized axes location map + hb_hashmap_t<hb_tag_t, int> *axes_location; + //user specified axes location map + hb_hashmap_t<hb_tag_t, float> *user_axes_location; + bool all_axes_pinned; + public: + template<typename T> + hb_blob_ptr_t<T> source_table() + { + if (sanitized_table_cache + && !sanitized_table_cache->in_error () + && sanitized_table_cache->has (T::tableTag)) { + return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ()); + } + + hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)}; + hb_blob_t* ret = hb_blob_reference (table_blob.get ()); + + if (likely (sanitized_table_cache)) + sanitized_table_cache->set (T::tableTag, + std::move (table_blob)); + + return ret; + } + bool in_error () const { return !successful; } bool check_success(bool success) diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.cc b/thirdparty/harfbuzz/src/hb-subset-repacker.cc index 2447d296b8..55ca48d709 100644 --- a/thirdparty/harfbuzz/src/hb-subset-repacker.cc +++ b/thirdparty/harfbuzz/src/hb-subset-repacker.cc @@ -25,25 +25,34 @@ #include "hb-repacker.hh" #ifdef HB_EXPERIMENTAL_API + /** * hb_subset_repack_or_fail: + * @table_tag: tag of the table being packed, needed to allow table specific optimizations. * @hb_objects: raw array of struct hb_object_t, which provides * object graph info * @num_hb_objs: number of hb_object_t in the hb_objects array. * * Given the input object graph info, repack a table to eliminate * offset overflows. A nullptr is returned if the repacking attempt fails. + * Table specific optimizations (eg. extension promotion in GSUB/GPOS) may be performed. + * Passing HB_TAG_NONE will disable table specific optimizations. * * Since: EXPERIMENTAL **/ -hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs) +hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag, + hb_object_t* hb_objects, + unsigned num_hb_objs) { hb_vector_t<const hb_object_t *> packed; packed.alloc (num_hb_objs + 1); packed.push (nullptr); for (unsigned i = 0 ; i < num_hb_objs ; i++) packed.push (&(hb_objects[i])); - return hb_resolve_overflows (packed, HB_OT_TAG_GSUB); + + return hb_resolve_overflows (packed, + table_tag, + 20, + true); } #endif - diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.h b/thirdparty/harfbuzz/src/hb-subset-repacker.h index f9a2383698..245cf60765 100644 --- a/thirdparty/harfbuzz/src/hb-subset-repacker.h +++ b/thirdparty/harfbuzz/src/hb-subset-repacker.h @@ -31,13 +31,13 @@ HB_BEGIN_DECLS #ifdef HB_EXPERIMENTAL_API -/** +/* * struct hb_link_t * width: offsetSize in bytes * position: position of the offset field in bytes * from beginning of subtable * objidx: index of subtable - **/ + */ struct hb_link_t { unsigned width; @@ -47,7 +47,7 @@ struct hb_link_t typedef struct hb_link_t hb_link_t; -/** +/* * struct hb_object_t * head: start of object data * tail: end of object data @@ -56,7 +56,7 @@ typedef struct hb_link_t hb_link_t; * num_virtual_links: num of objects that must be packed * after current object in the final serialized order * virtual_links: array of virtual link info - **/ + */ struct hb_object_t { char *head; @@ -70,7 +70,8 @@ struct hb_object_t typedef struct hb_object_t hb_object_t; HB_EXTERN hb_blob_t* -hb_subset_repack_or_fail (hb_object_t* hb_objects, +hb_subset_repack_or_fail (hb_tag_t table_tag, + hb_object_t* hb_objects, unsigned num_hb_objs); #endif diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index 10c572c2f7..f62e7e895b 100644 --- a/thirdparty/harfbuzz/src/hb-subset.cc +++ b/thirdparty/harfbuzz/src/hb-subset.cc @@ -53,9 +53,10 @@ #include "hb-ot-var-gvar-table.hh" #include "hb-ot-var-hvar-table.hh" #include "hb-ot-math-table.hh" +#include "hb-ot-stat-table.hh" #include "hb-repacker.hh" -using OT::Layout::GSUB::GSUB; +using OT::Layout::GSUB; using OT::Layout::GPOS; /** @@ -242,10 +243,15 @@ _try_subset (const TableType *table, unsigned buf_size = buf->allocated; buf_size = buf_size * 2 + 16; + + + + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (c->table_tag), buf_size); - if (unlikely (!buf->alloc (buf_size))) + if (unlikely (buf_size > c->source_blob->length * 16 || + !buf->alloc (buf_size))) { DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (c->table_tag), buf_size); @@ -260,15 +266,15 @@ template<typename TableType> static bool _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf) { - hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source); - const TableType *table = source_blob->as<TableType> (); + hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> (); + const TableType *table = source_blob.get (); hb_tag_t tag = TableType::tableTag; - if (!source_blob->data) + if (!source_blob.get_blob()->data) { DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); - hb_blob_destroy (source_blob); + source_blob.destroy (); return false; } @@ -278,23 +284,23 @@ _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf) TableType::tableTag == HB_OT_TAG_GPOS || TableType::tableTag == HB_OT_TAG_name; - unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length, same_size_table); + unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table); DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); if (unlikely (!buf.alloc (buf_size))) { DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); - hb_blob_destroy (source_blob); + source_blob.destroy (); return false; } bool needed = false; hb_serialize_context_t serializer (buf.arrayZ, buf.allocated); { - hb_subset_context_t c (source_blob, plan, &serializer, tag); + hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag); needed = _try_subset (table, &buf, &c); } - hb_blob_destroy (source_blob); + source_blob.destroy (); if (serializer.in_error () && !serializer.only_offset_overflow ()) { @@ -356,6 +362,8 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) switch (tag) { case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */ + return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING); + case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */ case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */ case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */ @@ -375,6 +383,14 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) return true; #endif + case HB_TAG ('a','v','a','r'): + case HB_TAG ('f','v','a','r'): + case HB_TAG ('g','v','a','r'): + case HB_OT_TAG_HVAR: + case HB_OT_TAG_VVAR: + case HB_TAG ('M','V','A','R'): + return plan->all_axes_pinned; + default: return false; } @@ -438,6 +454,11 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf); case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf); #endif + case HB_OT_TAG_STAT: + /*TODO(qxliu): change the condition as we support more complex + * instancing operation*/ + if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf); + else return _passthrough (plan, tag); default: if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h index a2799d91e8..08e52dbd2d 100644 --- a/thirdparty/harfbuzz/src/hb-subset.h +++ b/thirdparty/harfbuzz/src/hb-subset.h @@ -100,6 +100,8 @@ typedef enum { /*< flags >*/ * @HB_SUBSET_SETS_NAME_LANG_ID: the set of name lang ids that will be retained. * @HB_SUBSET_SETS_LAYOUT_FEATURE_TAG: the set of layout feature tags that will be retained * in the subset. + * @HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG: the set of layout script tags that will be retained + * in the subset. Defaults to all tags. Since: 5.0.0 * * List of sets that can be configured on the subset input. * @@ -113,6 +115,7 @@ typedef enum { HB_SUBSET_SETS_NAME_ID, HB_SUBSET_SETS_NAME_LANG_ID, HB_SUBSET_SETS_LAYOUT_FEATURE_TAG, + HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG, } hb_subset_sets_t; HB_EXTERN hb_subset_input_t * @@ -151,6 +154,21 @@ HB_EXTERN void hb_subset_input_set_flags (hb_subset_input_t *input, unsigned value); +#ifdef HB_EXPERIMENTAL_API +#ifndef HB_NO_VAR +HB_EXTERN hb_bool_t +hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag); + +HB_EXTERN hb_bool_t +hb_subset_input_pin_axis_location (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag, + float axis_value); +#endif +#endif + HB_EXTERN hb_face_t * hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input); diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh index 9e76ca460b..14734c91ea 100644 --- a/thirdparty/harfbuzz/src/hb-ucd-table.hh +++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh @@ -1068,2860 +1068,6 @@ _hb_ucd_dm2_u64_map[388] = #ifndef HB_OPTIMIZE_SIZE static const uint8_t -_hb_ucd_u8[33120] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 28, 26, 29, 30, 31, 32, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 33, 34, 34, 34, 34, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 26, 56, 57, 58, 58, 58, 58, 59, 26, 26, 60, 58, 58, 58, 58, 58, - 58, 58, 26, 61, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 26, 62, 58, 63, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 64, 26, 26, 65, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 66, 67, 68, 58, 58, 58, 58, 69, 58, - 58, 58, 58, 58, 58, 58, 58, 70, 71, 72, 73, 74, 75, 76, 58, 77, - 78, 79, 58, 80, 81, 58, 82, 83, 84, 85, 75, 86, 87, 88, 58, 58, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 89, 26, 26, 26, 26, 26, 26, 26, 90, 91, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 92, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 93, 58, 58, 58, 58, 58, 58, 26, 94, 58, 58, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 95, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 96, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 97, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 98, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21, - 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 21, 18, 24, 16, - 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 0, - 29, 21, 23, 23, 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, - 26, 25, 15, 15, 24, 5, 21, 21, 24, 15, 7, 19, 15, 15, 15, 21, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 5, 5, - 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, - 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, - 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 9, 5, 5, - 5, 9, 9, 5, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 9, 9, - 9, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 5, 9, 9, 5, 9, - 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 5, 9, 5, 9, 9, - 5, 9, 9, 9, 5, 9, 5, 9, 9, 5, 5, 7, 9, 5, 5, 5, - 7, 7, 7, 7, 9, 8, 5, 9, 8, 5, 9, 8, 5, 9, 5, 9, - 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, - 5, 9, 8, 5, 9, 5, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, - 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 9, 9, 5, 9, 9, 5, - 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 6, 6, 6, 6, 6, 24, 24, 24, 24, 24, 24, 24, 6, 24, 6, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 9, 5, 9, 5, 6, 24, 9, 5, 2, 2, 6, 5, 5, 5, 21, 9, - 2, 2, 2, 2, 24, 24, 9, 21, 9, 9, 9, 2, 9, 2, 9, 9, - 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, - 5, 5, 9, 9, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 5, 5, 5, 5, 9, 5, 25, 9, 5, 9, 9, 5, 5, 9, 9, 9, - 9, 5, 26, 12, 12, 12, 12, 12, 11, 11, 9, 5, 9, 5, 9, 5, - 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, - 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 2, 2, 6, 21, 21, 21, 21, 21, 21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 17, 2, 2, 26, 26, 23, - 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12, - 21, 12, 12, 21, 12, 12, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, - 7, 7, 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 1, 21, 21, 21, - 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 7, 7, - 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 21, 7, 12, 12, 12, 12, 12, 12, 12, 1, 26, 12, - 12, 12, 12, 12, 12, 6, 6, 12, 12, 26, 12, 12, 12, 12, 7, 7, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 26, 26, 7, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 1, - 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 6, 6, 26, 21, 21, 21, 6, 2, 2, 12, 23, 23, - 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 6, 12, 12, 12, 6, 12, 12, 12, 12, 12, 2, 2, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 2, 2, 21, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 24, 7, 7, 7, 7, 7, 7, 2, - 1, 1, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, - 12, 12, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 7, 10, 10, - 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10, - 7, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, - 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, - 7, 2, 7, 2, 2, 2, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10, - 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 7, 2, - 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 7, 7, 2, 7, - 7, 7, 12, 12, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 7, 7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23, 7, 21, 12, 2, - 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, - 7, 2, 7, 7, 2, 7, 7, 2, 7, 7, 2, 2, 12, 2, 10, 10, - 10, 12, 12, 2, 2, 2, 2, 12, 12, 2, 2, 12, 12, 12, 2, 2, - 2, 12, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 2, 7, 2, - 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 12, 12, 7, 7, 7, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, - 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10, - 10, 12, 12, 12, 12, 12, 2, 12, 12, 10, 2, 10, 10, 12, 2, 2, - 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 21, 23, 2, 2, 2, 2, 2, 2, 2, 7, 12, 12, 12, 12, 12, 12, - 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, - 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12, - 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 2, 2, - 2, 2, 2, 2, 2, 12, 12, 10, 2, 2, 2, 2, 7, 7, 2, 7, - 26, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 12, 7, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, - 7, 2, 7, 7, 7, 7, 2, 2, 2, 7, 7, 2, 7, 2, 7, 7, - 2, 2, 2, 7, 7, 2, 2, 2, 7, 7, 7, 2, 2, 2, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 10, 10, - 12, 10, 10, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 12, 2, 2, - 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26, 2, 2, 2, 2, 2, - 12, 10, 10, 10, 12, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, - 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 7, 12, 12, - 12, 10, 10, 10, 10, 2, 12, 12, 12, 2, 12, 12, 12, 12, 2, 2, - 2, 2, 2, 2, 2, 12, 12, 2, 7, 7, 7, 2, 2, 7, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 21, 15, 15, 15, 15, 15, 15, 15, 26, - 7, 12, 10, 10, 21, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, - 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12, - 10, 10, 10, 10, 10, 2, 12, 10, 10, 2, 10, 10, 12, 12, 2, 2, - 2, 2, 2, 2, 2, 10, 10, 2, 2, 2, 2, 2, 2, 7, 7, 2, - 2, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 7, 10, 10, - 10, 12, 12, 12, 12, 2, 10, 10, 10, 2, 10, 10, 10, 12, 7, 26, - 2, 2, 2, 2, 7, 7, 7, 10, 15, 15, 15, 15, 15, 15, 15, 7, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 7, 7, 7, 7, 7, 7, - 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, 7, 7, 7, 7, - 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 12, 2, 2, 2, 2, 10, - 10, 10, 12, 12, 12, 2, 12, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 2, 2, 10, 10, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 23, - 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, 12, 12, 21, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, - 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 2, 2, - 7, 7, 7, 7, 7, 2, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 7, 7, 7, 7, - 7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, - 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, - 12, 12, 12, 12, 12, 21, 12, 12, 7, 7, 7, 7, 7, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 26, 26, - 26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 2, 26, 26, - 21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 12, - 12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12, 7, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21, - 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 7, 7, 7, 7, 12, 12, - 12, 7, 10, 10, 10, 7, 7, 10, 10, 10, 10, 10, 10, 10, 7, 7, - 7, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12, 7, 10, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26, - 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 2, 2, 9, 2, 2, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 6, 5, 5, 5, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 2, - 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 2, - 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, - 9, 9, 9, 9, 9, 9, 2, 2, 5, 5, 5, 5, 5, 5, 2, 2, - 17, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 26, 21, 7, - 29, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22, 18, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 21, 21, 14, 14, - 14, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 12, 12, 12, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, - 7, 7, 12, 12, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, - 7, 2, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10, - 10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 21, 21, 21, 6, 21, 21, 21, 23, 7, 12, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, - 21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12, 1, 12, - 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 7, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, - 12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10, 2, 2, 2, 2, - 10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12, 2, 2, 2, 2, - 26, 2, 2, 2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, - 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 2, 2, 2, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 7, 7, 7, 7, 7, 7, 7, 12, 12, 10, 10, 12, 2, 2, 21, 21, - 7, 7, 7, 7, 7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12, 2, - 12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, - 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, - 21, 21, 21, 21, 21, 21, 21, 6, 21, 21, 21, 21, 21, 21, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, - 12, 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, - 10, 10, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, - 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 21, 21, 2, - 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12, 7, 7, - 7, 7, 7, 7, 7, 7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12, - 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, - 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, - 12, 12, 12, 12, 10, 10, 12, 12, 2, 2, 2, 21, 21, 21, 21, 21, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 21, 21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, - 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 10, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 12, 7, 7, - 7, 7, 7, 7, 12, 7, 7, 10, 12, 12, 7, 2, 2, 2, 2, 2, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, - 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, - 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2, - 5, 5, 5, 5, 5, 5, 5, 5, 2, 9, 2, 9, 2, 9, 2, 9, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, - 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8, - 5, 5, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 5, 24, - 24, 24, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 24, - 5, 5, 5, 5, 2, 2, 5, 5, 9, 9, 9, 9, 2, 24, 24, 24, - 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 24, 24, 24, - 2, 2, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 2, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1, - 17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20, - 21, 21, 21, 21, 21, 21, 21, 21, 27, 28, 1, 1, 1, 1, 1, 29, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16, - 16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 15, 6, 2, 2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 6, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 2, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, - 11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 9, 26, 26, 26, 26, 9, 26, 26, 5, 9, 9, 9, 5, 5, - 9, 9, 9, 5, 26, 9, 26, 26, 25, 9, 9, 9, 9, 9, 26, 26, - 26, 26, 26, 26, 9, 26, 9, 26, 9, 26, 9, 9, 9, 9, 26, 5, - 9, 9, 9, 9, 5, 7, 7, 7, 7, 5, 26, 26, 5, 5, 9, 9, - 25, 25, 25, 25, 25, 9, 5, 5, 5, 5, 26, 25, 26, 26, 5, 26, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 9, 5, 14, 14, 14, 14, 15, 26, 26, 2, 2, 2, 2, - 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26, - 25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, - 26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26, - 25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, - 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, - 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, - 22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, - 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, - 18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25, - 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26, - 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 9, 5, 9, 9, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, - 9, 5, 9, 5, 5, 9, 5, 5, 5, 5, 5, 5, 6, 6, 9, 9, - 9, 5, 9, 5, 5, 26, 26, 26, 26, 26, 26, 9, 5, 9, 5, 12, - 12, 12, 9, 5, 2, 2, 2, 2, 2, 21, 21, 21, 21, 15, 21, 21, - 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 6, - 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 2, - 21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21, - 20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21, 6, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21, - 17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 26, 26, 21, 21, 21, 22, 18, 22, 18, 22, 18, 22, 18, 17, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, - 29, 21, 21, 21, 26, 6, 7, 14, 22, 18, 22, 18, 22, 18, 22, 18, - 22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18, - 26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10, - 17, 6, 6, 6, 6, 6, 26, 26, 14, 14, 14, 6, 7, 21, 26, 26, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 24, 24, 6, 6, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 6, 6, 6, 7, - 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15, - 26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 21, 21, 21, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 2, 2, 2, 2, - 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 7, 12, - 11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 6, - 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 12, 12, - 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 12, 12, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, - 24, 24, 24, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 24, 24, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 6, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 9, 5, 9, 9, 5, - 9, 5, 9, 5, 9, 5, 9, 5, 6, 24, 24, 9, 5, 9, 5, 7, - 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, 9, 9, 5, - 9, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, - 9, 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 2, 2, 2, 2, 2, - 9, 5, 2, 5, 2, 5, 9, 5, 9, 5, 2, 2, 2, 2, 2, 2, - 2, 2, 6, 6, 6, 9, 5, 7, 6, 6, 5, 7, 7, 7, 7, 7, - 7, 7, 12, 7, 7, 7, 12, 7, 7, 7, 7, 12, 7, 7, 7, 7, - 7, 7, 7, 10, 10, 12, 12, 10, 26, 26, 26, 26, 12, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 26, 26, 23, 26, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, - 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, - 12, 12, 7, 7, 7, 7, 7, 7, 21, 21, 21, 7, 21, 7, 7, 12, - 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21, - 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, - 7, 7, 7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10, - 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 6, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 21, 21, - 7, 7, 7, 7, 7, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, - 10, 12, 12, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 21, 21, 21, 21, - 6, 7, 7, 7, 7, 7, 7, 26, 26, 26, 7, 10, 12, 10, 7, 7, - 12, 7, 12, 12, 12, 7, 7, 12, 12, 7, 7, 7, 7, 7, 12, 12, - 7, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 6, 21, 21, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 12, 12, 10, 10, - 21, 21, 7, 6, 6, 10, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 2, - 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 6, 6, 6, 6, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 24, 24, 2, 2, 2, 2, - 7, 7, 7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12, 2, 2, - 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 7, 12, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 25, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 2, - 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 22, - 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 26, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23, 26, 26, 26, - 21, 21, 21, 21, 21, 21, 21, 22, 18, 21, 2, 2, 2, 2, 2, 2, - 21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, - 18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16, - 21, 21, 21, 2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21, - 21, 21, 25, 17, 25, 25, 25, 2, 21, 23, 21, 21, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 1, - 2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 22, - 18, 21, 22, 18, 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, - 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, - 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 2, 2, 2, - 23, 23, 25, 24, 26, 23, 23, 2, 26, 25, 25, 25, 25, 26, 26, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 26, 26, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, - 21, 21, 21, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, - 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 2, 2, - 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, - 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, - 7, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 21, - 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, - 21, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, - 9, 9, 9, 9, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 2, 9, 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2, - 6, 6, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 2, 2, 7, 2, 2, 7, - 7, 7, 7, 7, 7, 7, 2, 21, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 7, 7, 7, 7, 7, 7, 26, 26, 15, 15, 15, 15, 15, 15, 15, - 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 7, 7, 2, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, - 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 21, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 21, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 15, 15, 7, 7, - 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 12, 12, 12, 2, 12, 12, 2, 2, 2, 2, 2, 12, 12, 12, 12, - 7, 7, 7, 7, 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, 2, 2, 2, 2, 12, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 21, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, - 7, 7, 7, 7, 7, 7, 7, 7, 26, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 12, 12, 2, 2, 2, 2, 15, 15, 15, 15, 15, - 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 2, 2, 2, 21, 21, 21, 21, 21, 21, 21, - 7, 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, - 7, 7, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, - 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, - 7, 7, 7, 7, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 12, 12, 17, 2, 2, - 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 7, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 15, 15, 15, 15, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, - 7, 7, 12, 12, 12, 12, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, - 10, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21, 2, 2, - 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 12, 7, 7, 12, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, - 10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21, 1, 21, 21, - 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, - 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 10, 12, 12, 12, - 12, 12, 12, 12, 12, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 7, 10, 10, 7, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 12, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, - 10, 7, 7, 7, 7, 21, 21, 21, 21, 12, 12, 12, 12, 21, 10, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 21, 7, 21, 21, 21, - 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 12, - 12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, - 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, - 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, - 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 12, 12, 7, 10, 10, - 12, 10, 10, 10, 10, 2, 2, 10, 10, 2, 2, 10, 10, 10, 2, 2, - 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 7, 7, 7, - 7, 7, 10, 10, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, - 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 12, 12, 12, 10, 12, 7, 7, 7, 7, 21, 21, 21, 21, 21, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 21, 12, 7, - 10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12, - 12, 10, 12, 12, 7, 7, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, - 10, 10, 12, 12, 12, 12, 2, 2, 10, 10, 10, 10, 12, 12, 10, 12, - 12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 7, 7, 7, 7, 12, 12, 2, 2, - 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12, - 12, 21, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 10, 10, - 12, 12, 12, 12, 12, 12, 10, 12, 7, 21, 2, 2, 2, 2, 2, 2, - 10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 2, 2, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26, - 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 2, 2, 2, 2, - 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, - 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 2, 7, 7, 7, 7, - 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, - 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 2, 12, 12, 10, 12, 7, - 10, 7, 10, 12, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, - 7, 10, 10, 10, 12, 12, 12, 12, 2, 2, 12, 12, 10, 10, 10, 10, - 12, 7, 21, 7, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, - 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, 7, 12, 12, 12, 12, 21, - 21, 21, 21, 21, 21, 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21, 7, 21, 21, - 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 10, 12, - 7, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 2, 10, 12, 12, 12, 12, 12, 12, - 12, 10, 12, 12, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, - 7, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 2, 12, 12, 2, 12, - 12, 12, 12, 12, 12, 12, 7, 12, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10, 2, - 12, 12, 2, 10, 10, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 12, 12, 10, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23, - 23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, - 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26, - 6, 6, 6, 6, 21, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 15, 15, 15, 15, 15, - 15, 15, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 7, 7, 7, - 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 12, - 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 12, - 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 21, 6, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 2, - 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 26, 12, 12, 21, - 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10, - 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, - 12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26, - 26, 26, 12, 12, 12, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, - 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 2, 9, 9, - 2, 2, 9, 2, 2, 9, 9, 2, 2, 9, 9, 9, 9, 2, 9, 9, - 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5, - 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, 2, 9, 9, 9, - 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, - 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 9, 9, 9, 9, 9, 9, - 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, - 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, - 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 5, 2, 2, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, - 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, - 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, - 12, 12, 2, 12, 12, 2, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, - 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 2, 2, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 7, 26, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 23, - 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 2, - 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 5, 5, 5, 5, 12, 12, 12, 12, 12, 12, 12, 6, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15, - 23, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, - 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, 7, 2, 2, 2, 2, - 2, 2, 7, 2, 2, 2, 2, 7, 2, 7, 2, 7, 2, 7, 7, 7, - 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 2, 7, 2, 7, 2, 7, - 2, 7, 7, 2, 7, 2, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, - 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, - 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, - 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, - 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24, - 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, - 26, 26, 26, 26, 26, 2, 2, 2, 26, 26, 26, 26, 26, 2, 2, 2, - 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 12, 12, 13, 14, 12, 15, 16, 17, 18, 19, 20, - 21, 22, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 24, 25, - 0, 26, 27, 0, 28, 29, 30, 31, 32, 33, 0, 34, 0, 0, 0, 0, - 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, 0, - 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, - 43, 44, 45, 46, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 50, 0, 0, 0, - 0, 0, 0, 51, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 56, 0, 0, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 67, 68, 0, 69, 70, 71, 72, 0, - 61, 0, 73, 74, 75, 76, 0, 0, 70, 0, 77, 78, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 79, 80, 0, 0, 0, 0, 0, 0, 0, 0, 81, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 0, 80, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 21, 0, 0, 0, 0, 0, 22, 23, 24, - 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, - 28, 29, 0, 0, 0, 0, 30, 0, 0, 0, 31, 32, 33, 34, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 13, 35, 36, 0, 0, 26, 37, 38, 39, 0, 0, 0, 0, 0, 40, - 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 42, 43, 1, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 50, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, - 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 52, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 56, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 58, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 0, 0, 0, 0, - 0, 0, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 71, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 0, 68, 77, 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 70, 0, 0, 0, - 0, 82, 83, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, - 85, 0, 84, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 87, - 88, 89, 90, 91, 0, 0, 0, 0, 0, 0, 0, 0, 92, 93, 94, 1, - 1, 1, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98, - 99,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 74, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 74,105,106, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 91, 0,107, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, - 1, 1, 91, 0, 0, 0, 0, 0, 0,108, 0, 0, 0, 0,109, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, 76, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,112,113, 0, 0, 0, - 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 49, 0, 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,115,116, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 26,117, 0,118, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 120, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,121, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122,123, 75, 0, - 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0, 0, 0, - 0, 0, 76,102, 0, 0, 0, 0, 0, 0, 0,125, 0, 0, 0, 0, - 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, - 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,126, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 0, 49, 0, 0, - 26,130,130, 0, 0, 0, 0, 0, 0, 0, 0, 0,131, 0, 0, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,132, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,133, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,134, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,110, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0,102, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,137, 0, 0, 0, - 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,138, 0, 0, 0, 0, 0, 0, 0,139, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,140, 0, 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142,143,144,145,146,147, 0, 0, 0,148, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0, - 0, 0, 0, 0,139, 1, 1,150,151,117, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, - 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,153, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230, - 230,230,230,230,230,230,230,230,230,232,220,220,220,220,232,216, - 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220, - 220,220,220,220,220,220,220,220, 1, 1, 1, 1, 1,220,220,220, - 220,230,230,230,230,230,230,230,230,240,230,220,220,220,230,230, - 230,220,220, 0,230,230,230,220,220,220,220,230,232,220,220,230, - 233,234,234,233,234,234,233,230,230,230,230,230, 0, 0, 0,230, - 230,230,230,230, 0,220,230,230,230,230,220,230,230,230,222,220, - 230,230,230,230,230,230,220,220,220,220,220,220,230,230,220,230, - 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, - 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, - 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230, - 230,220,220,230,230,230,230,230,220,230,230,220, 35, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230, - 230, 0, 0,230,230,230,230,220,230, 0, 0,230,230, 0,220,230, - 230,220, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0,230,220,230,230, - 220,230,230,220,220,220,230,220,220,230,220,230,230,230,220,230, - 220,230,220,230,220,230,230, 0, 0, 0, 0, 0,230,230,220,230, - 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0,230,230, 0,230, - 230,230,230,230,230,230,230,230, 0,230,230,230, 0,230,230,230, - 230,230, 0, 0, 0,220,220,220, 0, 0, 0, 0,230,220,220,220, - 230,230,230,230, 0, 0,230,230,230,230,230,220,220,220,220,220, - 230,230,230,230,230,230, 0,220,230,230,220,230,230,220,230,230, - 230,220,220,220, 27, 28, 29,230,230,230,220,230,230,220,220,230, - 230,230,230,230, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0, 0, 0, - 0, 0,230, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 9, - 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,103,103, 9, 0, - 0, 0, 0, 0,107,107,107,107, 0, 0, 0, 0,118,118, 9, 0, - 0, 0, 0, 0,122,122,122,122, 0, 0, 0, 0,220,220, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,220, 0,216, 0, 0, - 0, 0, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130, - 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0, 0, 0, - 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0, - 9, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 0,230, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0,222,230,220, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,220, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,230,230,230,230, - 230, 0, 0,220,230,230,230,230,230,220,220,220,220,220,220,230, - 230,220, 0,220,220,230,230,220,220,230,230,230,230,230,220,230, - 230,230,230, 0, 0, 0, 0,230,220,230,230,230,230,230,230,230, - 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 7, 0,230,230,230, 0, 1,220,220,220,220,220,230,230, - 220,220,220,220,230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0,220, 0, 0, 0, 0, 0, 0,230, 0, 0, 0,230,230, 0, 0, - 0, 0, 0, 0,230,230,220,230,230,230,230,230,230,230,220,230, - 230,234,214,220,202,230,230,230,230,230,230,230,230,230,230,230, - 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1, - 230,230,230,230, 1, 1, 1,230,230, 0, 0, 0, 0,230, 0, 0, - 0, 1, 1,230,220,230, 1, 1,220,220,220,220,230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,218,228, - 232,222,224,224, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 230,230,230,230,230,230,230,230,230,230, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,230, 0,230,230, - 220, 0, 0,230,230, 0, 0, 0, 0, 0,230,230, 0,230, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,230,230,230,230, - 230,230,230,220,220,220,220,220,220,220,230,230,230,230,230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,230,230, 1,220, 0, - 0, 0, 0, 9, 0, 0, 0, 0, 0,230,220, 0, 0, 0, 0,230, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,220,230,230,230,220, - 230,220,220,220, 0, 0,230,220,230,220, 0, 0, 0, 9, 7, 0, - 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, - 7, 0, 0, 0,230,230,230,230,230, 0, 0, 0, 0, 0, 9, 0, - 0, 0, 7, 0, 0, 0, 9, 7, 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, - 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, - 9, 9, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,230,230,230,230, - 230,230,230, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0,216,216, 1, 1, 1, 0, 0, - 0,226,216,216,216,216,216, 0, 0, 0, 0, 0, 0, 0, 0,220, - 220,220,220,220,220,220,220, 0, 0,230,230,230,230,230,220,220, - 0, 0, 0, 0, 0, 0,230,230,230,230, 0, 0, 0, 0,230,230, - 230, 0, 0, 0,230, 0, 0,230,230,230,230,230,230,230, 0,230, - 230, 0,230,230,220,220,220,220,220,220,220, 0,230,230, 7, 0, - 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19, - 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17,237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, - 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, - 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, - 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, - 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, - 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, - 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, - 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20, - 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0, - 0, 40, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21, - 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45, - 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, - 0, 0, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 17, 19, 20, 21, 22, 23, 24, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 27, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 34, 34, 34, 34, 58, 59, 59, 60, 34, - 34, 34, 34, 34, 34, 34, 61, 62, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 63, 64, 34, 65, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 67, 66, 68, 69, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 70, 71, 72, 34, 34, - 34, 34, 73, 34, 34, 34, 34, 34, 34, 34, 34, 74, 75, 76, 77, 78, - 79, 80, 34, 81, 82, 83, 34, 84, 85, 34, 86, 87, 88, 89, 17, 90, - 91, 92, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 93, 25, 25, 25, 25, 25, 25, 25, 94, - 95, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 96, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 97, 34, 34, 34, 34, 34, 34, - 25, 98, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 99, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, - 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, - 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, - 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, - 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, - 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 0, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 2, 2, 95, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, - 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, - 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, - 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, - 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, - 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11, - 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, - 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, - 2, 2, 11, 2, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, - 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, - 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, - 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, - 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, - 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10, - 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21, - 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, - 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, - 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, - 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2, - 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, - 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, - 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, - 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, - 22, 22, 22, 22, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, - 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23, - 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, - 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, - 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 2, - 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, - 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 2, 36, 2, 2, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, - 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 36, 36, - 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, - 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, - 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, - 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, - 2, 2, 2, 8, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, - 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 2, - 30, 30, 30, 30, 2, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, - 30, 30, 30, 30, 30, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 29, 29, - 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 0, 0, 0, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 2, - 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2, - 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2, - 2, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, - 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 2, 2, 8, 8, 8, 76, 76, 76, 76, 76, 76, 76, 76, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, - 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, - 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9, - 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 6, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, - 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, - 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, - 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, - 19, 19, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55, - 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2, - 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 61, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, - 30, 30, 30, 30, 30, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 1, 1, 1, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, - 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, - 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 2, 2, 2, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19, - 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 2, 2, - 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, - 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, - 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, - 84, 84, 84, 84, 2, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, - 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 30, - 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19, - 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, - 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, - 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14, - 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, - 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, - 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, - 12, 12, 12, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, - 118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, - 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 2, 2, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,106,106, - 106,106,106,106,106,106,106,106,106,106,106,106,106,106, 2, 2, - 2, 2, 2, 2, 2, 2,104,104,104,104,104,104,104,104,104,104, - 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, - 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, - 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161, - 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161, - 2,161,161, 2, 2, 2,110,110,110,110,110,110,110,110,110,110, - 110,110,110,110,110,110,110,110,110,110,110,110,110, 2, 2, 2, - 2, 2, 2, 2, 2, 2,110,110,110,110,110,110, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,110,110,110,110,110,110,110,110, 2, 2, - 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 2, 2, 2, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2, - 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81, 81, 81, - 81, 81, 81, 81, 81, 81,120,120,120,120,120,120,120,120,120,120, - 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116, - 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, - 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,116,116, - 116,116,116,116,116,116,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, - 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2, - 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2, - 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57, - 57, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, - 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,117,117, - 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112, - 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2, - 2,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, - 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 83, 83, - 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2, 82, 82, - 82, 82, 82, 82, 82, 82,122,122,122,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122, - 122,122,122, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,122, - 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, - 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, - 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,130,130,130, 2, 2, 2, 2, 2, 2, 2, - 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,144,144,144,144,144,144,144,144,144, 2, 2, - 2, 2, 2, 2, 2, 2,144,144,144,144,144,144,144,144,144,144, - 2, 2, 2, 2, 2, 2,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,147,147, - 147,147,147,147,147,147,147,147,147,147,147,147,147,147, 2, 2, - 2, 2, 2, 2, 2, 2,148,148,148,148,148,148,148,148,148,148, - 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, - 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158, - 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, - 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153, - 153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, - 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149, - 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101,101, - 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, 2, - 2, 2, 2, 2, 2, 2,101,101,101,101,101,101,101,101,101,101, - 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 2, - 2, 2, 2, 2, 2, 2,111,111,111,111,111,111,111,111,111,111, - 111,111,111,111,111,111,111,111,111,111,111,111,111, 2, 2, 2, - 2, 2, 2, 2, 2, 2,100,100,100,100,100,100,100,100,100,100, - 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,108,108,108,108,108,108,108,108,108,108, - 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, - 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, - 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2, - 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, - 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, - 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, - 109, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, - 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, - 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2, - 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107, - 2, 1,107,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, - 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, - 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, - 107,107,107, 2, 2, 2,107,107,107,107,107, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124, - 124,124,124,124,124,124,124,124,124,124,124,124,124,124, 2, 2, - 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124, - 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, - 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,123,123, - 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, - 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, - 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,114,114,114,114,114,114,114,114,114,114, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102, - 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, - 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126, 2, 2,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, - 2, 2, 2, 2, 2, 2,142,142,142,142,142,142,142,142,142,142, - 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, - 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154, - 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154, - 154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, - 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2, - 2,154,154,154,154,154,154,154,154,154,154,154,154, 2, 2, 2, - 2, 2, 2, 2, 2, 2,154,154,154,154,154,154,154,154,154,154, - 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2, - 150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, - 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,141,141,141,141,141,141,141,141,141,141, - 141,141,141,141,141,141,141,141,141,141,141,141,141,141, 2, 2, - 2, 2, 2, 2, 2, 2,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121,121, - 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, 2, - 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, - 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, - 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, - 133,133,133,133,133,133,133,133,133,133,133,133, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133,133, - 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134, 2,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134, 2, 2, 2, - 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138, 2,138,138, - 2,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, - 138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, 2, - 138, 2,138,138, 2,138,138,138,138,138,138,138,138,138, 2, 2, - 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138,138,138,138, - 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, - 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, - 2, 2, 2, 2, 2, 2,143,143,143,143,143,143,143,143,143,143, - 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145,145, - 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, 2, - 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, - 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2, - 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115, - 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - 115,115,115,115,115, 2,115,115,115,115,115,115,115,115,115,115, - 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159, 2,159,159,159,159,159,159,159,159,159,159, - 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103, - 103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, - 103,103,103,103, 2, 2,103,103,103,103,103,103, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119, - 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119, - 2,119,119,119,119,119,119,119, 2,119,119,119,119,119,119,119, - 119,119,119,119,119,119,119,119,119,119,119,119,119,119, 2, 2, - 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146, - 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, - 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, - 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136, 2, 2, - 2, 2, 2, 2, 2, 2,155,155,155,155,155,155,155,155,155,155, - 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136, 2, - 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, - 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 2, - 2, 2, 2, 2, 2, 2,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, - 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, - 105, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, - 105,105,105, 2, 2, 2,105,105,105,105,105,105,105,105,105, 2, - 2, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, - 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 2, 0, 0,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2,131,131,131,131,131, 2,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2, - 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, - 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151, - 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, - 151,151,151, 2, 2, 2,151,151,151,151,151,151,151,151,151,151, - 151,151,151,151, 2, 2,151,151,151,151,151,151,151,151,151,151, - 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152, - 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, - 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, - 30, 30, 2, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 2,113,113,113,113,113,113,113,113,113,113, - 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, - 113,113,113,113,113,113,113,113,113,113,113,113,113, 2, 2, 2, - 2, 2, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132, - 2, 2, 2, 2,132,132, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, - 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, - 2, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, - 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 2, 2, 3, 3, 3, - 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, - 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, - 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, - 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, - 0, 0, 0, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, - 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, - 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, 0, 0, 13, 0, - 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19, - 0, 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0, - 0, 0, 0, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 41, 0, 42, 43, 44, 45, - 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 64, 0, 0, 0, 0, 0, - 0, 0, 0, 65, 0, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 71, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 73, 74, 75, 76, 77, 78, 79, 80, 0, -}; -static const uint16_t -_hb_ucd_u16[11584] = -{ - 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, - 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, - 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31, - 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39, - 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13, - 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50, - 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58, - 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66, - 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32, - 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101, - 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113, - 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124, - 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135, - 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140, - 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140, - 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48, - 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177, - 178, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183, - 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193, - 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199, - 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209, - 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140, - 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225, - 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235, - 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13, - 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209, - 209, 209, 287, 140, 288, 140, 271, 271, 271, 289, 209, 209, 209, 209, 290, 271, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 291, 292, 209, 209, 293, - 209, 209, 209, 209, 209, 209, 294, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 279, 279, 279, 279, 279, 279, 279, 279, 300, 301, 279, 279, 279, 302, 279, 303, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 209, 209, 209, 279, 304, 209, 209, 305, 209, 306, 209, 209, 209, 209, 209, 209, - 9, 9, 9, 11, 11, 11, 307, 308, 13, 13, 13, 13, 13, 13, 309, 310, - 11, 11, 311, 48, 48, 48, 312, 313, 48, 314, 315, 315, 315, 315, 32, 32, - 316, 317, 318, 319, 320, 321, 140, 140, 209, 322, 209, 209, 209, 209, 209, 323, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324, 140, 325, - 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331, - 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48, - 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 209, 209, 209, 209, - 48, 338, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 287, 48, 48, 229, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345, - 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356, - 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364, - 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372, - 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382, - 383, 384, 315, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 388, 48, 389, 48, 48, 206, - 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, - 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140, - 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403, - 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410, - 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419, - 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71, - 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428, - 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430, - 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140, - 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439, - 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, - 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453, - 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271, - 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467, - 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474, - 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 271, 476, 48, 48, 477, 478, 140, 140, 140, 140, - 48, 464, 479, 48, 62, 480, 140, 48, 481, 140, 140, 48, 482, 140, 48, 314, - 483, 48, 48, 484, 485, 457, 486, 487, 222, 48, 48, 488, 489, 48, 196, 192, - 490, 48, 491, 492, 493, 48, 48, 494, 222, 48, 48, 495, 496, 497, 498, 499, - 48, 97, 500, 501, 140, 140, 140, 140, 502, 503, 504, 48, 48, 505, 506, 192, - 507, 83, 84, 508, 509, 510, 511, 512, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 518, 519, 520, 521, 140, 140, - 48, 48, 48, 522, 523, 192, 524, 140, 48, 48, 525, 526, 192, 140, 140, 140, - 48, 173, 527, 528, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530, - 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140, - 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140, - 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 557, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 100, 271, 558, 559, 560, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 207, 140, 140, 140, 140, 140, 140, - 272, 272, 272, 272, 272, 272, 561, 562, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563, - 48, 48, 200, 564, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565, - 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 440, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 140, - 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324, - 209, 209, 586, 209, 209, 209, 587, 588, 589, 209, 590, 209, 209, 209, 288, 140, - 209, 209, 209, 209, 591, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 592, - 209, 209, 209, 209, 209, 287, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140, - 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11, - 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11, - 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613, - 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 628, 629, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 630, 631, 632, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 151, 633, 634, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 638, 200, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 639, 585, 140, 140, - 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 498, 271, 271, 641, 642, 140, 140, 140, 140, - 498, 271, 643, 644, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324, - 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209, - 659, 209, 209, 325, 660, 661, 324, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 662, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 663, 426, 426, - 209, 209, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 660, 325, 427, - 325, 209, 209, 209, 664, 176, 209, 209, 664, 209, 657, 661, 140, 140, 140, 140, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 323, 657, 665, 287, 209, 426, 288, 324, 176, 664, 287, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 666, 209, 209, 288, 140, 140, 192, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 196, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 140, - 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 71, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 667, 140, 668, 668, 668, 668, 668, 668, 140, 140, 140, 140, 140, 140, 140, 140, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 669, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 670, - 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0, - 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24, - 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27, - 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38, - 39, 39, 40, 41, 42, 43, 44, 27, 45, 46, 27, 27, 27, 27, 47, 27, - 48, 48, 48, 48, 48, 49, 50, 48, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125, - 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143, - 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170, - 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176, - 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168, - 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125, - 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201, - 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211, - 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222, - 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229, - 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 125, 235, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0, - 239, 239, 239, 239, 239, 239, 4, 4, 240, 240, 240, 240, 240, 240, 240, 241, - 139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246, 14, 14, - 0, 0, 0, 0, 0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125, 252, - 253, 0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261, - 262, 263, 263, 264, 142, 142, 142, 142, 265, 0, 263, 263, 0, 0, 266, 260, - 142, 265, 0, 0, 0, 0, 142, 267, 0, 0, 0, 0, 0, 260, 260, 268, - 260, 260, 260, 260, 260, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 0, 0, 0, 0, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 271, 270, 270, 270, 272, 273, 273, 273, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277, - 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282, - 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48, - 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299, - 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308, - 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125, - 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 326, 27, 27, 27, 27, 27, 327, 27, 27, 328, 125, 125, 27, - 8, 285, 329, 0, 0, 330, 331, 332, 27, 27, 27, 27, 27, 27, 27, 333, - 334, 0, 1, 2, 1, 2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 345, 125, 125, 342, 342, 342, 342, 342, 342, 342, 346, - 347, 0, 0, 348, 11, 11, 11, 11, 349, 350, 351, 125, 125, 0, 0, 352, - 125, 125, 125, 125, 125, 125, 125, 125, 353, 354, 355, 355, 355, 356, 357, 252, - 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125, - 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376, - 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125, - 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 386, 385, 387, 388, 125, 389, 4, 4, 390, 125, 125, 125, 125, - 391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401, - 402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407, - 410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419, - 420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125, - 429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433, - 434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 125, - 440, 440, 441, 442, 442, 443, 125, 444, 445, 125, 125, 446, 447, 125, 448, 449, - 450, 450, 450, 450, 451, 452, 450, 453, 454, 454, 454, 454, 455, 456, 457, 458, - 459, 459, 459, 460, 461, 462, 462, 463, 464, 464, 464, 464, 464, 464, 465, 466, - 467, 468, 467, 469, 125, 125, 125, 125, 470, 471, 472, 473, 473, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, 483, 125, 125, 125, 125, 125, 125, 125, 125, - 484, 484, 484, 484, 484, 485, 486, 125, 487, 487, 487, 487, 488, 489, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 490, 490, 490, 491, 490, 492, 125, 125, - 493, 493, 493, 493, 494, 495, 496, 125, 497, 497, 497, 498, 498, 125, 125, 125, - 499, 500, 501, 499, 502, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 503, 503, 503, 504, 125, 125, 125, 125, 125, 125, 505, 505, 505, 505, 505, 506, - 507, 508, 509, 510, 511, 512, 125, 125, 125, 125, 513, 514, 514, 513, 515, 125, - 516, 516, 516, 516, 517, 518, 518, 518, 518, 518, 519, 154, 520, 520, 520, 521, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 522, 523, 523, 524, 525, 523, 526, 527, 527, 528, 529, 530, 125, 125, 125, 125, - 531, 532, 532, 533, 534, 535, 536, 537, 538, 539, 540, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 541, 542, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544, 544, 544, 545, - 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, - 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, - 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, - 546, 546, 546, 546, 546, 546, 546, 546, 546, 547, 125, 125, 125, 125, 125, 125, - 546, 546, 546, 546, 546, 546, 548, 549, 546, 546, 546, 546, 546, 546, 546, 546, - 546, 546, 546, 546, 550, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 551, 551, 551, 551, 551, 551, 552, - 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, - 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, - 553, 553, 554, 555, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, - 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, - 556, 556, 556, 556, 557, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - 276, 276, 276, 558, 559, 560, 561, 562, 562, 562, 562, 563, 564, 565, 566, 567, - 568, 568, 568, 568, 569, 570, 571, 572, 568, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 573, 573, 573, 573, 573, 574, 125, 125, 125, 125, 125, 125, - 575, 575, 575, 575, 576, 575, 575, 575, 577, 575, 125, 125, 125, 125, 578, 579, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 581, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, - 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 125, 125, - 584, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 585, - 586, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, - 257, 257, 587, 125, 125, 588, 589, 590, 590, 590, 590, 590, 590, 590, 590, 590, - 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 592, 592, 592, 592, 592, 592, 593, 594, 595, 596, 266, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 8, 8, 597, 8, 598, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 599, - 0, 0, 600, 0, 0, 0, 601, 602, 603, 0, 604, 0, 0, 0, 235, 125, - 11, 11, 11, 11, 605, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 266, - 0, 0, 0, 0, 0, 234, 0, 606, 125, 125, 125, 125, 125, 125, 125, 125, - 0, 0, 0, 0, 0, 224, 0, 0, 0, 607, 608, 609, 610, 0, 0, 0, - 611, 612, 0, 613, 614, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 617, 0, 0, 0, - 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, - 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, - 618, 618, 618, 618, 618, 618, 618, 618, 619, 620, 621, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 4, 622, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 623, 624, 625, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 626, 626, 627, 628, 629, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 630, 631, 125, 632, 632, 632, 633, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 634, 635, - 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 638, 125, 125, - 639, 639, 639, 639, 640, 641, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 334, 0, 0, 0, 642, 125, 125, 125, 125, - 334, 0, 0, 247, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 643, 27, 644, 645, 646, 647, 648, 649, 650, 651, 652, 651, 125, 125, 125, 653, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 599, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 125, 125, 125, 654, 0, - 655, 0, 0, 252, 606, 656, 599, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 657, 350, 350, - 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 606, 252, 228, - 252, 0, 0, 0, 658, 285, 0, 0, 658, 0, 247, 656, 125, 125, 125, 125, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 266, 247, 659, 234, 0, 350, 235, 599, 285, 658, 234, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 235, 125, 125, 285, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 125, 125, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 660, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 579, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 661, 125, - 248, 318, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 662, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 663, 125, 0, 0, 0, 0, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, - 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, - 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, - 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, - 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, - 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, - 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199, - 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, - 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231, - 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258, - 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275, - 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093, - 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010, - 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347, - 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424, - 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, - 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238, - 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, - 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232, - 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461, - 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486, - 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, - 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, - 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, - 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560, - 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, - 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, - 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, - 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, - 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, - 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0, - 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, - 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, - 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356, - 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214, - 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363, - 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251, - 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266, - 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287, - 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302, - 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, - 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375, - 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353, - 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234, - 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403, - 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412, - 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0, - 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721, - 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0, - 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757, - 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776, - 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0, - 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793, - 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814, - 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0, - 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728, - 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764, - 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821, - 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, - 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828, - 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833, - 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, - 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938, - 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0, - 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0, - 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0, - 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0, - 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0, - 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0, - 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0, - 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, - 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, - 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, - 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, - 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, - 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, - 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, - 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, - 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, - 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, - 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, - 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, - 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, - 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, - 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, - 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, - 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, - 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, - 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, - 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, - 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, - 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, - 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, - 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, - 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, - 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, - 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, - 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, - 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, - 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, - 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, - 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, - 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950, - 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959, - 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, - 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, - 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, - 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, - 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, - 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, - 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, - 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, - 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, - 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, - 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, - 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, - 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, - 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, - 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, - 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, - 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, - 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, - 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, - 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, - 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, - 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, - 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, - 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, - 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, - 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, - 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, - 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, - 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, - 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, - 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, - 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, - 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, - 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const int16_t -_hb_ucd_i16[196] = -{ - 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, - 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, - 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, - -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, - 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, - 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, - 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, - 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, - 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, - -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, - 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, - -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, - -1, 0, 1, -1, -}; - -static inline uint_fast8_t -_hb_ucd_gc (unsigned u) -{ - return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2; -} -static inline uint_fast8_t -_hb_ucd_ccc (unsigned u) -{ - return u<125259u?_hb_ucd_u8[15332+(((_hb_ucd_u8[13892+(((_hb_ucd_u8[12912+(u>>3>>4)])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:0; -} -static inline unsigned -_hb_ucd_b4 (const uint8_t* a, unsigned i) -{ - return (a[i>>1]>>((i&1u)<<2))&15u; -} -static inline int_fast16_t -_hb_ucd_bmg (unsigned u) -{ - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16692+(((_hb_ucd_b4(16564+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0; -} -static inline uint_fast8_t -_hb_ucd_sc (unsigned u) -{ - return u<918000u?_hb_ucd_u8[19446+(((_hb_ucd_u16[3168+(((_hb_ucd_u8[17652+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2; -} -static inline uint_fast16_t -_hb_ucd_dm (unsigned u) -{ - return u<195102u?_hb_ucd_u16[6400+(((_hb_ucd_u8[30070+(u>>6)])<<6)+((u)&63u))]:0; -} - - -#elif !defined(HB_NO_UCD_UNASSIGNED) - -static const uint8_t _hb_ucd_u8[17936] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, @@ -5675,10 +2821,1743 @@ _hb_ucd_dm (unsigned u) } +#elif !defined(HB_NO_UCD_UNASSIGNED) + +static const uint8_t +_hb_ucd_u8[17564] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7, + 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42, + 7, 7, 43, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73, + 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83, + 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34, + 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96, + 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105, + 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, + 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, + 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117, + 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131, + 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146, + 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122, + 160,161,162,163,164,165,122,122,166,167,168,169,122,170,122,171, + 34, 34, 34, 34, 34, 34, 34,172,173, 34,174,122,122,122,122,122, + 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,175, + 34, 34, 34, 34, 34, 34, 34, 34,176,122,122,122,122,122,122,122, + 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, + 122,122,122,122,122,122,122,122, 34, 34, 34, 34,177,122,122,122, + 34, 34, 34, 34,178,179,180,181,122,122,122,122,182,183,184,185, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,186, + 34, 34, 34, 34, 34, 34, 34, 34, 34,187,188,122,122,122,122,122, + 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,189, + 34, 34,190, 34, 34,191,122,122,122,122,122,122,122,122,122,122, + 122,122,122,122,122,122,122,122,192,193,122,122,122,122,122,122, + 122,122,122,122,122,122,122,122,122,122,122,122,122,122,194,195, + 69,196,197,198,199,200,201,122,202,203,204,205,206,207,208,209, + 69, 69, 69, 69,210,211,122,122,122,122,122,122,122,122,212,122, + 213,122,214,122,122,215,122,122,122,122,122,122,122,122,122,216, + 34,217,218,122,122,122,122,122,219,220,221,122,222,223,122,122, + 224,225,226,227,228,122, 69,229, 69, 69, 69, 69, 69,230,231,232, + 233,234, 69, 69,235,236, 69,237,122,122,122,122,122,122,122,122, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,238, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,239, 34, + 240, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,241, 34, 34, + 34, 34, 34, 34, 34, 34, 34,242,122,122,122,122,122,122,122,122, + 34, 34, 34, 34,243,122,122,122,122,122,122,122,122,122,122,122, + 34, 34, 34, 34, 34, 34,244,122,122,122,122,122,122,122,122,122, + 245,122,246,247,122,122,122,122,122,122,122,122,122,122,122,122, + 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,248, + 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,249, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, + 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25, + 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32, + 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11, + 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11, + 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34, + 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32, + 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32, + 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, + 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, + 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10, + 44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11, + 11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34, + 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11, + 32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16, + 48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52, 2, 2, 2, + 16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62, + 36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65, 8, 9, 66, 2, 67, + 43, 43, 43, 43, 43, 60, 68, 2, 69, 36, 36, 36, 36, 70, 43, 43, + 7, 7, 7, 7, 7, 2, 2, 36, 71, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36, + 7, 7, 7, 7, 7, 36, 77, 78, 2, 2, 2, 2, 2, 2, 2, 79, + 70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36, + 36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44, + 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, + 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43, + 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64, + 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44, + 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43, + 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43, + 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86, + 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36, + 36, 43, 2, 7, 7, 7, 7, 7, 88, 36, 36, 36, 36, 36, 36, 36, + 70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86, + 87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62, + 36, 43, 44, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 56, 63, 80, + 57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86, + 87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61, + 44, 44, 44, 7, 7, 7, 7, 7, 43, 36, 70, 64, 44, 44, 44, 44, + 57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36, + 61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44, + 61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43, + 57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87, + 87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62, + 78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36, + 61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36, + 36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44, + 61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44, + 85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44, + 44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91, + 70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87, + 86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61, + 62, 61, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36, + 36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77, + 44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36, + 57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36, + 36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89, + 86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44, + 62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96, + 36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36, + 36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44, + 36, 36, 61, 81, 43, 43, 43, 44, 7, 7, 7, 7, 7, 44, 36, 36, + 77, 67, 2, 2, 2, 2, 2, 2, 2, 97, 97, 67, 43, 67, 67, 67, + 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 50, 50, 50, 4, 4, 86, + 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, + 57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43, + 43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67, + 67, 67, 67, 76, 67, 67, 92, 67, 2, 2, 97, 67, 21, 64, 44, 44, + 36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71, + 7, 7, 7, 7, 7, 2, 2, 2, 36, 36, 36, 86, 43, 36, 36, 43, + 71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36, + 36, 85, 87, 85, 86, 86, 87, 94, 7, 7, 7, 7, 7, 86, 87, 67, + 11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16, + 36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, + 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36, + 36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43, + 2, 2, 2, 2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44, + 67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44, + 101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72, + 102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44, + 36, 36, 36, 36, 36, 63, 2,105,106, 36, 36, 36, 61, 44, 44, 44, + 36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44, + 36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36, + 61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86, + 86, 86, 86, 85, 87, 43, 43, 43, 43, 43, 2, 88, 2, 66, 70, 44, + 7, 7, 7, 7, 7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44, + 2, 2, 2,108, 2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36, + 36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44, + 86, 85, 86, 86, 87, 43, 44, 44, 92, 44, 2, 7, 7, 7, 7, 7, + 36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44, + 7, 7, 7, 7, 7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 36, 36, 36, 70, 85, 87, 44, 2, 36, 36, 94, 85, 43, 43, 43, 80, + 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57, + 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109, + 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36, + 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44, + 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64, + 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36, + 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2, + 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2, + 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2, + 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, + 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43, + 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44, + 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16, + 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40, + 32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11, + 16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48, + 16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112, + 16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41, + 16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41, + 44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65, + 120,120,120, 2,121,122,121,122, 2, 2, 2, 2,123, 65, 65,124, + 2, 2, 2, 2,125,126, 2,127,128, 2,129,130, 2, 2, 2, 2, + 2, 9,128, 2, 2, 2, 2,131, 65, 65,132, 65, 65, 65, 65, 65, + 133, 44, 27, 27, 27, 8,129,134, 27, 27, 27, 27, 27, 8,129,104, + 40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20, + 135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51, + 109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44, + 67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67, + 67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11, + 8, 8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27, + 105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44, + 8, 8,144, 67, 67, 8, 67, 67,144, 26, 67,144, 67, 67, 67,144, + 67, 67, 67, 67, 67, 67, 67, 8, 67,144,144, 67, 67, 67, 67, 67, + 67, 67, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67, + 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8, + 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, + 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67, + 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67, + 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8, + 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4, + 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, + 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, + 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, + 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67, + 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11, + 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149, + 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44, + 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57, + 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61, + 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2, + 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2, + 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44, + 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44, + 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157, + 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67, + 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69, + 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67, + 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, + 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2, + 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70, + 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43, + 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44, + 41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32, + 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32, + 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32, + 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44, + 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36, + 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44, + 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44, 2, + 43, 36, 36, 36, 2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43, 2, + 36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93, + 36, 70, 86, 43, 43, 86, 43, 86,107, 2, 2, 2, 2, 2, 2, 52, + 7, 7, 7, 7, 7, 44, 44, 2, 36, 36, 70, 69, 36, 36, 36, 36, + 7, 7, 7, 7, 7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85, + 87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44, + 7, 7, 7, 7, 7, 44, 2, 2, 69, 36, 36, 77, 67, 94, 85, 36, + 71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 62, 83, 2, 36, 36, 36, 36, 36, 94, 43, 86, + 2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61, + 62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40, + 16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44, + 36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36, + 170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171, + 16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71, + 36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61, + 36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41, + 41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67, + 2, 2, 2,152,130, 44, 44, 44, 6,173,174,148,148,148,148,148, + 148,148,130,152,130, 2,127,175, 2, 64, 2, 2,156,148,148,130, + 2,176, 8,177, 66, 2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 61, 79, 93, 2, 3, 2, 4, 5, 6, 2, + 16, 16, 16, 16, 16, 17, 18,129,130, 4, 2, 36, 36, 36, 36, 36, + 69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40, + 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44, + 20,178, 56,135, 26, 8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44, + 36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62, + 2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67, + 105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92, + 67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36, + 155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36, + 182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16, + 11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44, + 36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93, + 11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16, + 16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44, + 40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44, + 36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62, + 36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27, + 44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27, + 36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93, + 36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27, + 70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36, + 36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44, + 2, 2, 2, 2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30, + 36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36, + 36, 36, 70, 80, 44,179, 27, 27, 2, 2, 2, 64, 44, 44, 44, 44, + 36, 36, 36, 44, 93, 2, 2, 2, 36, 36, 36, 44, 27, 27, 27, 27, + 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44, + 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44, + 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44, + 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44, + 36, 44, 44, 44, 44, 44, 44, 44, 27, 27, 27, 95, 44, 44, 44, 44, + 180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44, + 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60, 2, 2, 2, 44, + 27, 27, 27, 7, 7, 7, 7, 7, 71, 70, 71, 44, 44, 44, 44, 57, + 86, 87, 43, 85, 87, 60,185, 2, 2, 80, 44, 44, 44, 44, 79, 44, + 43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 87, 43, + 43, 43, 80, 7, 7, 7, 7, 7, 2, 2, 94, 98, 44, 44, 44, 44, + 36, 70, 2, 61, 44, 44, 44, 44, 36, 94, 86, 43, 43, 43, 43, 85, + 98, 36, 63, 2, 59, 43, 60, 87, 7, 7, 7, 7, 7, 63, 63, 2, + 179, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 86, 87, 43, 86, 85, 43, 2, 2, 2, 80, + 36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62, + 36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70, + 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62, + 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44, + 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44, + 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43, + 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71, + 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87, + 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44, + 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44, + 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86, + 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44, + 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44, + 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36, + 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71, + 98, 87, 2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36, + 94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44, + 70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60, + 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36, + 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2, + 2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87, + 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36, + 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43, + 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36, + 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44, + 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90, + 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44, + 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67, + 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181, + 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44, + 65, 65, 65, 65,132, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44, + 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44, + 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44, + 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57, + 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44, + 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81, + 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44, + 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44, + 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86, + 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67, + 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44, + 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16, + 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, + 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11, + 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16, + 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16, + 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11, + 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, + 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11, + 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, + 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, + 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, + 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43, + 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67, + 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43, + 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110, + 43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43, + 43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44, + 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80, + 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96, + 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27, + 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27, + 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163, + 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36, + 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44, + 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62, + 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61, + 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36, + 8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, + 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44, + 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 55, 67, + 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 44, 67, 67, 92, 44, + 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44, + 65, 65, 65, 65, 65, 65, 65, 65,171,171,171,171,171,171,171, 44, + 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21, + 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9, + 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0, + 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15, + 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7, + 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12, + 2, 2, 6, 5, 9, 21, 9, 2, 2, 9, 25, 9, 26, 12, 11, 11, + 2, 6, 5, 21, 17, 2, 2, 26, 26, 23, 2, 12, 17, 12, 21, 12, + 12, 21, 7, 2, 2, 7, 7, 21, 21, 2, 1, 1, 21, 23, 26, 26, + 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, 6, 12, + 12, 26, 7, 26, 26, 7, 2, 1, 12, 2, 6, 2, 24, 7, 7, 6, + 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 2, 10, 10, 2, 15, 26, + 26, 2, 2, 21, 7, 10, 15, 7, 2, 23, 21, 26, 10, 7, 21, 15, + 15, 2, 17, 7, 29, 7, 7, 22, 18, 2, 14, 14, 14, 7, 10, 21, + 17, 21, 11, 12, 5, 2, 5, 6, 8, 8, 8, 24, 5, 24, 2, 24, + 9, 24, 24, 2, 29, 29, 29, 1, 17, 17, 20, 19, 22, 20, 27, 28, + 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29, + 1, 2, 15, 6, 18, 6, 23, 2, 12, 11, 9, 26, 26, 9, 26, 5, + 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, 18, 25, + 18, 22, 5, 12, 2, 5, 22, 21, 21, 22, 18, 17, 26, 6, 7, 14, + 17, 22, 18, 18, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15, + 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3, + 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15, + 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1, + 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, + 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34, 0, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, + 0, 0, 39, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5, + 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18, + 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, + 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, + 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0, + 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63, + 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0, + 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, + 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, + 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 75, 0, 0, 76, 77, 0, + 0, 78, 79, 0, 80, 62, 0, 81, 82, 0, 0, 83, 84, 85, 0, 0, + 0, 86, 0, 87, 0, 0, 51, 88, 51, 0, 89, 0, 90, 0, 0, 0, + 79, 0, 0, 0, 91, 92, 0, 93, 94, 95, 96, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 97, 98, 0, 0, 0, 0, 99,100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,101, 0, 0,102, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,103,104, 0, 0,105, 0, 0, 0, 0, 0, 0, + 106, 0, 0, 0,100, 0, 0, 0, 0, 0,107,108, 0, 0, 0, 0, + 0, 0, 0,109, 0,110, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, + 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, + 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, + 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, + 0, 27, 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, + 33, 0, 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, + 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, + 42, 0, 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, + 47, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, + 0, 51, 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, + 0, 56, 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, + 0, 0, 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, + 0, 0, 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, + 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, + 0, 81, 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, + 84, 0, 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, + 0, 0, 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, + 0, 0, 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, + 0, 0, 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, + 0, 0, 98, 0, 0, 0, 99, 0,100, 93, 0, 0,101, 0, 0, 0, + 84, 0, 0,102, 0, 0, 0,103,104, 0, 0,105,106, 0, 0, 0, + 0, 0, 0,107, 0, 0,108, 0, 0, 0, 0,109, 33, 0,110,111, + 112, 35, 0, 0,113, 0, 0, 0,114, 0, 0, 0, 0, 0, 0,115, + 0, 0,116, 0, 0, 0, 0,117, 88, 0, 0, 0, 0, 0, 57, 0, + 0, 0, 0, 52,118, 0, 0, 0, 0,119, 0, 0,120, 0, 0, 0, + 0,118, 0, 0, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0,123, + 0,124, 0, 0, 0, 0,125,126,127, 0,128, 0,129, 0, 0, 0, + 130,131,132, 0, 0, 0, 35, 0, 0, 0,133, 0, 0,134, 0, 0, + 135, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, + 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, + 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, + 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, + 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, + 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, + 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, + 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, + 54, 21, 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, + 0, 0, 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, + 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, + 0, 0, 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, + 0, 77, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, + 0, 80, 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, + 0, 0, 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, + 1, 52, 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, + 1, 0, 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, + 0, 78, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, + 21, 1, 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, + 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, + 0, 0, 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, + 0, 0, 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, + 61, 0, 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, + 0, 0, 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, + 0, 0, 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, + 0, 0, 19, 58, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, + 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, + 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58, + 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0, + 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0, + 0, 0, 56, 0, 89, 80, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0, + 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4, + 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1, + 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 4,122, 0, 0, + 0, 1,123, 0, 0, 0, 0, 0,230,230,230,230,230,232,220,220, + 220,220,232,216,220,220,220,220,220,202,202,220,220,220,220,202, + 202,220,220,220, 1, 1, 1, 1, 1,220,220,220,220,230,230,230, + 230,240,230,220,220,220,230,230,230,220,220, 0,230,230,230,220, + 220,220,220,230,232,220,220,230,233,234,234,233,234,234,233,230, + 0, 0, 0,230, 0,220,230,230,230,230,220,230,230,230,222,220, + 230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, + 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230, + 230,220,220,230,220,230,230,220, 35, 0, 0, 0, 0, 0,230,230, + 230, 0, 0,230,230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0, + 230,220,230,230,220,220,230,220,220,230,220,230,220,230,230, 0, + 0,220, 0, 0,230,230, 0,230, 0,230,230,230,230,230, 0, 0, + 0,220,220,220,230,220,220,220,230,230, 0,220, 27, 28, 29,230, + 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, + 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,118,118, 9, 0, + 122,122,122,122,220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, + 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0, + 130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, + 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0, + 0,222,230,220,220, 0, 0, 0,230, 0, 0,220,230,220, 0,220, + 230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1, + 1, 0, 0, 0,230,234,214,220,202,230,230,230,230,230,232,228, + 228,220,218,230,233,220,230,220,230,230, 1, 1, 1, 1, 1,230, + 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228,232,222,224,224, + 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230,220, 0, 0,230, + 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, 0,230,220, 0, + 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, + 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, + 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,220,220,220, 0, + 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19, + 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28, + 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 0, + 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, + 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12, + 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19, + 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8, + 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27, + 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20, + 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20, + 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20, + 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0, + 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45, + 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1, + 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0, + 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13, + 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 44, 0, 0, 1, + 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56, + 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61, + 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109, + 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123, + 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138, + 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151, + 152,153,154,155, 96, 96,156,157,158,159, 96,160, 96,161,162,162, + 162,162,162,162,162,163,164,162,165, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,166,167,167, + 167,167,167,167,167,167,168, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96,169,169,169,169,170, 96, 96, 96,171,171, + 171,171,172,173,174,175, 96, 96, 96, 96,176,177,178,179,180,180, + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180, + 180,180,180,180,180,180,180,180,180,180,180,180,180,181,180,180, + 180,180,180,180,182,182,182,183,184, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,185,186,187, + 188,189,189,190, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96,191,192, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, 59,195, + 196,197,198,199,200, 96,201,202,203, 59, 59,204, 59,205,206,206, + 206,206,206,207, 96, 96, 96, 96, 96, 96, 96, 96,208, 96,209, 96, + 210, 96, 96,211, 96, 96, 96, 96, 96, 96, 96, 96, 96,212,213,214, + 215, 96, 96, 96, 96, 96,216,217,218, 96,219,220, 96, 96,221,222, + 59,223,224, 96, 59, 59, 59, 59, 59, 59, 59,225,226,227,228,229, + 59, 59,230,231, 59,232, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,233, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,234, 70,235, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,236, 70, 70, 70, 70, + 70, 70, 70, 70, 70,237, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70,238, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, + 70, 70, 70, 70,239, 96, 96, 96, 96, 96, 96, 96, 96, 96,240, 96, + 241,242, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, + 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, + 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, + 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14, + 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, + 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, + 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, + 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5, + 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, + 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, + 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, + 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11, + 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, + 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, + 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, + 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, + 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10, + 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, + 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, + 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, + 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, + 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, + 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, + 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, + 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, + 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, + 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, + 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, + 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, + 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, + 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2, + 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, + 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, + 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, + 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23, + 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, + 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, + 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16, + 16, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2, + 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36, + 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, + 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2, + 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, + 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, + 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, + 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25, + 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, + 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, + 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, + 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, + 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, + 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, + 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, + 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, + 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, + 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48, + 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52, + 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58, + 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91, + 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76, + 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, + 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2, + 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, + 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, + 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, + 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, + 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, + 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, + 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27, + 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, + 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, + 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0, + 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13, + 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, + 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2, + 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, + 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, + 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, + 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19, + 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, + 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, + 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, + 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12, + 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, + 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, + 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30, + 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87, + 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12, + 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13, + 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, + 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14, + 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2, + 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1, + 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3, + 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, + 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, + 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, + 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, + 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, + 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, + 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, + 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104, + 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, + 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, + 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, + 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2, + 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120, + 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116, + 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128, + 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, + 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2, + 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2, + 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, + 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117, + 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112, + 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, + 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122, + 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122, + 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, + 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, + 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144, + 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156, + 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156, + 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,148,148, + 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,158,158, + 158,158,158,158,158,158,158,158, 2, 2, 2, 2, 2, 2,153,153, + 153,153,153,153,153,153,153,153,153,153, 2, 2, 2, 2,149,149, + 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, + 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2, + 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100, + 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108, + 2,108,108,108,108,108,108,108,108,108,108,108,108, 2,129,129, + 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129, + 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, + 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107, + 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, + 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2, + 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107, + 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2, + 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107, + 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,137,137, + 137,137,137,137,137,137,137,137,137,137, 2,137,137,137,137,137, + 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124, + 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, + 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102, + 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126, + 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,126,126, + 126,126,126,126,126, 2,142,142,142,142,142,142,142,142,142,142, + 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125, + 125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,154,154, + 154,154,154,154,154, 2, 2,154, 2, 2,154,154,154,154,154,154, + 154,154, 2,154,154, 2,154,154,154,154,154,154,154,154,154,154, + 154,154,154,154, 2,154,154, 2, 2,154,154,154,154,154,154,154, + 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2, + 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141, + 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140, + 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2, + 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, + 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, + 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, + 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, + 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, + 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, + 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, + 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, + 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2, 86, 2, + 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, + 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157, + 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 80, 2, + 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127, + 127,127,127,127,127, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115, + 115,115,115,115,115,115,115,115,115,115,115,115,115, 2,115,115, + 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103, + 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119, + 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119, + 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146, + 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2, + 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136, + 136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155, + 155,155,155,155, 2, 2,136, 2, 2, 2, 2, 2, 2, 2, 17, 17, + 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17, 17, 2, 17, 15, + 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 15, 15, + 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139, + 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105, + 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, + 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, + 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, + 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, + 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, + 131,131,131,131,131,131, 56, 56, 56, 56, 56, 56, 56, 2, 56, 2, + 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, + 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151, + 151,151,151, 2, 2, 2,151,151,151,151,151,151, 2, 2,151,151, + 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152, + 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 2, 30, 30, 2,113,113, + 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, + 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132, + 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 3, 3, + 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, + 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, + 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 2, + 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13, + 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, + 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, + 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, + 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, + 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, + 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, + 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0, + 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131, + 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147, + 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160, + 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176, + 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, + 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, +}; +static const uint16_t +_hb_ucd_u16[9200] = +{ + 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, + 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31, + 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39, + 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13, + 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50, + 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58, + 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66, + 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32, + 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101, + 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113, + 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124, + 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135, + 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140, + 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140, + 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48, + 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175, + 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183, + 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193, + 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199, + 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209, + 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140, + 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225, + 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235, + 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13, + 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282, + 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271, + 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209, + 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279, + 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305, + 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308, + 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313, + 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140, + 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325, + 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331, + 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48, + 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209, + 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48, + 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342, + 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349, + 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360, + 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151, + 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377, + 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11, + 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206, + 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391, + 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140, + 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48, + 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403, + 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410, + 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419, + 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71, + 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428, + 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430, + 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140, + 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439, + 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140, + 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, + 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453, + 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271, + 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467, + 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474, + 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476, + 48, 48, 477, 478, 140, 140, 140, 140, 48, 464, 479, 48, 62, 480, 140, 48, + 481, 140, 140, 48, 482, 140, 48, 314, 483, 48, 48, 484, 485, 457, 486, 487, + 222, 48, 48, 488, 489, 48, 196, 192, 490, 48, 491, 492, 493, 48, 48, 494, + 222, 48, 48, 495, 496, 497, 498, 499, 48, 97, 500, 501, 140, 140, 140, 140, + 502, 503, 504, 48, 48, 505, 506, 192, 507, 83, 84, 508, 509, 510, 511, 512, + 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140, + 48, 48, 518, 519, 520, 521, 140, 140, 48, 48, 48, 522, 523, 192, 524, 140, + 48, 48, 525, 526, 192, 140, 140, 140, 48, 173, 527, 528, 314, 140, 140, 140, + 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530, + 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140, + 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196, + 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140, + 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 48, 557, 140, 140, 140, 100, 271, 558, 559, 560, + 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 561, 562, + 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563, + 48, 48, 200, 564, 140, 140, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140, + 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565, + 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578, + 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140, + 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579, + 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 206, + 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140, + 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 586, 209, 209, 209, 587, 588, + 589, 209, 590, 209, 209, 209, 288, 140, 209, 209, 209, 209, 591, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 271, 592, 209, 209, 209, 209, 209, 287, 271, 461, + 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11, + 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11, + 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613, + 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622, + 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140, + 628, 629, 140, 140, 140, 140, 140, 140, 630, 631, 632, 140, 140, 140, 140, 140, + 48, 48, 151, 633, 634, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637, + 140, 140, 140, 140, 140, 140, 638, 200, 48, 48, 48, 48, 639, 585, 140, 140, + 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 498, + 271, 271, 641, 642, 140, 140, 140, 140, 498, 271, 643, 644, 140, 140, 140, 140, + 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654, + 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324, + 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209, + 659, 209, 209, 325, 660, 661, 324, 140, 209, 209, 209, 209, 209, 209, 209, 662, + 209, 209, 209, 209, 209, 663, 426, 426, 209, 209, 209, 209, 209, 209, 209, 323, + 209, 209, 209, 209, 209, 660, 325, 427, 325, 209, 209, 209, 664, 176, 209, 209, + 664, 209, 657, 661, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 657, 665, + 287, 209, 426, 288, 324, 176, 664, 287, 209, 666, 209, 209, 288, 140, 140, 192, + 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 196, 48, 48, 48, 48, + 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 100, 140, 48, 204, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 71, 140, 140, 140, 667, 140, 668, 668, 668, 668, 668, 668, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140, + 391, 391, 391, 391, 391, 391, 391, 669, 391, 391, 391, 391, 391, 391, 391, 670, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, + 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11, + 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21, + 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26, + 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31, + 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31, + 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43, + 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 31, 31, + 31, 50, 51, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 31, 31, 31, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53, + 56, 57, 58, 59, 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67, + 68, 69, 70, 71, 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26, + 80, 81, 82, 83, 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91, + 92, 93, 94, 95, 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26, + 103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112, + 113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113, + 122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26, + 131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131, + 136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26, + 146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26, + 150, 151, 152, 152, 153, 152, 152, 154, 155, 154, 152, 156, 26, 26, 26, 26, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 157, 157, 157, 159, 158, 157, + 157, 157, 157, 158, 157, 157, 157, 160, 157, 160, 161, 162, 26, 26, 26, 26, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 164, 164, 164, 164, 165, 166, 164, 164, 164, 164, 164, 167, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 171, 170, 169, 169, 169, 169, + 169, 170, 169, 169, 169, 169, 170, 171, 170, 169, 171, 169, 169, 169, 169, 169, + 169, 169, 170, 169, 169, 169, 169, 169, 169, 169, 169, 172, 169, 169, 169, 173, + 169, 169, 169, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 178, 178, 178, 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, 181, 180, 182, + 183, 183, 184, 185, 186, 186, 187, 26, 188, 188, 189, 26, 190, 191, 192, 26, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 194, 193, 195, 193, 195, + 196, 197, 197, 198, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 199, + 197, 197, 197, 197, 197, 200, 177, 177, 177, 177, 177, 177, 177, 177, 201, 26, + 202, 202, 202, 203, 202, 204, 202, 204, 205, 202, 206, 206, 206, 207, 208, 26, + 209, 209, 209, 209, 209, 210, 209, 209, 209, 211, 209, 212, 193, 193, 193, 193, + 213, 213, 213, 214, 215, 215, 215, 215, 215, 215, 215, 216, 215, 215, 215, 217, + 215, 218, 215, 218, 215, 219, 9, 9, 9, 220, 26, 26, 26, 26, 26, 26, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 221, 221, 221, 221, 221, 223, + 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227, + 228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231, + 18, 232, 164, 164, 164, 164, 164, 233, 224, 26, 234, 9, 235, 236, 237, 238, + 2, 2, 2, 2, 239, 240, 2, 2, 2, 2, 2, 241, 242, 243, 2, 244, + 2, 2, 2, 2, 2, 2, 2, 245, 9, 9, 9, 9, 9, 9, 9, 9, + 14, 14, 246, 246, 14, 14, 14, 14, 246, 246, 14, 247, 14, 14, 14, 246, + 14, 14, 14, 14, 14, 14, 248, 14, 248, 14, 249, 250, 14, 14, 251, 252, + 0, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 255, 256, + 0, 257, 2, 258, 0, 0, 0, 0, 259, 26, 9, 9, 9, 9, 260, 26, + 0, 0, 0, 0, 261, 262, 4, 0, 0, 263, 0, 0, 2, 2, 2, 2, + 2, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 257, 26, 26, 26, 0, 265, 26, 26, 0, 0, 0, 0, + 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, + 0, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 2, 2, 2, 2, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 270, 271, + 164, 164, 164, 164, 165, 166, 272, 272, 272, 272, 272, 272, 272, 273, 274, 273, + 169, 169, 171, 26, 171, 171, 171, 171, 171, 171, 171, 171, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, + 276, 276, 276, 277, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 278, 26, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 26, 26, 26, 0, 280, + 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, + 292, 293, 293, 293, 293, 293, 294, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 295, 0, 0, 293, 293, 293, 293, 0, 0, 0, 0, 280, 26, 290, 290, + 168, 168, 168, 295, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 296, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 290, 290, 290, 290, 297, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 0, 0, 0, 0, 0, + 276, 276, 276, 276, 276, 276, 276, 276, 0, 0, 0, 0, 0, 0, 0, 0, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 299, 298, 298, 298, 298, 298, 298, 300, 26, 301, 301, 301, 301, 301, 301, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 303, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 26, + 0, 0, 0, 0, 305, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 306, 2, 2, 2, 2, 2, 2, 2, 307, 308, 309, 26, 26, 310, 2, + 311, 311, 311, 311, 311, 312, 0, 313, 314, 314, 314, 314, 314, 314, 314, 26, + 315, 315, 315, 315, 315, 315, 315, 315, 316, 317, 315, 318, 53, 53, 53, 53, + 319, 319, 319, 319, 319, 320, 321, 321, 321, 321, 322, 323, 168, 168, 168, 324, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 326, 325, 327, 163, 163, 163, 328, + 329, 329, 329, 329, 329, 329, 330, 26, 329, 331, 329, 332, 163, 163, 163, 163, + 333, 333, 333, 333, 333, 333, 333, 333, 334, 26, 26, 335, 336, 336, 337, 26, + 338, 338, 338, 26, 171, 171, 2, 2, 2, 2, 2, 339, 340, 341, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 336, 336, 336, 336, 336, 342, 336, 343, + 168, 168, 168, 168, 344, 26, 168, 168, 295, 345, 168, 168, 168, 168, 168, 344, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 346, 26, 26, 26, 26, + 347, 26, 348, 349, 25, 25, 350, 351, 352, 25, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 353, 26, 354, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 355, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 356, 31, 31, 31, 31, 31, 31, 357, 26, 26, 26, 26, 31, 31, + 9, 9, 0, 313, 9, 358, 0, 0, 0, 0, 359, 0, 257, 280, 360, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 361, + 362, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 363, 290, 289, 290, + 290, 290, 290, 364, 168, 168, 168, 295, 365, 365, 365, 366, 257, 257, 26, 367, + 368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372, 26, 26, 26, 26, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373, + 374, 0, 0, 0, 0, 0, 375, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 252, 0, 376, 377, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 378, + 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 280, + 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390, + 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 26, 26, 26, 26, + 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397, + 398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402, + 403, 403, 403, 403, 403, 26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408, + 407, 408, 409, 407, 410, 407, 410, 411, 26, 26, 26, 26, 26, 26, 26, 26, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 413, 26, 412, 412, 414, 26, 412, 26, 26, 26, + 415, 2, 2, 2, 2, 2, 416, 307, 26, 26, 26, 26, 26, 26, 26, 26, + 417, 418, 419, 419, 419, 419, 420, 421, 422, 422, 423, 422, 424, 424, 424, 424, + 425, 425, 425, 426, 427, 425, 26, 26, 26, 26, 26, 26, 428, 428, 429, 430, + 431, 431, 431, 432, 433, 433, 433, 434, 26, 26, 26, 26, 26, 26, 26, 26, + 435, 435, 435, 435, 436, 436, 436, 437, 436, 436, 438, 436, 436, 436, 436, 436, + 439, 440, 441, 442, 443, 443, 444, 445, 443, 446, 443, 446, 447, 447, 447, 447, + 448, 448, 448, 448, 26, 26, 26, 26, 449, 449, 449, 449, 450, 451, 450, 26, + 452, 452, 452, 452, 452, 452, 453, 454, 455, 455, 456, 455, 457, 457, 458, 457, + 459, 459, 460, 461, 26, 462, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 464, 26, 26, 26, 26, 26, 26, + 465, 465, 465, 465, 465, 465, 466, 26, 465, 465, 465, 465, 465, 465, 466, 467, + 468, 468, 468, 468, 468, 26, 468, 469, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50, + 470, 470, 470, 470, 470, 471, 472, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 473, 473, 473, 473, 473, 26, 474, 474, 474, 474, 474, 475, 26, 26, 476, 476, + 476, 477, 26, 26, 26, 26, 478, 478, 478, 479, 26, 26, 480, 480, 481, 26, + 482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 484, 482, 482, 482, 483, 485, + 486, 486, 486, 486, 486, 486, 486, 486, 487, 488, 489, 489, 489, 490, 489, 491, + 492, 492, 492, 492, 492, 492, 493, 492, 492, 26, 494, 494, 494, 494, 495, 26, + 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 497, 137, 498, 26, + 499, 499, 500, 499, 499, 499, 499, 501, 26, 26, 26, 26, 26, 26, 26, 26, + 502, 503, 504, 505, 504, 506, 507, 507, 507, 507, 507, 507, 507, 508, 507, 509, + 510, 511, 512, 513, 513, 514, 515, 516, 511, 517, 518, 519, 520, 521, 521, 26, + 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 523, 524, 26, 26, 26, + 525, 525, 525, 525, 525, 525, 525, 525, 525, 26, 525, 526, 26, 26, 26, 26, + 527, 527, 527, 527, 527, 527, 528, 527, 527, 527, 527, 528, 26, 26, 26, 26, + 529, 529, 529, 529, 529, 529, 529, 529, 530, 26, 529, 531, 197, 532, 26, 26, + 533, 533, 533, 533, 533, 533, 533, 534, 533, 534, 26, 26, 26, 26, 26, 26, + 535, 535, 535, 536, 535, 537, 535, 535, 538, 26, 26, 26, 26, 26, 26, 26, + 539, 539, 539, 539, 539, 539, 539, 540, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 542, 543, + 544, 545, 546, 547, 547, 547, 548, 549, 544, 26, 547, 550, 26, 26, 26, 26, + 26, 26, 26, 26, 551, 552, 551, 551, 551, 551, 551, 552, 553, 26, 26, 26, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 26, 555, 555, 555, 555, 555, 555, + 555, 555, 555, 555, 556, 26, 177, 177, 557, 557, 557, 557, 557, 557, 557, 558, + 559, 560, 559, 559, 559, 559, 561, 559, 562, 26, 559, 559, 559, 563, 564, 564, + 564, 564, 565, 564, 564, 566, 567, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 568, 569, 570, 570, 570, 570, 568, 571, 570, 26, 570, 572, 573, 574, 575, 575, + 575, 576, 577, 578, 575, 579, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 580, 580, 580, 581, + 26, 26, 26, 26, 26, 26, 582, 26, 108, 108, 108, 108, 108, 108, 583, 584, + 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 586, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 587, 588, 26, + 585, 585, 585, 585, 585, 585, 585, 585, 589, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591, 26, + 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 593, 592, 594, 26, 26, 26, 26, 26, 26, 26, 26, + 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, + 595, 595, 595, 595, 595, 595, 595, 595, 596, 26, 26, 26, 26, 26, 26, 26, + 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, + 304, 304, 304, 304, 304, 304, 304, 597, 598, 598, 598, 599, 598, 600, 601, 601, + 601, 601, 601, 601, 601, 601, 601, 602, 601, 603, 604, 604, 604, 605, 605, 26, + 606, 606, 606, 606, 606, 606, 606, 606, 607, 26, 606, 608, 608, 606, 606, 609, + 606, 606, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 610, 610, 610, 610, 610, 610, 610, 610, + 610, 610, 610, 611, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 612, 612, 612, 612, 612, 612, 612, 612, 612, 613, 612, 612, 612, 612, 612, 612, + 612, 614, 612, 612, 26, 26, 26, 26, 26, 26, 26, 26, 615, 26, 346, 26, + 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, + 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 26, + 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, + 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 618, 26, 26, 26, 26, 26, + 616, 619, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 620, 621, + 622, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 623, 26, 26, 26, 26, 26, 624, 26, 625, 26, 626, 626, + 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, + 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 627, + 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 629, 628, 630, + 628, 631, 628, 632, 280, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 9, 9, 9, 9, 9, 633, 9, 9, 220, 26, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 26, 26, 26, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26, + 0, 0, 0, 0, 257, 362, 0, 0, 0, 0, 0, 0, 634, 635, 0, 636, + 637, 638, 0, 0, 0, 639, 0, 0, 0, 0, 0, 0, 0, 265, 26, 26, + 14, 14, 14, 14, 14, 14, 14, 14, 246, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 280, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 257, 26, 0, 0, 0, 259, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, + 0, 0, 0, 254, 640, 641, 0, 642, 643, 0, 0, 0, 0, 0, 0, 0, + 268, 644, 254, 254, 0, 0, 0, 645, 646, 647, 648, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 0, + 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, + 649, 650, 26, 651, 652, 649, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 2, 2, 2, 347, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 653, 269, 269, 654, 655, 656, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 657, 657, 657, 657, 657, 658, 657, 659, 657, 660, 26, 26, 26, 26, 26, 26, + 26, 26, 661, 661, 661, 662, 26, 26, 663, 663, 663, 663, 663, 663, 663, 664, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 171, 665, 169, 171, + 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, + 666, 666, 666, 666, 666, 666, 666, 666, 667, 666, 668, 26, 26, 26, 26, 26, + 669, 669, 669, 669, 669, 669, 669, 669, 669, 670, 669, 671, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 362, 0, + 0, 0, 0, 0, 0, 0, 376, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 362, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 26, 26, + 672, 31, 31, 31, 673, 674, 675, 676, 677, 678, 673, 679, 673, 675, 675, 680, + 31, 681, 31, 682, 683, 681, 31, 682, 26, 26, 26, 26, 26, 26, 51, 26, + 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 280, 26, 0, 257, 362, 0, 362, 0, 362, 0, 0, 0, 275, 26, + 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 684, 0, 0, 0, + 685, 26, 0, 0, 0, 0, 0, 280, 0, 259, 313, 26, 275, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, 0, 376, 0, 376, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 280, 259, 26, + 0, 280, 0, 0, 0, 0, 0, 0, 0, 26, 0, 313, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 275, 313, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 0, 275, 376, 376, + 257, 26, 0, 0, 0, 376, 0, 265, 275, 26, 0, 313, 0, 26, 257, 26, + 0, 0, 359, 0, 0, 0, 0, 0, 0, 265, 26, 26, 26, 26, 0, 313, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 26, 26, 26, 26, + 276, 276, 276, 276, 276, 276, 276, 687, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 279, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 346, 26, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 687, 26, 26, 26, + 276, 276, 276, 279, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 688, 26, 26, 26, 26, 26, 26, + 689, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, + 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, + 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, + 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, + 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, + 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, + 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199, + 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, + 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231, + 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258, + 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275, + 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0, + 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093, + 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010, + 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347, + 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424, + 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, + 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238, + 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, + 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232, + 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461, + 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486, + 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, + 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0, + 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, + 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, + 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560, + 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, + 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, + 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, + 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, + 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0, + 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, + 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, + 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, + 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, + 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, + 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0, + 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, + 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, + 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356, + 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214, + 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363, + 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251, + 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266, + 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287, + 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302, + 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, + 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375, + 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353, + 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234, + 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403, + 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412, + 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0, + 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721, + 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0, + 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757, + 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776, + 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0, + 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793, + 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814, + 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0, + 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728, + 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764, + 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821, + 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, + 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828, + 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833, + 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, + 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, + 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, + 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, + 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938, + 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0, + 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870, + 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0, + 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0, + 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0, + 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, + 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0, + 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0, + 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0, + 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, + 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, + 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, + 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, + 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, + 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, + 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, + 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, + 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, + 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, + 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, + 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, + 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, + 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, + 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, + 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, + 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, + 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, + 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, + 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, + 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, + 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, + 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, + 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, + 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, + 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, + 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, + 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, + 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, + 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, + 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, + 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, + 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, + 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950, + 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959, + 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, + 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, + 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, + 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, + 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, + 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, + 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, + 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, + 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, + 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, + 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, + 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, + 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, + 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, + 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, + 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, + 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, + 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, + 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, + 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, + 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, + 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, + 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, + 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, + 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, + 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, + 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, + 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, + 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, + 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, + 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, + 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, + 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, + 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, +}; +static const int16_t +_hb_ucd_i16[196] = +{ + 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, + 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, + 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, + -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, + 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, + 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, + 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, + 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, + -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, + 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, + -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, + -1, 0, 1, -1, +}; + +static inline uint_fast8_t +_hb_ucd_gc (unsigned u) +{ + return u<1114110u?_hb_ucd_u8[6664+(((_hb_ucd_u8[1296+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; +} +static inline uint_fast8_t +_hb_ucd_ccc (unsigned u) +{ + return u<125259u?_hb_ucd_u8[8612+(((_hb_ucd_u8[8068+(((_hb_ucd_u8[7624+(((_hb_ucd_u8[7288+(((_hb_ucd_u8[7042+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; +} +static inline unsigned +_hb_ucd_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline int_fast16_t +_hb_ucd_bmg (unsigned u) +{ + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9356+(((_hb_ucd_u8[9236+(((_hb_ucd_b4(9108+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; +} +static inline uint_fast8_t +_hb_ucd_sc (unsigned u) +{ + return u<918000u?_hb_ucd_u8[10862+(((_hb_ucd_u16[2000+(((_hb_ucd_u8[10142+(((_hb_ucd_u8[9692+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; +} +static inline uint_fast16_t +_hb_ucd_dm (unsigned u) +{ + return u<195102u?_hb_ucd_u16[5888+(((_hb_ucd_u8[16764+(((_hb_ucd_u8[16382+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; +} + + #else static const uint8_t -_hb_ucd_u8[13602] = +_hb_ucd_u8[13246] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 7, 11, 12, 12, 12, 13, @@ -6146,331 +5025,309 @@ _hb_ucd_u8[13602] = 220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216, - 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 17, 17, 17, - 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169, - 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 33, 17, 49, + 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, 3, 3, + 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, 3, 14, + 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, 3, 3, + 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, 3, 3, + 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, 17, 18, + 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, 19, 28, + 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 19, + 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, 40, 19, + 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, 0, 32, + 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, 48, 49, + 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, 0, 0, + 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, 0, 0, + 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, 14, 0, + 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, 61, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 4, + 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, 0, 8, + 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0, + 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, 0, 18, + 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, 0, 1, + 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, 1, 1, + 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, 0, 1, + 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, 9, 36, + 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, 21, 21, + 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, 0, 0, + 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, 8, 9, + 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, 8, 21, + 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 3, 3, 3, 3, 3, 3, + 3, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, 0, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, - 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, - 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, - 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, - 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, - 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, - 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, - 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, - 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, - 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, - 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, - 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, - 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, - 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, - 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, - 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, - 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, - 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, - 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, - 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 11, 12, 12, 12, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 12, 21, 12, 12, 12, 12, 22, - 23, 23, 23, 24, 12, 12, 12, 25, 26, 27, 12, 28, 29, 30, 31, 32, - 33, 34, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35, - 12, 36, 7, 7, 37, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 38, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 35, 35, 35, 35, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 2, 2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61, - 56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71, - 62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89, - 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103,104, - 105,105,105, 2,106,107,108,109,110,111,112,113,114,115,116, 87, - 89,117,118,119,120,121,122,123,124,125,126, 87,127,128, 87,129, - 130,131,132, 87,133,134,135,136,137,138, 87, 87,139,140,141,142, - 87,143, 87,144,145,145,145,145,145,145,145,145,145,145,145, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87,146,147,147,147,147,147,147,147,147,147, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,148,148,148,148, - 148, 87, 87, 87,149,149,149,149,150,151,152,152, 87, 87, 87, 87, - 153,153,154,155,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,156,156,156,156,156,157,157,157,157,156, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87,158,159,160,161,162,162,162, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,163,164, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87,165, 56, 56, 56,166,167, 51, 56, 56, 87, 56, 56, 56, 56, - 56, 56, 56, 56,168,168,168,168,168,168, 87, 87, 87, 87, 87, 87, - 87, 87, 2, 87,169, 87,170, 87, 87,171, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 33,172,172,173, 87, 87, 87, 87, 87, 56, 56, 56, 87, - 89, 89, 87, 87, 56, 56, 56, 56,174, 87, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87, - 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, - 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 56, 87,175,175, 0, 1, 2, 2, 0, 1, 2, 2, - 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, - 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, - 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, - 11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 16, 17, 18, 18, - 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24, 21, 21, 21, 21, - 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21, 27, 27, 27, 27, - 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 21, 21, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 0, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, + 18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 25, 25, 26, 27, + 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31, + 31, 31, 31, 54, 55, 55, 56, 31, 31, 31, 31, 31, 31, 31, 57, 58, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 59, 60, 31, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 63, 64, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 65, 66, 67, 31, 31, 31, 31, 68, 31, 31, 31, 31, 31, + 31, 31, 31, 69, 70, 71, 17, 17, 72, 73, 31, 74, 75, 76, 31, 77, + 78, 31, 79, 80, 17, 81, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23, + 23, 23, 31, 31, 31, 31, 31, 31, 23, 82, 31, 31, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 83, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 84, 0, 0, 1, + 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 11, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27, + 28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, + 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46, + 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51, + 60, 61, 62, 63, 64, 65, 66, 7, 67, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 7, 4, 4, 4, 4, 77, 77, 77, 77, 78, 79, 80, 81, + 82, 83, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, + 0, 0, 0, 0, 86, 87, 88, 88, 89, 90, 48, 91, 0, 0, 92, 92, + 92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102, 0,103, + 104,105, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 0,106,106,106,106,106,106,106,106,106,106,106,107, + 108,108,108,108,108, 11,109,110,111, 4,112, 4,113,114,115,116, + 117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47, + 47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128, + 92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19, + 131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138, + 0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150, + 151,152,153,153,154,154,154,154,154,154, 4, 4,155,156,157,158, + 159,160,161,162,163,164,165,166,167,168,169,169,170,170,171,171, + 172,172,128,128, 19, 19,173,173,174,175,176,177,178,178,179,180, + 181,182,183,184,185,185,186,187,188,189,128,128,190,190,191,191, + 128,128,192,192,193,194,195,195,196,196,128,128,197,197,198,198, + 199,199,200,200,201,202,203,204,128,128,128,128,205,206,207,207, + 208,209,210,210,128,128,211,211,128,128,212, 34,213,213,213,213, + 213,213,213,213,213,213,213,213,213,213,128,128,128,128,128,128, + 128,128,214,214,215,215,215,215,215,215,215,215,215,215,128,128, + 128,128,128,128,216,216,216,216,216,216,216,216,216,216,128,128, + 128,128,128,128,110,110,110,110,110,110,110,110,110,217,218,219, + 220,220,220,220,221,221,221,221,222,222,222,223,224,224,224,224, + 224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,225, + 224,224,128,128,128,128,128,128,128,128,104,104,226,227,227,227, + 228,229,230,230,230,230,230,230,128,128,128,128,231,231,232, 0, + 128,128,128,128,128,128,128,128, 7,233, 0, 0, 0, 0, 0, 0, + 0,234,235, 0, 77, 77, 0, 0, 0, 0,128,128,236,236,236,236, + 236,236,236,236,236,236,236,236,128,128,128,128,128,128,128,128, + 4, 4,128,128, 86, 86,128,128,237,237,128,128,128,128,238,239, + 128,128,128,128,128,128,128,128,128,128, 48, 48,240,240,240,240, + 241,241,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19, + 128,128,128,128,242, 0,128,128, 0, 0, 0, 0, 92, 92,128,128, + 128,128,128,128, 92, 92, 92, 92, 92, 92,128,128, 0, 0,128,128, + 7, 7, 7, 7, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, + 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 12, 11, + 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, + 16, 17, 18, 18, 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24, + 21, 21, 21, 21, 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21, + 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 31, 21, 32, 32, 32, 32, 32, 33, 34, 32, 35, 35, 35, 35, - 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, - 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, - 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, - 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, - 43, 43, 43, 43, 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46, - 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, - 50, 50, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, + 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, + 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46, 47, 47, 47, 47, + 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, + 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 57, 57, 57, 57, 58, 57, 59, 59, 60, 61, - 62, 62, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 65, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 55, 55, 55, 55, 55, 67, 67, 67, 67, - 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 64, 64, 70, 70, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 8, 8, 8, 8, 8, 72, 72, 72, 72, + 62, 62, 63, 63, 64, 64, 64, 64, 65, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 55, 67, 67, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69, + 69, 69, 64, 64, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 8, 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, 76, 13, 50, 50, 50, 73, 77, 78, 79, 4, 4, 80, 4, - 4, 81, 82, 83, 4, 4, 4, 84, 8, 8, 8, 8, 11, 11, 11, 11, - 11, 11, 11, 11, 85, 0, 0, 0, 0, 0, 0, 86, 0, 4, 0, 0, - 0, 8, 8, 8, 0, 0, 87, 88, 89, 0, 4, 4, 6, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, 90, - 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 4, 4, 92, 92, 92, 92, - 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93, 53, 53, 53, 53, - 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 0, 95, 0, 96, 97, 98, 99, 99, 99, 99,100,101,102, - 102,102,102,103,104,104,104,105, 52, 52, 52, 52, 52, 0,104,104, - 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106, 0, 0, 0, 0, - 0,102,102,107,102,102,102,102,102,108, 0, 0, 94, 94, 94, 94, - 0, 0, 0, 0,109,109,109,109,109,109,109,109,109,109,109,109, - 109,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111, - 13, 13, 13, 13, 13, 13,112,112,112,112,112,112, 0, 0,113, 4, - 4, 4, 4, 4,114, 4, 4, 4, 4, 4, 4, 4,115,115,115, 0, - 116,116,116,116,117,117,117,117,117,117, 32, 32,118,118,119,120, - 120,120, 52, 52,121,121,121,121,122,121, 49, 49,123,123,123,123, - 123,123, 49, 49,124,124,124,124,124,124,125,125, 53, 53, 53, 4, - 4,126,127, 54, 54, 54, 54, 54,125,125,125,125,128,128,128,128, - 128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21,130, 21, 21, 21, 21, 8, 0,131, 0, - 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21,132, 0, 0, 1, 2, - 1, 2,133,101,102,134, 52, 52, 52, 52, 0, 0,135,135,135,135, - 135,135,135,135, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 11, 11, - 11, 0, 0,136,137,137,138,138,138,138,139, 0,140,140,140,141, - 141,142,142,142,143,143,144,144,144,144,144,144,145,145,145,145, - 145,146,146,146,147,147,147,148,148,148,148,148,149,149,149,150, - 150,150,150,151,151,151,151,151,151,151,151,151,152,152,152,152, - 152,152,152,152,153,153,153,153,154,154,155,155,156,156,156,156, - 156,156,157,157,158,158,159,159,159,159,159,159,160,160,161,161, - 161,161,161,161,162,162,162,162,162,162,163,163,164,164,164,164, - 165,165,165,165,166,166,166,166,167,167,168,168,169,169,169,169, - 169,169,169,169,170,170,170,170,170,170,170,170,171,171,171,171, - 171,171,171,171,172,172,172,172,172,172,172,172,173,173,173,173, - 173,173,173,173,174,174,174,175,175,175,175,176,176,176,176,177, - 177,177,178,178,179,179,179,179,179,179,179,179,180,180,180,180, - 180,181,181,181,182,182,182,182,182,183,183,183,184,184,184,184, - 184,184,185, 43,186,186,186,186,186,186,186,186,187,187,187,188, + 4, 81, 82, 83, 4, 4, 4, 84, 11, 11, 11, 11, 85, 0, 0, 0, + 0, 0, 0, 86, 0, 4, 0, 0, 0, 8, 8, 8, 0, 0, 87, 88, + 89, 0, 4, 4, 6, 0, 0, 0, 90, 90, 90, 90, 91, 91, 91, 91, + 91, 91, 4, 4, 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93, + 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 0, 95, 0, 96, 97, + 98, 99, 99, 99, 99,100,101,102,102,102,102,103,104,104,104,105, + 52, 0,104,104, 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106, + 0,102,102,107,102,102,102,102,102,108, 0, 0,109,109,109,109, + 109,110,110,110,111,111,111,111, 13, 13,112,112,112,112,112,112, + 0, 0,113, 4,114, 4, 4, 4,115,115,115, 0,116,116,116,116, + 117,117,117,117,117,117, 32, 32,118,118,119,120,120,120, 52, 52, + 121,121,121,121,122,121, 49, 49,123,123,123,123,123,123, 49, 49, + 124,124,124,124,124,124,125,125, 53, 53, 53, 4, 4,126,127, 54, + 125,125,125,125,128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21, + 21, 21, 21,130, 8, 0,131, 0, 0, 0, 0, 21, 21, 21, 21,132, + 0, 0, 1, 2, 1, 2,133,101,102,134, 52, 52,135,135,135,135, + 11, 0, 11, 11, 11, 0, 0,136,137,137,138,138,138,138,139, 0, + 140,140,140,141,141,142,142,142,143,143,144,144,144,144,144,144, + 145,145,145,145,145,146,146,146,147,147,147,148,148,148,148,148, + 149,149,149,150,150,150,150,151,151,151,151,151,152,152,152,152, + 153,153,153,153,154,154,155,155,156,156,156,156,156,156,157,157, + 158,158,159,159,159,159,159,159,160,160,161,161,161,161,161,161, + 162,162,162,162,162,162,163,163,164,164,164,164,165,165,165,165, + 166,166,166,166,167,167,168,168,169,169,169,169,170,170,170,170, + 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,175, + 175,175,175,176,176,176,176,177,177,177,178,178,179,179,179,179, + 180,180,180,180,180,181,181,181,182,182,182,182,182,183,183,183, + 184,184,184,184,184,184,185, 43,186,186,186,186,187,187,187,188, 188,188,188,188,189,189,189,190,189,189,189,189,191,191,191,191, - 191,191,191,191,192,192,192,192,192,192,192,192,193,193,193,193, - 193,193,193,193,194,194,194,194,194,194, 66, 66,195,195,195,195, - 195,195,195,195,196,196,196,196,196,196,196,196,197,197,197,197, - 197,197,197,197,198,198,198,198,198,198,198,198,199,199,199,199, - 199,199,199,199,200,200,200,200,200,200,200,200,201,201,201,201, - 201,202,202,202,202,202,202, 55,203,203,203,203,204,204,204,204, - 204,204,204,205,205,205,205,205,205,205,205,205,206,206,206,206, - 206,206,207,207,207,207,207,207,207,207,207,207,208,208,208,208, - 208,208,208,208,110,110,110,110, 39, 39, 39, 39,209,209,209,209, - 209,209,209,209,210,210,210,210,210,210,210,210,211,211,211,211, - 211,211,211,211,212,212,212,212,212,212,212,212,112,112,112,112, - 112,112,112,112,112,112,112,112,213,213,213,214,214,214,214,214, - 214,215,215,215,216,216,216,216,216,216,216,216,217,217,217,217, - 217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218, - 218,218,219, 94,220,220,220,220,220,220,220,220,221,221,221,221, - 221,221,221,221,102,102,102,102,102,102,102,102,222, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,102,102, - 102, 99,223,224,224,224,224,224,224,224,224,224,225,225,225,225, - 225,225,225,225,225,225, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, - 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,226,227,228, 0,229, 0, - 0, 0, 0, 0,230,230,230,230,230,230,230,230, 91, 91, 91, 91, - 91, 91, 91, 91,231,231,231,231,231,231,231,231,232,232,232,232, - 233,233,233,233,234,234,234,234,234,234,234,234,235,235,235,235, - 235,235,235,235,236, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, - 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, - 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, - 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, - 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14, - 16, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19, - 20, 21, 20, 22, 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7, - 7, 25, 20, 20, 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27, - 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, - 32, 20, 20, 20, 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33, - 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, - 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, - 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48, - 49, 49, 49, 49, 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53, - 53, 53, 54, 53, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, - 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62, - 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66, - 67, 67, 67, 67, 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71, - 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, - 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, - 80, 80, 80, 80, 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85, - 0, 84, 86, 0, 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2, - 2, 2, 92, 2, 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94, - 0, 95, 96, 0, 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97, - 98, 98, 98, 98, 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100, - 0,101, 0, 0,102,100,103,104, 0, 0,100, 0,105,106,106,106, - 106,106,106,106,106,106,107,105,108,109,109,109,109,109,109,109, - 109,109,110,108,111,111,111,111,112, 55, 55, 55, 55, 55, 55,113, - 109,109,109,110,109,109, 0, 0,114,114,114,114,115,115,115,115, - 116,116,116,116,117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2, - 118,118,118,118,119,119,119,119,120,120,120,120,121,121,121,121, - 121,121,121,122,123,123,123,123,124,124,124,124,124,124,124,125, - 126,126,126,126,127,127,127,127,128,128,128,128, 2, 2, 3, 2, - 2,129,130, 0,131,131,131,131,132, 17, 17, 18, 20, 20, 20,133, - 7, 7, 7,134, 20, 20, 20, 23, 0,135,109,109,109,109,109,136, - 137,137,137,137, 0, 0, 0,138,139,139,139,139,140,140,140,140, - 84, 0, 0, 0,141,141,141,141,142,142,142,142,143,143,143,143, - 144,144,144,144,145,145,145,145,146,146,146,146,147,147,147,147, - 148,148,148,148,149,149,149,149,150,150,150,150,151,151,151,151, - 152,152,152,152,153,153,153,153,154,154,154,154,155,155,155,155, - 156,156,156,156,157,157,157,157,158,158,158,158,159,159,159,159, - 160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163, - 164,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167, - 168,168,168,168,169,169,169,169,170,170,170,170,171,171,171,171, - 172,172,172,172,173,173,173,173,174,174,174,174,175,175,175,175, - 176,176,176,176,177,177,177,177,178,178,178,178,179,179,179,179, - 180,180,180,180,181,181,181,181,182,182,182,182,183,183,183,183, - 184,184,184,184,185,185,185,185,186, 45, 45, 45,187,187,187,187, - 188,188,188,188,189,189,189,189,190,190,190,190,190,190,191,190, - 192,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195, - 196,196,196,196,197,197,197,197,198,198,198,198,199,199,199,199, - 200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203, - 204,204,204,204,205,205,205,205,206,206,206,206,207,207,207,207, - 208,208,208,208,209,209,209,209,210,210,210,210,211,211,211,211, - 212,212,212,212,213,213,213,213,214,214,214,214,215,215,215,215, - 216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219, - 220,221,221,221,222,222,222,222,221,221,221,221,223,106,106,106, - 106,109,109,109,224,224,224,224,225,225,225,225, 0,226, 86, 0, - 0, 0,226, 7, 82,138, 7, 0, 0, 0,227, 86,228,228,228,228, - 229,229,229,229,230,230,230,230,231,231,231,231,232,232,232,232, - 233,233,233,233,234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, - 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, - 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, - 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, - 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3, - 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, - 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64, - 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7, - 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, - 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22, - 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36, - 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25, - 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8, - 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29, - 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0, - 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0, - 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0, - 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52, - 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62, - 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73, - 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, - 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, - 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, - 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, - 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13, - 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15, - 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0, - 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, - 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69, - 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0, - 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19, - 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, - 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, - 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, - 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, - 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135, - 106,106,106,106,104,104,104,104,161,161,161,161,110,110,110,110, - 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116, - 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, - 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117, - 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82, - 122,122,122,122, 89, 89, 89, 89,130,130,130,130,144,144,144,144, - 156,156,156,156,147,147,147,147,148,148,148,148,158,158,158,158, - 153,153,153,153,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85, - 101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100, - 100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109, - 107,107,107,107,107,107,107, 1,137,137,137,137,124,124,124,124, - 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126, - 142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150, - 141,141,141,141,140,140,140,140,121,121,121,121,133,133,133,133, - 134,134,134,134,138,138,138,138,143,143,143,143,145,145,145,145, - 63, 63, 63, 63,157,157,157,157, 80, 80, 80, 80,127,127,127,127, - 115,115,115,115,159,159,159,159,103,103,103,103,119,119,119,119, - 146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155, - 136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105, - 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,151,151,151,151, - 160,160,160,160,152,152,152,152,113,113,113,113,132,132,132,132, - 15, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, - 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, + 192,192,192,192,193,193,193,193,194,194,194,194,194,194, 66, 66, + 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198, + 199,199,199,199,200,200,200,200,201,201,201,201,201,202,202,202, + 202,202,202, 55,203,203,203,203,204,204,204,204,204,204,204,205, + 205,205,205,205,206,206,206,206,206,206,207,207,207,207,207,207, + 208,208,208,208,110,110,110,110,209,209,209,209,210,210,210,210, + 211,211,211,211,212,212,212,212,213,213,213,214,214,214,214,214, + 214,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218, + 218,218,219, 94,220,220,220,220,221,221,221,221,222, 99, 99, 99, + 99, 99, 99, 99, 99, 99,102,102,102, 99,223,224,224,224,224,224, + 225,225,225,225,225,225, 0, 0, 8, 0, 0, 0, 0, 0,226,227, + 228, 0,229, 0,230,230,230,230,231,231,231,231,232,232,232,232, + 233,233,233,233,234,234,234,234,235,235,235,235,236, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 4, 0, + 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, 2, 5, 6, 0, + 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, 8, 8, 8, 8, + 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14, 16, 17, 17, 17, + 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19, 20, 21, 20, 22, + 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7, 7, 25, 20, 20, + 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27, 28, 28, 28, 28, + 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 20, 20, 20, + 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33, 37, 37, 37, 37, + 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, + 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48, 49, 49, 49, 49, + 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 53, + 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, + 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62, 63, 63, 63, 63, + 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66, 67, 67, 67, 67, + 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, + 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76, + 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, 80, 80, 80, 80, + 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85, 0, 84, 86, 0, + 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2, 2, 2, 92, 2, + 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94, 0, 95, 96, 0, + 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97, 98, 98, 98, 98, + 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100, 0,101, 0, 0, + 102,100,103,104, 0, 0,100, 0,105,106,106,106,106,106,106,106, + 106,106,107,105,108,109,109,109,109,109,109,109,109,109,110,108, + 111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,109,109,109,110, + 109,109, 0, 0,114,114,114,114,115,115,115,115,116,116,116,116, + 117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,118,118,118,118, + 119,119,119,119,120,120,120,120,121,121,121,121,121,121,121,122, + 123,123,123,123,124,124,124,124,124,124,124,125,126,126,126,126, + 127,127,127,127,128,128,128,128, 2, 2, 3, 2, 2,129,130, 0, + 131,131,131,131,132, 17, 17, 18, 20, 20, 20,133, 7, 7, 7,134, + 20, 20, 20, 23, 0,135,109,109,109,109,109,136,137,137,137,137, + 0, 0, 0,138,139,139,139,139,140,140,140,140, 84, 0, 0, 0, + 141,141,141,141,142,142,142,142,143,143,143,143,144,144,144,144, + 145,145,145,145,146,146,146,146,147,147,147,147,148,148,148,148, + 149,149,149,149,150,150,150,150,151,151,151,151,152,152,152,152, + 153,153,153,153,154,154,154,154,155,155,155,155,156,156,156,156, + 157,157,157,157,158,158,158,158,159,159,159,159,160,160,160,160, + 161,161,161,161,162,162,162,162,163,163,163,163,164,164,164,164, + 165,165,165,165,166,166,166,166,167,167,167,167,168,168,168,168, + 169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172, + 173,173,173,173,174,174,174,174,175,175,175,175,176,176,176,176, + 177,177,177,177,178,178,178,178,179,179,179,179,180,180,180,180, + 181,181,181,181,182,182,182,182,183,183,183,183,184,184,184,184, + 185,185,185,185,186, 45, 45, 45,187,187,187,187,188,188,188,188, + 189,189,189,189,190,190,190,190,190,190,191,190,192,192,192,192, + 193,193,193,193,194,194,194,194,195,195,195,195,196,196,196,196, + 197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200, + 201,201,201,201,202,202,202,202,203,203,203,203,204,204,204,204, + 205,205,205,205,206,206,206,206,207,207,207,207,208,208,208,208, + 209,209,209,209,210,210,210,210,211,211,211,211,212,212,212,212, + 213,213,213,213,214,214,214,214,215,215,215,215,216,216,216,216, + 217,217,217,217,218,218,218,218,219,219,219,219,220,221,221,221, + 222,222,222,222,221,221,221,221,223,106,106,106,106,109,109,109, + 224,224,224,224,225,225,225,225, 0,226, 86, 0, 0, 0,226, 7, + 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,229,229,229,229, + 230,230,230,230,231,231,231,231,232,232,232,232,233,233,233,233, + 234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, 26, 26, + 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9, + 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, + 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 14, 14, 14, + 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3, + 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64, 90, 90, 90, 90, + 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, + 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 11, 11, 11, 11, + 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, + 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36, 24, 24, 24, 24, + 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25, 25, 0, 0, 0, + 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 0, + 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, + 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, + 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0, 43, 43, 43, 43, + 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0, 32, 0, 32, 32, + 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52, 58, 58, 58, 58, + 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62, 76, 76, 76, 76, + 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73, 1, 1, 1, 0, + 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19, + 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, 0, 0, 0, 19, + 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 56, 56, 56, 56, + 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13, 0, 13, 13, 13, + 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0, 39, 39, 39, 39, + 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 60, 60, 60, 60, + 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69, + 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0, 68, 68, 68, 68, + 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19, 19, 19, 0, 0, + 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, 1, 1, 6, 6, + 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, 0, 1, 1, 1, + 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, 41, 41, 41, 41, + 118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, 40, 40, 40, 40, + 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,106,106,106,106, + 104,104,104,104,161,161,161,161,110,110,110,110, 47, 47, 47, 47, + 81, 81, 81, 81,120,120,120,120,116,116,116,116,128,128,128,128, + 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97, + 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,112,112,112,112, + 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122, + 89, 89, 89, 89,130,130,130,130,144,144,144,144,156,156,156,156, + 147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153, + 149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, + 96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36, + 108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107, + 107,107,107, 1,137,137,137,137,124,124,124,124,123,123,123,123, + 114,114,114,114,102,102,102,102,126,126,126,126,142,142,142,142, + 125,125,125,125,154,154,154,154,150,150,150,150,141,141,141,141, + 140,140,140,140,121,121,121,121,133,133,133,133,134,134,134,134, + 138,138,138,138,143,143,143,143,145,145,145,145, 63, 63, 63, 63, + 157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115, + 159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146, + 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136, + 17, 15, 15, 15,139,139,139,139,105,105,105,105, 0, 0, 0, 1, + 0, 0, 1, 1,131,131,131,131,151,151,151,151,160,160,160,160, + 152,152,152,152,113,113,113,113,132,132,132,132, 15, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, + 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, - 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -6479,58 +5336,57 @@ _hb_ucd_u8[13602] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, - 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, - 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, + 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, + 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, - 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, - 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, - 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, + 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, + 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, - 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, + 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0, + 109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100, - 101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, - 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0, - 115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, + 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126, - 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129, + 130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145, + 146,147,148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158, + 159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0, + 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128,129,130,131,132,133,134,135,136,137,138,139,140,141, - 142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, - 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, - 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, + 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174, + 175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, + 191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0, - 0, 0,173,174,175,176,177,178,179,180,181,182,183,184,185,186, - 187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202, - 203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, - 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t _hb_ucd_u16[4888] = @@ -6843,21 +5699,14 @@ _hb_ucd_u16[4888] = 817, 818, 819, 820, 821, 935, 0, 0, }; static const int16_t -_hb_ucd_i16[196] = +_hb_ucd_i16[92] = { - 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, - 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, - 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, - -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, - 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, - 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, - 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, - 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, - 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, - -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, - 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, - -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, - -1, 0, 1, -1, + 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16, + 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914, + 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8, + -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0, + 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0, }; static inline uint_fast8_t @@ -6878,17 +5727,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7714+(((_hb_ucd_u8[7594+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7858+(((_hb_ucd_u8[7626+(((_hb_ucd_u8[7530+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918016u?_hb_ucd_u8[11480+(((_hb_ucd_u8[10532+(((_hb_ucd_u8[9124+(((_hb_ucd_u8[8500+(((_hb_ucd_u8[8050+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; + return u<918016u?_hb_ucd_u8[11124+(((_hb_ucd_u8[10176+(((_hb_ucd_u8[9204+(((_hb_ucd_u8[8524+(((_hb_ucd_u8[8220+(((_hb_ucd_u8[8106+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12802+(((_hb_ucd_u8[12420+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12446+(((_hb_ucd_u8[12064+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } #endif diff --git a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh index c216379201..036c71a424 100644 --- a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh +++ b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh @@ -24,42 +24,37 @@ #include "hb-unicode.hh" static const uint8_t -_hb_emoji_u8[544] = +_hb_emoji_u8[464] = { 16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,118,152, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 3, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 7, 8, - 0, 0, 0, 9, 0, 0, 10, 11, 12, 13, 14, 13, 15, 16, 17, 0, - 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0, - 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, - 13, 13, 13, 13, 23, 24, 25, 26, 27, 28, 13, 13, 13, 13, 13, 29, - 13, 13, 13, 13, 30, 31, 13, 13, 13, 32, 13, 13, 0, 33, 0, 34, - 35, 36, 37, 13, 38, 39, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 30, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, 0, 6, 0, 0, - 0, 0, 0, 12, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0,128, 0, 0, 0,254, 15, 7, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0,120, - 191,255,247,255,255,255,255,255,255,255,255,255,255,255,255,255, - 63, 0,255,255,255,255,255,255, 63,255, 87, 32, 2, 1, 24, 0, - 144, 80,184, 0,248, 0, 0, 0, 0, 0,224, 0, 2, 0, 1,128, - 0, 0, 0, 0, 0, 0, 48, 0,224, 0, 0, 24, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, - 0, 0,128, 2, 0, 0, 0, 0, 0,224, 0, 0, 0,128, 0, 0, - 0, 0, 0, 0, 0,240, 3,192, 0, 64,254, 7, 0,224,255,255, - 255,255,255,255, 63, 0, 0, 0,254,255, 0, 4, 0,128,252,247, - 0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 7, - 255,255,255,255,255,255,255, 63,192,255,255,255,255,255,255,255, - 255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255, - 0, 0,224,255,255,255,255,255, 0,240, 0, 0, 0, 0, 0, 0, - 0,255, 0,252, 0, 0, 0, 0, 0,255, 0, 0, 0,192,255,255, - 0,240,255,255,255,255,255,247,191,255,255,255,255,255,255,255, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 3, 4, 0, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, 12, + 0, 0, 13, 0, 0, 0, 14, 0, 15, 0, 0, 0, 0, 16, 0, 0, + 17, 17, 18, 19, 20, 17, 17, 21, 17, 17, 22, 17, 23, 17, 24, 25, + 26, 27, 28, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 29, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0, + 5, 6, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, 0, 0, 11, 0, + 0, 12, 13, 14, 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21, + 22, 23, 0, 0, 0, 24, 0, 0, 25, 0, 26, 0, 0, 27, 0, 0, + 28, 0, 0, 0, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33, + 34, 35, 36, 16, 16, 16, 16, 37, 16, 38, 39, 16, 16, 16, 40, 0, + 0, 0, 0, 41, 0, 0, 42, 16, 43, 0, 44, 0, 45, 46, 16, 16, + 47, 48, 49, 16, 16, 16, 16, 38, 0, 0, 0, 0, 0, 66, 0, 0, + 0, 0, 0, 16, 0, 2, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, + 0, 6, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0,128, 0, 0, + 0,254, 15, 7, 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, + 0, 0, 0,120,191,255,247,255,255,255,255,255, 63, 0,255,255, + 63,255, 87, 32, 2, 1, 24, 0,144, 80,184, 0,248, 0, 0, 0, + 0, 0,224, 0, 2, 0, 1,128, 0, 0, 48, 0,224, 0, 0, 24, + 0, 0, 33, 0, 0, 0, 1, 32, 0, 0,128, 2, 0,224, 0, 0, + 0,240, 3,192, 0, 64,254, 7, 0,224,255,255, 63, 0, 0, 0, + 254,255, 0, 4, 0,128,252,247, 0,254,255,255,255,255,255, 7, + 255,255,255, 63,192,255,255,255,255,255, 0, 0, 0, 0,240,255, + 0, 0,224,255, 0,240, 0, 0, 0,255, 0,252, 0,255, 0, 0, + 0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255, }; static inline unsigned @@ -75,7 +70,7 @@ _hb_emoji_b1 (const uint8_t* a, unsigned i) static inline uint_fast8_t _hb_emoji_is_Extended_Pictographic (unsigned u) { - return u<131070u?_hb_emoji_b1(224+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0; + return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0; } diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc index 05f74b9237..c1795dc7f2 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.cc +++ b/thirdparty/harfbuzz/src/hb-unicode.cc @@ -281,7 +281,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) * * Attaches a user-data key/data pair to the specified Unicode-functions structure. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -308,8 +308,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, * Since: 0.9.2 **/ void * -hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key) +hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key) { return hb_object_get_user_data (ufuncs, key); } @@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) * Tests whether the specified Unicode-functions structure * is immutable. * - * Return value: %true if @ufuncs is immutable, %false otherwise + * Return value: `true` if @ufuncs is immutable, `false` otherwise * * Since: 0.9.2 **/ @@ -421,7 +421,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * Calls the composition function of the specified * Unicode-functions structure @ufuncs. * - * Return value: %true if @a and @b composed, %false otherwise + * Return value: `true` if @a and @b composed, `false` otherwise * * Since: 0.9.2 **/ @@ -446,7 +446,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs, * Calls the decomposition function of the specified * Unicode-functions structure @ufuncs. * - * Return value: %true if @ab was decomposed, %false otherwise + * Return value: `true` if @ab was decomposed, `false` otherwise * * Since: 0.9.2 **/ diff --git a/thirdparty/harfbuzz/src/hb-unicode.h b/thirdparty/harfbuzz/src/hb-unicode.h index c04ee15a09..faa8d67924 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.h +++ b/thirdparty/harfbuzz/src/hb-unicode.h @@ -317,8 +317,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, HB_EXTERN void * -hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key); +hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key); HB_EXTERN void @@ -429,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs, * The method must return an #hb_bool_t indicating the success * of the composition. * - * Return value: %true is @a,@b composed, %false otherwise + * Return value: `true` is @a,@b composed, `false` otherwise * **/ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs, @@ -453,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs, * output parameters (if successful). The method must return an * #hb_bool_t indicating the success of the composition. * - * Return value: %true if @ab decomposed, %false otherwise + * Return value: `true` if @ab decomposed, `false` otherwise * **/ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index 7b08e3b4d2..a6d9f6b3fb 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -43,7 +43,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type; hb_vector_t () = default; - hb_vector_t (std::nullptr_t) : hb_vector_t () {} hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t () { alloc (lst.size ()); diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index f036a12226..a1586a58b6 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -41,26 +41,26 @@ HB_BEGIN_DECLS * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 4 +#define HB_VERSION_MAJOR 5 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 4 +#define HB_VERSION_MINOR 1 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 1 +#define HB_VERSION_MICRO 0 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "4.4.1" +#define HB_VERSION_STRING "5.1.0" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/icu4c/godot_data.json b/thirdparty/icu4c/godot_data.json index 3a9c28af4c..e36e2b078b 100644 --- a/thirdparty/icu4c/godot_data.json +++ b/thirdparty/icu4c/godot_data.json @@ -6,5 +6,6 @@ brkitr_tree: include misc: include normalization: include + confusables: include } -}
\ No newline at end of file +} diff --git a/thirdparty/icu4c/i18n/scriptset.cpp b/thirdparty/icu4c/i18n/scriptset.cpp new file mode 100644 index 0000000000..6a1db8c01c --- /dev/null +++ b/thirdparty/icu4c/i18n/scriptset.cpp @@ -0,0 +1,313 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (C) 2014, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +* +* scriptset.cpp +* +* created on: 2013 Jan 7 +* created by: Andy Heninger +*/ + +#include "unicode/utypes.h" + +#include "unicode/uchar.h" +#include "unicode/unistr.h" + +#include "scriptset.h" +#include "uassert.h" +#include "cmemory.h" + +U_NAMESPACE_BEGIN + +//---------------------------------------------------------------------------- +// +// ScriptSet implementation +// +//---------------------------------------------------------------------------- +ScriptSet::ScriptSet() { + uprv_memset(bits, 0, sizeof(bits)); +} + +ScriptSet::~ScriptSet() { +} + +ScriptSet::ScriptSet(const ScriptSet &other) { + *this = other; +} + +ScriptSet & ScriptSet::operator =(const ScriptSet &other) { + uprv_memcpy(bits, other.bits, sizeof(bits)); + return *this; +} + +bool ScriptSet::operator == (const ScriptSet &other) const { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + if (bits[i] != other.bits[i]) { + return false; + } + } + return true; +} + +UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const { + if (U_FAILURE(status)) { + return FALSE; + } + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + uint32_t index = script / 32; + uint32_t bit = 1 << (script & 31); + return ((bits[index] & bit) != 0); +} + + +ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) { + if (U_FAILURE(status)) { + return *this; + } + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return *this; + } + uint32_t index = script / 32; + uint32_t bit = 1 << (script & 31); + bits[index] |= bit; + return *this; +} + +ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) { + if (U_FAILURE(status)) { + return *this; + } + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return *this; + } + uint32_t index = script / 32; + uint32_t bit = 1 << (script & 31); + bits[index] &= ~bit; + return *this; +} + + + +ScriptSet &ScriptSet::Union(const ScriptSet &other) { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + bits[i] |= other.bits[i]; + } + return *this; +} + +ScriptSet &ScriptSet::intersect(const ScriptSet &other) { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + bits[i] &= other.bits[i]; + } + return *this; +} + +ScriptSet &ScriptSet::intersect(UScriptCode script, UErrorCode &status) { + ScriptSet t; + t.set(script, status); + if (U_SUCCESS(status)) { + this->intersect(t); + } + return *this; +} + +UBool ScriptSet::intersects(const ScriptSet &other) const { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + if ((bits[i] & other.bits[i]) != 0) { + return true; + } + } + return false; +} + +UBool ScriptSet::contains(const ScriptSet &other) const { + ScriptSet t(*this); + t.intersect(other); + return (t == other); +} + + +ScriptSet &ScriptSet::setAll() { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + bits[i] = 0xffffffffu; + } + return *this; +} + + +ScriptSet &ScriptSet::resetAll() { + uprv_memset(bits, 0, sizeof(bits)); + return *this; +} + +int32_t ScriptSet::countMembers() const { + // This bit counter is good for sparse numbers of '1's, which is + // very much the case that we will usually have. + int32_t count = 0; + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + uint32_t x = bits[i]; + while (x > 0) { + count++; + x &= (x - 1); // and off the least significant one bit. + } + } + return count; +} + +int32_t ScriptSet::hashCode() const { + int32_t hash = 0; + for (int32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + hash ^= bits[i]; + } + return hash; +} + +int32_t ScriptSet::nextSetBit(int32_t fromIndex) const { + // TODO: Wants a better implementation. + if (fromIndex < 0) { + return -1; + } + UErrorCode status = U_ZERO_ERROR; + for (int32_t scriptIndex = fromIndex; scriptIndex < SCRIPT_LIMIT; scriptIndex++) { + if (test((UScriptCode)scriptIndex, status)) { + return scriptIndex; + } + } + return -1; +} + +UBool ScriptSet::isEmpty() const { + for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) { + if (bits[i] != 0) { + return FALSE; + } + } + return TRUE; +} + +UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const { + UBool firstTime = TRUE; + for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) { + if (!firstTime) { + dest.append((UChar)0x20); + } + firstTime = FALSE; + const char *scriptName = uscript_getShortName((UScriptCode(i))); + dest.append(UnicodeString(scriptName, -1, US_INV)); + } + return dest; +} + +ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode &status) { + resetAll(); + if (U_FAILURE(status)) { + return *this; + } + UnicodeString oneScriptName; + for (int32_t i=0; i<scriptString.length();) { + UChar32 c = scriptString.char32At(i); + i = scriptString.moveIndex32(i, 1); + if (!u_isUWhiteSpace(c)) { + oneScriptName.append(c); + if (i < scriptString.length()) { + continue; + } + } + if (oneScriptName.length() > 0) { + char buf[40]; + oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INV); + buf[sizeof(buf)-1] = 0; + int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf); + if (sc == UCHAR_INVALID_CODE) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } else { + this->set((UScriptCode)sc, status); + } + if (U_FAILURE(status)) { + return *this; + } + oneScriptName.remove(); + } + } + return *this; +} + +void ScriptSet::setScriptExtensions(UChar32 codePoint, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + static const int32_t FIRST_GUESS_SCRIPT_CAPACITY = 20; + MaybeStackArray<UScriptCode,FIRST_GUESS_SCRIPT_CAPACITY> scripts; + UErrorCode internalStatus = U_ZERO_ERROR; + int32_t script_count = -1; + + while (TRUE) { + script_count = uscript_getScriptExtensions( + codePoint, scripts.getAlias(), scripts.getCapacity(), &internalStatus); + if (internalStatus == U_BUFFER_OVERFLOW_ERROR) { + // Need to allocate more space + if (scripts.resize(script_count) == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + internalStatus = U_ZERO_ERROR; + } else { + break; + } + } + + // Check if we failed for some reason other than buffer overflow + if (U_FAILURE(internalStatus)) { + status = internalStatus; + return; + } + + // Load the scripts into the ScriptSet and return + for (int32_t i = 0; i < script_count; i++) { + this->set(scripts[i], status); + if (U_FAILURE(status)) { return; } + } +} + +U_NAMESPACE_END + +U_CAPI UBool U_EXPORT2 +uhash_equalsScriptSet(const UElement key1, const UElement key2) { + icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer); + icu::ScriptSet *s2 = static_cast<icu::ScriptSet *>(key2.pointer); + return (*s1 == *s2); +} + +U_CAPI int8_t U_EXPORT2 +uhash_compareScriptSet(UElement key0, UElement key1) { + icu::ScriptSet *s0 = static_cast<icu::ScriptSet *>(key0.pointer); + icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer); + int32_t diff = s0->countMembers() - s1->countMembers(); + if (diff != 0) return static_cast<UBool>(diff); + int32_t i0 = s0->nextSetBit(0); + int32_t i1 = s1->nextSetBit(0); + while ((diff = i0-i1) == 0 && i0 > 0) { + i0 = s0->nextSetBit(i0+1); + i1 = s1->nextSetBit(i1+1); + } + return (int8_t)diff; +} + +U_CAPI int32_t U_EXPORT2 +uhash_hashScriptSet(const UElement key) { + icu::ScriptSet *s = static_cast<icu::ScriptSet *>(key.pointer); + return s->hashCode(); +} + +U_CAPI void U_EXPORT2 +uhash_deleteScriptSet(void *obj) { + icu::ScriptSet *s = static_cast<icu::ScriptSet *>(obj); + delete s; +} diff --git a/thirdparty/icu4c/i18n/scriptset.h b/thirdparty/icu4c/i18n/scriptset.h new file mode 100644 index 0000000000..51980ab7b3 --- /dev/null +++ b/thirdparty/icu4c/i18n/scriptset.h @@ -0,0 +1,86 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (C) 2013, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +* +* scriptset.h +* +* created on: 2013 Jan 7 +* created by: Andy Heninger +*/ + +#ifndef __SCRIPTSET_H__ +#define __SCRIPTSET_H__ + +#include "unicode/utypes.h" +#include "unicode/uobject.h" +#include "unicode/uscript.h" + +#include "uelement.h" + +U_NAMESPACE_BEGIN + +//------------------------------------------------------------------------------- +// +// ScriptSet - A bit set representing a set of scripts. +// +// This class was originally used exclusively with script sets appearing +// as part of the spoof check whole script confusable binary data. Its +// use has since become more general, but the continued use to wrap +// prebuilt binary data does constrain the design. +// +//------------------------------------------------------------------------------- +class U_I18N_API ScriptSet: public UMemory { + public: + static constexpr int32_t SCRIPT_LIMIT = 224; // multiple of 32! + + ScriptSet(); + ScriptSet(const ScriptSet &other); + ~ScriptSet(); + + bool operator == (const ScriptSet &other) const; + bool operator != (const ScriptSet &other) const {return !(*this == other);} + ScriptSet & operator = (const ScriptSet &other); + + UBool test(UScriptCode script, UErrorCode &status) const; + ScriptSet &Union(const ScriptSet &other); + ScriptSet &set(UScriptCode script, UErrorCode &status); + ScriptSet &reset(UScriptCode script, UErrorCode &status); + ScriptSet &intersect(const ScriptSet &other); + ScriptSet &intersect(UScriptCode script, UErrorCode &status); + UBool intersects(const ScriptSet &other) const; // Sets contain at least one script in common. + UBool contains(const ScriptSet &other) const; // All set bits in other are also set in this. + + ScriptSet &setAll(); + ScriptSet &resetAll(); + int32_t countMembers() const; + int32_t hashCode() const; + int32_t nextSetBit(int32_t script) const; + + UBool isEmpty() const; + + UnicodeString &displayScripts(UnicodeString &dest) const; // append script names to dest string. + ScriptSet & parseScripts(const UnicodeString &scriptsString, UErrorCode &status); // Replaces ScriptSet contents. + + // Wraps around UScript::getScriptExtensions() and adds the corresponding scripts to this instance. + void setScriptExtensions(UChar32 codePoint, UErrorCode& status); + + private: + uint32_t bits[SCRIPT_LIMIT / 32]; +}; + +U_NAMESPACE_END + +U_CAPI UBool U_EXPORT2 +uhash_compareScriptSet(const UElement key1, const UElement key2); + +U_CAPI int32_t U_EXPORT2 +uhash_hashScriptSet(const UElement key); + +U_CAPI void U_EXPORT2 +uhash_deleteScriptSet(void *obj); + +#endif // __SCRIPTSET_H__ diff --git a/thirdparty/icu4c/i18n/ucln_in.cpp b/thirdparty/icu4c/i18n/ucln_in.cpp new file mode 100644 index 0000000000..f29cbe41dd --- /dev/null +++ b/thirdparty/icu4c/i18n/ucln_in.cpp @@ -0,0 +1,65 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +****************************************************************************** +* * +* Copyright (C) 2001-2014, International Business Machines * +* Corporation and others. All Rights Reserved. * +* * +****************************************************************************** +* file name: ucln_in.cpp +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2001July05 +* created by: George Rhoten +*/ + +#include "ucln.h" +#include "ucln_in.h" +#include "mutex.h" +#include "uassert.h" + +/** Auto-client for UCLN_I18N **/ +#define UCLN_TYPE UCLN_I18N +#include "ucln_imp.h" + +/* Leave this copyright notice here! It needs to go somewhere in this library. */ +static const char copyright[] = U_COPYRIGHT_STRING; + +static cleanupFunc *gCleanupFunctions[UCLN_I18N_COUNT]; + +static UBool U_CALLCONV i18n_cleanup(void) +{ + int32_t libType = UCLN_I18N_START; + (void)copyright; /* Suppress unused variable warning with clang. */ + + while (++libType<UCLN_I18N_COUNT) { + if (gCleanupFunctions[libType]) + { + gCleanupFunctions[libType](); + gCleanupFunctions[libType] = NULL; + } + } +#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) + ucln_unRegisterAutomaticCleanup(); +#endif + return TRUE; +} + +void ucln_i18n_registerCleanup(ECleanupI18NType type, + cleanupFunc *func) { + U_ASSERT(UCLN_I18N_START < type && type < UCLN_I18N_COUNT); + { + icu::Mutex m; // See ticket 10295 for discussion. + ucln_registerCleanup(UCLN_I18N, i18n_cleanup); + if (UCLN_I18N_START < type && type < UCLN_I18N_COUNT) { + gCleanupFunctions[type] = func; + } + } +#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) + ucln_registerAutomaticCleanup(); +#endif +} + diff --git a/thirdparty/icu4c/i18n/ucln_in.h b/thirdparty/icu4c/i18n/ucln_in.h new file mode 100644 index 0000000000..765cdd559f --- /dev/null +++ b/thirdparty/icu4c/i18n/ucln_in.h @@ -0,0 +1,74 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +****************************************************************************** +* Copyright (C) 2001-2016, International Business Machines +* Corporation and others. All Rights Reserved. +****************************************************************************** +* file name: ucln_in.h +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2001July05 +* created by: George Rhoten +*/ + +#ifndef __UCLN_IN_H__ +#define __UCLN_IN_H__ + +#include "unicode/utypes.h" +#include "ucln.h" + +/* +Please keep the order of enums declared in same order +as the functions are suppose to be called. +It's usually best to have child dependencies called first. */ +typedef enum ECleanupI18NType { + UCLN_I18N_START = -1, + UCLN_I18N_UNIT_EXTRAS, + UCLN_I18N_NUMBER_SKELETONS, + UCLN_I18N_CURRENCY_SPACING, + UCLN_I18N_SPOOF, + UCLN_I18N_SPOOFDATA, + UCLN_I18N_TRANSLITERATOR, + UCLN_I18N_REGEX, + UCLN_I18N_JAPANESE_CALENDAR, + UCLN_I18N_ISLAMIC_CALENDAR, + UCLN_I18N_CHINESE_CALENDAR, + UCLN_I18N_HEBREW_CALENDAR, + UCLN_I18N_ASTRO_CALENDAR, + UCLN_I18N_DANGI_CALENDAR, + UCLN_I18N_CALENDAR, + UCLN_I18N_TIMEZONEFORMAT, + UCLN_I18N_TZDBTIMEZONENAMES, + UCLN_I18N_TIMEZONEGENERICNAMES, + UCLN_I18N_TIMEZONENAMES, + UCLN_I18N_ZONEMETA, + UCLN_I18N_TIMEZONE, + UCLN_I18N_DIGITLIST, + UCLN_I18N_DECFMT, + UCLN_I18N_NUMFMT, + UCLN_I18N_ALLOWED_HOUR_FORMATS, + UCLN_I18N_DAYPERIODRULES, + UCLN_I18N_SMPDTFMT, + UCLN_I18N_USEARCH, + UCLN_I18N_COLLATOR, + UCLN_I18N_UCOL_RES, + UCLN_I18N_CSDET, + UCLN_I18N_COLLATION_ROOT, + UCLN_I18N_GENDERINFO, + UCLN_I18N_CDFINFO, + UCLN_I18N_REGION, + UCLN_I18N_LIST_FORMATTER, + UCLN_I18N_NUMSYS, + UCLN_I18N_COUNT /* This must be last */ +} ECleanupI18NType; + +/* Main library cleanup registration function. */ +/* See common/ucln.h for details on adding a cleanup function. */ +/* Note: the global mutex must not be held when calling this function. */ +U_CFUNC void U_EXPORT2 ucln_i18n_registerCleanup(ECleanupI18NType type, + cleanupFunc *func); + +#endif diff --git a/thirdparty/icu4c/i18n/unicode/uspoof.h b/thirdparty/icu4c/i18n/unicode/uspoof.h new file mode 100644 index 0000000000..b674c91b2c --- /dev/null +++ b/thirdparty/icu4c/i18n/unicode/uspoof.h @@ -0,0 +1,1577 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +*************************************************************************** +* Copyright (C) 2008-2016, International Business Machines Corporation +* and others. All Rights Reserved. +*************************************************************************** +* file name: uspoof.h +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2008Feb13 +* created by: Andy Heninger +* +* Unicode Spoof Detection +*/ + +#ifndef USPOOF_H +#define USPOOF_H + +#include "unicode/utypes.h" +#include "unicode/uset.h" +#include "unicode/parseerr.h" + +#if !UCONFIG_NO_NORMALIZATION + + +#if U_SHOW_CPLUSPLUS_API +#include "unicode/localpointer.h" +#include "unicode/unistr.h" +#include "unicode/uniset.h" +#endif + + +/** + * \file + * \brief Unicode Security and Spoofing Detection, C API. + * + * <p> + * This class, based on <a href="http://unicode.org/reports/tr36">Unicode Technical Report #36</a> and + * <a href="http://unicode.org/reports/tr39">Unicode Technical Standard #39</a>, has two main functions: + * + * <ol> + * <li>Checking whether two strings are visually <em>confusable</em> with each other, such as "Harvest" and + * "Ηarvest", where the second string starts with the Greek capital letter Eta.</li> + * <li>Checking whether an individual string is likely to be an attempt at confusing the reader (<em>spoof + * detection</em>), such as "paypal" with some Latin characters substituted with Cyrillic look-alikes.</li> + * </ol> + * + * <p> + * Although originally designed as a method for flagging suspicious identifier strings such as URLs, + * <code>USpoofChecker</code> has a number of other practical use cases, such as preventing attempts to evade bad-word + * content filters. + * + * <p> + * The functions of this class are exposed as C API, with a handful of syntactical conveniences for C++. + * + * <h2>Confusables</h2> + * + * <p> + * The following example shows how to use <code>USpoofChecker</code> to check for confusability between two strings: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * UChar* str1 = (UChar*) u"Harvest"; + * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status); + * + * int32_t bitmask = uspoof_areConfusable(sc, str1, -1, str2, -1, &status); + * UBool result = bitmask != 0; + * // areConfusable: 1 (status: U_ZERO_ERROR) + * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status)); + * uspoof_close(sc); + * \endcode + * + * <p> + * The call to {@link uspoof_open} creates a <code>USpoofChecker</code> object; the call to {@link uspoof_setChecks} + * enables confusable checking and disables all other checks; the call to {@link uspoof_areConfusable} performs the + * confusability test; and the following line extracts the result out of the return value. For best performance, + * the instance should be created once (e.g., upon application startup), and the efficient + * {@link uspoof_areConfusable} method can be used at runtime. + * + * <p> + * The type {@link LocalUSpoofCheckerPointer} is exposed for C++ programmers. It will automatically call + * {@link uspoof_close} when the object goes out of scope: + * + * \code{.cpp} + * UErrorCode status = U_ZERO_ERROR; + * LocalUSpoofCheckerPointer sc(uspoof_open(&status)); + * uspoof_setChecks(sc.getAlias(), USPOOF_CONFUSABLE, &status); + * // ... + * \endcode + * + * UTS 39 defines two strings to be <em>confusable</em> if they map to the same <em>skeleton string</em>. A skeleton can + * be thought of as a "hash code". {@link uspoof_getSkeleton} computes the skeleton for a particular string, so + * the following snippet is equivalent to the example above: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * UChar* str1 = (UChar*) u"Harvest"; + * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status); + * + * // Get skeleton 1 + * int32_t skel1Len = uspoof_getSkeleton(sc, 0, str1, -1, NULL, 0, &status); + * UChar* skel1 = (UChar*) malloc(++skel1Len * sizeof(UChar)); + * status = U_ZERO_ERROR; + * uspoof_getSkeleton(sc, 0, str1, -1, skel1, skel1Len, &status); + * + * // Get skeleton 2 + * int32_t skel2Len = uspoof_getSkeleton(sc, 0, str2, -1, NULL, 0, &status); + * UChar* skel2 = (UChar*) malloc(++skel2Len * sizeof(UChar)); + * status = U_ZERO_ERROR; + * uspoof_getSkeleton(sc, 0, str2, -1, skel2, skel2Len, &status); + * + * // Are the skeletons the same? + * UBool result = u_strcmp(skel1, skel2) == 0; + * // areConfusable: 1 (status: U_ZERO_ERROR) + * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status)); + * uspoof_close(sc); + * free(skel1); + * free(skel2); + * \endcode + * + * If you need to check if a string is confusable with any string in a dictionary of many strings, rather than calling + * {@link uspoof_areConfusable} many times in a loop, {@link uspoof_getSkeleton} can be used instead, as shown below: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * #define DICTIONARY_LENGTH 2 + * UChar* dictionary[DICTIONARY_LENGTH] = { (UChar*) u"lorem", (UChar*) u"ipsum" }; + * UChar* skeletons[DICTIONARY_LENGTH]; + * UChar* str = (UChar*) u"1orern"; + * + * // Setup: + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status); + * for (size_t i=0; i<DICTIONARY_LENGTH; i++) { + * UChar* word = dictionary[i]; + * int32_t len = uspoof_getSkeleton(sc, 0, word, -1, NULL, 0, &status); + * skeletons[i] = (UChar*) malloc(++len * sizeof(UChar)); + * status = U_ZERO_ERROR; + * uspoof_getSkeleton(sc, 0, word, -1, skeletons[i], len, &status); + * } + * + * // Live Check: + * { + * int32_t len = uspoof_getSkeleton(sc, 0, str, -1, NULL, 0, &status); + * UChar* skel = (UChar*) malloc(++len * sizeof(UChar)); + * status = U_ZERO_ERROR; + * uspoof_getSkeleton(sc, 0, str, -1, skel, len, &status); + * UBool result = false; + * for (size_t i=0; i<DICTIONARY_LENGTH; i++) { + * result = u_strcmp(skel, skeletons[i]) == 0; + * if (result == true) { break; } + * } + * // Has confusable in dictionary: 1 (status: U_ZERO_ERROR) + * printf("Has confusable in dictionary: %d (status: %s)\n", result, u_errorName(status)); + * free(skel); + * } + * + * for (size_t i=0; i<DICTIONARY_LENGTH; i++) { + * free(skeletons[i]); + * } + * uspoof_close(sc); + * \endcode + * + * <b>Note:</b> Since the Unicode confusables mapping table is frequently updated, confusable skeletons are <em>not</em> + * guaranteed to be the same between ICU releases. We therefore recommend that you always compute confusable skeletons + * at runtime and do not rely on creating a permanent, or difficult to update, database of skeletons. + * + * <h2>Spoof Detection</h2> + * + * The following snippet shows a minimal example of using <code>USpoofChecker</code> to perform spoof detection on a + * string: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A + * + * // Get the default set of allowable characters: + * USet* allowed = uset_openEmpty(); + * uset_addAll(allowed, uspoof_getRecommendedSet(&status)); + * uset_addAll(allowed, uspoof_getInclusionSet(&status)); + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setAllowedChars(sc, allowed, &status); + * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE); + * + * int32_t bitmask = uspoof_check(sc, str, -1, NULL, &status); + * UBool result = bitmask != 0; + * // fails checks: 1 (status: U_ZERO_ERROR) + * printf("fails checks: %d (status: %s)\n", result, u_errorName(status)); + * uspoof_close(sc); + * uset_close(allowed); + * \endcode + * + * As in the case for confusability checking, it is good practice to create one <code>USpoofChecker</code> instance at + * startup, and call the cheaper {@link uspoof_check} online. We specify the set of + * allowed characters to be those with type RECOMMENDED or INCLUSION, according to the recommendation in UTS 39. + * + * In addition to {@link uspoof_check}, the function {@link uspoof_checkUTF8} is exposed for UTF8-encoded char* strings, + * and {@link uspoof_checkUnicodeString} is exposed for C++ programmers. + * + * If the {@link USPOOF_AUX_INFO} check is enabled, a limited amount of information on why a string failed the checks + * is available in the returned bitmask. For complete information, use the {@link uspoof_check2} class of functions + * with a {@link USpoofCheckResult} parameter: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A + * + * // Get the default set of allowable characters: + * USet* allowed = uset_openEmpty(); + * uset_addAll(allowed, uspoof_getRecommendedSet(&status)); + * uset_addAll(allowed, uspoof_getInclusionSet(&status)); + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setAllowedChars(sc, allowed, &status); + * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE); + * + * USpoofCheckResult* checkResult = uspoof_openCheckResult(&status); + * int32_t bitmask = uspoof_check2(sc, str, -1, checkResult, &status); + * + * int32_t failures1 = bitmask; + * int32_t failures2 = uspoof_getCheckResultChecks(checkResult, &status); + * assert(failures1 == failures2); + * // checks that failed: 0x00000010 (status: U_ZERO_ERROR) + * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status)); + * + * // Cleanup: + * uspoof_close(sc); + * uset_close(allowed); + * uspoof_closeCheckResult(checkResult); + * \endcode + * + * C++ users can take advantage of a few syntactical conveniences. The following snippet is functionally + * equivalent to the one above: + * + * \code{.cpp} + * UErrorCode status = U_ZERO_ERROR; + * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A + * + * // Get the default set of allowable characters: + * UnicodeSet allowed; + * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status)); + * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status)); + * + * LocalUSpoofCheckerPointer sc(uspoof_open(&status)); + * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status); + * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE); + * + * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status)); + * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status); + * + * int32_t failures1 = bitmask; + * int32_t failures2 = uspoof_getCheckResultChecks(checkResult.getAlias(), &status); + * assert(failures1 == failures2); + * // checks that failed: 0x00000010 (status: U_ZERO_ERROR) + * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status)); + * + * // Explicit cleanup not necessary. + * \endcode + * + * The return value is a bitmask of the checks that failed. In this case, there was one check that failed: + * {@link USPOOF_RESTRICTION_LEVEL}, corresponding to the fifth bit (16). The possible checks are: + * + * <ul> + * <li><code>RESTRICTION_LEVEL</code>: flags strings that violate the + * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">Restriction Level</a> test as specified in UTS + * 39; in most cases, this means flagging strings that contain characters from multiple different scripts.</li> + * <li><code>INVISIBLE</code>: flags strings that contain invisible characters, such as zero-width spaces, or character + * sequences that are likely not to display, such as multiple occurrences of the same non-spacing mark.</li> + * <li><code>CHAR_LIMIT</code>: flags strings that contain characters outside of a specified set of acceptable + * characters. See {@link uspoof_setAllowedChars} and {@link uspoof_setAllowedLocales}.</li> + * <li><code>MIXED_NUMBERS</code>: flags strings that contain digits from multiple different numbering systems.</li> + * </ul> + * + * <p> + * These checks can be enabled independently of each other. For example, if you were interested in checking for only the + * INVISIBLE and MIXED_NUMBERS conditions, you could do: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * UChar* str = (UChar*) u"8\u09EA"; // 8 mixed with U+09EA BENGALI DIGIT FOUR + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setChecks(sc, USPOOF_INVISIBLE | USPOOF_MIXED_NUMBERS, &status); + * + * int32_t bitmask = uspoof_check2(sc, str, -1, NULL, &status); + * UBool result = bitmask != 0; + * // fails checks: 1 (status: U_ZERO_ERROR) + * printf("fails checks: %d (status: %s)\n", result, u_errorName(status)); + * uspoof_close(sc); + * \endcode + * + * Here is an example in C++ showing how to compute the restriction level of a string: + * + * \code{.cpp} + * UErrorCode status = U_ZERO_ERROR; + * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A + * + * // Get the default set of allowable characters: + * UnicodeSet allowed; + * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status)); + * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status)); + * + * LocalUSpoofCheckerPointer sc(uspoof_open(&status)); + * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status); + * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE); + * uspoof_setChecks(sc.getAlias(), USPOOF_RESTRICTION_LEVEL | USPOOF_AUX_INFO, &status); + * + * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status)); + * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status); + * + * URestrictionLevel restrictionLevel = uspoof_getCheckResultRestrictionLevel(checkResult.getAlias(), &status); + * // Since USPOOF_AUX_INFO was enabled, the restriction level is also available in the upper bits of the bitmask: + * assert((restrictionLevel & bitmask) == restrictionLevel); + * // Restriction level: 0x50000000 (status: U_ZERO_ERROR) + * printf("Restriction level: %#010x (status: %s)\n", restrictionLevel, u_errorName(status)); + * \endcode + * + * The code '0x50000000' corresponds to the restriction level USPOOF_MINIMALLY_RESTRICTIVE. Since + * USPOOF_MINIMALLY_RESTRICTIVE is weaker than USPOOF_MODERATELY_RESTRICTIVE, the string fails the check. + * + * <b>Note:</b> The Restriction Level is the most powerful of the checks. The full logic is documented in + * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">UTS 39</a>, but the basic idea is that strings + * are restricted to contain characters from only a single script, <em>except</em> that most scripts are allowed to have + * Latin characters interspersed. Although the default restriction level is <code>HIGHLY_RESTRICTIVE</code>, it is + * recommended that users set their restriction level to <code>MODERATELY_RESTRICTIVE</code>, which allows Latin mixed + * with all other scripts except Cyrillic, Greek, and Cherokee, with which it is often confusable. For more details on + * the levels, see UTS 39 or {@link URestrictionLevel}. The Restriction Level test is aware of the set of + * allowed characters set in {@link uspoof_setAllowedChars}. Note that characters which have script code + * COMMON or INHERITED, such as numbers and punctuation, are ignored when computing whether a string has multiple + * scripts. + * + * <h2>Additional Information</h2> + * + * A <code>USpoofChecker</code> instance may be used repeatedly to perform checks on any number of identifiers. + * + * <b>Thread Safety:</b> The test functions for checking a single identifier, or for testing whether + * two identifiers are possible confusable, are thread safe. They may called concurrently, from multiple threads, + * using the same USpoofChecker instance. + * + * More generally, the standard ICU thread safety rules apply: functions that take a const USpoofChecker parameter are + * thread safe. Those that take a non-const USpoofChecker are not thread safe.. + * + * @stable ICU 4.6 + */ + +U_CDECL_BEGIN + +struct USpoofChecker; +/** + * @stable ICU 4.2 + */ +typedef struct USpoofChecker USpoofChecker; /**< typedef for C of USpoofChecker */ + +struct USpoofCheckResult; +/** + * @see uspoof_openCheckResult + * @stable ICU 58 + */ +typedef struct USpoofCheckResult USpoofCheckResult; + +/** + * Enum for the kinds of checks that USpoofChecker can perform. + * These enum values are used both to select the set of checks that + * will be performed, and to report results from the check function. + * + * @stable ICU 4.2 + */ +typedef enum USpoofChecks { + /** + * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates + * that the two strings are visually confusable and that they are from the same script, according to UTS 39 section + * 4. + * + * @see uspoof_areConfusable + * @stable ICU 4.2 + */ + USPOOF_SINGLE_SCRIPT_CONFUSABLE = 1, + + /** + * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates + * that the two strings are visually confusable and that they are <b>not</b> from the same script, according to UTS + * 39 section 4. + * + * @see uspoof_areConfusable + * @stable ICU 4.2 + */ + USPOOF_MIXED_SCRIPT_CONFUSABLE = 2, + + /** + * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates + * that the two strings are visually confusable and that they are not from the same script but both of them are + * single-script strings, according to UTS 39 section 4. + * + * @see uspoof_areConfusable + * @stable ICU 4.2 + */ + USPOOF_WHOLE_SCRIPT_CONFUSABLE = 4, + + /** + * Enable this flag in {@link uspoof_setChecks} to turn on all types of confusables. You may set + * the checks to some subset of SINGLE_SCRIPT_CONFUSABLE, MIXED_SCRIPT_CONFUSABLE, or WHOLE_SCRIPT_CONFUSABLE to + * make {@link uspoof_areConfusable} return only those types of confusables. + * + * @see uspoof_areConfusable + * @see uspoof_getSkeleton + * @stable ICU 58 + */ + USPOOF_CONFUSABLE = USPOOF_SINGLE_SCRIPT_CONFUSABLE | USPOOF_MIXED_SCRIPT_CONFUSABLE | USPOOF_WHOLE_SCRIPT_CONFUSABLE, + +#ifndef U_HIDE_DEPRECATED_API + /** + * This flag is deprecated and no longer affects the behavior of SpoofChecker. + * + * @deprecated ICU 58 Any case confusable mappings were removed from UTS 39; the corresponding ICU API was deprecated. + */ + USPOOF_ANY_CASE = 8, +#endif /* U_HIDE_DEPRECATED_API */ + + /** + * Check that an identifier is no looser than the specified RestrictionLevel. + * The default if {@link uspoof_setRestrictionLevel} is not called is HIGHLY_RESTRICTIVE. + * + * If USPOOF_AUX_INFO is enabled the actual restriction level of the + * identifier being tested will also be returned by uspoof_check(). + * + * @see URestrictionLevel + * @see uspoof_setRestrictionLevel + * @see USPOOF_AUX_INFO + * + * @stable ICU 51 + */ + USPOOF_RESTRICTION_LEVEL = 16, + +#ifndef U_HIDE_DEPRECATED_API + /** Check that an identifier contains only characters from a + * single script (plus chars from the common and inherited scripts.) + * Applies to checks of a single identifier check only. + * @deprecated ICU 51 Use RESTRICTION_LEVEL instead. + */ + USPOOF_SINGLE_SCRIPT = USPOOF_RESTRICTION_LEVEL, +#endif /* U_HIDE_DEPRECATED_API */ + + /** Check an identifier for the presence of invisible characters, + * such as zero-width spaces, or character sequences that are + * likely not to display, such as multiple occurrences of the same + * non-spacing mark. This check does not test the input string as a whole + * for conformance to any particular syntax for identifiers. + */ + USPOOF_INVISIBLE = 32, + + /** Check that an identifier contains only characters from a specified set + * of acceptable characters. See {@link uspoof_setAllowedChars} and + * {@link uspoof_setAllowedLocales}. Note that a string that fails this check + * will also fail the {@link USPOOF_RESTRICTION_LEVEL} check. + */ + USPOOF_CHAR_LIMIT = 64, + + /** + * Check that an identifier does not mix numbers from different numbering systems. + * For more information, see UTS 39 section 5.3. + * + * @stable ICU 51 + */ + USPOOF_MIXED_NUMBERS = 128, + + /** + * Check that an identifier does not have a combining character following a character in which that + * combining character would be hidden; for example 'i' followed by a U+0307 combining dot. + * + * More specifically, the following characters are forbidden from preceding a U+0307: + * <ul> + * <li>Those with the Soft_Dotted Unicode property (which includes 'i' and 'j')</li> + * <li>Latin lowercase letter 'l'</li> + * <li>Dotless 'i' and 'j' ('ı' and 'È·', U+0131 and U+0237)</li> + * <li>Any character whose confusable prototype ends with such a character + * (Soft_Dotted, 'l', 'ı', or 'È·')</li> + * </ul> + * In addition, combining characters are allowed between the above characters and U+0307 except those + * with combining class 0 or combining class "Above" (230, same class as U+0307). + * + * This list and the number of combing characters considered by this check may grow over time. + * + * @stable ICU 62 + */ + USPOOF_HIDDEN_OVERLAY = 256, + + /** + * Enable all spoof checks. + * + * @stable ICU 4.6 + */ + USPOOF_ALL_CHECKS = 0xFFFF, + + /** + * Enable the return of auxiliary (non-error) information in the + * upper bits of the check results value. + * + * If this "check" is not enabled, the results of {@link uspoof_check} will be + * zero when an identifier passes all of the enabled checks. + * + * If this "check" is enabled, (uspoof_check() & {@link USPOOF_ALL_CHECKS}) will + * be zero when an identifier passes all checks. + * + * @stable ICU 51 + */ + USPOOF_AUX_INFO = 0x40000000 + + } USpoofChecks; + + + /** + * Constants from UAX #39 for use in {@link uspoof_setRestrictionLevel}, and + * for returned identifier restriction levels in check results. + * + * @stable ICU 51 + * + * @see uspoof_setRestrictionLevel + * @see uspoof_check + */ + typedef enum URestrictionLevel { + /** + * All characters in the string are in the identifier profile and all characters in the string are in the + * ASCII range. + * + * @stable ICU 51 + */ + USPOOF_ASCII = 0x10000000, + /** + * The string classifies as ASCII-Only, or all characters in the string are in the identifier profile and + * the string is single-script, according to the definition in UTS 39 section 5.1. + * + * @stable ICU 53 + */ + USPOOF_SINGLE_SCRIPT_RESTRICTIVE = 0x20000000, + /** + * The string classifies as Single Script, or all characters in the string are in the identifier profile and + * the string is covered by any of the following sets of scripts, according to the definition in UTS 39 + * section 5.1: + * <ul> + * <li>Latin + Han + Bopomofo (or equivalently: Latn + Hanb)</li> + * <li>Latin + Han + Hiragana + Katakana (or equivalently: Latn + Jpan)</li> + * <li>Latin + Han + Hangul (or equivalently: Latn +Kore)</li> + * </ul> + * This is the default restriction in ICU. + * + * @stable ICU 51 + */ + USPOOF_HIGHLY_RESTRICTIVE = 0x30000000, + /** + * The string classifies as Highly Restrictive, or all characters in the string are in the identifier profile + * and the string is covered by Latin and any one other Recommended or Aspirational script, except Cyrillic, + * Greek, and Cherokee. + * + * @stable ICU 51 + */ + USPOOF_MODERATELY_RESTRICTIVE = 0x40000000, + /** + * All characters in the string are in the identifier profile. Allow arbitrary mixtures of scripts. + * + * @stable ICU 51 + */ + USPOOF_MINIMALLY_RESTRICTIVE = 0x50000000, + /** + * Any valid identifiers, including characters outside of the Identifier Profile. + * + * @stable ICU 51 + */ + USPOOF_UNRESTRICTIVE = 0x60000000, + /** + * Mask for selecting the Restriction Level bits from the return value of {@link uspoof_check}. + * + * @stable ICU 53 + */ + USPOOF_RESTRICTION_LEVEL_MASK = 0x7F000000, +#ifndef U_HIDE_INTERNAL_API + /** + * An undefined restriction level. + * @internal + */ + USPOOF_UNDEFINED_RESTRICTIVE = -1 +#endif /* U_HIDE_INTERNAL_API */ + } URestrictionLevel; + +/** + * Create a Unicode Spoof Checker, configured to perform all + * checks except for USPOOF_LOCALE_LIMIT and USPOOF_CHAR_LIMIT. + * Note that additional checks may be added in the future, + * resulting in the changes to the default checking behavior. + * + * @param status The error code, set if this function encounters a problem. + * @return the newly created Spoof Checker + * @stable ICU 4.2 + */ +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_open(UErrorCode *status); + + +/** + * Open a Spoof checker from its serialized form, stored in 32-bit-aligned memory. + * Inverse of uspoof_serialize(). + * The memory containing the serialized data must remain valid and unchanged + * as long as the spoof checker, or any cloned copies of the spoof checker, + * are in use. Ownership of the memory remains with the caller. + * The spoof checker (and any clones) must be closed prior to deleting the + * serialized data. + * + * @param data a pointer to 32-bit-aligned memory containing the serialized form of spoof data + * @param length the number of bytes available at data; + * can be more than necessary + * @param pActualLength receives the actual number of bytes at data taken up by the data; + * can be NULL + * @param pErrorCode ICU error code + * @return the spoof checker. + * + * @see uspoof_open + * @see uspoof_serialize + * @stable ICU 4.2 + */ +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength, + UErrorCode *pErrorCode); + +/** + * Open a Spoof Checker from the source form of the spoof data. + * The input corresponds to the Unicode data file confusables.txt + * as described in Unicode UAX #39. The syntax of the source data + * is as described in UAX #39 for this file, and the content of + * this file is acceptable input. + * + * The character encoding of the (char *) input text is UTF-8. + * + * @param confusables a pointer to the confusable characters definitions, + * as found in file confusables.txt from unicode.org. + * @param confusablesLen The length of the confusables text, or -1 if the + * input string is zero terminated. + * @param confusablesWholeScript + * Deprecated in ICU 58. No longer used. + * @param confusablesWholeScriptLen + * Deprecated in ICU 58. No longer used. + * @param errType In the event of an error in the input, indicates + * which of the input files contains the error. + * The value is one of USPOOF_SINGLE_SCRIPT_CONFUSABLE or + * USPOOF_WHOLE_SCRIPT_CONFUSABLE, or + * zero if no errors are found. + * @param pe In the event of an error in the input, receives the position + * in the input text (line, offset) of the error. + * @param status an in/out ICU UErrorCode. Among the possible errors is + * U_PARSE_ERROR, which is used to report syntax errors + * in the input. + * @return A spoof checker that uses the rules from the input files. + * @stable ICU 4.2 + */ +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_openFromSource(const char *confusables, int32_t confusablesLen, + const char *confusablesWholeScript, int32_t confusablesWholeScriptLen, + int32_t *errType, UParseError *pe, UErrorCode *status); + + +/** + * Close a Spoof Checker, freeing any memory that was being held by + * its implementation. + * @stable ICU 4.2 + */ +U_CAPI void U_EXPORT2 +uspoof_close(USpoofChecker *sc); + +/** + * Clone a Spoof Checker. The clone will be set to perform the same checks + * as the original source. + * + * @param sc The source USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return + * @stable ICU 4.2 + */ +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_clone(const USpoofChecker *sc, UErrorCode *status); + + +/** + * Specify the bitmask of checks that will be performed by {@link uspoof_check}. Calling this method + * overwrites any checks that may have already been enabled. By default, all checks are enabled. + * + * To enable specific checks and disable all others, + * OR together only the bit constants for the desired checks. + * For example, to fail strings containing characters outside of + * the set specified by {@link uspoof_setAllowedChars} and + * also strings that contain digits from mixed numbering systems: + * + * <pre> + * {@code + * uspoof_setChecks(USPOOF_CHAR_LIMIT | USPOOF_MIXED_NUMBERS); + * } + * </pre> + * + * To disable specific checks and enable all others, + * start with ALL_CHECKS and "AND away" the not-desired checks. + * For example, if you are not planning to use the {@link uspoof_areConfusable} functionality, + * it is good practice to disable the CONFUSABLE check: + * + * <pre> + * {@code + * uspoof_setChecks(USPOOF_ALL_CHECKS & ~USPOOF_CONFUSABLE); + * } + * </pre> + * + * Note that methods such as {@link uspoof_setAllowedChars}, {@link uspoof_setAllowedLocales}, and + * {@link uspoof_setRestrictionLevel} will enable certain checks when called. Those methods will OR the check they + * enable onto the existing bitmask specified by this method. For more details, see the documentation of those + * methods. + * + * @param sc The USpoofChecker + * @param checks The set of checks that this spoof checker will perform. + * The value is a bit set, obtained by OR-ing together + * values from enum USpoofChecks. + * @param status The error code, set if this function encounters a problem. + * @stable ICU 4.2 + * + */ +U_CAPI void U_EXPORT2 +uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status); + +/** + * Get the set of checks that this Spoof Checker has been configured to perform. + * + * @param sc The USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return The set of checks that this spoof checker will perform. + * The value is a bit set, obtained by OR-ing together + * values from enum USpoofChecks. + * @stable ICU 4.2 + * + */ +U_CAPI int32_t U_EXPORT2 +uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status); + +/** + * Set the loosest restriction level allowed for strings. The default if this is not called is + * {@link USPOOF_HIGHLY_RESTRICTIVE}. Calling this method enables the {@link USPOOF_RESTRICTION_LEVEL} and + * {@link USPOOF_MIXED_NUMBERS} checks, corresponding to Sections 5.1 and 5.2 of UTS 39. To customize which checks are + * to be performed by {@link uspoof_check}, see {@link uspoof_setChecks}. + * + * @param sc The USpoofChecker + * @param restrictionLevel The loosest restriction level allowed. + * @see URestrictionLevel + * @stable ICU 51 + */ +U_CAPI void U_EXPORT2 +uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel); + + +/** + * Get the Restriction Level that will be tested if the checks include {@link USPOOF_RESTRICTION_LEVEL}. + * + * @return The restriction level + * @see URestrictionLevel + * @stable ICU 51 + */ +U_CAPI URestrictionLevel U_EXPORT2 +uspoof_getRestrictionLevel(const USpoofChecker *sc); + +/** + * Limit characters that are acceptable in identifiers being checked to those + * normally used with the languages associated with the specified locales. + * Any previously specified list of locales is replaced by the new settings. + * + * A set of languages is determined from the locale(s), and + * from those a set of acceptable Unicode scripts is determined. + * Characters from this set of scripts, along with characters from + * the "common" and "inherited" Unicode Script categories + * will be permitted. + * + * Supplying an empty string removes all restrictions; + * characters from any script will be allowed. + * + * The {@link USPOOF_CHAR_LIMIT} test is automatically enabled for this + * USpoofChecker when calling this function with a non-empty list + * of locales. + * + * The Unicode Set of characters that will be allowed is accessible + * via the uspoof_getAllowedChars() function. uspoof_setAllowedLocales() + * will <i>replace</i> any previously applied set of allowed characters. + * + * Adjustments, such as additions or deletions of certain classes of characters, + * can be made to the result of uspoof_setAllowedLocales() by + * fetching the resulting set with uspoof_getAllowedChars(), + * manipulating it with the Unicode Set API, then resetting the + * spoof detectors limits with uspoof_setAllowedChars(). + * + * @param sc The USpoofChecker + * @param localesList A list list of locales, from which the language + * and associated script are extracted. The locales + * are comma-separated if there is more than one. + * White space may not appear within an individual locale, + * but is ignored otherwise. + * The locales are syntactically like those from the + * HTTP Accept-Language header. + * If the localesList is empty, no restrictions will be placed on + * the allowed characters. + * + * @param status The error code, set if this function encounters a problem. + * @stable ICU 4.2 + */ +U_CAPI void U_EXPORT2 +uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status); + +/** + * Get a list of locales for the scripts that are acceptable in strings + * to be checked. If no limitations on scripts have been specified, + * an empty string will be returned. + * + * uspoof_setAllowedChars() will reset the list of allowed to be empty. + * + * The format of the returned list is the same as that supplied to + * uspoof_setAllowedLocales(), but returned list may not be identical + * to the originally specified string; the string may be reformatted, + * and information other than languages from + * the originally specified locales may be omitted. + * + * @param sc The USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return A string containing a list of locales corresponding + * to the acceptable scripts, formatted like an + * HTTP Accept Language value. + * + * @stable ICU 4.2 + */ +U_CAPI const char * U_EXPORT2 +uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status); + + +/** + * Limit the acceptable characters to those specified by a Unicode Set. + * Any previously specified character limit is + * is replaced by the new settings. This includes limits on + * characters that were set with the uspoof_setAllowedLocales() function. + * + * The USPOOF_CHAR_LIMIT test is automatically enabled for this + * USpoofChecker by this function. + * + * @param sc The USpoofChecker + * @param chars A Unicode Set containing the list of + * characters that are permitted. Ownership of the set + * remains with the caller. The incoming set is cloned by + * this function, so there are no restrictions on modifying + * or deleting the USet after calling this function. + * @param status The error code, set if this function encounters a problem. + * @stable ICU 4.2 + */ +U_CAPI void U_EXPORT2 +uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status); + + +/** + * Get a USet for the characters permitted in an identifier. + * This corresponds to the limits imposed by the Set Allowed Characters + * functions. Limitations imposed by other checks will not be + * reflected in the set returned by this function. + * + * The returned set will be frozen, meaning that it cannot be modified + * by the caller. + * + * Ownership of the returned set remains with the Spoof Detector. The + * returned set will become invalid if the spoof detector is closed, + * or if a new set of allowed characters is specified. + * + * + * @param sc The USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return A USet containing the characters that are permitted by + * the USPOOF_CHAR_LIMIT test. + * @stable ICU 4.2 + */ +U_CAPI const USet * U_EXPORT2 +uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status); + + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * \note + * Consider using the newer API, {@link uspoof_check2}, instead. + * The newer API exposes additional information from the check procedure + * and is otherwise identical to this method. + * + * @param sc The USpoofChecker + * @param id The identifier to be checked for possible security issues, + * in UTF-16 format. + * @param length the length of the string to be checked, expressed in + * 16 bit UTF-16 code units, or -1 if the string is + * zero terminated. + * @param position Deprecated in ICU 51. Always returns zero. + * Originally, an out parameter for the index of the first + * string position that failed a check. + * This parameter may be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. + * @see uspoof_check2 + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_check(const USpoofChecker *sc, + const UChar *id, int32_t length, + int32_t *position, + UErrorCode *status); + + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * \note + * Consider using the newer API, {@link uspoof_check2UTF8}, instead. + * The newer API exposes additional information from the check procedure + * and is otherwise identical to this method. + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues, in UTF8 format. + * @param length the length of the string to be checked, or -1 if the string is + * zero terminated. + * @param position Deprecated in ICU 51. Always returns zero. + * Originally, an out parameter for the index of the first + * string position that failed a check. + * This parameter may be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * If the input contains invalid UTF-8 sequences, + * a status of U_INVALID_CHAR_FOUND will be returned. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. + * @see uspoof_check2UTF8 + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_checkUTF8(const USpoofChecker *sc, + const char *id, int32_t length, + int32_t *position, + UErrorCode *status); + + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * @param sc The USpoofChecker + * @param id The identifier to be checked for possible security issues, + * in UTF-16 format. + * @param length the length of the string to be checked, or -1 if the string is + * zero terminated. + * @param checkResult An instance of USpoofCheckResult to be filled with + * details about the identifier. Can be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. Any information in this bitmask will be + * consistent with the information saved in the optional + * checkResult parameter. + * @see uspoof_openCheckResult + * @see uspoof_check2UTF8 + * @see uspoof_check2UnicodeString + * @stable ICU 58 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_check2(const USpoofChecker *sc, + const UChar* id, int32_t length, + USpoofCheckResult* checkResult, + UErrorCode *status); + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * This version of {@link uspoof_check} accepts a USpoofCheckResult, which + * returns additional information about the identifier. For more + * information, see {@link uspoof_openCheckResult}. + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues, in UTF8 format. + * @param length the length of the string to be checked, or -1 if the string is + * zero terminated. + * @param checkResult An instance of USpoofCheckResult to be filled with + * details about the identifier. Can be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. Any information in this bitmask will be + * consistent with the information saved in the optional + * checkResult parameter. + * @see uspoof_openCheckResult + * @see uspoof_check2 + * @see uspoof_check2UnicodeString + * @stable ICU 58 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_check2UTF8(const USpoofChecker *sc, + const char *id, int32_t length, + USpoofCheckResult* checkResult, + UErrorCode *status); + +/** + * Create a USpoofCheckResult, used by the {@link uspoof_check2} class of functions to return + * information about the identifier. Information includes: + * <ul> + * <li>A bitmask of the checks that failed</li> + * <li>The identifier's restriction level (UTS 39 section 5.2)</li> + * <li>The set of numerics in the string (UTS 39 section 5.3)</li> + * </ul> + * The data held in a USpoofCheckResult is cleared whenever it is passed into a new call + * of {@link uspoof_check2}. + * + * @param status The error code, set if this function encounters a problem. + * @return the newly created USpoofCheckResult + * @see uspoof_check2 + * @see uspoof_check2UTF8 + * @see uspoof_check2UnicodeString + * @stable ICU 58 + */ +U_CAPI USpoofCheckResult* U_EXPORT2 +uspoof_openCheckResult(UErrorCode *status); + +/** + * Close a USpoofCheckResult, freeing any memory that was being held by + * its implementation. + * + * @param checkResult The instance of USpoofCheckResult to close + * @stable ICU 58 + */ +U_CAPI void U_EXPORT2 +uspoof_closeCheckResult(USpoofCheckResult *checkResult); + +/** + * Indicates which of the spoof check(s) have failed. The value is a bitwise OR of the constants for the tests + * in question: USPOOF_RESTRICTION_LEVEL, USPOOF_CHAR_LIMIT, and so on. + * + * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult} + * @param status The error code, set if an error occurred. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. + * @see uspoof_setChecks + * @stable ICU 58 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status); + +/** + * Gets the restriction level that the text meets, if the USPOOF_RESTRICTION_LEVEL check + * was enabled; otherwise, undefined. + * + * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult} + * @param status The error code, set if an error occurred. + * @return The restriction level contained in the USpoofCheckResult + * @see uspoof_setRestrictionLevel + * @stable ICU 58 + */ +U_CAPI URestrictionLevel U_EXPORT2 +uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status); + +/** + * Gets the set of numerics found in the string, if the USPOOF_MIXED_NUMBERS check was enabled; + * otherwise, undefined. The set will contain the zero digit from each decimal number system found + * in the input string. Ownership of the returned USet remains with the USpoofCheckResult. + * The USet will be free'd when {@link uspoof_closeCheckResult} is called. + * + * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult} + * @return The set of numerics contained in the USpoofCheckResult + * @param status The error code, set if an error occurred. + * @stable ICU 58 + */ +U_CAPI const USet* U_EXPORT2 +uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status); + + +/** + * Check the whether two specified strings are visually confusable. + * + * If the strings are confusable, the return value will be nonzero, as long as + * {@link USPOOF_CONFUSABLE} was enabled in uspoof_setChecks(). + * + * The bits in the return value correspond to flags for each of the classes of + * confusables applicable to the two input strings. According to UTS 39 + * section 4, the possible flags are: + * + * <ul> + * <li>{@link USPOOF_SINGLE_SCRIPT_CONFUSABLE}</li> + * <li>{@link USPOOF_MIXED_SCRIPT_CONFUSABLE}</li> + * <li>{@link USPOOF_WHOLE_SCRIPT_CONFUSABLE}</li> + * </ul> + * + * If one or more of the above flags were not listed in uspoof_setChecks(), this + * function will never report that class of confusable. The check + * {@link USPOOF_CONFUSABLE} enables all three flags. + * + * + * @param sc The USpoofChecker + * @param id1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-16 format. + * @param length1 the length of the first identifier, expressed in + * 16 bit UTF-16 code units, or -1 if the string is + * nul terminated. + * @param id2 The second of the two identifiers to be compared for + * confusability. The identifiers are in UTF-16 format. + * @param length2 The length of the second identifiers, expressed in + * 16 bit UTF-16 code units, or -1 if the string is + * nul terminated. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the identifiers is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the identifiers + * are not confusable. + * + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusable(const USpoofChecker *sc, + const UChar *id1, int32_t length1, + const UChar *id2, int32_t length2, + UErrorCode *status); + + + +/** + * A version of {@link uspoof_areConfusable} accepting strings in UTF-8 format. + * + * @param sc The USpoofChecker + * @param id1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param length1 the length of the first identifiers, in bytes, or -1 + * if the string is nul terminated. + * @param id2 The second of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param length2 The length of the second string in bytes, or -1 + * if the string is nul terminated. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the strings is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the strings + * are not confusable. + * + * @stable ICU 4.2 + * + * @see uspoof_areConfusable + */ +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusableUTF8(const USpoofChecker *sc, + const char *id1, int32_t length1, + const char *id2, int32_t length2, + UErrorCode *status); + + + + +/** + * Get the "skeleton" for an identifier. + * Skeletons are a transformation of the input identifier; + * Two identifiers are confusable if their skeletons are identical. + * See Unicode UAX #39 for additional information. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker + * @param type Deprecated in ICU 58. You may pass any number. + * Originally, controlled which of the Unicode confusable data + * tables to use. + * @param id The input identifier whose skeleton will be computed. + * @param length The length of the input identifier, expressed in 16 bit + * UTF-16 code units, or -1 if the string is zero terminated. + * @param dest The output buffer, to receive the skeleton string. + * @param destCapacity The length of the output buffer, in 16 bit units. + * The destCapacity may be zero, in which case the function will + * return the actual length of the skeleton. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * @return The length of the skeleton string. The returned length + * is always that of the complete skeleton, even when the + * supplied buffer is too small (or of zero length) + * + * @stable ICU 4.2 + * @see uspoof_areConfusable + */ +U_CAPI int32_t U_EXPORT2 +uspoof_getSkeleton(const USpoofChecker *sc, + uint32_t type, + const UChar *id, int32_t length, + UChar *dest, int32_t destCapacity, + UErrorCode *status); + +/** + * Get the "skeleton" for an identifier. + * Skeletons are a transformation of the input identifier; + * Two identifiers are confusable if their skeletons are identical. + * See Unicode UAX #39 for additional information. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker + * @param type Deprecated in ICU 58. You may pass any number. + * Originally, controlled which of the Unicode confusable data + * tables to use. + * @param id The UTF-8 format identifier whose skeleton will be computed. + * @param length The length of the input string, in bytes, + * or -1 if the string is zero terminated. + * @param dest The output buffer, to receive the skeleton string. + * @param destCapacity The length of the output buffer, in bytes. + * The destCapacity may be zero, in which case the function will + * return the actual length of the skeleton. + * @param status The error code, set if an error occurred while attempting to + * perform the check. Possible Errors include U_INVALID_CHAR_FOUND + * for invalid UTF-8 sequences, and + * U_BUFFER_OVERFLOW_ERROR if the destination buffer is too small + * to hold the complete skeleton. + * @return The length of the skeleton string, in bytes. The returned length + * is always that of the complete skeleton, even when the + * supplied buffer is too small (or of zero length) + * + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_getSkeletonUTF8(const USpoofChecker *sc, + uint32_t type, + const char *id, int32_t length, + char *dest, int32_t destCapacity, + UErrorCode *status); + +/** + * Get the set of Candidate Characters for Inclusion in Identifiers, as defined + * in http://unicode.org/Public/security/latest/xidmodifications.txt + * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms. + * + * The returned set is frozen. Ownership of the set remains with the ICU library; it must not + * be deleted by the caller. + * + * @param status The error code, set if a problem occurs while creating the set. + * + * @stable ICU 51 + */ +U_CAPI const USet * U_EXPORT2 +uspoof_getInclusionSet(UErrorCode *status); + +/** + * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined + * in http://unicode.org/Public/security/latest/xidmodifications.txt + * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms. + * + * The returned set is frozen. Ownership of the set remains with the ICU library; it must not + * be deleted by the caller. + * + * @param status The error code, set if a problem occurs while creating the set. + * + * @stable ICU 51 + */ +U_CAPI const USet * U_EXPORT2 +uspoof_getRecommendedSet(UErrorCode *status); + +/** + * Serialize the data for a spoof detector into a chunk of memory. + * The flattened spoof detection tables can later be used to efficiently + * instantiate a new Spoof Detector. + * + * The serialized spoof checker includes only the data compiled from the + * Unicode data tables by uspoof_openFromSource(); it does not include + * include any other state or configuration that may have been set. + * + * @param sc the Spoof Detector whose data is to be serialized. + * @param data a pointer to 32-bit-aligned memory to be filled with the data, + * can be NULL if capacity==0 + * @param capacity the number of bytes available at data, + * or 0 for preflighting + * @param status an in/out ICU UErrorCode; possible errors include: + * - U_BUFFER_OVERFLOW_ERROR if the data storage block is too small for serialization + * - U_ILLEGAL_ARGUMENT_ERROR the data or capacity parameters are bad + * @return the number of bytes written or needed for the spoof data + * + * @see utrie2_openFromSerialized() + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_serialize(USpoofChecker *sc, + void *data, int32_t capacity, + UErrorCode *status); + +U_CDECL_END + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUSpoofCheckerPointer + * "Smart pointer" class, closes a USpoofChecker via uspoof_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +/** + * \cond + * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. + * For now, suppress with a Doxygen cond + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckerPointer, USpoofChecker, uspoof_close); +/** \endcond */ + +/** + * \class LocalUSpoofCheckResultPointer + * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`. + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 58 + */ + +/** + * \cond + * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. + * For now, suppress with a Doxygen cond + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult); +/** \endcond */ + +U_NAMESPACE_END + +/** + * Limit the acceptable characters to those specified by a Unicode Set. + * Any previously specified character limit is + * is replaced by the new settings. This includes limits on + * characters that were set with the uspoof_setAllowedLocales() function. + * + * The USPOOF_CHAR_LIMIT test is automatically enabled for this + * USoofChecker by this function. + * + * @param sc The USpoofChecker + * @param chars A Unicode Set containing the list of + * characters that are permitted. Ownership of the set + * remains with the caller. The incoming set is cloned by + * this function, so there are no restrictions on modifying + * or deleting the UnicodeSet after calling this function. + * @param status The error code, set if this function encounters a problem. + * @stable ICU 4.2 + */ +U_CAPI void U_EXPORT2 +uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const icu::UnicodeSet *chars, UErrorCode *status); + + +/** + * Get a UnicodeSet for the characters permitted in an identifier. + * This corresponds to the limits imposed by the Set Allowed Characters / + * UnicodeSet functions. Limitations imposed by other checks will not be + * reflected in the set returned by this function. + * + * The returned set will be frozen, meaning that it cannot be modified + * by the caller. + * + * Ownership of the returned set remains with the Spoof Detector. The + * returned set will become invalid if the spoof detector is closed, + * or if a new set of allowed characters is specified. + * + * + * @param sc The USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return A UnicodeSet containing the characters that are permitted by + * the USPOOF_CHAR_LIMIT test. + * @stable ICU 4.2 + */ +U_CAPI const icu::UnicodeSet * U_EXPORT2 +uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status); + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * \note + * Consider using the newer API, {@link uspoof_check2UnicodeString}, instead. + * The newer API exposes additional information from the check procedure + * and is otherwise identical to this method. + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues. + * @param position Deprecated in ICU 51. Always returns zero. + * Originally, an out parameter for the index of the first + * string position that failed a check. + * This parameter may be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. + * @see uspoof_check2UnicodeString + * @stable ICU 4.2 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_checkUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + int32_t *position, + UErrorCode *status); + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues. + * @param checkResult An instance of USpoofCheckResult to be filled with + * details about the identifier. Can be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. Any information in this bitmask will be + * consistent with the information saved in the optional + * checkResult parameter. + * @see uspoof_openCheckResult + * @see uspoof_check2 + * @see uspoof_check2UTF8 + * @stable ICU 58 + */ +U_CAPI int32_t U_EXPORT2 +uspoof_check2UnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + USpoofCheckResult* checkResult, + UErrorCode *status); + +/** + * A version of {@link uspoof_areConfusable} accepting UnicodeStrings. + * + * @param sc The USpoofChecker + * @param s1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param s2 The second of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the identifiers is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the identifiers + * are not confusable. + * + * @stable ICU 4.2 + * + * @see uspoof_areConfusable + */ +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusableUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &s1, + const icu::UnicodeString &s2, + UErrorCode *status); + +/** + * Get the "skeleton" for an identifier. + * Skeletons are a transformation of the input identifier; + * Two identifiers are confusable if their skeletons are identical. + * See Unicode UAX #39 for additional information. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker. + * @param type Deprecated in ICU 58. You may pass any number. + * Originally, controlled which of the Unicode confusable data + * tables to use. + * @param id The input identifier whose skeleton will be computed. + * @param dest The output identifier, to receive the skeleton string. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * @return A reference to the destination (skeleton) string. + * + * @stable ICU 4.2 + */ +U_I18N_API icu::UnicodeString & U_EXPORT2 +uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, + uint32_t type, + const icu::UnicodeString &id, + icu::UnicodeString &dest, + UErrorCode *status); + +/** + * Get the set of Candidate Characters for Inclusion in Identifiers, as defined + * in http://unicode.org/Public/security/latest/xidmodifications.txt + * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms. + * + * The returned set is frozen. Ownership of the set remains with the ICU library; it must not + * be deleted by the caller. + * + * @param status The error code, set if a problem occurs while creating the set. + * + * @stable ICU 51 + */ +U_CAPI const icu::UnicodeSet * U_EXPORT2 +uspoof_getInclusionUnicodeSet(UErrorCode *status); + +/** + * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined + * in http://unicode.org/Public/security/latest/xidmodifications.txt + * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms. + * + * The returned set is frozen. Ownership of the set remains with the ICU library; it must not + * be deleted by the caller. + * + * @param status The error code, set if a problem occurs while creating the set. + * + * @stable ICU 51 + */ +U_CAPI const icu::UnicodeSet * U_EXPORT2 +uspoof_getRecommendedUnicodeSet(UErrorCode *status); + +#endif /* U_SHOW_CPLUSPLUS_API */ + +#endif /* UCONFIG_NO_NORMALIZATION */ + +#endif /* USPOOF_H */ diff --git a/thirdparty/icu4c/i18n/uspoof.cpp b/thirdparty/icu4c/i18n/uspoof.cpp new file mode 100644 index 0000000000..dd4618baa7 --- /dev/null +++ b/thirdparty/icu4c/i18n/uspoof.cpp @@ -0,0 +1,839 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +*************************************************************************** +* Copyright (C) 2008-2015, International Business Machines Corporation +* and others. All Rights Reserved. +*************************************************************************** +* file name: uspoof.cpp +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2008Feb13 +* created by: Andy Heninger +* +* Unicode Spoof Detection +*/ +#include "unicode/utypes.h" +#include "unicode/normalizer2.h" +#include "unicode/uspoof.h" +#include "unicode/ustring.h" +#include "unicode/utf16.h" +#include "cmemory.h" +#include "cstring.h" +#include "mutex.h" +#include "scriptset.h" +#include "uassert.h" +#include "ucln_in.h" +#include "uspoof_impl.h" +#include "umutex.h" + + +#if !UCONFIG_NO_NORMALIZATION + +U_NAMESPACE_USE + + +// +// Static Objects used by the spoof impl, their thread safe initialization and their cleanup. +// +static UnicodeSet *gInclusionSet = NULL; +static UnicodeSet *gRecommendedSet = NULL; +static const Normalizer2 *gNfdNormalizer = NULL; +static UInitOnce gSpoofInitStaticsOnce = U_INITONCE_INITIALIZER; + +namespace { + +UBool U_CALLCONV +uspoof_cleanup(void) { + delete gInclusionSet; + gInclusionSet = NULL; + delete gRecommendedSet; + gRecommendedSet = NULL; + gNfdNormalizer = NULL; + gSpoofInitStaticsOnce.reset(); + return TRUE; +} + +void U_CALLCONV initializeStatics(UErrorCode &status) { + static const char16_t *inclusionPat = + u"['\\-.\\:\\u00B7\\u0375\\u058A\\u05F3\\u05F4\\u06FD\\u06FE\\u0F0B\\u200C" + u"\\u200D\\u2010\\u2019\\u2027\\u30A0\\u30FB]"; + gInclusionSet = new UnicodeSet(UnicodeString(inclusionPat), status); + if (gInclusionSet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + gInclusionSet->freeze(); + + // Note: data from IdentifierStatus.txt & IdentifierType.txt + // There is tooling to generate this constant in the unicodetools project: + // org.unicode.text.tools.RecommendedSetGenerator + // It will print the Java and C++ code to the console for easy copy-paste into this file. + static const char16_t *recommendedPat = + u"[0-9A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u0131\\u0134-\\u013E" + u"\\u0141-\\u0148\\u014A-\\u017E\\u018F\\u01A0\\u01A1\\u01AF\\u01B0\\u01CD-" + u"\\u01DC\\u01DE-\\u01E3\\u01E6-\\u01F0\\u01F4\\u01F5\\u01F8-\\u021B\\u021E" + u"\\u021F\\u0226-\\u0233\\u0259\\u02BB\\u02BC\\u02EC\\u0300-\\u0304\\u0306-" + u"\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u0328\\u032D\\u032E" + u"\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386" + u"\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-" + u"\\u04FF\\u0510-\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0586" + u"\\u05B4\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-" + u"\\u0669\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06A0\\u06A2-\\u06D3" + u"\\u06D5\\u06E5\\u06E6\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u0870-\\u0887" + u"\\u0889-\\u088E\\u08A0-\\u08AC\\u08B2\\u08B5-\\u08C9\\u0901-\\u094D\\u094F" + u"\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096F\\u0971-\\u0977\\u0979-" + u"\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-" + u"\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE" + u"\\u09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u09FE\\u0A01-\\u0A03\\u0A05-\\u0A0A" + u"\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A35\\u0A38\\u0A39" + u"\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A5C\\u0A66-\\u0A74" + u"\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0" + u"\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD" + u"\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0AFA-\\u0AFF\\u0B01-\\u0B03\\u0B05-" + u"\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-" + u"\\u0B39\\u0B3C-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B55-\\u0B57\\u0B5F-" + u"\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90" + u"\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-" + u"\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0" + u"\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-" + u"\\u0C33\\u0C35-\\u0C39\\u0C3C-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55" + u"\\u0C56\\u0C5D\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80\\u0C82\\u0C83\\u0C85-" + u"\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-" + u"\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDD\\u0CE0-\\u0CE3" + u"\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02\\u0D03\\u0D05-\\u0D0C\\u0D0E-" + u"\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-" + u"\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-" + u"\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD" + u"\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-" + u"\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84" + u"\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB2\\u0EB4-\\u0EBD\\u0EC0-" + u"\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00\\u0F20-" + u"\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C\\u0F4E-" + u"\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C\\u0F71" + u"\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84\\u0F86-\\u0F92\\u0F94-\\u0F97" + u"\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8" + u"\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10C7\\u10CD\\u10D0-" + u"\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D\\u1250-" + u"\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0" + u"\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-" + u"\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u1780-" + u"\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-\\u17CD\\u17D0\\u17D2\\u17D7" + u"\\u17DC\\u17E0-\\u17E9\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1E00-\\u1E99\\u1E9E" + u"\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D" + u"\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72\\u1F74\\u1F76" + u"\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC\\u1FC2-\\u1FC4" + u"\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-\\u1FDA\\u1FE0-\\u1FE2" + u"\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8\\u1FFA\\u1FFC\\u2D27" + u"\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-" + u"\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u3005-" + u"\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-\\u30FA\\u30FC-" + u"\\u30FE\\u3105-\\u312D\\u312F\\u31A0-\\u31BF\\u3400-\\u4DBF\\u4E00-\\u9FFF" + u"\\uA67F\\uA717-\\uA71F\\uA788\\uA78D\\uA792\\uA793\\uA7AA\\uA7AE\\uA7B8" + u"\\uA7B9\\uA7C0-\\uA7CA\\uA7D0\\uA7D1\\uA7D3\\uA7D5-\\uA7D9\\uA9E7-\\uA9FE" + u"\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16" + u"\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB66\\uAB67\\uAC00-\\uD7A3\\uFA0E\\uFA0F" + u"\\uFA11\\uFA13\\uFA14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29\\U00011301" + u"\\U00011303\\U0001133B\\U0001133C\\U00016FF0\\U00016FF1\\U0001B11F-" + u"\\U0001B122\\U0001B150-\\U0001B152\\U0001B164-\\U0001B167\\U0001DF00-" + u"\\U0001DF1E\\U0001E7E0-\\U0001E7E6\\U0001E7E8-\\U0001E7EB\\U0001E7ED" + u"\\U0001E7EE\\U0001E7F0-\\U0001E7FE\\U00020000-\\U0002A6DF\\U0002A700-" + u"\\U0002B738\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-" + u"\\U0002EBE0\\U00030000-\\U0003134A]"; + + gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status); + if (gRecommendedSet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + delete gInclusionSet; + return; + } + gRecommendedSet->freeze(); + gNfdNormalizer = Normalizer2::getNFDInstance(status); + ucln_i18n_registerCleanup(UCLN_I18N_SPOOF, uspoof_cleanup); +} + +} // namespace + +U_CFUNC void uspoof_internalInitStatics(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); +} + +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_open(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + if (U_FAILURE(*status)) { + return NULL; + } + SpoofImpl *si = new SpoofImpl(*status); + if (si == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + if (U_FAILURE(*status)) { + delete si; + return NULL; + } + return si->asUSpoofChecker(); +} + + +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength, + UErrorCode *status) { + if (U_FAILURE(*status)) { + return NULL; + } + + if (data == NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return NULL; + } + + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + if (U_FAILURE(*status)) + { + return NULL; + } + + SpoofData *sd = new SpoofData(data, length, *status); + if (sd == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + + if (U_FAILURE(*status)) { + delete sd; + return NULL; + } + + SpoofImpl *si = new SpoofImpl(sd, *status); + if (si == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + delete sd; // explicit delete as the destructor for si won't be called. + return NULL; + } + + if (U_FAILURE(*status)) { + delete si; // no delete for sd, as the si destructor will delete it. + return NULL; + } + + if (pActualLength != NULL) { + *pActualLength = sd->size(); + } + return si->asUSpoofChecker(); +} + + +U_CAPI USpoofChecker * U_EXPORT2 +uspoof_clone(const USpoofChecker *sc, UErrorCode *status) { + const SpoofImpl *src = SpoofImpl::validateThis(sc, *status); + if (src == NULL) { + return NULL; + } + SpoofImpl *result = new SpoofImpl(*src, *status); // copy constructor + if (result == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + if (U_FAILURE(*status)) { + delete result; + result = NULL; + } + return result->asUSpoofChecker(); +} + + +U_CAPI void U_EXPORT2 +uspoof_close(USpoofChecker *sc) { + UErrorCode status = U_ZERO_ERROR; + SpoofImpl *This = SpoofImpl::validateThis(sc, status); + delete This; +} + + +U_CAPI void U_EXPORT2 +uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status) { + SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return; + } + + // Verify that the requested checks are all ones (bits) that + // are acceptable, known values. + if (checks & ~(USPOOF_ALL_CHECKS | USPOOF_AUX_INFO)) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + This->fChecks = checks; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return 0; + } + return This->fChecks; +} + +U_CAPI void U_EXPORT2 +uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel) { + UErrorCode status = U_ZERO_ERROR; + SpoofImpl *This = SpoofImpl::validateThis(sc, status); + if (This != NULL) { + This->fRestrictionLevel = restrictionLevel; + This->fChecks |= USPOOF_RESTRICTION_LEVEL; + } +} + +U_CAPI URestrictionLevel U_EXPORT2 +uspoof_getRestrictionLevel(const USpoofChecker *sc) { + UErrorCode status = U_ZERO_ERROR; + const SpoofImpl *This = SpoofImpl::validateThis(sc, status); + if (This == NULL) { + return USPOOF_UNRESTRICTIVE; + } + return This->fRestrictionLevel; +} + +U_CAPI void U_EXPORT2 +uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status) { + SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return; + } + This->setAllowedLocales(localesList, *status); +} + +U_CAPI const char * U_EXPORT2 +uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status) { + SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return NULL; + } + return This->getAllowedLocales(*status); +} + + +U_CAPI const USet * U_EXPORT2 +uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status) { + const UnicodeSet *result = uspoof_getAllowedUnicodeSet(sc, status); + return result->toUSet(); +} + +U_CAPI const UnicodeSet * U_EXPORT2 +uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return NULL; + } + return This->fAllowedCharsSet; +} + + +U_CAPI void U_EXPORT2 +uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status) { + const UnicodeSet *set = UnicodeSet::fromUSet(chars); + uspoof_setAllowedUnicodeSet(sc, set, status); +} + + +U_CAPI void U_EXPORT2 +uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const UnicodeSet *chars, UErrorCode *status) { + SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return; + } + if (chars->isBogus()) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + UnicodeSet *clonedSet = chars->clone(); + if (clonedSet == NULL || clonedSet->isBogus()) { + *status = U_MEMORY_ALLOCATION_ERROR; + return; + } + clonedSet->freeze(); + delete This->fAllowedCharsSet; + This->fAllowedCharsSet = clonedSet; + This->fChecks |= USPOOF_CHAR_LIMIT; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_check(const USpoofChecker *sc, + const UChar *id, int32_t length, + int32_t *position, + UErrorCode *status) { + + // Backwards compatibility: + if (position != NULL) { + *position = 0; + } + + // Delegate to uspoof_check2 + return uspoof_check2(sc, id, length, NULL, status); +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_check2(const USpoofChecker *sc, + const UChar* id, int32_t length, + USpoofCheckResult* checkResult, + UErrorCode *status) { + + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return 0; + } + if (length < -1) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + UnicodeString idStr((length == -1), id, length); // Aliasing constructor. + int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status); + return result; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_checkUTF8(const USpoofChecker *sc, + const char *id, int32_t length, + int32_t *position, + UErrorCode *status) { + + // Backwards compatibility: + if (position != NULL) { + *position = 0; + } + + // Delegate to uspoof_check2 + return uspoof_check2UTF8(sc, id, length, NULL, status); +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_check2UTF8(const USpoofChecker *sc, + const char *id, int32_t length, + USpoofCheckResult* checkResult, + UErrorCode *status) { + + if (U_FAILURE(*status)) { + return 0; + } + UnicodeString idStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id)))); + int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status); + return result; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusable(const USpoofChecker *sc, + const UChar *id1, int32_t length1, + const UChar *id2, int32_t length2, + UErrorCode *status) { + SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + if (length1 < -1 || length2 < -1) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + UnicodeString id1Str((length1==-1), id1, length1); // Aliasing constructor + UnicodeString id2Str((length2==-1), id2, length2); // Aliasing constructor + return uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status); +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusableUTF8(const USpoofChecker *sc, + const char *id1, int32_t length1, + const char *id2, int32_t length2, + UErrorCode *status) { + SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + if (length1 < -1 || length2 < -1) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + UnicodeString id1Str = UnicodeString::fromUTF8(StringPiece(id1, length1>=0? length1 : static_cast<int32_t>(uprv_strlen(id1)))); + UnicodeString id2Str = UnicodeString::fromUTF8(StringPiece(id2, length2>=0? length2 : static_cast<int32_t>(uprv_strlen(id2)))); + int32_t results = uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status); + return results; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_areConfusableUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id1, + const icu::UnicodeString &id2, + UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + // + // See section 4 of UAX 39 for the algorithm for checking whether two strings are confusable, + // and for definitions of the types (single, whole, mixed-script) of confusables. + + // We only care about a few of the check flags. Ignore the others. + // If no tests relevant to this function have been specified, return an error. + // TODO: is this really the right thing to do? It's probably an error on the caller's part, + // but logically we would just return 0 (no error). + if ((This->fChecks & USPOOF_CONFUSABLE) == 0) { + *status = U_INVALID_STATE_ERROR; + return 0; + } + + // Compute the skeletons and check for confusability. + UnicodeString id1Skeleton; + uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id1, id1Skeleton, status); + UnicodeString id2Skeleton; + uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id2, id2Skeleton, status); + if (U_FAILURE(*status)) { return 0; } + if (id1Skeleton != id2Skeleton) { + return 0; + } + + // If we get here, the strings are confusable. Now we just need to set the flags for the appropriate classes + // of confusables according to UTS 39 section 4. + // Start by computing the resolved script sets of id1 and id2. + ScriptSet id1RSS; + This->getResolvedScriptSet(id1, id1RSS, *status); + ScriptSet id2RSS; + This->getResolvedScriptSet(id2, id2RSS, *status); + + // Turn on all applicable flags + int32_t result = 0; + if (id1RSS.intersects(id2RSS)) { + result |= USPOOF_SINGLE_SCRIPT_CONFUSABLE; + } else { + result |= USPOOF_MIXED_SCRIPT_CONFUSABLE; + if (!id1RSS.isEmpty() && !id2RSS.isEmpty()) { + result |= USPOOF_WHOLE_SCRIPT_CONFUSABLE; + } + } + + // Turn off flags that the user doesn't want + if ((This->fChecks & USPOOF_SINGLE_SCRIPT_CONFUSABLE) == 0) { + result &= ~USPOOF_SINGLE_SCRIPT_CONFUSABLE; + } + if ((This->fChecks & USPOOF_MIXED_SCRIPT_CONFUSABLE) == 0) { + result &= ~USPOOF_MIXED_SCRIPT_CONFUSABLE; + } + if ((This->fChecks & USPOOF_WHOLE_SCRIPT_CONFUSABLE) == 0) { + result &= ~USPOOF_WHOLE_SCRIPT_CONFUSABLE; + } + + return result; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_checkUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + int32_t *position, + UErrorCode *status) { + + // Backwards compatibility: + if (position != NULL) { + *position = 0; + } + + // Delegate to uspoof_check2 + return uspoof_check2UnicodeString(sc, id, NULL, status); +} + +namespace { + +int32_t checkImpl(const SpoofImpl* This, const UnicodeString& id, CheckResult* checkResult, UErrorCode* status) { + U_ASSERT(This != NULL); + U_ASSERT(checkResult != NULL); + checkResult->clear(); + int32_t result = 0; + + if (0 != (This->fChecks & USPOOF_RESTRICTION_LEVEL)) { + URestrictionLevel idRestrictionLevel = This->getRestrictionLevel(id, *status); + if (idRestrictionLevel > This->fRestrictionLevel) { + result |= USPOOF_RESTRICTION_LEVEL; + } + checkResult->fRestrictionLevel = idRestrictionLevel; + } + + if (0 != (This->fChecks & USPOOF_MIXED_NUMBERS)) { + UnicodeSet numerics; + This->getNumerics(id, numerics, *status); + if (numerics.size() > 1) { + result |= USPOOF_MIXED_NUMBERS; + } + checkResult->fNumerics = numerics; // UnicodeSet::operator= + } + + if (0 != (This->fChecks & USPOOF_HIDDEN_OVERLAY)) { + int32_t index = This->findHiddenOverlay(id, *status); + if (index != -1) { + result |= USPOOF_HIDDEN_OVERLAY; + } + } + + + if (0 != (This->fChecks & USPOOF_CHAR_LIMIT)) { + int32_t i; + UChar32 c; + int32_t length = id.length(); + for (i=0; i<length ;) { + c = id.char32At(i); + i += U16_LENGTH(c); + if (!This->fAllowedCharsSet->contains(c)) { + result |= USPOOF_CHAR_LIMIT; + break; + } + } + } + + if (0 != (This->fChecks & USPOOF_INVISIBLE)) { + // This check needs to be done on NFD input + UnicodeString nfdText; + gNfdNormalizer->normalize(id, nfdText, *status); + int32_t nfdLength = nfdText.length(); + + // scan for more than one occurrence of the same non-spacing mark + // in a sequence of non-spacing marks. + int32_t i; + UChar32 c; + UChar32 firstNonspacingMark = 0; + UBool haveMultipleMarks = FALSE; + UnicodeSet marksSeenSoFar; // Set of combining marks in a single combining sequence. + + for (i=0; i<nfdLength ;) { + c = nfdText.char32At(i); + i += U16_LENGTH(c); + if (u_charType(c) != U_NON_SPACING_MARK) { + firstNonspacingMark = 0; + if (haveMultipleMarks) { + marksSeenSoFar.clear(); + haveMultipleMarks = FALSE; + } + continue; + } + if (firstNonspacingMark == 0) { + firstNonspacingMark = c; + continue; + } + if (!haveMultipleMarks) { + marksSeenSoFar.add(firstNonspacingMark); + haveMultipleMarks = TRUE; + } + if (marksSeenSoFar.contains(c)) { + // report the error, and stop scanning. + // No need to find more than the first failure. + result |= USPOOF_INVISIBLE; + break; + } + marksSeenSoFar.add(c); + } + } + + checkResult->fChecks = result; + return checkResult->toCombinedBitmask(This->fChecks); +} + +} // namespace + +U_CAPI int32_t U_EXPORT2 +uspoof_check2UnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + USpoofCheckResult* checkResult, + UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + return FALSE; + } + + if (checkResult != NULL) { + CheckResult* ThisCheckResult = CheckResult::validateThis(checkResult, *status); + if (ThisCheckResult == NULL) { + return FALSE; + } + return checkImpl(This, id, ThisCheckResult, status); + } else { + // Stack-allocate the checkResult since this method doesn't return it + CheckResult stackCheckResult; + return checkImpl(This, id, &stackCheckResult, status); + } +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_getSkeleton(const USpoofChecker *sc, + uint32_t type, + const UChar *id, int32_t length, + UChar *dest, int32_t destCapacity, + UErrorCode *status) { + + SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + UnicodeString idStr((length==-1), id, length); // Aliasing constructor + UnicodeString destStr; + uspoof_getSkeletonUnicodeString(sc, type, idStr, destStr, status); + destStr.extract(dest, destCapacity, *status); + return destStr.length(); +} + + + +U_I18N_API UnicodeString & U_EXPORT2 +uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, + uint32_t /*type*/, + const UnicodeString &id, + UnicodeString &dest, + UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return dest; + } + + UnicodeString nfdId; + gNfdNormalizer->normalize(id, nfdId, *status); + + // Apply the skeleton mapping to the NFD normalized input string + // Accumulate the skeleton, possibly unnormalized, in a UnicodeString. + int32_t inputIndex = 0; + UnicodeString skelStr; + int32_t normalizedLen = nfdId.length(); + for (inputIndex=0; inputIndex < normalizedLen; ) { + UChar32 c = nfdId.char32At(inputIndex); + inputIndex += U16_LENGTH(c); + This->fSpoofData->confusableLookup(c, skelStr); + } + + gNfdNormalizer->normalize(skelStr, dest, *status); + return dest; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_getSkeletonUTF8(const USpoofChecker *sc, + uint32_t type, + const char *id, int32_t length, + char *dest, int32_t destCapacity, + UErrorCode *status) { + SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + UnicodeString srcStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id)))); + UnicodeString destStr; + uspoof_getSkeletonUnicodeString(sc, type, srcStr, destStr, status); + if (U_FAILURE(*status)) { + return 0; + } + + int32_t lengthInUTF8 = 0; + u_strToUTF8(dest, destCapacity, &lengthInUTF8, + destStr.getBuffer(), destStr.length(), status); + return lengthInUTF8; +} + + +U_CAPI int32_t U_EXPORT2 +uspoof_serialize(USpoofChecker *sc,void *buf, int32_t capacity, UErrorCode *status) { + SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (This == NULL) { + U_ASSERT(U_FAILURE(*status)); + return 0; + } + + return This->fSpoofData->serialize(buf, capacity, *status); +} + +U_CAPI const USet * U_EXPORT2 +uspoof_getInclusionSet(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + return gInclusionSet->toUSet(); +} + +U_CAPI const USet * U_EXPORT2 +uspoof_getRecommendedSet(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + return gRecommendedSet->toUSet(); +} + +U_I18N_API const UnicodeSet * U_EXPORT2 +uspoof_getInclusionUnicodeSet(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + return gInclusionSet; +} + +U_I18N_API const UnicodeSet * U_EXPORT2 +uspoof_getRecommendedUnicodeSet(UErrorCode *status) { + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + return gRecommendedSet; +} + +//------------------ +// CheckResult APIs +//------------------ + +U_CAPI USpoofCheckResult* U_EXPORT2 +uspoof_openCheckResult(UErrorCode *status) { + CheckResult* checkResult = new CheckResult(); + if (checkResult == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + return checkResult->asUSpoofCheckResult(); +} + +U_CAPI void U_EXPORT2 +uspoof_closeCheckResult(USpoofCheckResult* checkResult) { + UErrorCode status = U_ZERO_ERROR; + CheckResult* This = CheckResult::validateThis(checkResult, status); + delete This; +} + +U_CAPI int32_t U_EXPORT2 +uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status) { + const CheckResult* This = CheckResult::validateThis(checkResult, *status); + if (U_FAILURE(*status)) { return 0; } + return This->fChecks; +} + +U_CAPI URestrictionLevel U_EXPORT2 +uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status) { + const CheckResult* This = CheckResult::validateThis(checkResult, *status); + if (U_FAILURE(*status)) { return USPOOF_UNRESTRICTIVE; } + return This->fRestrictionLevel; +} + +U_CAPI const USet* U_EXPORT2 +uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status) { + const CheckResult* This = CheckResult::validateThis(checkResult, *status); + if (U_FAILURE(*status)) { return NULL; } + return This->fNumerics.toUSet(); +} + + + +#endif // !UCONFIG_NO_NORMALIZATION diff --git a/thirdparty/icu4c/i18n/uspoof_impl.cpp b/thirdparty/icu4c/i18n/uspoof_impl.cpp new file mode 100644 index 0000000000..b283d81321 --- /dev/null +++ b/thirdparty/icu4c/i18n/uspoof_impl.cpp @@ -0,0 +1,959 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (C) 2008-2016, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ + +#include "unicode/utypes.h" +#include "unicode/uspoof.h" +#include "unicode/uchar.h" +#include "unicode/uniset.h" +#include "unicode/utf16.h" +#include "utrie2.h" +#include "cmemory.h" +#include "cstring.h" +#include "scriptset.h" +#include "umutex.h" +#include "udataswp.h" +#include "uassert.h" +#include "ucln_in.h" +#include "uspoof_impl.h" + +#if !UCONFIG_NO_NORMALIZATION + + +U_NAMESPACE_BEGIN + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl) + +SpoofImpl::SpoofImpl(SpoofData *data, UErrorCode& status) { + construct(status); + fSpoofData = data; +} + +SpoofImpl::SpoofImpl(UErrorCode& status) { + construct(status); + + // TODO: Call this method where it is actually needed, instead of in the + // constructor, to allow for lazy data loading. See #12696. + fSpoofData = SpoofData::getDefault(status); +} + +SpoofImpl::SpoofImpl() { + UErrorCode status = U_ZERO_ERROR; + construct(status); + + // TODO: Call this method where it is actually needed, instead of in the + // constructor, to allow for lazy data loading. See #12696. + fSpoofData = SpoofData::getDefault(status); +} + +void SpoofImpl::construct(UErrorCode& status) { + fChecks = USPOOF_ALL_CHECKS; + fSpoofData = NULL; + fAllowedCharsSet = NULL; + fAllowedLocales = NULL; + fRestrictionLevel = USPOOF_HIGHLY_RESTRICTIVE; + + if (U_FAILURE(status)) { return; } + + UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff); + fAllowedCharsSet = allowedCharsSet; + fAllowedLocales = uprv_strdup(""); + if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + allowedCharsSet->freeze(); +} + + +// Copy Constructor, used by the user level clone() function. +SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) : + fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) , + fAllowedLocales(NULL) { + if (U_FAILURE(status)) { + return; + } + fChecks = src.fChecks; + if (src.fSpoofData != NULL) { + fSpoofData = src.fSpoofData->addReference(); + } + fAllowedCharsSet = src.fAllowedCharsSet->clone(); + fAllowedLocales = uprv_strdup(src.fAllowedLocales); + if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + } + fRestrictionLevel = src.fRestrictionLevel; +} + +SpoofImpl::~SpoofImpl() { + if (fSpoofData != NULL) { + fSpoofData->removeReference(); // Will delete if refCount goes to zero. + } + delete fAllowedCharsSet; + uprv_free((void *)fAllowedLocales); +} + +// Cast this instance as a USpoofChecker for the C API. +USpoofChecker *SpoofImpl::asUSpoofChecker() { + return exportForC(); +} + +// +// Incoming parameter check on Status and the SpoofChecker object +// received from the C API. +// +const SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) { + auto* This = validate(sc, status); + if (U_FAILURE(status)) { + return NULL; + } + if (This->fSpoofData != NULL && !This->fSpoofData->validateDataVersion(status)) { + return NULL; + } + return This; +} + +SpoofImpl *SpoofImpl::validateThis(USpoofChecker *sc, UErrorCode &status) { + return const_cast<SpoofImpl *> + (SpoofImpl::validateThis(const_cast<const USpoofChecker *>(sc), status)); +} + + +void SpoofImpl::setAllowedLocales(const char *localesList, UErrorCode &status) { + UnicodeSet allowedChars; + UnicodeSet *tmpSet = NULL; + const char *locStart = localesList; + const char *locEnd = NULL; + const char *localesListEnd = localesList + uprv_strlen(localesList); + int32_t localeListCount = 0; // Number of locales provided by caller. + + // Loop runs once per locale from the localesList, a comma separated list of locales. + do { + locEnd = uprv_strchr(locStart, ','); + if (locEnd == NULL) { + locEnd = localesListEnd; + } + while (*locStart == ' ') { + locStart++; + } + const char *trimmedEnd = locEnd-1; + while (trimmedEnd > locStart && *trimmedEnd == ' ') { + trimmedEnd--; + } + if (trimmedEnd <= locStart) { + break; + } + const char *locale = uprv_strndup(locStart, (int32_t)(trimmedEnd + 1 - locStart)); + localeListCount++; + + // We have one locale from the locales list. + // Add the script chars for this locale to the accumulating set of allowed chars. + // If the locale is no good, we will be notified back via status. + addScriptChars(locale, &allowedChars, status); + uprv_free((void *)locale); + if (U_FAILURE(status)) { + break; + } + locStart = locEnd + 1; + } while (locStart < localesListEnd); + + // If our caller provided an empty list of locales, we disable the allowed characters checking + if (localeListCount == 0) { + uprv_free((void *)fAllowedLocales); + fAllowedLocales = uprv_strdup(""); + tmpSet = new UnicodeSet(0, 0x10ffff); + if (fAllowedLocales == NULL || tmpSet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + tmpSet->freeze(); + delete fAllowedCharsSet; + fAllowedCharsSet = tmpSet; + fChecks &= ~USPOOF_CHAR_LIMIT; + return; + } + + + // Add all common and inherited characters to the set of allowed chars. + UnicodeSet tempSet; + tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_COMMON, status); + allowedChars.addAll(tempSet); + tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_INHERITED, status); + allowedChars.addAll(tempSet); + + // If anything went wrong, we bail out without changing + // the state of the spoof checker. + if (U_FAILURE(status)) { + return; + } + + // Store the updated spoof checker state. + tmpSet = allowedChars.clone(); + const char *tmpLocalesList = uprv_strdup(localesList); + if (tmpSet == NULL || tmpLocalesList == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + uprv_free((void *)fAllowedLocales); + fAllowedLocales = tmpLocalesList; + tmpSet->freeze(); + delete fAllowedCharsSet; + fAllowedCharsSet = tmpSet; + fChecks |= USPOOF_CHAR_LIMIT; +} + + +const char * SpoofImpl::getAllowedLocales(UErrorCode &/*status*/) { + return fAllowedLocales; +} + + +// Given a locale (a language), add all the characters from all of the scripts used with that language +// to the allowedChars UnicodeSet + +void SpoofImpl::addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status) { + UScriptCode scripts[30]; + + int32_t numScripts = uscript_getCode(locale, scripts, UPRV_LENGTHOF(scripts), &status); + if (U_FAILURE(status)) { + return; + } + if (status == U_USING_DEFAULT_WARNING) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + UnicodeSet tmpSet; + int32_t i; + for (i=0; i<numScripts; i++) { + tmpSet.applyIntPropertyValue(UCHAR_SCRIPT, scripts[i], status); + allowedChars->addAll(tmpSet); + } +} + +// Computes the augmented script set for a code point, according to UTS 39 section 5.1. +void SpoofImpl::getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status) { + result.resetAll(); + result.setScriptExtensions(codePoint, status); + if (U_FAILURE(status)) { return; } + + // Section 5.1 step 1 + if (result.test(USCRIPT_HAN, status)) { + result.set(USCRIPT_HAN_WITH_BOPOMOFO, status); + result.set(USCRIPT_JAPANESE, status); + result.set(USCRIPT_KOREAN, status); + } + if (result.test(USCRIPT_HIRAGANA, status)) { + result.set(USCRIPT_JAPANESE, status); + } + if (result.test(USCRIPT_KATAKANA, status)) { + result.set(USCRIPT_JAPANESE, status); + } + if (result.test(USCRIPT_HANGUL, status)) { + result.set(USCRIPT_KOREAN, status); + } + if (result.test(USCRIPT_BOPOMOFO, status)) { + result.set(USCRIPT_HAN_WITH_BOPOMOFO, status); + } + + // Section 5.1 step 2 + if (result.test(USCRIPT_COMMON, status) || result.test(USCRIPT_INHERITED, status)) { + result.setAll(); + } +} + +// Computes the resolved script set for a string, according to UTS 39 section 5.1. +void SpoofImpl::getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const { + getResolvedScriptSetWithout(input, USCRIPT_CODE_LIMIT, result, status); +} + +// Computes the resolved script set for a string, omitting characters having the specified script. +// If USCRIPT_CODE_LIMIT is passed as the second argument, all characters are included. +void SpoofImpl::getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const { + result.setAll(); + + ScriptSet temp; + UChar32 codePoint; + for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) { + codePoint = input.char32At(i); + + // Compute the augmented script set for the character + getAugmentedScriptSet(codePoint, temp, status); + if (U_FAILURE(status)) { return; } + + // Intersect the augmented script set with the resolved script set, but only if the character doesn't + // have the script specified in the function call + if (script == USCRIPT_CODE_LIMIT || !temp.test(script, status)) { + result.intersect(temp); + } + } +} + +// Computes the set of numerics for a string, according to UTS 39 section 5.3. +void SpoofImpl::getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& /*status*/) const { + result.clear(); + + UChar32 codePoint; + for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) { + codePoint = input.char32At(i); + + // Store a representative character for each kind of decimal digit + if (u_charType(codePoint) == U_DECIMAL_DIGIT_NUMBER) { + // Store the zero character as a representative for comparison. + // Unicode guarantees it is codePoint - value + result.add(codePoint - (UChar32)u_getNumericValue(codePoint)); + } + } +} + +// Computes the restriction level of a string, according to UTS 39 section 5.2. +URestrictionLevel SpoofImpl::getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const { + // Section 5.2 step 1: + if (!fAllowedCharsSet->containsAll(input)) { + return USPOOF_UNRESTRICTIVE; + } + + // Section 5.2 step 2 + // Java use a static UnicodeSet for this test. In C++, avoid the static variable + // and just do a simple for loop. + UBool allASCII = TRUE; + for (int32_t i=0, length=input.length(); i<length; i++) { + if (input.charAt(i) > 0x7f) { + allASCII = FALSE; + break; + } + } + if (allASCII) { + return USPOOF_ASCII; + } + + // Section 5.2 steps 3: + ScriptSet resolvedScriptSet; + getResolvedScriptSet(input, resolvedScriptSet, status); + if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; } + + // Section 5.2 step 4: + if (!resolvedScriptSet.isEmpty()) { + return USPOOF_SINGLE_SCRIPT_RESTRICTIVE; + } + + // Section 5.2 step 5: + ScriptSet resolvedNoLatn; + getResolvedScriptSetWithout(input, USCRIPT_LATIN, resolvedNoLatn, status); + if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; } + + // Section 5.2 step 6: + if (resolvedNoLatn.test(USCRIPT_HAN_WITH_BOPOMOFO, status) + || resolvedNoLatn.test(USCRIPT_JAPANESE, status) + || resolvedNoLatn.test(USCRIPT_KOREAN, status)) { + return USPOOF_HIGHLY_RESTRICTIVE; + } + + // Section 5.2 step 7: + if (!resolvedNoLatn.isEmpty() + && !resolvedNoLatn.test(USCRIPT_CYRILLIC, status) + && !resolvedNoLatn.test(USCRIPT_GREEK, status) + && !resolvedNoLatn.test(USCRIPT_CHEROKEE, status)) { + return USPOOF_MODERATELY_RESTRICTIVE; + } + + // Section 5.2 step 8: + return USPOOF_MINIMALLY_RESTRICTIVE; +} + +int32_t SpoofImpl::findHiddenOverlay(const UnicodeString& input, UErrorCode&) const { + bool sawLeadCharacter = false; + for (int32_t i=0; i<input.length();) { + UChar32 cp = input.char32At(i); + if (sawLeadCharacter && cp == 0x0307) { + return i; + } + uint8_t combiningClass = u_getCombiningClass(cp); + // Skip over characters except for those with combining class 0 (non-combining characters) or with + // combining class 230 (same class as U+0307) + U_ASSERT(u_getCombiningClass(0x0307) == 230); + if (combiningClass == 0 || combiningClass == 230) { + sawLeadCharacter = isIllegalCombiningDotLeadCharacter(cp); + } + i += U16_LENGTH(cp); + } + return -1; +} + +static inline bool isIllegalCombiningDotLeadCharacterNoLookup(UChar32 cp) { + return cp == u'i' || cp == u'j' || cp == u'ı' || cp == u'È·' || cp == u'l' || + u_hasBinaryProperty(cp, UCHAR_SOFT_DOTTED); +} + +bool SpoofImpl::isIllegalCombiningDotLeadCharacter(UChar32 cp) const { + if (isIllegalCombiningDotLeadCharacterNoLookup(cp)) { + return true; + } + UnicodeString skelStr; + fSpoofData->confusableLookup(cp, skelStr); + UChar32 finalCp = skelStr.char32At(skelStr.moveIndex32(skelStr.length(), -1)); + if (finalCp != cp && isIllegalCombiningDotLeadCharacterNoLookup(finalCp)) { + return true; + } + return false; +} + + + +// Convert a text format hex number. Utility function used by builder code. Static. +// Input: UChar *string text. Output: a UChar32 +// Input has been pre-checked, and will have no non-hex chars. +// The number must fall in the code point range of 0..0x10ffff +// Static Function. +UChar32 SpoofImpl::ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status) { + if (U_FAILURE(status)) { + return 0; + } + U_ASSERT(limit-start > 0); + uint32_t val = 0; + int i; + for (i=start; i<limit; i++) { + int digitVal = s[i] - 0x30; + if (digitVal>9) { + digitVal = 0xa + (s[i] - 0x41); // Upper Case 'A' + } + if (digitVal>15) { + digitVal = 0xa + (s[i] - 0x61); // Lower Case 'a' + } + U_ASSERT(digitVal <= 0xf); + val <<= 4; + val += digitVal; + } + if (val > 0x10ffff) { + status = U_PARSE_ERROR; + val = 0; + } + return (UChar32)val; +} + + +//----------------------------------------- +// +// class CheckResult Implementation +// +//----------------------------------------- + +CheckResult::CheckResult() { + clear(); +} + +USpoofCheckResult* CheckResult::asUSpoofCheckResult() { + return exportForC(); +} + +// +// Incoming parameter check on Status and the CheckResult object +// received from the C API. +// +const CheckResult* CheckResult::validateThis(const USpoofCheckResult *ptr, UErrorCode &status) { + return validate(ptr, status); +} + +CheckResult* CheckResult::validateThis(USpoofCheckResult *ptr, UErrorCode &status) { + return validate(ptr, status); +} + +void CheckResult::clear() { + fChecks = 0; + fNumerics.clear(); + fRestrictionLevel = USPOOF_UNDEFINED_RESTRICTIVE; +} + +int32_t CheckResult::toCombinedBitmask(int32_t enabledChecks) { + if ((enabledChecks & USPOOF_AUX_INFO) != 0 && fRestrictionLevel != USPOOF_UNDEFINED_RESTRICTIVE) { + return fChecks | fRestrictionLevel; + } else { + return fChecks; + } +} + +CheckResult::~CheckResult() { +} + +//---------------------------------------------------------------------------------------------- +// +// class SpoofData Implementation +// +//---------------------------------------------------------------------------------------------- + + +UBool SpoofData::validateDataVersion(UErrorCode &status) const { + if (U_FAILURE(status) || + fRawData == NULL || + fRawData->fMagic != USPOOF_MAGIC || + fRawData->fFormatVersion[0] != USPOOF_CONFUSABLE_DATA_FORMAT_VERSION || + fRawData->fFormatVersion[1] != 0 || + fRawData->fFormatVersion[2] != 0 || + fRawData->fFormatVersion[3] != 0) { + status = U_INVALID_FORMAT_ERROR; + return FALSE; + } + return TRUE; +} + +static UBool U_CALLCONV +spoofDataIsAcceptable(void *context, + const char * /* type */, const char * /*name*/, + const UDataInfo *pInfo) { + if( + pInfo->size >= 20 && + pInfo->isBigEndian == U_IS_BIG_ENDIAN && + pInfo->charsetFamily == U_CHARSET_FAMILY && + pInfo->dataFormat[0] == 0x43 && // dataFormat="Cfu " + pInfo->dataFormat[1] == 0x66 && + pInfo->dataFormat[2] == 0x75 && + pInfo->dataFormat[3] == 0x20 && + pInfo->formatVersion[0] == USPOOF_CONFUSABLE_DATA_FORMAT_VERSION + ) { + UVersionInfo *version = static_cast<UVersionInfo *>(context); + if(version != NULL) { + uprv_memcpy(version, pInfo->dataVersion, 4); + } + return TRUE; + } else { + return FALSE; + } +} + +// Methods for the loading of the default confusables data file. The confusable +// data is loaded only when it is needed. +// +// SpoofData::getDefault() - Return the default confusables data, and call the +// initOnce() if it is not available. Adds a reference +// to the SpoofData that the caller is responsible for +// decrementing when they are done with the data. +// +// uspoof_loadDefaultData - Called once, from initOnce(). The resulting SpoofData +// is shared by all spoof checkers using the default data. +// +// uspoof_cleanupDefaultData - Called during cleanup. +// + +static UInitOnce gSpoofInitDefaultOnce = U_INITONCE_INITIALIZER; +static SpoofData* gDefaultSpoofData; + +static UBool U_CALLCONV +uspoof_cleanupDefaultData(void) { + if (gDefaultSpoofData) { + // Will delete, assuming all user-level spoof checkers were closed. + gDefaultSpoofData->removeReference(); + gDefaultSpoofData = nullptr; + gSpoofInitDefaultOnce.reset(); + } + return TRUE; +} + +static void U_CALLCONV uspoof_loadDefaultData(UErrorCode& status) { + UDataMemory *udm = udata_openChoice(nullptr, "cfu", "confusables", + spoofDataIsAcceptable, + nullptr, // context, would receive dataVersion if supplied. + &status); + if (U_FAILURE(status)) { return; } + gDefaultSpoofData = new SpoofData(udm, status); + if (U_FAILURE(status)) { + delete gDefaultSpoofData; + gDefaultSpoofData = nullptr; + return; + } + if (gDefaultSpoofData == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_i18n_registerCleanup(UCLN_I18N_SPOOFDATA, uspoof_cleanupDefaultData); +} + +SpoofData* SpoofData::getDefault(UErrorCode& status) { + umtx_initOnce(gSpoofInitDefaultOnce, &uspoof_loadDefaultData, status); + if (U_FAILURE(status)) { return NULL; } + gDefaultSpoofData->addReference(); + return gDefaultSpoofData; +} + + + +SpoofData::SpoofData(UDataMemory *udm, UErrorCode &status) +{ + reset(); + if (U_FAILURE(status)) { + return; + } + fUDM = udm; + // fRawData is non-const because it may be constructed by the data builder. + fRawData = reinterpret_cast<SpoofDataHeader *>( + const_cast<void *>(udata_getMemory(udm))); + validateDataVersion(status); + initPtrs(status); +} + + +SpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status) +{ + reset(); + if (U_FAILURE(status)) { + return; + } + if ((size_t)length < sizeof(SpoofDataHeader)) { + status = U_INVALID_FORMAT_ERROR; + return; + } + if (data == NULL) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + void *ncData = const_cast<void *>(data); + fRawData = static_cast<SpoofDataHeader *>(ncData); + if (length < fRawData->fLength) { + status = U_INVALID_FORMAT_ERROR; + return; + } + validateDataVersion(status); + initPtrs(status); +} + + +// Spoof Data constructor for use from data builder. +// Initializes a new, empty data area that will be populated later. +SpoofData::SpoofData(UErrorCode &status) { + reset(); + if (U_FAILURE(status)) { + return; + } + fDataOwned = true; + + // The spoof header should already be sized to be a multiple of 16 bytes. + // Just in case it's not, round it up. + uint32_t initialSize = (sizeof(SpoofDataHeader) + 15) & ~15; + U_ASSERT(initialSize == sizeof(SpoofDataHeader)); + + fRawData = static_cast<SpoofDataHeader *>(uprv_malloc(initialSize)); + fMemLimit = initialSize; + if (fRawData == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + uprv_memset(fRawData, 0, initialSize); + + fRawData->fMagic = USPOOF_MAGIC; + fRawData->fFormatVersion[0] = USPOOF_CONFUSABLE_DATA_FORMAT_VERSION; + fRawData->fFormatVersion[1] = 0; + fRawData->fFormatVersion[2] = 0; + fRawData->fFormatVersion[3] = 0; + initPtrs(status); +} + +// reset() - initialize all fields. +// Should be updated if any new fields are added. +// Called by constructors to put things in a known initial state. +void SpoofData::reset() { + fRawData = NULL; + fDataOwned = FALSE; + fUDM = NULL; + fMemLimit = 0; + fRefCount = 1; + fCFUKeys = NULL; + fCFUValues = NULL; + fCFUStrings = NULL; +} + + +// SpoofData::initPtrs() +// Initialize the pointers to the various sections of the raw data. +// +// This function is used both during the Trie building process (multiple +// times, as the individual data sections are added), and +// during the opening of a Spoof Checker from prebuilt data. +// +// The pointers for non-existent data sections (identified by an offset of 0) +// are set to NULL. +// +// Note: During building the data, adding each new data section +// reallocs the raw data area, which likely relocates it, which +// in turn requires reinitializing all of the pointers into it, hence +// multiple calls to this function during building. +// +void SpoofData::initPtrs(UErrorCode &status) { + fCFUKeys = NULL; + fCFUValues = NULL; + fCFUStrings = NULL; + if (U_FAILURE(status)) { + return; + } + if (fRawData->fCFUKeys != 0) { + fCFUKeys = (int32_t *)((char *)fRawData + fRawData->fCFUKeys); + } + if (fRawData->fCFUStringIndex != 0) { + fCFUValues = (uint16_t *)((char *)fRawData + fRawData->fCFUStringIndex); + } + if (fRawData->fCFUStringTable != 0) { + fCFUStrings = (UChar *)((char *)fRawData + fRawData->fCFUStringTable); + } +} + + +SpoofData::~SpoofData() { + if (fDataOwned) { + uprv_free(fRawData); + } + fRawData = NULL; + if (fUDM != NULL) { + udata_close(fUDM); + } + fUDM = NULL; +} + + +void SpoofData::removeReference() { + if (umtx_atomic_dec(&fRefCount) == 0) { + delete this; + } +} + + +SpoofData *SpoofData::addReference() { + umtx_atomic_inc(&fRefCount); + return this; +} + + +void *SpoofData::reserveSpace(int32_t numBytes, UErrorCode &status) { + if (U_FAILURE(status)) { + return NULL; + } + if (!fDataOwned) { + UPRV_UNREACHABLE_EXIT; + } + + numBytes = (numBytes + 15) & ~15; // Round up to a multiple of 16 + uint32_t returnOffset = fMemLimit; + fMemLimit += numBytes; + fRawData = static_cast<SpoofDataHeader *>(uprv_realloc(fRawData, fMemLimit)); + fRawData->fLength = fMemLimit; + uprv_memset((char *)fRawData + returnOffset, 0, numBytes); + initPtrs(status); + return (char *)fRawData + returnOffset; +} + +int32_t SpoofData::serialize(void *buf, int32_t capacity, UErrorCode &status) const { + int32_t dataSize = fRawData->fLength; + if (capacity < dataSize) { + status = U_BUFFER_OVERFLOW_ERROR; + return dataSize; + } + uprv_memcpy(buf, fRawData, dataSize); + return dataSize; +} + +int32_t SpoofData::size() const { + return fRawData->fLength; +} + +//------------------------------- +// +// Front-end APIs for SpoofData +// +//------------------------------- + +int32_t SpoofData::confusableLookup(UChar32 inChar, UnicodeString &dest) const { + // Perform a binary search. + // [lo, hi), i.e lo is inclusive, hi is exclusive. + // The result after the loop will be in lo. + int32_t lo = 0; + int32_t hi = length(); + do { + int32_t mid = (lo + hi) / 2; + if (codePointAt(mid) > inChar) { + hi = mid; + } else if (codePointAt(mid) < inChar) { + lo = mid; + } else { + // Found result. Break early. + lo = mid; + break; + } + } while (hi - lo > 1); + + // Did we find an entry? If not, the char maps to itself. + if (codePointAt(lo) != inChar) { + dest.append(inChar); + return 1; + } + + // Add the element to the string builder and return. + return appendValueTo(lo, dest); +} + +int32_t SpoofData::length() const { + return fRawData->fCFUKeysSize; +} + +UChar32 SpoofData::codePointAt(int32_t index) const { + return ConfusableDataUtils::keyToCodePoint(fCFUKeys[index]); +} + +int32_t SpoofData::appendValueTo(int32_t index, UnicodeString& dest) const { + int32_t stringLength = ConfusableDataUtils::keyToLength(fCFUKeys[index]); + + // Value is either a char (for strings of length 1) or + // an index into the string table (for longer strings) + uint16_t value = fCFUValues[index]; + if (stringLength == 1) { + dest.append((UChar)value); + } else { + dest.append(fCFUStrings + value, stringLength); + } + + return stringLength; +} + + +U_NAMESPACE_END + +U_NAMESPACE_USE + +//----------------------------------------------------------------------------- +// +// uspoof_swap - byte swap and char encoding swap of spoof data +// +//----------------------------------------------------------------------------- +U_CAPI int32_t U_EXPORT2 +uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, + UErrorCode *status) { + + if (status == NULL || U_FAILURE(*status)) { + return 0; + } + if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) { + *status=U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + // + // Check that the data header is for spoof data. + // (Header contents are defined in gencfu.cpp) + // + const UDataInfo *pInfo = (const UDataInfo *)((const char *)inData+4); + if(!( pInfo->dataFormat[0]==0x43 && /* dataFormat="Cfu " */ + pInfo->dataFormat[1]==0x66 && + pInfo->dataFormat[2]==0x75 && + pInfo->dataFormat[3]==0x20 && + pInfo->formatVersion[0]==USPOOF_CONFUSABLE_DATA_FORMAT_VERSION && + pInfo->formatVersion[1]==0 && + pInfo->formatVersion[2]==0 && + pInfo->formatVersion[3]==0 )) { + udata_printError(ds, "uspoof_swap(): data format %02x.%02x.%02x.%02x " + "(format version %02x %02x %02x %02x) is not recognized\n", + pInfo->dataFormat[0], pInfo->dataFormat[1], + pInfo->dataFormat[2], pInfo->dataFormat[3], + pInfo->formatVersion[0], pInfo->formatVersion[1], + pInfo->formatVersion[2], pInfo->formatVersion[3]); + *status=U_UNSUPPORTED_ERROR; + return 0; + } + + // + // Swap the data header. (This is the generic ICU Data Header, not the uspoof Specific + // header). This swap also conveniently gets us + // the size of the ICU d.h., which lets us locate the start + // of the uspoof specific data. + // + int32_t headerSize=udata_swapDataHeader(ds, inData, length, outData, status); + + + // + // Get the Spoof Data Header, and check that it appears to be OK. + // + // + const uint8_t *inBytes =(const uint8_t *)inData+headerSize; + SpoofDataHeader *spoofDH = (SpoofDataHeader *)inBytes; + if (ds->readUInt32(spoofDH->fMagic) != USPOOF_MAGIC || + ds->readUInt32(spoofDH->fLength) < sizeof(SpoofDataHeader)) + { + udata_printError(ds, "uspoof_swap(): Spoof Data header is invalid.\n"); + *status=U_UNSUPPORTED_ERROR; + return 0; + } + + // + // Prefight operation? Just return the size + // + int32_t spoofDataLength = ds->readUInt32(spoofDH->fLength); + int32_t totalSize = headerSize + spoofDataLength; + if (length < 0) { + return totalSize; + } + + // + // Check that length passed in is consistent with length from Spoof data header. + // + if (length < totalSize) { + udata_printError(ds, "uspoof_swap(): too few bytes (%d after ICU Data header) for spoof data.\n", + spoofDataLength); + *status=U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + + // + // Swap the Data. Do the data itself first, then the Spoof Data Header, because + // we need to reference the header to locate the data, and an + // inplace swap of the header leaves it unusable. + // + uint8_t *outBytes = (uint8_t *)outData + headerSize; + SpoofDataHeader *outputDH = (SpoofDataHeader *)outBytes; + + int32_t sectionStart; + int32_t sectionLength; + + // + // If not swapping in place, zero out the output buffer before starting. + // Gaps may exist between the individual sections, and these must be zeroed in + // the output buffer. The simplest way to do that is to just zero the whole thing. + // + if (inBytes != outBytes) { + uprv_memset(outBytes, 0, spoofDataLength); + } + + // Confusables Keys Section (fCFUKeys) + sectionStart = ds->readUInt32(spoofDH->fCFUKeys); + sectionLength = ds->readUInt32(spoofDH->fCFUKeysSize) * 4; + ds->swapArray32(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); + + // String Index Section + sectionStart = ds->readUInt32(spoofDH->fCFUStringIndex); + sectionLength = ds->readUInt32(spoofDH->fCFUStringIndexSize) * 2; + ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); + + // String Table Section + sectionStart = ds->readUInt32(spoofDH->fCFUStringTable); + sectionLength = ds->readUInt32(spoofDH->fCFUStringTableLen) * 2; + ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); + + // And, last, swap the header itself. + // int32_t fMagic // swap this + // uint8_t fFormatVersion[4] // Do not swap this, just copy + // int32_t fLength and all the rest // Swap the rest, all is 32 bit stuff. + // + uint32_t magic = ds->readUInt32(spoofDH->fMagic); + ds->writeUInt32((uint32_t *)&outputDH->fMagic, magic); + + if (outputDH->fFormatVersion != spoofDH->fFormatVersion) { + uprv_memcpy(outputDH->fFormatVersion, spoofDH->fFormatVersion, sizeof(spoofDH->fFormatVersion)); + } + // swap starting at fLength + ds->swapArray32(ds, &spoofDH->fLength, sizeof(SpoofDataHeader)-8 /* minus magic and fFormatVersion[4] */, &outputDH->fLength, status); + + return totalSize; +} + +#endif + + diff --git a/thirdparty/icu4c/i18n/uspoof_impl.h b/thirdparty/icu4c/i18n/uspoof_impl.h new file mode 100644 index 0000000000..e75ae262bd --- /dev/null +++ b/thirdparty/icu4c/i18n/uspoof_impl.h @@ -0,0 +1,343 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +*************************************************************************** +* Copyright (C) 2008-2013, International Business Machines Corporation +* and others. All Rights Reserved. +*************************************************************************** +* +* uspoof_impl.h +* +* Implementation header for spoof detection +* +*/ + +#ifndef USPOOFIM_H +#define USPOOFIM_H + +#include "uassert.h" +#include "unicode/utypes.h" +#include "unicode/uspoof.h" +#include "unicode/uscript.h" +#include "unicode/udata.h" +#include "udataswp.h" +#include "utrie2.h" + +#if !UCONFIG_NO_NORMALIZATION + +#ifdef __cplusplus + +#include "capi_helper.h" + +U_NAMESPACE_BEGIN + +// The maximum length (in UTF-16 UChars) of the skeleton replacement string resulting from +// a single input code point. This is function of the unicode.org data. +#define USPOOF_MAX_SKELETON_EXPANSION 20 + +// The default stack buffer size for copies or conversions or normalizations +// of input strings being checked. (Used in multiple places.) +#define USPOOF_STACK_BUFFER_SIZE 100 + +// Magic number for sanity checking spoof data. +#define USPOOF_MAGIC 0x3845fdef + +// Magic number for sanity checking spoof checkers. +#define USPOOF_CHECK_MAGIC 0x2734ecde + +class ScriptSet; +class SpoofData; +struct SpoofDataHeader; +class ConfusableDataUtils; + +/** + * Class SpoofImpl corresponds directly to the plain C API opaque type + * USpoofChecker. One can be cast to the other. + */ +class SpoofImpl : public UObject, + public IcuCApiHelper<USpoofChecker, SpoofImpl, USPOOF_MAGIC> { +public: + SpoofImpl(SpoofData *data, UErrorCode& status); + SpoofImpl(UErrorCode& status); + SpoofImpl(); + void construct(UErrorCode& status); + virtual ~SpoofImpl(); + + /** Copy constructor, used by the user level uspoof_clone() function. + */ + SpoofImpl(const SpoofImpl &src, UErrorCode &status); + + USpoofChecker *asUSpoofChecker(); + static SpoofImpl *validateThis(USpoofChecker *sc, UErrorCode &status); + static const SpoofImpl *validateThis(const USpoofChecker *sc, UErrorCode &status); + + /** Set and Get AllowedLocales, implementations of the corresponding API */ + void setAllowedLocales(const char *localesList, UErrorCode &status); + const char * getAllowedLocales(UErrorCode &status); + + // Add (union) to the UnicodeSet all of the characters for the scripts used for + // the specified locale. Part of the implementation of setAllowedLocales. + void addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status); + + // Functions implementing the features of UTS 39 section 5. + static void getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status); + void getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const; + void getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const; + void getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& status) const; + URestrictionLevel getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const; + + int32_t findHiddenOverlay(const UnicodeString& input, UErrorCode& status) const; + bool isIllegalCombiningDotLeadCharacter(UChar32 cp) const; + + /** parse a hex number. Untility used by the builders. */ + static UChar32 ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status); + + static UClassID U_EXPORT2 getStaticClassID(void); + virtual UClassID getDynamicClassID(void) const override; + + // + // Data Members + // + + int32_t fChecks; // Bit vector of checks to perform. + + SpoofData *fSpoofData; + + const UnicodeSet *fAllowedCharsSet; // The UnicodeSet of allowed characters. + // for this Spoof Checker. Defaults to all chars. + + const char *fAllowedLocales; // The list of allowed locales. + URestrictionLevel fRestrictionLevel; // The maximum restriction level for an acceptable identifier. +}; + +/** + * Class CheckResult corresponds directly to the plain C API opaque type + * USpoofCheckResult. One can be cast to the other. + */ +class CheckResult : public UObject, + public IcuCApiHelper<USpoofCheckResult, CheckResult, USPOOF_CHECK_MAGIC> { +public: + CheckResult(); + virtual ~CheckResult(); + + USpoofCheckResult *asUSpoofCheckResult(); + static CheckResult *validateThis(USpoofCheckResult *ptr, UErrorCode &status); + static const CheckResult *validateThis(const USpoofCheckResult *ptr, UErrorCode &status); + + void clear(); + + // Used to convert this CheckResult to the older int32_t return value API + int32_t toCombinedBitmask(int32_t expectedChecks); + + // Data Members + int32_t fChecks; // Bit vector of checks that were failed. + UnicodeSet fNumerics; // Set of numerics found in the string. + URestrictionLevel fRestrictionLevel; // The restriction level of the string. +}; + + +// +// Confusable Mappings Data Structures, version 2.0 +// +// For the confusable data, we are essentially implementing a map, +// key: a code point +// value: a string. Most commonly one char in length, but can be more. +// +// The keys are stored as a sorted array of 32 bit ints. +// bits 0-23 a code point value +// bits 24-31 length of value string, in UChars (between 1 and 256 UChars). +// The key table is sorted in ascending code point order. (not on the +// 32 bit int value, the flag bits do not participate in the sorting.) +// +// Lookup is done by means of a binary search in the key table. +// +// The corresponding values are kept in a parallel array of 16 bit ints. +// If the value string is of length 1, it is literally in the value array. +// For longer strings, the value array contains an index into the strings table. +// +// String Table: +// The strings table contains all of the value strings (those of length two or greater) +// concatenated together into one long UChar (UTF-16) array. +// +// There is no nul character or other mark between adjacent strings. +// +//---------------------------------------------------------------------------- +// +// Changes from format version 1 to format version 2: +// 1) Removal of the whole-script confusable data tables. +// 2) Removal of the SL/SA/ML/MA and multi-table flags in the key bitmask. +// 3) Expansion of string length value in the key bitmask from 2 bits to 8 bits. +// 4) Removal of the string lengths table since 8 bits is sufficient for the +// lengths of all entries in confusables.txt. + + + +// Internal functions for manipulating confusable data table keys +#define USPOOF_CONFUSABLE_DATA_FORMAT_VERSION 2 // version for ICU 58 +class ConfusableDataUtils { +public: + inline static UChar32 keyToCodePoint(int32_t key) { + return key & 0x00ffffff; + } + inline static int32_t keyToLength(int32_t key) { + return ((key & 0xff000000) >> 24) + 1; + } + inline static int32_t codePointAndLengthToKey(UChar32 codePoint, int32_t length) { + U_ASSERT((codePoint & 0x00ffffff) == codePoint); + U_ASSERT(length <= 256); + return codePoint | ((length - 1) << 24); + } +}; + + +//------------------------------------------------------------------------------------- +// +// SpoofData +// +// A small class that wraps the raw (usually memory mapped) spoof data. +// Serves two primary functions: +// 1. Convenience. Contains real pointers to the data, to avoid dealing with +// the offsets in the raw data. +// 2. Reference counting. When a spoof checker is cloned, the raw data is shared +// and must be retained until all checkers using the data are closed. +// Nothing in this struct includes state that is specific to any particular +// USpoofDetector object. +// +//--------------------------------------------------------------------------------------- +class SpoofData: public UMemory { + public: + static SpoofData* getDefault(UErrorCode &status); // Get standard ICU spoof data. + static void releaseDefault(); // Cleanup reference to default spoof data. + + SpoofData(UErrorCode &status); // Create new spoof data wrapper. + // Only used when building new data from rules. + + // Constructor for use when creating from prebuilt default data. + // A UDataMemory is what the ICU internal data loading functions provide. + // The udm is adopted by the SpoofData. + SpoofData(UDataMemory *udm, UErrorCode &status); + + // Constructor for use when creating from serialized data. + // + SpoofData(const void *serializedData, int32_t length, UErrorCode &status); + + // Check raw Spoof Data Version compatibility. + // Return true it looks good. + UBool validateDataVersion(UErrorCode &status) const; + + ~SpoofData(); // Destructor not normally used. + // Use removeReference() instead. + // Reference Counting functions. + // Clone of a user-level spoof detector increments the ref count on the data. + // Close of a user-level spoof detector decrements the ref count. + // If the data is owned by us, it will be deleted when count goes to zero. + SpoofData *addReference(); + void removeReference(); + + // Reset all fields to an initial state. + // Called from the top of all constructors. + void reset(); + + // Copy this instance's raw data buffer to the specified address. + int32_t serialize(void *buf, int32_t capacity, UErrorCode &status) const; + + // Get the total number of bytes of data backed by this SpoofData. + // Not to be confused with length, which returns the number of confusable entries. + int32_t size() const; + + // Get the confusable skeleton transform for a single code point. + // The result is a string with a length between 1 and 18 as of Unicode 9. + // This is the main public endpoint for this class. + // @return The length in UTF-16 code units of the substitution string. + int32_t confusableLookup(UChar32 inChar, UnicodeString &dest) const; + + // Get the number of confusable entries in this SpoofData. + int32_t length() const; + + // Get the code point (key) at the specified index. + UChar32 codePointAt(int32_t index) const; + + // Get the confusable skeleton (value) at the specified index. + // Append it to the specified UnicodeString&. + // @return The length in UTF-16 code units of the skeleton string. + int32_t appendValueTo(int32_t index, UnicodeString& dest) const; + + private: + // Reserve space in the raw data. For use by builder when putting together a + // new set of data. Init the new storage to zero, to prevent inconsistent + // results if it is not all otherwise set by the requester. + // Return: + // pointer to the new space that was added by this function. + void *reserveSpace(int32_t numBytes, UErrorCode &status); + + // initialize the pointers from this object to the raw data. + void initPtrs(UErrorCode &status); + + SpoofDataHeader *fRawData; // Ptr to the raw memory-mapped data + UBool fDataOwned; // True if the raw data is owned, and needs + // to be deleted when refcount goes to zero. + UDataMemory *fUDM; // If not NULL, our data came from a + // UDataMemory, which we must close when + // we are done. + + uint32_t fMemLimit; // Limit of available raw data space + u_atomic_int32_t fRefCount; + + // Confusable data + int32_t *fCFUKeys; + uint16_t *fCFUValues; + UChar *fCFUStrings; + + friend class ConfusabledataBuilder; +}; + +//--------------------------------------------------------------------------------------- +// +// Raw Binary Data Formats, as loaded from the ICU data file, +// or as built by the builder. +// +//--------------------------------------------------------------------------------------- +struct SpoofDataHeader { + int32_t fMagic; // (0x3845fdef) + uint8_t fFormatVersion[4]; // Data Format. Same as the value in struct UDataInfo + // if there is one associated with this data. + int32_t fLength; // Total length in bytes of this spoof data, + // including all sections, not just the header. + + // The following four sections refer to data representing the confusable data + // from the Unicode.org data from "confusables.txt" + + int32_t fCFUKeys; // byte offset to Keys table (from SpoofDataHeader *) + int32_t fCFUKeysSize; // number of entries in keys table (32 bits each) + + // TODO: change name to fCFUValues, for consistency. + int32_t fCFUStringIndex; // byte offset to String Indexes table + int32_t fCFUStringIndexSize; // number of entries in String Indexes table (16 bits each) + // (number of entries must be same as in Keys table + + int32_t fCFUStringTable; // byte offset of String table + int32_t fCFUStringTableLen; // length of string table (in 16 bit UChars) + + // The following sections are for data from xidmodifications.txt + + int32_t unused[15]; // Padding, Room for Expansion +}; + + + +U_NAMESPACE_END +#endif /* __cplusplus */ + +/** + * Endianness swap function for binary spoof data. + * @internal + */ +U_CAPI int32_t U_EXPORT2 +uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, + UErrorCode *status); + + +#endif + +#endif /* USPOOFIM_H */ + diff --git a/thirdparty/icu4c/icudt71l.dat b/thirdparty/icu4c/icudt71l.dat Binary files differindex 4c2c1c4d16..3fa3af9c23 100644 --- a/thirdparty/icu4c/icudt71l.dat +++ b/thirdparty/icu4c/icudt71l.dat diff --git a/thirdparty/mbedtls/LICENSE b/thirdparty/mbedtls/LICENSE index e15ea821d2..d645695673 100644 --- a/thirdparty/mbedtls/LICENSE +++ b/thirdparty/mbedtls/LICENSE @@ -1,5 +1,202 @@ -Unless specifically indicated otherwise in a file, Mbed TLS files are provided -under the Apache License 2.0, or the GNU General Public License v2.0 or later -(SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later). -A copy of these licenses can be found in apache-2.0.txt and gpl-2.0.txt + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/thirdparty/mbedtls/apache-2.0.txt b/thirdparty/mbedtls/apache-2.0.txt deleted file mode 100644 index d645695673..0000000000 --- a/thirdparty/mbedtls/apache-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index e280dbb1c6..401ac39de8 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -564,7 +564,7 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * - * Note that for both stategies, sizes are measured in blocks and + * Note that for both strategies, sizes are measured in blocks and * that an AES block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h index 226e2dbf3c..d294c47f2d 100644 --- a/thirdparty/mbedtls/include/mbedtls/aria.h +++ b/thirdparty/mbedtls/include/mbedtls/aria.h @@ -44,7 +44,7 @@ #define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ #define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ -#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */ #define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) @@ -321,7 +321,7 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * - * Note that for both stategies, sizes are measured in blocks and + * Note that for both strategies, sizes are measured in blocks and * that an ARIA block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its diff --git a/thirdparty/mbedtls/include/mbedtls/asn1.h b/thirdparty/mbedtls/include/mbedtls/asn1.h index 10f7905b7e..5117fc7a41 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1.h @@ -61,7 +61,7 @@ /** Buffer too small when writing ASN.1 data structure. */ #define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C -/* \} name */ +/** \} name ASN1 Error codes */ /** * \name DER constants @@ -121,8 +121,7 @@ #define MBEDTLS_ASN1_TAG_PC_MASK 0x20 #define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F -/* \} name */ -/* \} addtogroup asn1_module */ +/** \} name DER constants */ /** Returns the size of the binary string, without the trailing \\0 */ #define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) @@ -210,7 +209,7 @@ mbedtls_asn1_named_data; * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. - * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_len( unsigned char **p, const unsigned char *end, @@ -235,7 +234,7 @@ int mbedtls_asn1_get_len( unsigned char **p, * with the requested tag. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. - * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_tag( unsigned char **p, const unsigned char *end, @@ -607,6 +606,9 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); */ void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); +/** \} name Functions to parse ASN.1 data structures */ +/** \} addtogroup asn1_module */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h index 9d2cff3275..dd594c512d 100644 --- a/thirdparty/mbedtls/include/mbedtls/bignum.h +++ b/thirdparty/mbedtls/include/mbedtls/bignum.h @@ -989,7 +989,7 @@ MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, * generate yourself and that are supposed to be prime, then * \p rounds should be at least the half of the security * strength of the cryptographic algorithm. On the other hand, - * if \p X is chosen uniformly or non-adversially (as is the + * if \p X is chosen uniformly or non-adversarially (as is the * case when mbedtls_mpi_gen_prime calls this function), then * \p rounds can be much lower. * diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h index 77dca70d31..d5f809921f 100644 --- a/thirdparty/mbedtls/include/mbedtls/blowfish.h +++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h @@ -185,7 +185,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or * #MBEDTLS_BLOWFISH_DECRYPT for decryption. * \param length The length of the input data in Bytes. - * \param iv_off The offset in the initialiation vector. + * \param iv_off The offset in the initialization vector. * The value pointed to must be smaller than \c 8 Bytes. * It is updated by this function to support the aforementioned * streaming usage. @@ -246,7 +246,7 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, * The recommended way to ensure uniqueness is to use a message * counter. * - * Note that for both stategies, sizes are measured in blocks and + * Note that for both strategies, sizes are measured in blocks and * that a Blowfish block is 8 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h index 925a623e47..d39d932fa2 100644 --- a/thirdparty/mbedtls/include/mbedtls/camellia.h +++ b/thirdparty/mbedtls/include/mbedtls/camellia.h @@ -273,7 +273,7 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, * encrypted: for example, with 96-bit random nonces, you should * not encrypt more than 2**32 messages with the same key. * - * Note that for both stategies, sizes are measured in blocks and + * Note that for both strategies, sizes are measured in blocks and * that a CAMELLIA block is \c 16 Bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h index c4ec7b5f2a..ed568bc98b 100644 --- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -161,7 +161,7 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, * \param ctx The ChaCha20-Poly1305 context. This must be initialized * and bound to a key. * \param nonce The nonce/IV to use for the message. - * This must be a redable buffer of length \c 12 Bytes. + * This must be a readable buffer of length \c 12 Bytes. * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). * diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index 396fe7dfc2..be5c548e56 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -173,7 +173,11 @@ #endif #if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_PKCS5_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ @@ -214,11 +218,32 @@ #error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" #endif +#if defined(MBEDTLS_CCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_CCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_CCM_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_GCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C) #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C) +#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C) +#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" #endif @@ -338,11 +363,11 @@ #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) -#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites" #endif #if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) -#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" #endif #if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) @@ -619,6 +644,18 @@ #error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." #endif +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ + !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C) +#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \ + MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined." +#endif + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) && \ + !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_C, MBEDTLS_RSA_C and MBEDTLS_PKCS1_V15 defined, \ + but not all prerequisites" +#endif + #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ !defined(MBEDTLS_OID_C) ) #error "MBEDTLS_RSA_C defined, but not all prerequisites" @@ -761,14 +798,14 @@ !defined(MBEDTLS_SSL_PROTO_TLS1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !defined(MBEDTLS_SSL_PROTO_TLS1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index 87b4e9192e..1cd6eb6634 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -128,7 +128,12 @@ * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and * MBEDTLS_PLATFORM_STD_TIME. * - * Comment if your system does not support time functions + * Comment if your system does not support time functions. + * + * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing + * interface - timing.c will include time.h on suitable platforms + * regardless of the setting of MBEDTLS_HAVE_TIME, unless + * MBEDTLS_TIMING_ALT is used. See timing.c for more information. */ #define MBEDTLS_HAVE_TIME @@ -321,7 +326,7 @@ */ //#define MBEDTLS_CHECK_PARAMS_ASSERT -/* \} name SECTION: System support */ +/** \} name SECTION: System support */ /** * \name SECTION: mbed TLS feature support @@ -395,7 +400,7 @@ //#define MBEDTLS_XTEA_ALT /* - * When replacing the elliptic curve module, pleace consider, that it is + * When replacing the elliptic curve module, please consider, that it is * implemented with two .c files: * - ecp.c * - ecp_curves.c @@ -1493,7 +1498,7 @@ * Enable an implementation of SHA-256 that has lower ROM footprint but also * lower performance. * - * The default implementation is meant to be a reasonnable compromise between + * The default implementation is meant to be a reasonable compromise between * performance and size. This version optimizes more aggressively for size at * the expense of performance. Eg on Cortex-M4 it reduces the size of * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about @@ -1658,7 +1663,7 @@ * Enable support for RFC 7627: Session Hash and Extended Master Secret * Extension. * - * This was introduced as "the proper fix" to the Triple Handshake familiy of + * This was introduced as "the proper fix" to the Triple Handshake family of * attacks, but it is recommended to always use it (even if you disable * renegotiation), since it actually fixes a more fundamental issue in the * original SSL/TLS design, and has implications beyond Triple Handshake. @@ -1704,7 +1709,7 @@ * \note This option has no influence on the protection against the * triple handshake attack. Even if it is disabled, Mbed TLS will * still ensure that certificates do not change during renegotiation, - * for exaple by keeping a hash of the peer's certificate. + * for example by keeping a hash of the peer's certificate. * * Comment this macro to disable storing the peer's certificate * after the handshake. @@ -1909,7 +1914,7 @@ * unless you know for sure amplification cannot be a problem in the * environment in which your server operates. * - * \warning Disabling this can ba a security risk! (see above) + * \warning Disabling this can be a security risk! (see above) * * Requires: MBEDTLS_SSL_PROTO_DTLS * @@ -2162,8 +2167,19 @@ * This setting allows support for cryptographic mechanisms through the PSA * API to be configured separately from support through the mbedtls API. * - * Uncomment this to enable use of PSA Crypto configuration settings which - * can be found in include/psa/crypto_config.h. + * When this option is disabled, the PSA API exposes the cryptographic + * mechanisms that can be implemented on top of the `mbedtls_xxx` API + * configured with `MBEDTLS_XXX` symbols. + * + * When this option is enabled, the PSA API exposes the cryptographic + * mechanisms requested by the `PSA_WANT_XXX` symbols defined in + * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are + * automatically enabled if required (i.e. if no PSA driver provides the + * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols + * in config.h. + * + * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies + * an alternative header to include instead of include/psa/crypto_config.h. * * If you enable this option and write your own configuration file, you must * include mbedtls/config_psa.h in your configuration file. The default @@ -2289,7 +2305,7 @@ * Uncomment to enable use of ZLIB */ //#define MBEDTLS_ZLIB_SUPPORT -/* \} name SECTION: mbed TLS feature support */ +/** \} name SECTION: mbed TLS feature support */ /** * \name SECTION: mbed TLS modules @@ -2902,7 +2918,7 @@ * * Requires: MBEDTLS_MD_C * - * Uncomment to enable the HMAC_DRBG random number geerator. + * Uncomment to enable the HMAC_DRBG random number generator. */ #define MBEDTLS_HMAC_DRBG_C @@ -3096,7 +3112,7 @@ /** * \def MBEDTLS_PK_C * - * Enable the generic public (asymetric) key layer. + * Enable the generic public (asymmetric) key layer. * * Module: library/pk.c * Caller: library/ssl_tls.c @@ -3112,7 +3128,7 @@ /** * \def MBEDTLS_PK_PARSE_C * - * Enable the generic public (asymetric) key parser. + * Enable the generic public (asymmetric) key parser. * * Module: library/pkparse.c * Caller: library/x509_crt.c @@ -3127,7 +3143,7 @@ /** * \def MBEDTLS_PK_WRITE_C * - * Enable the generic public (asymetric) key writer. + * Enable the generic public (asymmetric) key writer. * * Module: library/pkwrite.c * Caller: library/x509write.c @@ -3466,6 +3482,10 @@ * your own implementation of the whole module by setting * \c MBEDTLS_TIMING_ALT in the current file. * + * \note The timing module will include time.h on suitable platforms + * regardless of the setting of MBEDTLS_HAVE_TIME, unless + * MBEDTLS_TIMING_ALT is used. See timing.c for more information. + * * \note See also our Knowledge Base article about porting to a new * environment: * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS @@ -3598,7 +3618,88 @@ */ #define MBEDTLS_XTEA_C -/* \} name SECTION: mbed TLS modules */ +/** \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: General configuration options + * + * This section contains Mbed TLS build settings that are not associated + * with a particular module. + * + * \{ + */ + +/** + * \def MBEDTLS_CONFIG_FILE + * + * If defined, this is a header which will be included instead of + * `"mbedtls/config.h"`. + * This header file specifies the compile-time configuration of Mbed TLS. + * Unlike other configuration options, this one must be defined on the + * compiler command line: a definition in `config.h` would have no effect. + * + * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an <tt>\#include</tt> line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_CONFIG_FILE "mbedtls/config.h" + +/** + * \def MBEDTLS_USER_CONFIG_FILE + * + * If defined, this is a header which will be included after + * `"mbedtls/config.h"` or #MBEDTLS_CONFIG_FILE. + * This allows you to modify the default configuration, including the ability + * to undefine options that are enabled by default. + * + * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an <tt>\#include</tt> line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_USER_CONFIG_FILE "/dev/null" + +/** + * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE + * + * If defined, this is a header which will be included instead of + * `"psa/crypto_config.h"`. + * This header file specifies which cryptographic mechanisms are available + * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and + * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled. + * + * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an <tt>\#include</tt> line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h" + +/** + * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE + * + * If defined, this is a header which will be included after + * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE. + * This allows you to modify the default configuration, including the ability + * to undefine options that are enabled by default. + * + * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an <tt>\#include</tt> line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null" + +/** \} name SECTION: General configuration options */ /** * \name SECTION: Module configuration options @@ -3609,11 +3710,15 @@ * * Our advice is to enable options and change their values here * only if you have a good reason and know the consequences. - * - * Please check the respective header file for documentation on these - * parameters (to prevent duplicate documentation). * \{ */ +/* The Doxygen documentation here is used when a user comments out a + * setting and runs doxygen themselves. On the other hand, when we typeset + * the full documentation including disabled settings, the documentation + * in specific modules' header files is used if present. When editing this + * file, make sure that each option is documented in exactly one place, + * plus optionally a same-line Doxygen comment here if there is a Doxygen + * comment in the specific module. */ /* MPI / BIGNUM options */ //#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ @@ -4002,7 +4107,7 @@ */ //#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED -/* \} name SECTION: Customisation configuration options */ +/** \} name SECTION: Module configuration options */ /* Target and application specific configurations * diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index dc4adc896d..e68237a439 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -138,7 +138,7 @@ /**< The maximum size of seed or reseed buffer in bytes. */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< Prediction resistance is disabled. */ diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h index 3c08244f3d..4fc4662d9a 100644 --- a/thirdparty/mbedtls/include/mbedtls/debug.h +++ b/thirdparty/mbedtls/include/mbedtls/debug.h @@ -139,7 +139,7 @@ extern "C" { * discarded. * (Default value: 0 = No debug ) * - * \param threshold theshold level of messages to filter on. Messages at a + * \param threshold threshold level of messages to filter on. Messages at a * higher level will be discarded. * - Debug levels * - 0 No debug diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h index 891705d8c4..3564ff8dd3 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h +++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h @@ -68,7 +68,7 @@ typedef enum { * (KeyExchange) as defined by the Thread spec. * * In order to benefit from this symmetry, we choose a different naming - * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * convention from the Thread v1.0 spec. Correspondence is indicated in the * description as a pair C: client name, S: server name */ typedef struct mbedtls_ecjpake_context diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index 0924341e00..64a0bccda0 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -315,7 +315,7 @@ mbedtls_ecp_group; #if !defined(MBEDTLS_ECP_WINDOW_SIZE) /* * Maximum "window" size used for point multiplication. - * Default: a point where higher memory usage yields disminishing performance + * Default: a point where higher memory usage yields diminishing performance * returns. * Minimum value: 2. Maximum value: 7. * @@ -351,7 +351,7 @@ mbedtls_ecp_group; #define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #else /* MBEDTLS_ECP_ALT */ #include "ecp_alt.h" diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index deb3c50300..40259ebc8a 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -75,7 +75,7 @@ #define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h index 223004b8ed..111d960e56 100644 --- a/thirdparty/mbedtls/include/mbedtls/hkdf.h +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -39,7 +39,7 @@ */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 -/* \} name */ +/** \} name */ #ifdef __cplusplus extern "C" { diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 79132d4d91..6d372b9788 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -74,7 +74,7 @@ #define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ #define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ @@ -207,7 +207,7 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, size_t len ); /** - * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * \brief Initialisation of simplified HMAC_DRBG (never reseeds). * * This function is meant for use in algorithms that need a pseudorandom * input such as deterministic ECDSA. diff --git a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h index 233977252a..3954b36ab5 100644 --- a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -42,7 +42,7 @@ #define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #define MBEDTLS_MEMORY_VERIFY_NONE 0 #define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index 1c39186a49..0186217804 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -143,7 +143,7 @@ #define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ #define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ #define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ -#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ #define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ #define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h index dfb4ff218e..daa71c886b 100644 --- a/thirdparty/mbedtls/include/mbedtls/pem.h +++ b/thirdparty/mbedtls/include/mbedtls/pem.h @@ -54,7 +54,7 @@ #define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /** Bad input parameters to function. */ #define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 -/* \} name */ +/** \} name PEM Error codes */ #ifdef __cplusplus extern "C" { diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h index 8f2abf2a60..c9a13f484e 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk.h +++ b/thirdparty/mbedtls/include/mbedtls/pk.h @@ -217,32 +217,6 @@ typedef struct typedef void mbedtls_pk_restart_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ -#if defined(MBEDTLS_RSA_C) -/** - * Quick access to an RSA context inside a PK context. - * - * \warning You must make sure the PK context actually holds an RSA context - * before using this function! - */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) -{ - return( (mbedtls_rsa_context *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * Quick access to an EC context inside a PK context. - * - * \warning You must make sure the PK context actually holds an EC context - * before using this function! - */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) -{ - return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_ECP_C */ - #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** * \brief Types for RSA-alt abstraction @@ -656,6 +630,55 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); */ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal RSA context held by the PK context, or NULL. + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + switch( mbedtls_pk_get_type( &pk ) ) + { + case MBEDTLS_PK_RSA: + return( (mbedtls_rsa_context *) (pk).pk_ctx ); + default: + return( NULL ); + } +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, + * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal EC context held by the PK context, or NULL. + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + switch( mbedtls_pk_get_type( &pk ) ) + { + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); + default: + return( NULL ); + } +} +#endif /* MBEDTLS_ECP_C */ + #if defined(MBEDTLS_PK_PARSE_C) /** \ingroup pk_module */ /** diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index bdef07498d..06dd192eab 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -70,7 +70,9 @@ extern "C" { #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) #include <stdio.h> #include <stdlib.h> +#if defined(MBEDTLS_HAVE_TIME) #include <time.h> +#endif #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) #define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ @@ -127,7 +129,7 @@ extern "C" { #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ /* * The function pointers for calloc and free. diff --git a/thirdparty/mbedtls/include/mbedtls/platform_time.h b/thirdparty/mbedtls/include/mbedtls/platform_time.h index 7e7daab692..94055711b2 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_time.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_time.h @@ -32,14 +32,6 @@ extern "C" { #endif -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - /* * The time_t datatype */ diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h index f982db8c01..cd112ab58e 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_util.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h @@ -67,7 +67,7 @@ extern "C" { * \brief User supplied callback function for parameter validation failure. * See #MBEDTLS_CHECK_PARAMS for context. * - * This function will be called unless an alternative treatement + * This function will be called unless an alternative treatment * is defined through the #MBEDTLS_PARAM_FAILED macro. * * This function can return, and the operation will be aborted, or @@ -198,7 +198,7 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; * * This macro has an empty expansion. It exists for documentation purposes: * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function - * has been analyzed for return-check usefuless, whereas the lack of + * has been analyzed for return-check usefulness, whereas the lack of * an annotation indicates that the function has not been analyzed and its * return-check usefulness is unknown. */ diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 3c481e12a1..062df73aa0 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -88,7 +88,7 @@ /* * The above constants may be used even if the RSA module is compile out, - * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + * eg for alternative (PKCS#11) RSA implementations in the PK layers. */ #ifdef __cplusplus @@ -552,7 +552,7 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, * * \note Blinding is used if and only if a PRNG is provided. * - * \note If blinding is used, both the base of exponentation + * \note If blinding is used, both the base of exponentiation * and the exponent are blinded, providing protection * against some side-channel attacks. * @@ -687,7 +687,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * - * \param ctx The initnialized RSA context to use. + * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is needed for padding * generation and must be provided. * \param p_rng The RNG context to be passed to \p f_rng. This may diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index 209dbf6053..5064ec5689 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -349,7 +349,7 @@ #define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ /* * Length of the verify data for secure renegotiation @@ -1152,7 +1152,7 @@ struct mbedtls_ssl_config #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - /** Callback to create & write a cookie for ClientHello veirifcation */ + /** Callback to create & write a cookie for ClientHello verification */ int (*f_cookie_write)( void *, unsigned char **, unsigned char *, const unsigned char *, size_t ); /** Callback to verify validity of a ClientHello cookie */ @@ -1405,7 +1405,7 @@ struct mbedtls_ssl_context unsigned char *compress_buf; /*!< zlib data buffer */ #endif /* MBEDTLS_ZLIB_SUPPORT */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - signed char split_done; /*!< current record already splitted? */ + signed char split_done; /*!< current record already split? */ #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ /* @@ -1688,7 +1688,7 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, * * \note The two most common use cases are: * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL - * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL * * \note For DTLS, you need to provide either a non-NULL * f_recv_timeout callback, or a f_recv that doesn't block. @@ -1846,7 +1846,7 @@ int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /** - * \brief Set the Maximum Tranport Unit (MTU). + * \brief Set the Maximum Transport Unit (MTU). * Special value: 0 means unset (no limit). * This represents the maximum size of a datagram payload * handled by the transport layer (usually UDP) as determined @@ -2387,7 +2387,7 @@ void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); * ones going through the authentication-decryption phase. * * \note This is a security trade-off related to the fact that it's - * often relatively easy for an active attacker ot inject UDP + * often relatively easy for an active attacker to inject UDP * datagrams. On one hand, setting a low limit here makes it * easier for such an attacker to forcibly terminated a * connection. On the other hand, a high limit or no limit @@ -2498,7 +2498,7 @@ void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, * successfully cached, return 1 otherwise. * * \param conf SSL configuration - * \param p_cache parmater (context) for both callbacks + * \param p_cache parameter (context) for both callbacks * \param f_get_cache session get callback * \param f_set_cache session set callback */ @@ -2529,7 +2529,7 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session /** * \brief Load serialized session data into a session structure. * On client, this can be used for loading saved sessions - * before resuming them with mbedstls_ssl_set_session(). + * before resuming them with mbedtls_ssl_set_session(). * On server, this can be used for alternative implementations * of session cache or session tickets. * @@ -2793,7 +2793,7 @@ void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, * * \note On client, only the first call has any effect. That is, * only one client certificate can be provisioned. The - * server's preferences in its CertficateRequest message will + * server's preferences in its CertificateRequest message will * be ignored and our only cert will be sent regardless of * whether it matches those preferences - the server can then * decide what it wants to do with it. @@ -3241,7 +3241,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, * \param protos Pointer to a NULL-terminated list of supported protocols, * in decreasing preference order. The pointer to the list is * recorded by the library for later reference as required, so - * the lifetime of the table must be atleast as long as the + * the lifetime of the table must be at least as long as the * lifetime of the SSL configuration structure. * * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. @@ -3255,7 +3255,7 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot * * \param ssl SSL context * - * \return Protcol name, or NULL if no protocol was negotiated. + * \return Protocol name, or NULL if no protocol was negotiated. */ const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_ALPN */ @@ -3338,7 +3338,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, unsigned char *mki_value, uint16_t mki_len ); /** - * \brief Get the negotiated DTLS-SRTP informations: + * \brief Get the negotiated DTLS-SRTP information: * Protection profile and MKI value. * * \warning This function must be called after the handshake is @@ -3346,7 +3346,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, * not be trusted or acted upon before the handshake completes. * * \param ssl The SSL context to query. - * \param dtls_srtp_info The negotiated DTLS-SRTP informations: + * \param dtls_srtp_info The negotiated DTLS-SRTP information: * - Protection profile in use. * A direct mapping of the iana defined value for protection * profile on an uint16_t. @@ -3508,7 +3508,7 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, * \c mbedtls_ssl_get_record_expansion(). * * \note For DTLS, it is also possible to set a limit for the total - * size of daragrams passed to the transport layer, including + * size of datagrams passed to the transport layer, including * record overhead, see \c mbedtls_ssl_set_mtu(). * * \param conf SSL configuration @@ -3568,7 +3568,7 @@ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets * initiated by peer * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) * - * \warning It is recommended to always disable renegotation unless you + * \warning It is recommended to always disable renegotiation unless you * know you need it and you know what you're doing. In the * past, there have been several issues associated with * renegotiation or a poor understanding of its properties. @@ -3631,7 +3631,7 @@ void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_ * scenario. * * \note With DTLS and server-initiated renegotiation, the - * HelloRequest is retransmited every time mbedtls_ssl_read() times + * HelloRequest is retransmitted every time mbedtls_ssl_read() times * out or receives Application Data, until: * - max_records records have beens seen, if it is >= 0, or * - the number of retransmits that would happen during an @@ -4263,7 +4263,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed - * while reseting the context. + * while resetting the context. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with an AEAD @@ -4357,7 +4357,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); /** - * \brief Load reasonnable default SSL configuration values. + * \brief Load reasonable default SSL configuration values. * (You need to call mbedtls_ssl_config_init() first.) * * \param conf SSL configuration context diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h index c6ef2960f4..02eab96d45 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h @@ -50,7 +50,7 @@ #define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h index 0a238708e5..2aa373177b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h @@ -45,7 +45,7 @@ #define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ #endif -/* \} name SECTION: Module settings */ +/** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { @@ -84,7 +84,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, * \brief Set expiration delay for cookies * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) * - * \param ctx Cookie contex + * \param ctx Cookie context * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies * issued in the meantime. * 0 to disable expiration (NOT recommended) diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index 6913dc0f66..46ade67b9c 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -934,16 +934,22 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); */ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); @@ -1023,27 +1029,39 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); * following the above definition. * */ +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, unsigned update_hs_digest ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); /** @@ -1108,13 +1126,18 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); #if defined(MBEDTLS_ECP_C) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id ); #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, mbedtls_md_type_t md ); #endif @@ -1170,6 +1193,7 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) * * Return 0 if everything is OK, -1 if not. */ +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int cert_endpoint, @@ -1218,21 +1242,26 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); #endif /* Visible for testing purposes only */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ); void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); #endif +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ); #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, unsigned char *output, unsigned char *data, size_t data_len ); @@ -1242,6 +1271,7 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, @@ -1254,11 +1284,13 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, #endif void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec ); @@ -1276,10 +1308,12 @@ static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ); void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); @@ -1287,6 +1321,7 @@ void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform ); void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) @@ -1296,6 +1331,7 @@ void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); #if defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -1305,4 +1341,12 @@ void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_TEST_HOOKS) +int mbedtls_ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_context *ssl, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ); +#endif + #endif /* ssl_internal.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h index a882eed23b..8221051b24 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h @@ -101,7 +101,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); * supported. Usually that means a 256-bit key. * * \note The lifetime of the keys is twice the lifetime of tickets. - * It is recommended to pick a reasonnable lifetime so as not + * It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * * \return 0 if successful, diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index b1a92b2bcf..44adcbfe03 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -38,16 +38,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 28 -#define MBEDTLS_VERSION_PATCH 0 +#define MBEDTLS_VERSION_PATCH 1 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x021C0000 -#define MBEDTLS_VERSION_STRING "2.28.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.0" +#define MBEDTLS_VERSION_NUMBER 0x021C0100 +#define MBEDTLS_VERSION_STRING "2.28.1" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.1" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/include/mbedtls/x509.h b/thirdparty/mbedtls/include/mbedtls/x509.h index c177501430..31b78df32f 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509.h +++ b/thirdparty/mbedtls/include/mbedtls/x509.h @@ -96,7 +96,7 @@ #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ #define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 -/* \} name */ +/** \} name X509 Error codes */ /** * \name X509 Verify codes @@ -124,8 +124,8 @@ #define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ #define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ -/* \} name */ -/* \} addtogroup x509_module */ +/** \} name X509 Verify codes */ +/** \} addtogroup x509_module */ /* * X.509 v3 Subject Alternative Name types. @@ -255,7 +255,6 @@ typedef struct mbedtls_x509_time mbedtls_x509_time; /** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ -/** \} addtogroup x509_module */ /** * \brief Store the certificate DN in printable form into buf; @@ -311,6 +310,8 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); */ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); +/** \} addtogroup x509_module */ + #if defined(MBEDTLS_SELF_TEST) /** diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crl.h b/thirdparty/mbedtls/include/mbedtls/x509_crl.h index 7e9e8885f4..9222009019 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crl.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crl.h @@ -162,8 +162,8 @@ void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); */ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); -/* \} name */ -/* \} addtogroup x509_module */ +/** \} name Structures and functions for parsing CRLs */ +/** \} addtogroup x509_module */ #ifdef __cplusplus } diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h index 64ccb433ba..0f2885a7ee 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h @@ -107,7 +107,7 @@ mbedtls_x509_crt; typedef struct mbedtls_x509_san_other_name { /** - * The type_id is an OID as deifned in RFC 5280. + * The type_id is an OID as defined in RFC 5280. * To check the value of the type id, you should use * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. */ @@ -159,7 +159,9 @@ mbedtls_x509_subject_alternative_name; typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ - uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_pks; /**< PK algs for public keys; + * this applies to all certificates + * in the provided chain. */ uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ } @@ -850,8 +852,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ -/* \} name */ -/* \} addtogroup x509_module */ +/** \} name Structures and functions for parsing and writing X.509 certificates */ #if defined(MBEDTLS_X509_CRT_WRITE_C) /** @@ -862,7 +863,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); /** - * \brief Set the verion for a Certificate + * \brief Set the version for a Certificate * Default: MBEDTLS_X509_CRT_VERSION_3 * * \param ctx CRT context to use @@ -978,7 +979,7 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, * \param is_ca is this a CA certificate * \param max_pathlen maximum length of certificate chains below this * certificate (only for CA certificates, -1 is - * inlimited) + * unlimited) * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ @@ -1087,6 +1088,8 @@ int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ +/** \} addtogroup x509_module */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/x509_csr.h b/thirdparty/mbedtls/include/mbedtls/x509_csr.h index b1dfc21f1f..2a1c046131 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_csr.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_csr.h @@ -151,8 +151,7 @@ void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); #endif /* MBEDTLS_X509_CSR_PARSE_C */ -/* \} name */ -/* \} addtogroup x509_module */ +/** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */ #if defined(MBEDTLS_X509_CSR_WRITE_C) /** @@ -182,7 +181,7 @@ int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, * private key used to sign the CSR when writing it) * * \param ctx CSR context to use - * \param key Asymetric key to include + * \param key Asymmetric key to include */ void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); @@ -298,6 +297,8 @@ int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, s #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CSR_WRITE_C */ +/** \} addtogroup x509_module */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 31824e75cf..03d8b7ea61 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -1106,7 +1106,7 @@ typedef unsigned char mbedtls_be128[16]; * * This function multiplies a field element by x in the polynomial field * representation. It uses 64-bit word operations to gain speed but compensates - * for machine endianess and hence works correctly on both big and little + * for machine endianness and hence works correctly on both big and little * endian machines. */ static void mbedtls_gf128mul_x_ble( unsigned char r[16], @@ -1206,7 +1206,7 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, unsigned char *prev_output = output - 16; /* Copy ciphertext bytes from the previous block to our output for each - * byte of cyphertext we won't steal. At the same time, copy the + * byte of ciphertext we won't steal. At the same time, copy the * remainder of the input for this final round (since the loop bounds * are the same). */ for( i = 0; i < leftover; i++ ) diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index 3811ef27a3..afa26a6be9 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -133,6 +133,11 @@ int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedt // len = mbedtls_mpi_size( X ); + /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not + * as 0 digits. We need to end up with 020100, not with 0200. */ + if( len == 0 ) + len = 1; + if( *p < start || (size_t)( *p - start ) < len ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); @@ -472,7 +477,7 @@ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( cur->val.len = val_len; } - if( val != NULL ) + if( val != NULL && val_len != 0 ) memcpy( cur->val.p, val, val_len ); return( cur ); diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 62e7f76727..32578e2c68 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -1829,7 +1829,7 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_ /* * handle trivial cases */ - if( b == 1 ) + if( b == 1 || A->n == 0 ) { *r = 0; return( 0 ); @@ -2317,7 +2317,7 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B * TA-TB is even so the division by 2 has an integer result. * Invariant (I) is preserved since any odd divisor of both TA and TB * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 - * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also + * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also * divides TA. */ if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index 4ec40d2cac..f3b4bd29ce 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -386,6 +386,12 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, #if defined(MBEDTLS_CHACHA20_C) if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) { + /* Even though the actual_iv_size is overwritten with a correct value + * of 12 from the cipher info, return an error to indicate that + * the input iv_len is wrong. */ + if( iv_len != 12 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, iv, 0U ) ) /* Initial counter value */ @@ -393,6 +399,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } } +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 && + iv_len != 12 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#endif #endif if ( actual_iv_size != 0 ) diff --git a/thirdparty/mbedtls/library/constant_time.c b/thirdparty/mbedtls/library/constant_time.c index 18f1b20daa..e276d23ca0 100644 --- a/thirdparty/mbedtls/library/constant_time.c +++ b/thirdparty/mbedtls/library/constant_time.c @@ -489,6 +489,12 @@ int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + /* Fill the hash buffer in advance with something that is + * not a valid hash (barring an attack on the hash and + * deliberately-crafted input), in case the caller doesn't + * check the return status properly. */ + memset( output, '!', hash_size ); + /* For each possible length, compute the hash up to that point */ for( offset = min_data_len; offset <= max_data_len; offset++ ) { @@ -533,6 +539,13 @@ cleanup: * about whether the assignment was made or not. * (Leaking information about the respective sizes of X and Y is ok however.) */ +#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103) +/* + * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: + * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 + */ +__declspec(noinline) +#endif int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) @@ -562,7 +575,7 @@ cleanup: /* * Conditionally swap X and Y, without leaking information * about whether the swap was made or not. - * Here it is not ok to simply swap the pointers, which whould lead to + * Here it is not ok to simply swap the pointers, which would lead to * different memory access patterns when X and Y are used afterwards. */ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, diff --git a/thirdparty/mbedtls/library/constant_time_internal.h b/thirdparty/mbedtls/library/constant_time_internal.h index bbb3a90670..a550b38fa5 100644 --- a/thirdparty/mbedtls/library/constant_time_internal.h +++ b/thirdparty/mbedtls/library/constant_time_internal.h @@ -221,6 +221,13 @@ void mbedtls_ct_memcpy_if_eq( unsigned char *dest, * offset_secret, but only on \p offset_min, \p offset_max and \p len. * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`. * + * \note This function reads from \p dest, but the value that + * is read does not influence the result and this + * function's behavior is well-defined regardless of the + * contents of the buffers. This may result in false + * positives from static or dynamic analyzers, especially + * if \p dest is not initialized. + * * \param dest The destination buffer. This must point to a writable * buffer of at least \p len bytes. * \param src The base of the source buffer. This must point to a diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index a604ec0761..a00d66ce87 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -828,7 +828,7 @@ static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, return( 1 ); \ } -#define SELF_TEST_OUPUT_DISCARD_LENGTH 64 +#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 /* * Checkup routine @@ -854,7 +854,7 @@ int mbedtls_ctr_drbg_self_test( int verbose ) (void *) entropy_source_pr, pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) ); CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) ); @@ -879,7 +879,7 @@ int mbedtls_ctr_drbg_self_test( int verbose ) (void *) entropy_source_nopr, pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) ); CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) ); diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c index 9dfa868063..60c6e429de 100644 --- a/thirdparty/mbedtls/library/ecdh.c +++ b/thirdparty/mbedtls/library/ecdh.c @@ -399,7 +399,7 @@ static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, } /* - * Read the ServerKeyExhange parameters (RFC 4492) + * Read the ServerKeyExchange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index 368b6c7124..0b9bffb93e 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -435,7 +435,7 @@ cleanup: /* * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs - * Ouputs: verified peer public keys Xa, Xb + * Outputs: verified peer public keys Xa, Xb */ static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, const mbedtls_ecp_group *grp, diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index 7f9e1045d4..890f364a08 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -1307,7 +1307,7 @@ cleanup: * For curves in short Weierstrass form, we do all the internal operations in * Jacobian coordinates. * - * For multiplication, we'll use a comb method with coutermeasueres against + * For multiplication, we'll use a comb method with countermeasures against * SPA, hence timing attacks. */ @@ -2251,7 +2251,7 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, * This function is mainly responsible for administrative work: * - managing the restart context if enabled * - managing the table of precomputed points (passed between the below two - * functions): allocation, computation, ownership tranfer, freeing. + * functions): allocation, computation, ownership transfer, freeing. * * It delegates the actual arithmetic work to: * ecp_precompute_comb() and ecp_mul_comb_with_precomp() @@ -2422,7 +2422,7 @@ cleanup: /* * For Montgomery curves, we do all the internal arithmetic in projective * coordinates. Import/export of points uses only the x coordinates, which is - * internaly represented as X / Z. + * internally represented as X / Z. * * For scalar multiplication, we'll use a Montgomery ladder. */ @@ -2592,7 +2592,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); mbedtls_mpi_free( &R->Y ); - /* RP.X might be sligtly larger than P, so reduce it */ + /* RP.X might be slightly larger than P, so reduce it */ MOD_ADD( RP.X ); /* Randomize coordinates of the starting point */ diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index ff26a18e8f..2199be6461 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -755,6 +755,8 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) ECP_VALIDATE_RET( grp != NULL ); mbedtls_ecp_group_free( grp ); + mbedtls_ecp_group_init( grp ); + grp->id = id; switch( id ) diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c index 0d5d27d3de..cc62324bdc 100644 --- a/thirdparty/mbedtls/library/memory_buffer_alloc.c +++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c @@ -555,8 +555,8 @@ static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) static void buffer_alloc_free_mutexed( void *ptr ) { - /* We have to good option here, but corrupting the heap seems - * worse than loosing memory. */ + /* We have no good option here, but corrupting the heap seems + * worse than losing memory. */ if( mbedtls_mutex_lock( &heap.mutex ) ) return; buffer_alloc_free( ptr ); diff --git a/thirdparty/mbedtls/library/mps_common.h b/thirdparty/mbedtls/library/mps_common.h index d20776f159..668876ccfc 100644 --- a/thirdparty/mbedtls/library/mps_common.h +++ b/thirdparty/mbedtls/library/mps_common.h @@ -51,7 +51,7 @@ * the function's behavior is entirely undefined. * In addition to state integrity, all MPS structures have a more refined * notion of abstract state that the API operates on. For example, all layers - * have a notion of 'abtract read state' which indicates if incoming data has + * have a notion of 'abstract read state' which indicates if incoming data has * been passed to the user, e.g. through mps_l2_read_start() for Layer 2 * or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to * call these reading functions again until the incoming data has been diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 5fbe1f764a..8c765e1c8c 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -107,7 +107,9 @@ static int wsa_init_done = 0; #include <stdio.h> +#if defined(MBEDTLS_HAVE_TIME) #include <time.h> +#endif #include <stdint.h> diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index 535ed70eb1..ea5c6b69cb 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -474,7 +474,7 @@ static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *g } /* - * grp may already be initilialized; if so, make sure IDs match + * grp may already be initialized; if so, make sure IDs match */ if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); @@ -807,7 +807,7 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, goto cleanup; #else - /* Verify existance of the CRT params */ + /* Verify existence of the CRT params */ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) @@ -1463,10 +1463,16 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, { p = pem.buf; if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + { + mbedtls_pem_free( &pem ); return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + } if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + { + mbedtls_pem_free( &pem ); return( ret ); + } if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) mbedtls_pk_free( ctx ); diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index 8a5d40ff1e..d1f6ddb177 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -832,10 +832,10 @@ cleanup: * the more bits of the key can be recovered. See [3]. * * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) - * observations on avarage. + * observations on average. * * For example with 28 byte blinding to achieve 2 collisions the adversary has - * to make 2^112 observations on avarage. + * to make 2^112 observations on average. * * (With the currently (as of 2017 April) known best algorithms breaking 2048 * bit RSA requires approximately as much time as trying out 2^112 random keys. diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index 3826ad27fa..ceec77efb0 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -2181,6 +2181,7 @@ const int *mbedtls_ssl_list_ciphersuites( void ) static int supported_ciphersuites[MAX_CIPHERSUITES]; static int supported_init = 0; +MBEDTLS_CHECK_RETURN_CRITICAL static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) { (void)cs_info; diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index b87879ce6a..72351c9757 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -53,6 +53,7 @@ #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) { if( conf->psk_identity == NULL || @@ -73,6 +74,7 @@ static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) { if( conf->psk_identity == NULL || @@ -91,6 +93,7 @@ static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -161,6 +164,7 @@ static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -204,6 +208,7 @@ static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -302,6 +307,7 @@ static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -373,6 +379,7 @@ static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -404,6 +411,7 @@ static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -477,6 +485,7 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_cid_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -523,6 +532,7 @@ static int ssl_write_cid_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -555,6 +565,7 @@ static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -585,6 +596,7 @@ static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -616,6 +628,7 @@ static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -647,6 +660,7 @@ static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -689,6 +703,7 @@ static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -748,6 +763,7 @@ static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, @@ -868,6 +884,7 @@ static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, /* * Generate random bytes for ClientHello */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_generate_random( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -917,6 +934,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) * * \return 0 if valid, else 1 */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, const mbedtls_ssl_context * ssl, @@ -960,6 +978,7 @@ static int ssl_validate_ciphersuite( return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -1450,6 +1469,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1494,6 +1514,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1520,6 +1541,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1545,6 +1567,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1601,6 +1624,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1627,6 +1651,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1653,6 +1678,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1679,6 +1705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1724,6 +1751,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1758,6 +1786,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { @@ -1828,6 +1857,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -1948,6 +1978,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, * Parse HelloVerifyRequest. Only called after verifying the HS type. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) { const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); @@ -2031,6 +2062,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_PROTO_DTLS */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) { int ret, i; @@ -2276,16 +2308,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) else { ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( ret ); - } } MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", @@ -2538,6 +2560,24 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } /* + * mbedtls_ssl_derive_keys() has to be called after the parsing of the + * extensions. It sets the transform data for the resumed session which in + * case of DTLS includes the server CID extracted from the CID extension. + */ + if( ssl->handshake->resume ) + { + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + /* * Renegotiation security checks */ if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && @@ -2591,6 +2631,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -2637,6 +2678,7 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) { const mbedtls_ecp_curve_info *curve_info; @@ -2678,6 +2720,7 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -2703,6 +2746,10 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, tls_id <<= 8; tls_id |= *(*p)++; + /* Check it's a curve we offered */ + if( mbedtls_ssl_check_curve_tls_id( ssl, tls_id ) != 0 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + /* Convert EC group to PSA key type. */ if( ( handshake->ecdh_psa_type = mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 ) @@ -2740,6 +2787,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -2779,6 +2827,7 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -2825,6 +2874,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, /* * Generate a pre-master secret and encrypt it with the server's RSA key */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, size_t offset, size_t *olen, size_t pms_offset ) @@ -2912,6 +2962,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end, @@ -2978,6 +3029,7 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -2996,6 +3048,8 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* This is a public key, so it can't be opaque, so can_do() is a good + * enough check to ensure pk_ec() is safe to use below. */ if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); @@ -3029,6 +3083,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3147,7 +3202,7 @@ start_processing: MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - } /* FALLTROUGH */ + } /* FALLTHROUGH */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ @@ -3435,6 +3490,7 @@ exit: } #if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -3453,6 +3509,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } #else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3624,6 +3681,7 @@ exit: } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3663,6 +3721,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3718,7 +3777,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) { - psa_status_t status; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -3761,13 +3821,19 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) own_pubkey, sizeof( own_pubkey ), &own_pubkey_len ); if( status != PSA_SUCCESS ) + { + psa_destroy_key( handshake->ecdh_psa_privkey ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey, own_pubkey_len, &own_pubkey_ecpoint, &own_pubkey_ecpoint_len ) != 0 ) { + psa_destroy_key( handshake->ecdh_psa_privkey ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } @@ -3787,13 +3853,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ssl->handshake->premaster, sizeof( ssl->handshake->premaster ), &ssl->handshake->pmslen ); - if( status != PSA_SUCCESS ) - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - status = psa_destroy_key( handshake->ecdh_psa_privkey ); - if( status != PSA_SUCCESS ) - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + destruction_status = psa_destroy_key( handshake->ecdh_psa_privkey ); handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if( status != PSA_SUCCESS || destruction_status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } else #endif /* MBEDTLS_USE_PSA_CRYPTO && @@ -3918,7 +3983,10 @@ ecdh_calc_secret: #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if( ( ret = ssl_write_encrypted_pms( ssl, header_len, @@ -3933,7 +4001,10 @@ ecdh_calc_secret: #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* @@ -3970,7 +4041,10 @@ ecdh_calc_secret: #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* @@ -4080,6 +4154,7 @@ ecdh_calc_secret: } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -4105,6 +4180,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -4277,6 +4353,7 @@ sign: #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c index abf29ae717..3781796b72 100644 --- a/thirdparty/mbedtls/library/ssl_cookie.c +++ b/thirdparty/mbedtls/library/ssl_cookie.c @@ -63,7 +63,7 @@ /* * Cookies are formed of a 4-bytes timestamp (or serial number) and - * an HMAC of timestemp and client ID. + * an HMAC of timestamp and client ID. */ #define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) @@ -122,6 +122,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, /* * Generate the HMAC part of a cookie */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, const unsigned char time[4], unsigned char **p, unsigned char *end, diff --git a/thirdparty/mbedtls/library/ssl_msg.c b/thirdparty/mbedtls/library/ssl_msg.c index 0b696dd561..e47c538888 100644 --- a/thirdparty/mbedtls/library/ssl_msg.c +++ b/thirdparty/mbedtls/library/ssl_msg.c @@ -91,6 +91,7 @@ int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_RECORD_CHECKING) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, @@ -165,11 +166,16 @@ exit: static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, uint8_t slot ); static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, mbedtls_record const *rec ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) @@ -187,6 +193,7 @@ static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) return( out_buf_len ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) { size_t const bytes_written = ssl->out_left; @@ -203,6 +210,7 @@ static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) return( (int) ( mtu - bytes_written ) ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -254,6 +262,7 @@ static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) { uint32_t new_timeout; @@ -353,6 +362,7 @@ static size_t ssl_compute_padding_length( size_t len, * - A negative error code if `max_len` didn't offer enough space * for the expansion. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_build_inner_plaintext( unsigned char *content, size_t *content_size, size_t remaining, @@ -380,6 +390,7 @@ static int ssl_build_inner_plaintext( unsigned char *content, /* This function parses a (D)TLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for details. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_inner_plaintext( unsigned char const *content, size_t *content_size, uint8_t *rec_type ) @@ -474,6 +485,7 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data, /* * SSLv3.0 MAC functions */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_mac( mbedtls_md_context_t *md_ctx, const unsigned char *secret, const unsigned char *buf, size_t len, @@ -541,6 +553,7 @@ static int ssl_mac( mbedtls_md_context_t *md_ctx, #if defined(MBEDTLS_GCM_C) || \ defined(MBEDTLS_CCM_C) || \ defined(MBEDTLS_CHACHAPOLY_C) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_transform_aead_dynamic_iv_is_explicit( mbedtls_ssl_transform const *transform ) { @@ -1245,7 +1258,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, add_data, add_data_len ); /* Because of the check above, we know that there are - * explicit_iv_len Bytes preceeding data, and taglen + * explicit_iv_len Bytes preceding data, and taglen * bytes following data + data_len. This justifies * the debug message and the invocation of * mbedtls_cipher_auth_decrypt() below. */ @@ -1590,8 +1603,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) if( auth_done == 0 ) { - unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; - unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 }; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 }; /* If the initial value of padlen was such that * data_len < maclen + padlen + 1, then padlen @@ -1738,6 +1751,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, /* * Compression/decompression functions */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_compress_buf( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -1790,6 +1804,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -2149,6 +2164,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) /* * Append current handshake message to current outgoing flight */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_flight_append( mbedtls_ssl_context *ssl ) { mbedtls_ssl_flight_item *msg; @@ -2215,6 +2231,7 @@ void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ) /* * Swap transform_out and out_ctr with the alternative ones */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) { mbedtls_ssl_transform *tmp_transform; @@ -2857,6 +2874,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) #if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) { if( ssl->in_msglen < ssl->in_hslen || @@ -2882,6 +2900,7 @@ static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) ssl->in_msg[8] ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) { uint32_t msg_len, frag_off, frag_len; @@ -2948,6 +2967,7 @@ static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) /* * Check that bitmask is full */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_bitmask_check( unsigned char *mask, size_t len ) { size_t i; @@ -3147,6 +3167,7 @@ static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) ( (uint64_t) buf[5] ) ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3229,8 +3250,8 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* - * Without any SSL context, check if a datagram looks like a ClientHello with - * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Check if a datagram looks like a ClientHello with a valid cookie, + * and if it doesn't, generate a HelloVerifyRequest message. * Both input and output include full DTLS headers. * * - if cookie is valid, return 0 @@ -3239,10 +3260,10 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED * - otherwise return a specific error code */ -static int ssl_check_dtls_clihlo_cookie( - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie, +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_context *ssl, const unsigned char *cli_id, size_t cli_id_len, const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen ) @@ -3276,26 +3297,53 @@ static int ssl_check_dtls_clihlo_cookie( * * Minimum length is 61 bytes. */ - if( in_len < 61 || - in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u", + (unsigned) in_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len ); + if( in_len < 61 ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || in[3] != 0 || in[4] != 0 || in[19] != 0 || in[20] != 0 || in[21] != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) ); + MBEDTLS_SSL_DEBUG_MSG( 4, ( " type=%u epoch=%u fragment_offset=%u", + in[0], + (unsigned) in[3] << 8 | in[4], + (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } sid_len = in[59]; - if( sid_len > in_len - 61 ) + if( 59 + 1 + sid_len + 1 > in_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u", + (unsigned) sid_len, + (unsigned) in_len - 61 ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network", + in + 60, sid_len ); cookie_len = in[60 + sid_len]; - if( cookie_len > in_len - 60 ) + if( 59 + 1 + sid_len + 1 + cookie_len > in_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u", + (unsigned) cookie_len, + (unsigned) ( in_len - sid_len - 61 ) ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } - if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, - cli_id, cli_id_len ) == 0 ) + MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network", + in + sid_len + 61, cookie_len ); + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) { - /* Valid cookie */ + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) ); return( 0 ); } @@ -3330,8 +3378,9 @@ static int ssl_check_dtls_clihlo_cookie( /* Generate and write actual cookie */ p = obuf + 28; - if( f_cookie_write( p_cookie, - &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + if( ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, obuf + buf_len, + cli_id, cli_id_len ) != 0 ) { return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } @@ -3370,6 +3419,7 @@ static int ssl_check_dtls_clihlo_cookie( * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected * errors, and is the right thing to do in both cases). */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3385,15 +3435,13 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) return( 0 ); } - ret = ssl_check_dtls_clihlo_cookie( - ssl->conf->f_cookie_write, - ssl->conf->f_cookie_check, - ssl->conf->p_cookie, + ret = mbedtls_ssl_check_dtls_clihlo_cookie( + ssl, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); - MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret ); if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) { @@ -3427,6 +3475,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_record_type( uint8_t record_type ) { if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && @@ -3459,6 +3508,7 @@ static int ssl_check_record_type( uint8_t record_type ) * Point 2 is needed when the peer is resending, and we have already received * the first record from a datagram but are still waiting for the others. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, @@ -3571,7 +3621,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, /* * Parse and validate record version */ - rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; mbedtls_ssl_read_version( &major_ver, &minor_ver, @@ -3580,16 +3629,19 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, if( major_ver != ssl->major_ver ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u", + (unsigned) major_ver, + (unsigned) ssl->major_ver ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } if( minor_ver > ssl->conf->max_minor_ver ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u", + (unsigned) minor_ver, + (unsigned) ssl->conf->max_minor_ver ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } - /* * Parse/Copy record sequence number. */ @@ -3692,6 +3744,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) { unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; @@ -3721,6 +3774,7 @@ static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) /* * If applicable, decrypt record content */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, mbedtls_record *rec ) { @@ -3854,7 +3908,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, /* Check actual (decrypted) record content length against * configured maximum. */ - if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3872,8 +3926,11 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, */ /* Helper functions for mbedtls_ssl_read_record(). */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, @@ -3961,6 +4018,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) { if( ssl->in_left > ssl->next_record_offset ) @@ -3969,6 +4027,7 @@ static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; @@ -4066,6 +4125,7 @@ exit: return( ret ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, size_t desired ) { @@ -4108,6 +4168,7 @@ static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, return( -1 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message( mbedtls_ssl_context *ssl ) { int ret = 0; @@ -4312,6 +4373,7 @@ exit: } #endif /* MBEDTLS_SSL_PROTO_DTLS */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) { /* @@ -4399,6 +4461,7 @@ static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) { if( ssl->in_msglen > 0 ) @@ -4425,6 +4488,7 @@ static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) } } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; @@ -4482,6 +4546,7 @@ exit: return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, mbedtls_record const *rec ) { @@ -4540,6 +4605,7 @@ static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_PROTO_DTLS */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -4918,6 +4984,9 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, if( ssl == NULL || ssl->conf == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); @@ -5287,6 +5356,7 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) /* * Check record counters and renegotiate if they're above the limit. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) { size_t ep_len = mbedtls_ssl_ep_len( ssl ); @@ -5637,6 +5707,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * Therefore, it is possible that the input message length is 0 and the * corresponding return code is 0 on success. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { @@ -5708,6 +5779,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, * remember whether we already did the split or not. */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_split( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { @@ -5790,9 +5862,6 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) { if( ( ret = mbedtls_ssl_send_alert_message( ssl, diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index 1a63173204..2efb13cc33 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -78,6 +78,7 @@ void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -147,6 +148,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) { if( conf->f_psk != NULL ) @@ -167,6 +169,7 @@ static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) { if( ssl->conf->f_psk != NULL ) @@ -188,6 +191,7 @@ static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -239,6 +243,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, * This needs to be done at a later stage. * */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -317,6 +322,7 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -383,6 +389,7 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -425,6 +432,7 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -454,6 +462,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -473,6 +482,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -545,6 +555,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -567,6 +578,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -592,6 +604,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -617,6 +630,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) @@ -691,6 +705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { @@ -779,6 +794,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -907,6 +923,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, * Return 0 if the given key uses one of the acceptable curves, -1 otherwise */ #if defined(MBEDTLS_ECDSA_C) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_key_curve( mbedtls_pk_context *pk, const mbedtls_ecp_curve_info **curves ) { @@ -928,6 +945,7 @@ static int ssl_check_key_curve( mbedtls_pk_context *pk, * Try picking a certificate for this ciphersuite, * return 0 on success and -1 on failure. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_pick_cert( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) { @@ -1032,6 +1050,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, * Check if a given ciphersuite is suitable for use with our config/keys/etc * Sets ciphersuite_info only if the suite matches. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) { @@ -1147,6 +1166,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, } #if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) { int ret, got_common_suite; @@ -1410,6 +1430,7 @@ have_ciphersuite_v2: /* This function doesn't alert on errors that happen early during ClientHello parsing because they might indicate that the client is not talking SSL/TLS at all and would not understand our alert. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) { int ret, got_common_suite; @@ -1583,7 +1604,7 @@ read_record_header: * Handshake layer: * 0 . 0 handshake type * 1 . 3 handshake length - * 4 . 5 DTLS only: message seqence number + * 4 . 5 DTLS only: message sequence number * 6 . 8 DTLS only: fragment offset * 9 . 11 DTLS only: fragment length */ @@ -1604,11 +1625,19 @@ read_record_header: MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + if( buf[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0", + (unsigned) buf[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } /* We don't support fragmentation of ClientHello (yet?) */ - if( buf[1] != 0 || - msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u", + (unsigned) msg_len, + (unsigned) mbedtls_ssl_hs_hdr_len( ssl ), + (unsigned) ( buf[2] << 8 ) | buf[3] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1649,6 +1678,11 @@ read_record_header: * For now we don't support fragmentation, so make sure * fragment_offset == 0 and fragment_length == length */ + MBEDTLS_SSL_DEBUG_MSG( + 4, ( "fragment_offset=%u fragment_length=%u length=%u", + (unsigned) ( ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8] ), + (unsigned) ( ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11] ), + (unsigned) ( ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3] ) ) ); if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) { @@ -2354,12 +2388,8 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite = NULL; const mbedtls_cipher_info_t *cipher = NULL; - if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - *olen = 0; - return; - } + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; /* * RFC 7366: "If a server receives an encrypt-then-MAC request extension @@ -2372,6 +2402,11 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || cipher->mode != MBEDTLS_MODE_CBC ) { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + } + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ) + { *olen = 0; return; } @@ -2685,6 +2720,7 @@ static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -2805,6 +2841,7 @@ exit: mbedtls_ssl_session_free( &session_tmp ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) { #if defined(MBEDTLS_HAVE_TIME) @@ -3035,6 +3072,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -3053,6 +3091,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -3222,18 +3261,23 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *own_key = mbedtls_ssl_own_key( ssl ); - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + /* Check if the key is a transparent ECDH key. + * This also ensures that it is safe to call mbedtls_pk_ec(). */ + if( mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY && + mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY_DH ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, - mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + mbedtls_pk_ec( *own_key ), MBEDTLS_ECDH_OURS ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); @@ -3247,6 +3291,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, size_t *signature_len ) { @@ -3274,6 +3319,7 @@ static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, /* Prepare the ServerKeyExchange message, up to and including * calculating the signature if any, but excluding formatting the * signature and sending the message. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, size_t *signature_len ) { @@ -3643,6 +3689,7 @@ curve_matching_done: * that do not include a ServerKeyExchange message, do nothing. Either * way, if successful, move on to the next step in the SSL state * machine. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3664,7 +3711,12 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) { - ssl_get_ecdh_params_from_cert( ssl ); + ret = ssl_get_ecdh_params_from_cert( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + return( ret ); + } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ @@ -3740,6 +3792,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) return( 0 ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3779,6 +3832,7 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end ) { @@ -3822,6 +3876,7 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char * defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, unsigned char *peer_pms, size_t *peer_pmslen, @@ -3839,6 +3894,7 @@ static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, @@ -3931,6 +3987,7 @@ static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, return( ret ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, @@ -4020,6 +4077,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end ) { @@ -4080,6 +4138,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -4207,7 +4266,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) - /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically + /* For opaque PSKs, we perform the PSK-to-MS derivation automatically * and skip the intermediate PMS. */ if( ssl_use_opaque_psk( ssl ) == 1 ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); @@ -4247,7 +4306,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only. */ if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) @@ -4282,7 +4344,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only. */ if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif if( p != end ) @@ -4319,7 +4384,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only. */ if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } #endif MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, @@ -4386,6 +4454,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -4404,6 +4473,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -4597,6 +4667,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c index 046ed1b2ff..e0126cc9d1 100644 --- a/thirdparty/mbedtls/library/ssl_ticket.c +++ b/thirdparty/mbedtls/library/ssl_ticket.c @@ -37,7 +37,7 @@ #include <string.h> /* - * Initialze context + * Initialize context */ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) { @@ -66,6 +66,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) /* * Generate/update a key */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, unsigned char index ) { @@ -96,6 +97,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, /* * Rotate/generate keys if necessary */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) { #if !defined(MBEDTLS_HAVE_TIME) diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index 2e6469de83..7badec51ae 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -245,6 +245,7 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old ) { unsigned char* resized_buffer = mbedtls_calloc( 1, len_new ); @@ -337,6 +338,7 @@ static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing, * Key material generation */ #if defined(MBEDTLS_SSL_PROTO_SSL3) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl3_prf( const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, @@ -398,6 +400,7 @@ exit: #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +MBEDTLS_CHECK_RETURN_CRITICAL static int tls1_prf( const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, @@ -605,6 +608,7 @@ static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* de return( PSA_SUCCESS ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic( mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, @@ -679,6 +683,7 @@ static int tls_prf_generic( mbedtls_md_type_t md_type, #else /* MBEDTLS_USE_PSA_CRYPTO */ +MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic( mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, @@ -770,6 +775,7 @@ exit: } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SHA256_C) +MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha256( const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, @@ -781,6 +787,7 @@ static int tls_prf_sha256( const unsigned char *secret, size_t slen, #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha384( const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, @@ -825,6 +832,7 @@ static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char * #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) { if( ssl->conf->f_psk != NULL ) @@ -949,6 +957,7 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_populate_transform( mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], @@ -990,6 +999,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, #if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; @@ -1361,7 +1371,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, * the structure field for the IV, which the PSA-based * implementation currently doesn't. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc, cipher_info, transform->taglen ); @@ -1404,7 +1414,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, * the structure field for the IV, which the PSA-based * implementation currently doesn't. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec, cipher_info, transform->taglen ); @@ -1511,6 +1521,7 @@ end: * Outputs: * - the tls_prf, calc_verify and calc_finished members of handshake structure */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, int minor_ver, mbedtls_md_type_t hash ) @@ -1580,6 +1591,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) * PSA-PSA: minor_ver, conf */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, unsigned char *master, const mbedtls_ssl_context *ssl ) @@ -2108,6 +2120,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -2323,6 +2336,7 @@ write_msg: #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len ) @@ -2338,6 +2352,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len ) @@ -2372,6 +2387,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, * Once the certificate message is read, parse it into a cert chain and * perform basic checks, but leave actual verification to the caller */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, mbedtls_x509_crt *chain ) { @@ -2521,6 +2537,7 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_SRV_C) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) { if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) @@ -2570,6 +2587,7 @@ static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) */ #define SSL_CERTIFICATE_EXPECTED 0 #define SSL_CERTIFICATE_SKIP 1 +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, int authmode ) { @@ -2599,6 +2617,7 @@ static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, return( SSL_CERTIFICATE_EXPECTED ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, int authmode, mbedtls_x509_crt *chain, @@ -2696,7 +2715,9 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, { const mbedtls_pk_context *pk = &chain->pk; - /* If certificate uses an EC key, make sure the curve is OK */ + /* If certificate uses an EC key, make sure the curve is OK. + * This is a public key, so it can't be opaque, so can_do() is a good + * enough check to ensure pk_ec() is safe to use here. */ if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) { @@ -2787,6 +2808,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl, unsigned char *start, size_t len ) { @@ -2818,6 +2840,7 @@ static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl, return( ret ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl, unsigned char *start, size_t len ) { @@ -3428,7 +3451,7 @@ void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) ssl->handshake = NULL; /* - * Free the previous transform and swith in the current one + * Free the previous transform and switch in the current one */ if( ssl->transform ) { @@ -3796,6 +3819,7 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) memset( session, 0, sizeof(mbedtls_ssl_session) ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handshake_init( mbedtls_ssl_context *ssl ) { /* Clear old handshake information if present */ @@ -3873,6 +3897,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /* Dummy cookie callbacks for defaults */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_write_dummy( void *ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len ) @@ -3886,6 +3911,7 @@ static int ssl_cookie_write_dummy( void *ctx, return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_check_dummy( void *ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len ) @@ -4303,6 +4329,7 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, } /* Append a new keycert entry to a (possibly empty) list */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key ) @@ -4471,6 +4498,7 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) * It checks that the provided identity is well-formed and attempts * to make a copy of it in the SSL config. * On failure, the PSK identity in the config remains unset. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf, unsigned char const *psk_identity, size_t psk_identity_len ) @@ -4632,6 +4660,9 @@ int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) { @@ -4647,6 +4678,9 @@ int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) { @@ -5384,6 +5418,7 @@ static unsigned char ssl_serialized_session_header[] = { * verify_result is put before peer_cert so that all mandatory fields come * together in one block. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_save( const mbedtls_ssl_session *session, unsigned char omit_header, unsigned char *buf, @@ -5583,6 +5618,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, * This internal version is wrapped by a public function that cleans up in * case of error, and has an extra option omit_header. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_load( mbedtls_ssl_session *session, unsigned char omit_header, const unsigned char *buf, @@ -5886,6 +5922,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) /* * Write HelloRequest to request renegotiation on server */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -6497,6 +6534,7 @@ static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) * This internal version is wrapped by a public function that cleans up in * case of error. */ +MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -7320,6 +7358,18 @@ int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_i return( -1 ); } + +/* + * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve. + */ +int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_id ); + if( curve_info == NULL ) + return( -1 ); + return( mbedtls_ssl_check_curve( ssl, curve_info->grp_id ) ); +} #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index 2de117f52a..5e0aaa4f21 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -113,7 +113,7 @@ int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_ int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; /* - * With phtreads we can statically initialize mutexes + * With pthreads we can statically initialize mutexes */ #define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index eb41461320..57bc9bcc12 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -56,15 +56,15 @@ struct _hr_time #include <unistd.h> #include <sys/types.h> -#include <sys/time.h> #include <signal.h> +/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the + * platform matches the ifdefs above, it will be used. */ #include <time.h> - +#include <sys/time.h> struct _hr_time { struct timeval start; }; - #endif /* _WIN32 && !EFIX64 && !EFI32 */ #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ @@ -364,7 +364,6 @@ int mbedtls_timing_get_delay( void *data ) return( 0 ); } -#endif /* !MBEDTLS_TIMING_ALT */ #if defined(MBEDTLS_SELF_TEST) @@ -526,5 +525,5 @@ hard_test_done: } #endif /* MBEDTLS_SELF_TEST */ - +#endif /* !MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_C */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index f21e9e6944..3997ebd1f3 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -741,7 +741,7 @@ int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, n; + size_t i, j, n; unsigned char c, merge = 0; const mbedtls_x509_name *name; const char *short_name = NULL; @@ -775,17 +775,24 @@ int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) ret = mbedtls_snprintf( p, n, "\?\?=" ); MBEDTLS_X509_SAFE_SNPRINTF; - for( i = 0; i < name->val.len; i++ ) + for( i = 0, j = 0; i < name->val.len; i++, j++ ) { - if( i >= sizeof( s ) - 1 ) - break; + if( j >= sizeof( s ) - 1 ) + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); c = name->val.p[i]; + // Special characters requiring escaping, RFC 1779 + if( c && strchr( ",=+<>#;\"\\", c ) ) + { + if( j + 1 >= sizeof( s ) - 1 ) + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + s[j++] = '\\'; + } if( c < 32 || c >= 127 ) - s[i] = '?'; - else s[i] = c; + s[j] = '?'; + else s[j] = c; } - s[i] = '\0'; + s[j] = '\0'; ret = mbedtls_snprintf( p, n, "%s", s ); MBEDTLS_X509_SAFE_SNPRINTF; diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c index ac4fc75de3..d2d8042029 100644 --- a/thirdparty/mbedtls/library/x509_crl.c +++ b/thirdparty/mbedtls/library/x509_crl.c @@ -52,11 +52,13 @@ #define mbedtls_snprintf snprintf #endif +#if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include <windows.h> #else #include <time.h> #endif +#endif #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include <stdio.h> diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index 60312bf2f5..96477e4c9d 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -63,6 +63,7 @@ #include "mbedtls/threading.h" #endif +#if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include <windows.h> #if defined(_MSC_VER) && _MSC_VER <= 1600 @@ -81,6 +82,7 @@ #else #include <time.h> #endif +#endif #if defined(MBEDTLS_FS_IO) #include <stdio.h> diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c index 184c90cd33..0c5e991834 100644 --- a/thirdparty/mbedtls/library/x509write_crt.c +++ b/thirdparty/mbedtls/library/x509write_crt.c @@ -299,7 +299,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start, /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ - if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) ) { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, (const unsigned char *) t + 2, diff --git a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h index c15736e255..ae81f141c4 100644 --- a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h +++ b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h @@ -70,6 +70,7 @@ typedef enum SpvSourceLanguage_ { SpvSourceLanguageOpenCL_CPP = 4, SpvSourceLanguageHLSL = 5, SpvSourceLanguageCPP_for_OpenCL = 6, + SpvSourceLanguageSYCL = 7, SpvSourceLanguageMax = 0x7fffffff, } SpvSourceLanguage; @@ -184,6 +185,7 @@ typedef enum SpvExecutionMode_ { SpvExecutionModeNoGlobalOffsetINTEL = 5895, SpvExecutionModeNumSIMDWorkitemsINTEL = 5896, SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, + SpvExecutionModeNamedBarrierCountINTEL = 6417, SpvExecutionModeMax = 0x7fffffff, } SpvExecutionMode; @@ -546,6 +548,8 @@ typedef enum SpvDecoration_ { SpvDecorationPrefetchINTEL = 5902, SpvDecorationStallEnableINTEL = 5905, SpvDecorationFuseLoopsInFunctionINTEL = 5907, + SpvDecorationAliasScopeINTEL = 5914, + SpvDecorationNoAliasINTEL = 5915, SpvDecorationBufferLocationINTEL = 5921, SpvDecorationIOPipeStorageINTEL = 5944, SpvDecorationFunctionFloatingPointModeINTEL = 6080, @@ -677,6 +681,7 @@ typedef enum SpvBuiltIn_ { SpvBuiltInSMCountNV = 5375, SpvBuiltInWarpIDNV = 5376, SpvBuiltInSMIDNV = 5377, + SpvBuiltInCullMaskKHR = 6021, SpvBuiltInMax = 0x7fffffff, } SpvBuiltIn; @@ -804,6 +809,8 @@ typedef enum SpvMemoryAccessShift_ { SpvMemoryAccessMakePointerVisibleKHRShift = 4, SpvMemoryAccessNonPrivatePointerShift = 5, SpvMemoryAccessNonPrivatePointerKHRShift = 5, + SpvMemoryAccessAliasScopeINTELMaskShift = 16, + SpvMemoryAccessNoAliasINTELMaskShift = 17, SpvMemoryAccessMax = 0x7fffffff, } SpvMemoryAccessShift; @@ -818,6 +825,8 @@ typedef enum SpvMemoryAccessMask_ { SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, SpvMemoryAccessNonPrivatePointerMask = 0x00000020, SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, + SpvMemoryAccessAliasScopeINTELMaskMask = 0x00010000, + SpvMemoryAccessNoAliasINTELMaskMask = 0x00020000, } SpvMemoryAccessMask; typedef enum SpvScope_ { @@ -1059,6 +1068,7 @@ typedef enum SpvCapability_ { SpvCapabilityFPGAMemoryAccessesINTEL = 5898, SpvCapabilityFPGAClusterAttributesINTEL = 5904, SpvCapabilityLoopFuseINTEL = 5906, + SpvCapabilityMemoryAccessAliasingINTEL = 5910, SpvCapabilityFPGABufferLocationINTEL = 5920, SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922, SpvCapabilityUSMStorageClassesINTEL = 5935, @@ -1073,13 +1083,17 @@ typedef enum SpvCapability_ { SpvCapabilityDotProductInput4x8BitPackedKHR = 6018, SpvCapabilityDotProduct = 6019, SpvCapabilityDotProductKHR = 6019, + SpvCapabilityRayCullMaskKHR = 6020, SpvCapabilityBitInstructions = 6025, + SpvCapabilityGroupNonUniformRotateKHR = 6026, SpvCapabilityAtomicFloat32AddEXT = 6033, SpvCapabilityAtomicFloat64AddEXT = 6034, SpvCapabilityLongConstantCompositeINTEL = 6089, SpvCapabilityOptNoneINTEL = 6094, SpvCapabilityAtomicFloat16AddEXT = 6095, SpvCapabilityDebugInfoModuleINTEL = 6114, + SpvCapabilitySplitBarrierINTEL = 6141, + SpvCapabilityGroupUniformArithmeticKHR = 6400, SpvCapabilityMax = 0x7fffffff, } SpvCapability; @@ -1535,6 +1549,7 @@ typedef enum SpvOp_ { SpvOpSubgroupAllKHR = 4428, SpvOpSubgroupAnyKHR = 4429, SpvOpSubgroupAllEqualKHR = 4430, + SpvOpGroupNonUniformRotateKHR = 4431, SpvOpSubgroupReadInvocationKHR = 4432, SpvOpTraceRayKHR = 4445, SpvOpExecuteCallableKHR = 4446, @@ -1801,6 +1816,9 @@ typedef enum SpvOp_ { SpvOpArbitraryFloatPowRINTEL = 5881, SpvOpArbitraryFloatPowNINTEL = 5882, SpvOpLoopControlINTEL = 5887, + SpvOpAliasDomainDeclINTEL = 5911, + SpvOpAliasScopeDeclINTEL = 5912, + SpvOpAliasScopeListDeclINTEL = 5913, SpvOpFixedSqrtINTEL = 5923, SpvOpFixedRecipINTEL = 5924, SpvOpFixedRsqrtINTEL = 5925, @@ -1839,10 +1857,23 @@ typedef enum SpvOp_ { SpvOpTypeStructContinuedINTEL = 6090, SpvOpConstantCompositeContinuedINTEL = 6091, SpvOpSpecConstantCompositeContinuedINTEL = 6092, + SpvOpControlBarrierArriveINTEL = 6142, + SpvOpControlBarrierWaitINTEL = 6143, + SpvOpGroupIMulKHR = 6401, + SpvOpGroupFMulKHR = 6402, + SpvOpGroupBitwiseAndKHR = 6403, + SpvOpGroupBitwiseOrKHR = 6404, + SpvOpGroupBitwiseXorKHR = 6405, + SpvOpGroupLogicalAndKHR = 6406, + SpvOpGroupLogicalOrKHR = 6407, + SpvOpGroupLogicalXorKHR = 6408, SpvOpMax = 0x7fffffff, } SpvOp; #ifdef SPV_ENABLE_UTILITY_CODE +#ifndef __cplusplus +#include <stdbool.h> +#endif inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) { *hasResult = *hasResultType = false; switch (opcode) { @@ -2197,6 +2228,7 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break; case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; case SpvOpTraceRayKHR: *hasResult = false; *hasResultType = false; break; case SpvOpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break; @@ -2452,6 +2484,9 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy case SpvOpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break; case SpvOpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break; case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break; case SpvOpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break; case SpvOpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break; case SpvOpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break; @@ -2490,9 +2525,18 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy case SpvOpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break; case SpvOpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; case SpvOpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupIMulKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMulKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break; } } #endif /* SPV_ENABLE_UTILITY_CODE */ #endif - diff --git a/thirdparty/spirv-reflect/patches/specialization-constants.patch b/thirdparty/spirv-reflect/patches/specialization-constants.patch index 9bb5f97cd3..99815c9162 100644 --- a/thirdparty/spirv-reflect/patches/specialization-constants.patch +++ b/thirdparty/spirv-reflect/patches/specialization-constants.patch @@ -1,8 +1,8 @@ diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c -index e9b11bf495..f181df5fa2 100644 +index cdcf3ca663..c174ae1900 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c -@@ -125,6 +125,9 @@ typedef struct SpvReflectPrvDecorations { +@@ -126,6 +126,9 @@ typedef struct SpvReflectPrvDecorations { SpvReflectPrvNumberDecoration location; SpvReflectPrvNumberDecoration offset; SpvReflectPrvNumberDecoration uav_counter_buffer; @@ -12,7 +12,7 @@ index e9b11bf495..f181df5fa2 100644 SpvReflectPrvStringDecoration semantic; uint32_t array_stride; uint32_t matrix_stride; -@@ -631,6 +634,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) +@@ -639,6 +642,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE; p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE; p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE; @@ -22,7 +22,7 @@ index e9b11bf495..f181df5fa2 100644 } // Mark source file id node p_parser->source_file_id = (uint32_t)INVALID_VALUE; -@@ -821,10 +827,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) +@@ -829,10 +835,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); } break; @@ -41,7 +41,7 @@ index e9b11bf495..f181df5fa2 100644 case SpvOpSpecConstantComposite: case SpvOpSpecConstantOp: { CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); -@@ -856,7 +868,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) +@@ -864,7 +876,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id); // // SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index: @@ -50,7 +50,7 @@ index e9b11bf495..f181df5fa2 100644 // p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET); if (p_access_chain->index_count > 0) { -@@ -1338,6 +1350,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) +@@ -1346,6 +1358,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) skip = true; } break; @@ -60,7 +60,7 @@ index e9b11bf495..f181df5fa2 100644 case SpvDecorationRelaxedPrecision: case SpvDecorationBlock: case SpvDecorationBufferBlock: -@@ -1481,7 +1496,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) +@@ -1495,7 +1510,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) p_target_decorations->input_attachment_index.word_offset = word_offset; } break; @@ -76,7 +76,7 @@ index e9b11bf495..f181df5fa2 100644 case SpvReflectDecorationHlslCounterBufferGOOGLE: { uint32_t word_offset = p_node->word_offset + member_offset+ 3; CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value); -@@ -1789,6 +1811,13 @@ static SpvReflectResult ParseType( +@@ -1803,6 +1825,13 @@ static SpvReflectResult ParseType( p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE; } break; @@ -90,7 +90,7 @@ index e9b11bf495..f181df5fa2 100644 } if (result == SPV_REFLECT_RESULT_SUCCESS) { -@@ -3269,6 +3298,69 @@ static SpvReflectResult ParseExecutionModes( +@@ -3332,6 +3361,69 @@ static SpvReflectResult ParseExecutionModes( return SPV_REFLECT_RESULT_SUCCESS; } @@ -160,7 +160,7 @@ index e9b11bf495..f181df5fa2 100644 static SpvReflectResult ParsePushConstantBlocks( SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) -@@ -3650,6 +3742,12 @@ static SpvReflectResult CreateShaderModule( +@@ -3717,6 +3809,12 @@ static SpvReflectResult CreateShaderModule( result = ParsePushConstantBlocks(&parser, p_module); SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } @@ -173,8 +173,8 @@ index e9b11bf495..f181df5fa2 100644 if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseEntryPoints(&parser, p_module); SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); -@@ -3807,6 +3905,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) - SafeFree(p_entry->used_push_constants); +@@ -3875,6 +3973,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) + SafeFree(p_entry->execution_modes); } SafeFree(p_module->entry_points); +// -- GODOT begin -- @@ -183,7 +183,7 @@ index e9b11bf495..f181df5fa2 100644 // Push constants for (size_t i = 0; i < p_module->push_constant_block_count; ++i) { -@@ -4077,6 +4178,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( +@@ -4145,6 +4246,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( return SPV_REFLECT_RESULT_SUCCESS; } @@ -223,10 +223,10 @@ index e9b11bf495..f181df5fa2 100644 const SpvReflectShaderModule* p_module, uint32_t* p_count, diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h -index e9e4c40755..948533d3c0 100644 +index 02b81613a1..02850f8811 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.h +++ b/thirdparty/spirv-reflect/spirv_reflect.h -@@ -323,6 +323,28 @@ typedef struct SpvReflectTypeDescription { +@@ -329,6 +329,28 @@ typedef struct SpvReflectTypeDescription { struct SpvReflectTypeDescription* members; } SpvReflectTypeDescription; @@ -255,7 +255,7 @@ index e9e4c40755..948533d3c0 100644 /*! @struct SpvReflectInterfaceVariable -@@ -472,6 +494,10 @@ typedef struct SpvReflectShaderModule { +@@ -483,6 +505,10 @@ typedef struct SpvReflectShaderModule { SpvReflectInterfaceVariable* interface_variables; // Uses value(s) from first entry point uint32_t push_constant_block_count; // Uses value(s) from first entry point SpvReflectBlockVariable* push_constant_blocks; // Uses value(s) from first entry point @@ -266,7 +266,7 @@ index e9e4c40755..948533d3c0 100644 struct Internal { SpvReflectModuleFlags module_flags; -@@ -744,6 +770,33 @@ SpvReflectResult spvReflectEnumerateInputVariables( +@@ -755,6 +781,33 @@ SpvReflectResult spvReflectEnumerateInputVariables( SpvReflectInterfaceVariable** pp_variables ); diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c index f181df5fa2..c174ae1900 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c @@ -119,6 +119,7 @@ typedef struct SpvReflectPrvDecorations { bool is_noperspective; bool is_flat; bool is_non_writable; + bool is_non_readable; SpvReflectPrvNumberDecoration set; SpvReflectPrvNumberDecoration binding; SpvReflectPrvNumberDecoration input_attachment_index; @@ -306,7 +307,12 @@ static SpvReflectResult IntersectSortedUint32( size_t* res_size ) { + *pp_res = NULL; *res_size = 0; + if (IsNull(p_arr0) || IsNull(p_arr1)) { + return SPV_REFLECT_RESULT_SUCCESS; + } + const uint32_t* arr0_end = p_arr0 + arr0_size; const uint32_t* arr1_end = p_arr1 + arr1_size; @@ -324,7 +330,6 @@ static SpvReflectResult IntersectSortedUint32( } } - *pp_res = NULL; if (*res_size > 0) { *pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res)); if (IsNull(*pp_res)) { @@ -488,6 +493,9 @@ static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations if (p_decoration_fields->is_non_writable) { decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE; } + if (p_decoration_fields->is_non_readable) { + decorations |= SPV_REFLECT_DECORATION_NON_READABLE; + } return decorations; } @@ -1364,6 +1372,7 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) case SpvDecorationNoPerspective: case SpvDecorationFlat: case SpvDecorationNonWritable: + case SpvDecorationNonReadable: case SpvDecorationLocation: case SpvDecorationBinding: case SpvDecorationDescriptorSet: @@ -1462,6 +1471,11 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) } break; + case SpvDecorationNonReadable: { + p_target_decorations->is_non_readable = true; + } + break; + case SpvDecorationLocation: { uint32_t word_offset = p_node->word_offset + member_offset + 3; CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value); @@ -1970,6 +1984,7 @@ static SpvReflectResult ParseDescriptorBindings( p_descriptor->count = 1; p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value; p_descriptor->type_description = p_type; + p_descriptor->decoration_flags = ApplyDecorations(&p_node->decorations); // If this is in the StorageBuffer storage class, it's for sure a storage // buffer descriptor. We need to handle this case earlier because in SPIR-V @@ -3208,8 +3223,8 @@ static SpvReflectResult ParseExecutionModes( // Read entry point id uint32_t entry_point_id = 0; CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id); - - // Find entry point + + // Find entry point SpvReflectEntryPoint* p_entry_point = NULL; for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { if (p_module->entry_points[entry_point_idx].id == entry_point_id) { @@ -3221,7 +3236,7 @@ static SpvReflectResult ParseExecutionModes( if (IsNull(p_entry_point)) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT; } - + // Read execution mode uint32_t execution_mode = (uint32_t)INVALID_VALUE; CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode); @@ -3288,12 +3303,60 @@ static SpvReflectResult ParseExecutionModes( case SpvExecutionModeLocalSizeId: case SpvExecutionModeLocalSizeHintId: case SpvExecutionModePostDepthCoverage: + case SpvExecutionModeDenormPreserve: + case SpvExecutionModeDenormFlushToZero: + case SpvExecutionModeSignedZeroInfNanPreserve: + case SpvExecutionModeRoundingModeRTE: + case SpvExecutionModeRoundingModeRTZ: case SpvExecutionModeStencilRefReplacingEXT: + case SpvExecutionModeOutputLinesNV: case SpvExecutionModeOutputPrimitivesNV: case SpvExecutionModeOutputTrianglesNV: break; } + p_entry_point->execution_mode_count++; + } + uint32_t* indices = (uint32_t*)calloc(p_module->entry_point_count, sizeof(indices)); + if (IsNull(indices)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; } + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx]; + p_entry_point->execution_modes = + (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); + if (IsNull(p_entry_point->execution_modes)) { + SafeFree(indices); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]); + if (p_node->op != SpvOpExecutionMode) { + continue; + } + + // Read entry point id + uint32_t entry_point_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id); + + // Find entry point + SpvReflectEntryPoint* p_entry_point = NULL; + uint32_t* idx = NULL; + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + if (p_module->entry_points[entry_point_idx].id == entry_point_id) { + p_entry_point = &p_module->entry_points[entry_point_idx]; + idx = &indices[entry_point_idx]; + break; + } + } + + // Read execution mode + uint32_t execution_mode = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode); + p_entry_point->execution_modes[(*idx)++] = (SpvExecutionMode)execution_mode; + } + SafeFree(indices); } return SPV_REFLECT_RESULT_SUCCESS; } @@ -3649,7 +3712,11 @@ static SpvReflectResult CreateShaderModule( if (flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) { // Set internal size and pointer to args passed in p_module->_internal->spirv_size = size; +#if defined(__cplusplus) + p_module->_internal->spirv_code = const_cast<uint32_t*>(static_cast<const uint32_t*>(p_code)); // cast that const away +#else p_module->_internal->spirv_code = (void*)p_code; // cast that const away +#endif p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE); } else { @@ -3903,6 +3970,7 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) SafeFree(p_entry->interface_variables); SafeFree(p_entry->used_uniforms); SafeFree(p_entry->used_push_constants); + SafeFree(p_entry->execution_modes); } SafeFree(p_module->entry_points); // -- GODOT begin -- @@ -5093,6 +5161,7 @@ const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang) case SpvSourceLanguageOpenCL_CPP : return "OpenCL_CPP"; case SpvSourceLanguageHLSL : return "HLSL"; case SpvSourceLanguageCPP_for_OpenCL : return "CPP_for_OpenCL"; + case SpvSourceLanguageSYCL : return "SYCL"; case SpvSourceLanguageMax: break; } diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h index 948533d3c0..02850f8811 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.h +++ b/thirdparty/spirv-reflect/spirv_reflect.h @@ -30,7 +30,12 @@ VERSION HISTORY #ifndef SPIRV_REFLECT_H #define SPIRV_REFLECT_H +#if defined(SPIRV_REFLECT_USE_SYSTEM_SPIRV_H) +#include <spirv/unified1/spirv.h> +#else #include "./include/spirv/unified1/spirv.h" +#endif + #include <stdint.h> #include <string.h> @@ -139,6 +144,7 @@ typedef enum SpvReflectDecorationFlagBits { SPV_REFLECT_DECORATION_FLAT = 0x00000040, SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080, SPV_REFLECT_DECORATION_RELAXED_PRECISION = 0x00000100, + SPV_REFLECT_DECORATION_NON_READABLE = 0x00000200, } SpvReflectDecorationFlagBits; typedef uint32_t SpvReflectDecorationFlags; @@ -422,6 +428,8 @@ typedef struct SpvReflectDescriptorBinding { uint32_t binding; uint32_t set; } word_offset; + + SpvReflectDecorationFlags decoration_flags; } SpvReflectDescriptorBinding; /*! @struct SpvReflectDescriptorSet @@ -458,6 +466,9 @@ typedef struct SpvReflectEntryPoint { uint32_t used_push_constant_count; uint32_t* used_push_constants; + uint32_t execution_mode_count; + SpvExecutionMode* execution_modes; + struct LocalSize { uint32_t x; uint32_t y; |